1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20 package org.apache.commons.compress.compressors.pack200;
21
22 import java.io.File;
23 import java.io.IOException;
24 import java.io.InputStream;
25 import java.io.UncheckedIOException;
26 import java.util.Map;
27 import java.util.jar.JarOutputStream;
28
29 import org.apache.commons.compress.compressors.CompressorInputStream;
30 import org.apache.commons.compress.java.util.jar.Pack200;
31 import org.apache.commons.io.IOUtils;
32
33
34
35
36
37
38
39
40
41
42
43 public class Pack200CompressorInputStream extends CompressorInputStream {
44
45 private static final byte[] CAFE_DOOD = { (byte) 0xCA, (byte) 0xFE, (byte) 0xD0, (byte) 0x0D };
46 private static final int SIG_LENGTH = CAFE_DOOD.length;
47
48
49
50
51
52
53
54
55 public static boolean matches(final byte[] signature, final int length) {
56 if (length < SIG_LENGTH) {
57 return false;
58 }
59
60 for (int i = 0; i < SIG_LENGTH; i++) {
61 if (signature[i] != CAFE_DOOD[i]) {
62 return false;
63 }
64 }
65
66 return true;
67 }
68
69 private final InputStream originalInputStream;
70
71 private final AbstractStreamBridge abstractStreamBridge;
72
73
74
75
76
77
78
79 public Pack200CompressorInputStream(final File file) throws IOException {
80 this(file, Pack200Strategy.IN_MEMORY);
81 }
82
83
84
85
86
87
88
89
90 public Pack200CompressorInputStream(final File file, final Map<String, String> properties) throws IOException {
91 this(file, Pack200Strategy.IN_MEMORY, properties);
92 }
93
94
95
96
97
98
99
100
101 public Pack200CompressorInputStream(final File file, final Pack200Strategy mode) throws IOException {
102 this(null, file, mode, null);
103 }
104
105
106
107
108
109
110
111
112
113 public Pack200CompressorInputStream(final File file, final Pack200Strategy mode, final Map<String, String> properties) throws IOException {
114 this(null, file, mode, properties);
115 }
116
117
118
119
120
121
122
123
124
125
126
127 public Pack200CompressorInputStream(final InputStream inputStream) throws IOException {
128 this(inputStream, Pack200Strategy.IN_MEMORY);
129 }
130
131 private Pack200CompressorInputStream(final InputStream inputStream, final File file, final Pack200Strategy mode, final Map<String, String> properties)
132 throws IOException {
133 this.originalInputStream = inputStream;
134 this.abstractStreamBridge = mode.newStreamBridge();
135 try (JarOutputStream jarOut = new JarOutputStream(abstractStreamBridge)) {
136 final Pack200.Unpacker unpacker = Pack200.newUnpacker();
137 if (properties != null) {
138 unpacker.properties().putAll(properties);
139 }
140 if (file == null) {
141 unpacker.unpack(inputStream, jarOut);
142 } else {
143 unpacker.unpack(file, jarOut);
144 }
145 }
146 }
147
148
149
150
151
152
153
154
155
156
157
158
159 public Pack200CompressorInputStream(final InputStream inputStream, final Map<String, String> properties) throws IOException {
160 this(inputStream, Pack200Strategy.IN_MEMORY, properties);
161 }
162
163
164
165
166
167
168
169
170
171
172
173
174 public Pack200CompressorInputStream(final InputStream inputStream, final Pack200Strategy mode) throws IOException {
175 this(inputStream, null, mode, null);
176 }
177
178
179
180
181
182
183
184
185
186
187
188
189
190 public Pack200CompressorInputStream(final InputStream inputStream, final Pack200Strategy mode, final Map<String, String> properties) throws IOException {
191 this(inputStream, null, mode, properties);
192 }
193
194 @SuppressWarnings("resource")
195 @Override
196 public int available() throws IOException {
197 return getInputStream().available();
198 }
199
200 @Override
201 public void close() throws IOException {
202 try {
203 abstractStreamBridge.stop();
204 } finally {
205 IOUtils.close(originalInputStream);
206 }
207 }
208
209 private InputStream getInputStream() throws IOException {
210 return abstractStreamBridge.getInputStream();
211 }
212
213 @SuppressWarnings("resource")
214 @Override
215 public synchronized void mark(final int limit) {
216 try {
217 getInputStream().mark(limit);
218 } catch (final IOException ex) {
219 throw new UncheckedIOException(ex);
220 }
221 }
222
223 @SuppressWarnings("resource")
224 @Override
225 public boolean markSupported() {
226 try {
227 return getInputStream().markSupported();
228 } catch (final IOException ex) {
229 return false;
230 }
231 }
232
233 @SuppressWarnings("resource")
234 @Override
235 public int read() throws IOException {
236 return getInputStream().read();
237 }
238
239 @SuppressWarnings("resource")
240 @Override
241 public int read(final byte[] b) throws IOException {
242 return getInputStream().read(b);
243 }
244
245 @SuppressWarnings("resource")
246 @Override
247 public int read(final byte[] b, final int off, final int count) throws IOException {
248 return getInputStream().read(b, off, count);
249 }
250
251 @SuppressWarnings("resource")
252 @Override
253 public synchronized void reset() throws IOException {
254 getInputStream().reset();
255 }
256
257 @SuppressWarnings("resource")
258 @Override
259 public long skip(final long count) throws IOException {
260 return IOUtils.skip(getInputStream(), count);
261 }
262 }