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 public Pack200CompressorOutputStream(final OutputStream out) 048 throws IOException { 049 this(out, Pack200Strategy.IN_MEMORY); 050 } 051 052 /** 053 * Compresses the given stream using the given strategy to cache 054 * the results. 055 */ 056 public Pack200CompressorOutputStream(final OutputStream out, 057 final Pack200Strategy mode) 058 throws IOException { 059 this(out, mode, null); 060 } 061 062 /** 063 * Compresses the given stream, caching the compressed data in 064 * memory and using the given properties. 065 */ 066 public Pack200CompressorOutputStream(final OutputStream out, 067 final Map<String, String> props) 068 throws IOException { 069 this(out, Pack200Strategy.IN_MEMORY, props); 070 } 071 072 /** 073 * Compresses the given stream using the given strategy to cache 074 * the results and the given properties. 075 */ 076 public Pack200CompressorOutputStream(final OutputStream out, 077 final Pack200Strategy mode, 078 final Map<String, String> props) 079 throws IOException { 080 originalOutput = out; 081 streamBridge = mode.newStreamBridge(); 082 properties = props; 083 } 084 085 @Override 086 public void write(int b) throws IOException { 087 streamBridge.write(b); 088 } 089 090 @Override 091 public void write(byte[] b) throws IOException { 092 streamBridge.write(b); 093 } 094 095 @Override 096 public void write(byte[] b, int from, int length) throws IOException { 097 streamBridge.write(b, from, length); 098 } 099 100 @Override 101 public void close() throws IOException { 102 finish(); 103 try { 104 streamBridge.stop(); 105 } finally { 106 originalOutput.close(); 107 } 108 } 109 110 public void finish() throws IOException { 111 if (!finished) { 112 finished = true; 113 Pack200.Packer p = Pack200.newPacker(); 114 if (properties != null) { 115 p.properties().putAll(properties); 116 } 117 JarInputStream ji = null; 118 boolean success = false; 119 try { 120 p.pack(ji = new JarInputStream(streamBridge.getInput()), 121 originalOutput); 122 success = true; 123 } finally { 124 if (!success) { 125 IOUtils.closeQuietly(ji); 126 } 127 } 128 } 129 } 130}