001/* 002 * Licensed to the Apache Software Foundation (ASF) under one 003 * or more contributor license agreements. See the NOTICE file 004 * distributed with this work for additional information 005 * regarding copyright ownership. The ASF licenses this file 006 * to you under the Apache License, Version 2.0 (the 007 * "License"); you may not use this file except in compliance 008 * with the License. You may obtain a copy of the License at 009 * 010 * http://www.apache.org/licenses/LICENSE-2.0 011 * 012 * Unless required by applicable law or agreed to in writing, 013 * software distributed under the License is distributed on an 014 * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY 015 * KIND, either express or implied. See the License for the 016 * specific language governing permissions and limitations 017 * under the License. 018 */ 019 020package org.apache.commons.compress.compressors.pack200; 021 022import java.io.IOException; 023import java.io.OutputStream; 024import java.util.Map; 025import java.util.jar.JarInputStream; 026 027import org.apache.commons.compress.compressors.CompressorOutputStream; 028import org.apache.commons.compress.java.util.jar.Pack200; 029 030/** 031 * An output stream that compresses using the Pack200 format. 032 * 033 * @NotThreadSafe 034 * @since 1.3 035 */ 036public class Pack200CompressorOutputStream extends CompressorOutputStream { 037 private boolean finished; 038 private final OutputStream originalOutput; 039 private final AbstractStreamBridge abstractStreamBridge; 040 private final Map<String, String> properties; 041 042 /** 043 * Compresses the given stream, caching the compressed data in memory. 044 * 045 * @param out the stream to write to 046 * @throws IOException if writing fails 047 */ 048 public Pack200CompressorOutputStream(final OutputStream out) throws IOException { 049 this(out, Pack200Strategy.IN_MEMORY); 050 } 051 052 /** 053 * Compresses the given stream, caching the compressed data in memory and using the given properties. 054 * 055 * @param out the stream to write to 056 * @param props Pack200 properties to use 057 * @throws IOException if writing fails 058 */ 059 public Pack200CompressorOutputStream(final OutputStream out, final Map<String, String> props) throws IOException { 060 this(out, Pack200Strategy.IN_MEMORY, props); 061 } 062 063 /** 064 * Compresses the given stream using the given strategy to cache the results. 065 * 066 * @param out the stream to write to 067 * @param mode the strategy to use 068 * @throws IOException if writing fails 069 */ 070 public Pack200CompressorOutputStream(final OutputStream out, final Pack200Strategy mode) throws IOException { 071 this(out, mode, null); 072 } 073 074 /** 075 * Compresses the given stream using the given strategy to cache the results and the given properties. 076 * 077 * @param out the stream to write to 078 * @param mode the strategy to use 079 * @param props Pack200 properties to use 080 * @throws IOException if writing fails 081 */ 082 public Pack200CompressorOutputStream(final OutputStream out, final Pack200Strategy mode, final Map<String, String> props) throws IOException { 083 originalOutput = out; 084 abstractStreamBridge = mode.newStreamBridge(); 085 properties = props; 086 } 087 088 @Override 089 public void close() throws IOException { 090 try { 091 finish(); 092 } finally { 093 try { 094 abstractStreamBridge.stop(); 095 } finally { 096 originalOutput.close(); 097 } 098 } 099 } 100 101 public void finish() throws IOException { 102 if (!finished) { 103 finished = true; 104 final Pack200.Packer p = Pack200.newPacker(); 105 if (properties != null) { 106 p.properties().putAll(properties); 107 } 108 try (JarInputStream ji = new JarInputStream(abstractStreamBridge.getInputStream())) { 109 p.pack(ji, originalOutput); 110 } 111 } 112 } 113 114 @Override 115 public void write(final byte[] b) throws IOException { 116 abstractStreamBridge.write(b); 117 } 118 119 @Override 120 public void write(final byte[] b, final int from, final int length) throws IOException { 121 abstractStreamBridge.write(b, from, length); 122 } 123 124 @Override 125 public void write(final int b) throws IOException { 126 abstractStreamBridge.write(b); 127 } 128}