author | ksrini |
Tue, 29 May 2012 14:56:48 -0700 | |
changeset 12857 | 0a5f341c2a28 |
parent 10115 | eb08d08c7ef7 |
child 16076 | d7183f4305e5 |
permissions | -rw-r--r-- |
2 | 1 |
/* |
9035
1255eb81cc2f
7033660: Update copyright year to 2011 on any files changed in 2011
ohair
parents:
8803
diff
changeset
|
2 |
* Copyright (c) 2003, 2011, Oracle and/or its affiliates. All rights reserved. |
2 | 3 |
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. |
4 |
* |
|
5 |
* This code is free software; you can redistribute it and/or modify it |
|
6 |
* under the terms of the GNU General Public License version 2 only, as |
|
5506 | 7 |
* published by the Free Software Foundation. Oracle designates this |
2 | 8 |
* particular file as subject to the "Classpath" exception as provided |
5506 | 9 |
* by Oracle in the LICENSE file that accompanied this code. |
2 | 10 |
* |
11 |
* This code is distributed in the hope that it will be useful, but WITHOUT |
|
12 |
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or |
|
13 |
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License |
|
14 |
* version 2 for more details (a copy is included in the LICENSE file that |
|
15 |
* accompanied this code). |
|
16 |
* |
|
17 |
* You should have received a copy of the GNU General Public License version |
|
18 |
* 2 along with this work; if not, write to the Free Software Foundation, |
|
19 |
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. |
|
20 |
* |
|
5506 | 21 |
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA |
22 |
* or visit www.oracle.com if you need additional information or have any |
|
23 |
* questions. |
|
2 | 24 |
*/ |
25 |
||
26 |
package com.sun.java.util.jar.pack; |
|
27 |
||
28 |
import java.beans.PropertyChangeListener; |
|
7192
445c518364c4
7003227: (pack200) intermittent failures compiling pack200
ksrini
parents:
7171
diff
changeset
|
29 |
import java.io.BufferedInputStream; |
445c518364c4
7003227: (pack200) intermittent failures compiling pack200
ksrini
parents:
7171
diff
changeset
|
30 |
import java.io.ByteArrayOutputStream; |
445c518364c4
7003227: (pack200) intermittent failures compiling pack200
ksrini
parents:
7171
diff
changeset
|
31 |
import java.io.File; |
445c518364c4
7003227: (pack200) intermittent failures compiling pack200
ksrini
parents:
7171
diff
changeset
|
32 |
import java.io.FileInputStream; |
445c518364c4
7003227: (pack200) intermittent failures compiling pack200
ksrini
parents:
7171
diff
changeset
|
33 |
import java.io.IOException; |
445c518364c4
7003227: (pack200) intermittent failures compiling pack200
ksrini
parents:
7171
diff
changeset
|
34 |
import java.io.InputStream; |
445c518364c4
7003227: (pack200) intermittent failures compiling pack200
ksrini
parents:
7171
diff
changeset
|
35 |
import java.io.OutputStream; |
445c518364c4
7003227: (pack200) intermittent failures compiling pack200
ksrini
parents:
7171
diff
changeset
|
36 |
import java.util.HashSet; |
7795
98021fc612af
6990106: FindBugs scan - Malicious code vulnerability Warnings in com.sun.java.util.jar.pack.*
ksrini
parents:
7192
diff
changeset
|
37 |
import java.util.Set; |
7192
445c518364c4
7003227: (pack200) intermittent failures compiling pack200
ksrini
parents:
7171
diff
changeset
|
38 |
import java.util.SortedMap; |
445c518364c4
7003227: (pack200) intermittent failures compiling pack200
ksrini
parents:
7171
diff
changeset
|
39 |
import java.util.TimeZone; |
445c518364c4
7003227: (pack200) intermittent failures compiling pack200
ksrini
parents:
7171
diff
changeset
|
40 |
import java.util.jar.JarEntry; |
445c518364c4
7003227: (pack200) intermittent failures compiling pack200
ksrini
parents:
7171
diff
changeset
|
41 |
import java.util.jar.JarInputStream; |
445c518364c4
7003227: (pack200) intermittent failures compiling pack200
ksrini
parents:
7171
diff
changeset
|
42 |
import java.util.jar.JarOutputStream; |
445c518364c4
7003227: (pack200) intermittent failures compiling pack200
ksrini
parents:
7171
diff
changeset
|
43 |
import java.util.jar.Pack200; |
445c518364c4
7003227: (pack200) intermittent failures compiling pack200
ksrini
parents:
7171
diff
changeset
|
44 |
import java.util.zip.CRC32; |
445c518364c4
7003227: (pack200) intermittent failures compiling pack200
ksrini
parents:
7171
diff
changeset
|
45 |
import java.util.zip.CheckedOutputStream; |
445c518364c4
7003227: (pack200) intermittent failures compiling pack200
ksrini
parents:
7171
diff
changeset
|
46 |
import java.util.zip.ZipEntry; |
2 | 47 |
|
48 |
/* |
|
49 |
* Implementation of the Pack provider. |
|
50 |
* </pre></blockquote> |
|
51 |
* @author John Rose |
|
52 |
* @author Kumar Srinivasan |
|
53 |
*/ |
|
54 |
||
55 |
||
6313 | 56 |
public class UnpackerImpl extends TLGlobals implements Pack200.Unpacker { |
2 | 57 |
|
58 |
||
59 |
/** |
|
60 |
* Register a listener for changes to options. |
|
61 |
* @param listener An object to be invoked when a property is changed. |
|
62 |
*/ |
|
63 |
public void addPropertyChangeListener(PropertyChangeListener listener) { |
|
6313 | 64 |
props.addListener(listener); |
2 | 65 |
} |
66 |
||
67 |
||
68 |
/** |
|
69 |
* Remove a listener for the PropertyChange event. |
|
70 |
* @param listener The PropertyChange listener to be removed. |
|
71 |
*/ |
|
72 |
public void removePropertyChangeListener(PropertyChangeListener listener) { |
|
6313 | 73 |
props.removeListener(listener); |
2 | 74 |
} |
75 |
||
6313 | 76 |
public UnpackerImpl() {} |
2 | 77 |
|
78 |
||
79 |
||
80 |
/** |
|
81 |
* Get the set of options for the pack and unpack engines. |
|
82 |
* @return A sorted association of option key strings to option values. |
|
83 |
*/ |
|
10115 | 84 |
public SortedMap<String, String> properties() { |
6313 | 85 |
return props; |
2 | 86 |
} |
87 |
||
88 |
// Back-pointer to NativeUnpacker, when active. |
|
89 |
Object _nunp; |
|
90 |
||
91 |
||
92 |
public String toString() { |
|
93 |
return Utils.getVersionString(); |
|
94 |
} |
|
95 |
||
96 |
//Driver routines |
|
97 |
||
98 |
// The unpack worker... |
|
99 |
/** |
|
100 |
* Takes a packed-stream InputStream, and writes to a JarOutputStream. Internally |
|
101 |
* the entire buffer must be read, it may be more efficient to read the packed-stream |
|
102 |
* to a file and pass the File object, in the alternate method described below. |
|
103 |
* <p> |
|
104 |
* Closes its input but not its output. (The output can accumulate more elements.) |
|
105 |
* @param in an InputStream. |
|
106 |
* @param out a JarOutputStream. |
|
107 |
* @exception IOException if an error is encountered. |
|
108 |
*/ |
|
7171
ee97f78e7482
6985763: Pack200.Packer.pack(...) and Pack200.Unpacker.unpack(...) throw unspecified exceptions
ksrini
parents:
6313
diff
changeset
|
109 |
public void unpack(InputStream in, JarOutputStream out) throws IOException { |
ee97f78e7482
6985763: Pack200.Packer.pack(...) and Pack200.Unpacker.unpack(...) throw unspecified exceptions
ksrini
parents:
6313
diff
changeset
|
110 |
if (in == null) { |
ee97f78e7482
6985763: Pack200.Packer.pack(...) and Pack200.Unpacker.unpack(...) throw unspecified exceptions
ksrini
parents:
6313
diff
changeset
|
111 |
throw new NullPointerException("null input"); |
ee97f78e7482
6985763: Pack200.Packer.pack(...) and Pack200.Unpacker.unpack(...) throw unspecified exceptions
ksrini
parents:
6313
diff
changeset
|
112 |
} |
ee97f78e7482
6985763: Pack200.Packer.pack(...) and Pack200.Unpacker.unpack(...) throw unspecified exceptions
ksrini
parents:
6313
diff
changeset
|
113 |
if (out == null) { |
ee97f78e7482
6985763: Pack200.Packer.pack(...) and Pack200.Unpacker.unpack(...) throw unspecified exceptions
ksrini
parents:
6313
diff
changeset
|
114 |
throw new NullPointerException("null output"); |
ee97f78e7482
6985763: Pack200.Packer.pack(...) and Pack200.Unpacker.unpack(...) throw unspecified exceptions
ksrini
parents:
6313
diff
changeset
|
115 |
} |
2 | 116 |
assert(Utils.currentInstance.get() == null); |
6313 | 117 |
TimeZone tz = (props.getBoolean(Utils.PACK_DEFAULT_TIMEZONE)) |
118 |
? null |
|
119 |
: TimeZone.getDefault(); |
|
2 | 120 |
|
121 |
try { |
|
122 |
Utils.currentInstance.set(this); |
|
123 |
if (tz != null) TimeZone.setDefault(TimeZone.getTimeZone("UTC")); |
|
6313 | 124 |
final int verbose = props.getInteger(Utils.DEBUG_VERBOSE); |
7171
ee97f78e7482
6985763: Pack200.Packer.pack(...) and Pack200.Unpacker.unpack(...) throw unspecified exceptions
ksrini
parents:
6313
diff
changeset
|
125 |
BufferedInputStream in0 = new BufferedInputStream(in); |
ee97f78e7482
6985763: Pack200.Packer.pack(...) and Pack200.Unpacker.unpack(...) throw unspecified exceptions
ksrini
parents:
6313
diff
changeset
|
126 |
if (Utils.isJarMagic(Utils.readMagic(in0))) { |
2 | 127 |
if (verbose > 0) |
128 |
Utils.log.info("Copying unpacked JAR file..."); |
|
7171
ee97f78e7482
6985763: Pack200.Packer.pack(...) and Pack200.Unpacker.unpack(...) throw unspecified exceptions
ksrini
parents:
6313
diff
changeset
|
129 |
Utils.copyJarFile(new JarInputStream(in0), out); |
6313 | 130 |
} else if (props.getBoolean(Utils.DEBUG_DISABLE_NATIVE)) { |
7171
ee97f78e7482
6985763: Pack200.Packer.pack(...) and Pack200.Unpacker.unpack(...) throw unspecified exceptions
ksrini
parents:
6313
diff
changeset
|
131 |
(new DoUnpack()).run(in0, out); |
ee97f78e7482
6985763: Pack200.Packer.pack(...) and Pack200.Unpacker.unpack(...) throw unspecified exceptions
ksrini
parents:
6313
diff
changeset
|
132 |
in0.close(); |
2 | 133 |
Utils.markJarFile(out); |
134 |
} else { |
|
7171
ee97f78e7482
6985763: Pack200.Packer.pack(...) and Pack200.Unpacker.unpack(...) throw unspecified exceptions
ksrini
parents:
6313
diff
changeset
|
135 |
(new NativeUnpack(this)).run(in0, out); |
ee97f78e7482
6985763: Pack200.Packer.pack(...) and Pack200.Unpacker.unpack(...) throw unspecified exceptions
ksrini
parents:
6313
diff
changeset
|
136 |
in0.close(); |
2 | 137 |
Utils.markJarFile(out); |
138 |
} |
|
139 |
} finally { |
|
140 |
_nunp = null; |
|
141 |
Utils.currentInstance.set(null); |
|
142 |
if (tz != null) TimeZone.setDefault(tz); |
|
143 |
} |
|
144 |
} |
|
145 |
||
146 |
/** |
|
147 |
* Takes an input File containing the pack file, and generates a JarOutputStream. |
|
148 |
* <p> |
|
149 |
* Does not close its output. (The output can accumulate more elements.) |
|
150 |
* @param in a File. |
|
151 |
* @param out a JarOutputStream. |
|
152 |
* @exception IOException if an error is encountered. |
|
153 |
*/ |
|
154 |
public void unpack(File in, JarOutputStream out) throws IOException { |
|
7171
ee97f78e7482
6985763: Pack200.Packer.pack(...) and Pack200.Unpacker.unpack(...) throw unspecified exceptions
ksrini
parents:
6313
diff
changeset
|
155 |
if (in == null) { |
ee97f78e7482
6985763: Pack200.Packer.pack(...) and Pack200.Unpacker.unpack(...) throw unspecified exceptions
ksrini
parents:
6313
diff
changeset
|
156 |
throw new NullPointerException("null input"); |
ee97f78e7482
6985763: Pack200.Packer.pack(...) and Pack200.Unpacker.unpack(...) throw unspecified exceptions
ksrini
parents:
6313
diff
changeset
|
157 |
} |
ee97f78e7482
6985763: Pack200.Packer.pack(...) and Pack200.Unpacker.unpack(...) throw unspecified exceptions
ksrini
parents:
6313
diff
changeset
|
158 |
if (out == null) { |
ee97f78e7482
6985763: Pack200.Packer.pack(...) and Pack200.Unpacker.unpack(...) throw unspecified exceptions
ksrini
parents:
6313
diff
changeset
|
159 |
throw new NullPointerException("null output"); |
ee97f78e7482
6985763: Pack200.Packer.pack(...) and Pack200.Unpacker.unpack(...) throw unspecified exceptions
ksrini
parents:
6313
diff
changeset
|
160 |
} |
2 | 161 |
// Use the stream-based implementation. |
162 |
// %%% Reconsider if native unpacker learns to memory-map the file. |
|
8803
b3f57bfca459
7022382: convert pack200 library code to use try-with-resources
smarks
parents:
7795
diff
changeset
|
163 |
try (FileInputStream instr = new FileInputStream(in)) { |
b3f57bfca459
7022382: convert pack200 library code to use try-with-resources
smarks
parents:
7795
diff
changeset
|
164 |
unpack(instr, out); |
b3f57bfca459
7022382: convert pack200 library code to use try-with-resources
smarks
parents:
7795
diff
changeset
|
165 |
} |
6313 | 166 |
if (props.getBoolean(Utils.UNPACK_REMOVE_PACKFILE)) { |
2 | 167 |
in.delete(); |
168 |
} |
|
169 |
} |
|
170 |
||
171 |
private class DoUnpack { |
|
6313 | 172 |
final int verbose = props.getInteger(Utils.DEBUG_VERBOSE); |
2 | 173 |
|
174 |
{ |
|
6313 | 175 |
props.setInteger(Pack200.Unpacker.PROGRESS, 0); |
2 | 176 |
} |
177 |
||
178 |
// Here's where the bits are read from disk: |
|
179 |
final Package pkg = new Package(); |
|
180 |
||
181 |
final boolean keepModtime |
|
6313 | 182 |
= Pack200.Packer.KEEP.equals( |
183 |
props.getProperty(Utils.UNPACK_MODIFICATION_TIME, Pack200.Packer.KEEP)); |
|
2 | 184 |
final boolean keepDeflateHint |
6313 | 185 |
= Pack200.Packer.KEEP.equals( |
186 |
props.getProperty(Pack200.Unpacker.DEFLATE_HINT, Pack200.Packer.KEEP)); |
|
2 | 187 |
final int modtime; |
188 |
final boolean deflateHint; |
|
189 |
{ |
|
190 |
if (!keepModtime) { |
|
6313 | 191 |
modtime = props.getTime(Utils.UNPACK_MODIFICATION_TIME); |
2 | 192 |
} else { |
193 |
modtime = pkg.default_modtime; |
|
194 |
} |
|
195 |
||
196 |
deflateHint = (keepDeflateHint) ? false : |
|
6313 | 197 |
props.getBoolean(java.util.jar.Pack200.Unpacker.DEFLATE_HINT); |
2 | 198 |
} |
199 |
||
200 |
// Checksum apparatus. |
|
201 |
final CRC32 crc = new CRC32(); |
|
202 |
final ByteArrayOutputStream bufOut = new ByteArrayOutputStream(); |
|
203 |
final OutputStream crcOut = new CheckedOutputStream(bufOut, crc); |
|
204 |
||
205 |
public void run(BufferedInputStream in, JarOutputStream out) throws IOException { |
|
206 |
if (verbose > 0) { |
|
6313 | 207 |
props.list(System.out); |
2 | 208 |
} |
209 |
for (int seg = 1; ; seg++) { |
|
210 |
unpackSegment(in, out); |
|
211 |
||
212 |
// Try to get another segment. |
|
213 |
if (!Utils.isPackMagic(Utils.readMagic(in))) break; |
|
214 |
if (verbose > 0) |
|
215 |
Utils.log.info("Finished segment #"+seg); |
|
216 |
} |
|
217 |
} |
|
218 |
||
219 |
private void unpackSegment(InputStream in, JarOutputStream out) throws IOException { |
|
6313 | 220 |
props.setProperty(java.util.jar.Pack200.Unpacker.PROGRESS,"0"); |
2 | 221 |
// Process the output directory or jar output. |
222 |
new PackageReader(pkg, in).read(); |
|
223 |
||
6313 | 224 |
if (props.getBoolean("unpack.strip.debug")) pkg.stripAttributeKind("Debug"); |
225 |
if (props.getBoolean("unpack.strip.compile")) pkg.stripAttributeKind("Compile"); |
|
226 |
props.setProperty(java.util.jar.Pack200.Unpacker.PROGRESS,"50"); |
|
2 | 227 |
pkg.ensureAllClassFiles(); |
228 |
// Now write out the files. |
|
7795
98021fc612af
6990106: FindBugs scan - Malicious code vulnerability Warnings in com.sun.java.util.jar.pack.*
ksrini
parents:
7192
diff
changeset
|
229 |
Set<Package.Class> classesToWrite = new HashSet<>(pkg.getClasses()); |
98021fc612af
6990106: FindBugs scan - Malicious code vulnerability Warnings in com.sun.java.util.jar.pack.*
ksrini
parents:
7192
diff
changeset
|
230 |
for (Package.File file : pkg.getFiles()) { |
2 | 231 |
String name = file.nameString; |
232 |
JarEntry je = new JarEntry(Utils.getJarEntryName(name)); |
|
233 |
boolean deflate; |
|
234 |
||
6313 | 235 |
deflate = (keepDeflateHint) |
236 |
? (((file.options & Constants.FO_DEFLATE_HINT) != 0) || |
|
237 |
((pkg.default_options & Constants.AO_DEFLATE_HINT) != 0)) |
|
238 |
: deflateHint; |
|
2 | 239 |
|
240 |
boolean needCRC = !deflate; // STORE mode requires CRC |
|
241 |
||
242 |
if (needCRC) crc.reset(); |
|
243 |
bufOut.reset(); |
|
244 |
if (file.isClassStub()) { |
|
245 |
Package.Class cls = file.getStubClass(); |
|
246 |
assert(cls != null); |
|
247 |
new ClassWriter(cls, needCRC ? crcOut : bufOut).write(); |
|
248 |
classesToWrite.remove(cls); // for an error check |
|
249 |
} else { |
|
250 |
// collect data & maybe CRC |
|
251 |
file.writeTo(needCRC ? crcOut : bufOut); |
|
252 |
} |
|
253 |
je.setMethod(deflate ? JarEntry.DEFLATED : JarEntry.STORED); |
|
254 |
if (needCRC) { |
|
255 |
if (verbose > 0) |
|
256 |
Utils.log.info("stored size="+bufOut.size()+" and crc="+crc.getValue()); |
|
257 |
||
258 |
je.setMethod(JarEntry.STORED); |
|
259 |
je.setSize(bufOut.size()); |
|
260 |
je.setCrc(crc.getValue()); |
|
261 |
} |
|
262 |
if (keepModtime) { |
|
263 |
je.setTime(file.modtime); |
|
264 |
// Convert back to milliseconds |
|
265 |
je.setTime((long)file.modtime * 1000); |
|
266 |
} else { |
|
267 |
je.setTime((long)modtime * 1000); |
|
268 |
} |
|
269 |
out.putNextEntry(je); |
|
270 |
bufOut.writeTo(out); |
|
271 |
out.closeEntry(); |
|
272 |
if (verbose > 0) |
|
273 |
Utils.log.info("Writing "+Utils.zeString((ZipEntry)je)); |
|
274 |
} |
|
275 |
assert(classesToWrite.isEmpty()); |
|
6313 | 276 |
props.setProperty(java.util.jar.Pack200.Unpacker.PROGRESS,"100"); |
2 | 277 |
pkg.reset(); // reset for the next segment, if any |
278 |
} |
|
279 |
} |
|
280 |
} |