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; 026import java.util.jar.Pack200; 027 028import org.apache.commons.compress.compressors.CompressorOutputStream; 029import org.apache.commons.compress.utils.IOUtils; 030 031/** 032 * An output stream that compresses using the Pack200 format. 033 * 034 * @NotThreadSafe 035 * @since 1.3 036 */ 037public class Pack200CompressorOutputStream extends CompressorOutputStream { 038 private boolean finished = false; 039 private final OutputStream originalOutput; 040 private final StreamBridge streamBridge; 041 private final Map<String, String> properties; 042 043 /** 044 * Compresses the given stream, caching the compressed data in 045 * memory. 046 * 047 * @param out the stream to write to 048 * @throws IOException if writing fails 049 */ 050 public Pack200CompressorOutputStream(final OutputStream out) 051 throws IOException { 052 this(out, Pack200Strategy.IN_MEMORY); 053 } 054 055 /** 056 * Compresses the given stream using the given strategy to cache 057 * the results. 058 * 059 * @param out the stream to write to 060 * @param mode the strategy to use 061 * @throws IOException if writing fails 062 */ 063 public Pack200CompressorOutputStream(final OutputStream out, 064 final Pack200Strategy mode) 065 throws IOException { 066 this(out, mode, null); 067 } 068 069 /** 070 * Compresses the given stream, caching the compressed data in 071 * memory and using the given properties. 072 * 073 * @param out the stream to write to 074 * @param props Pack200 properties to use 075 * @throws IOException if writing fails 076 */ 077 public Pack200CompressorOutputStream(final OutputStream out, 078 final Map<String, String> props) 079 throws IOException { 080 this(out, Pack200Strategy.IN_MEMORY, props); 081 } 082 083 /** 084 * Compresses the given stream using the given strategy to cache 085 * the results and the given properties. 086 * 087 * @param out the stream to write to 088 * @param mode the strategy to use 089 * @param props Pack200 properties to use 090 * @throws IOException if writing fails 091 */ 092 public Pack200CompressorOutputStream(final OutputStream out, 093 final Pack200Strategy mode, 094 final Map<String, String> props) 095 throws IOException { 096 originalOutput = out; 097 streamBridge = mode.newStreamBridge(); 098 properties = props; 099 } 100 101 @Override 102 public void write(final int b) throws IOException { 103 streamBridge.write(b); 104 } 105 106 @Override 107 public void write(final byte[] b) throws IOException { 108 streamBridge.write(b); 109 } 110 111 @Override 112 public void write(final byte[] b, final int from, final int length) throws IOException { 113 streamBridge.write(b, from, length); 114 } 115 116 @Override 117 public void close() throws IOException { 118 finish(); 119 try { 120 streamBridge.stop(); 121 } finally { 122 originalOutput.close(); 123 } 124 } 125 126 public void finish() throws IOException { 127 if (!finished) { 128 finished = true; 129 final Pack200.Packer p = Pack200.newPacker(); 130 if (properties != null) { 131 p.properties().putAll(properties); 132 } 133 JarInputStream ji = null; 134 boolean success = false; 135 try { 136 ji = new JarInputStream(streamBridge.getInput()); 137 p.pack(ji, originalOutput); 138 success = true; 139 } finally { 140 if (!success) { 141 IOUtils.closeQuietly(ji); 142 } 143 } 144 } 145 } 146}