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 Apache Commons Compress 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 }