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