1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17 package org.apache.commons.compress.harmony.pack200;
18
19 import java.io.BufferedInputStream;
20 import java.io.ByteArrayOutputStream;
21 import java.io.IOException;
22 import java.io.InputStream;
23 import java.io.OutputStream;
24 import java.util.ArrayList;
25 import java.util.Enumeration;
26 import java.util.Iterator;
27 import java.util.List;
28 import java.util.jar.JarEntry;
29 import java.util.jar.JarFile;
30 import java.util.jar.JarInputStream;
31 import java.util.jar.JarOutputStream;
32 import java.util.jar.Manifest;
33 import java.util.logging.FileHandler;
34 import java.util.logging.Level;
35 import java.util.logging.LogManager;
36 import java.util.logging.LogRecord;
37 import java.util.logging.Logger;
38 import java.util.logging.SimpleFormatter;
39
40 import org.apache.commons.compress.harmony.pack200.Archive.PackingFile;
41
42 public class PackingUtils {
43
44 private static final class PackingLogger extends Logger {
45
46 private boolean verbose;
47
48 protected PackingLogger(final String name, final String resourceBundleName) {
49 super(name, resourceBundleName);
50 }
51
52 @Override
53 public void log(final LogRecord logRecord) {
54 if (verbose) {
55 super.log(logRecord);
56 }
57 }
58
59 private void setVerbose(final boolean isVerbose) {
60 verbose = isVerbose;
61 }
62 }
63
64 private static PackingLogger packingLogger;
65 private static FileHandler fileHandler;
66
67 static {
68 packingLogger = new PackingLogger("org.harmony.apache.pack200", null);
69 LogManager.getLogManager().addLogger(packingLogger);
70 }
71
72 public static void config(final PackingOptions options) throws IOException {
73 final String logFileName = options != null ? options.getLogFile() : null;
74 if (fileHandler != null) {
75 fileHandler.close();
76 }
77 if (logFileName != null) {
78 fileHandler = new FileHandler(logFileName, false);
79 fileHandler.setFormatter(new SimpleFormatter());
80 packingLogger.addHandler(fileHandler);
81 packingLogger.setUseParentHandlers(false);
82 }
83 if (options != null) {
84 packingLogger.setVerbose(options.isVerbose());
85 }
86 }
87
88
89
90
91
92
93
94
95 public static void copyThroughJar(final JarFile jarFile, final OutputStream outputStream) throws IOException {
96 try (JarOutputStream jarOutputStream = new JarOutputStream(outputStream)) {
97 jarOutputStream.setComment("PACK200");
98 final byte[] bytes = new byte[16384];
99 final Enumeration<JarEntry> entries = jarFile.entries();
100 while (entries.hasMoreElements()) {
101 final JarEntry jarEntry = entries.nextElement();
102 jarOutputStream.putNextEntry(jarEntry);
103 try (InputStream inputStream = jarFile.getInputStream(jarEntry)) {
104 int bytesRead;
105 while ((bytesRead = inputStream.read(bytes)) != -1) {
106 jarOutputStream.write(bytes, 0, bytesRead);
107 }
108 jarOutputStream.closeEntry();
109 log("Packed " + jarEntry.getName());
110 }
111 }
112 jarFile.close();
113 }
114 }
115
116
117
118
119
120
121
122
123 public static void copyThroughJar(final JarInputStream jarInputStream, final OutputStream outputStream) throws IOException {
124 final Manifest manifest = jarInputStream.getManifest();
125 try (JarOutputStream jarOutputStream = new JarOutputStream(outputStream, manifest)) {
126 jarOutputStream.setComment("PACK200");
127 log("Packed " + JarFile.MANIFEST_NAME);
128
129 final byte[] bytes = new byte[16384];
130 JarEntry jarEntry;
131 int bytesRead;
132 while ((jarEntry = jarInputStream.getNextJarEntry()) != null) {
133 jarOutputStream.putNextEntry(jarEntry);
134 while ((bytesRead = jarInputStream.read(bytes)) != -1) {
135 jarOutputStream.write(bytes, 0, bytesRead);
136 }
137 log("Packed " + jarEntry.getName());
138 }
139 jarInputStream.close();
140 }
141 }
142
143 public static List<PackingFile> getPackingFileListFromJar(final JarFile jarFile, final boolean keepFileOrder) throws IOException {
144 final List<PackingFile> packingFileList = new ArrayList<>();
145 final Enumeration<JarEntry> jarEntries = jarFile.entries();
146 while (jarEntries.hasMoreElements()) {
147 final JarEntry jarEntry = jarEntries.nextElement();
148 try (InputStream inputStream = jarFile.getInputStream(jarEntry)) {
149 final byte[] bytes = readJarEntry(jarEntry, new BufferedInputStream(inputStream));
150 packingFileList.add(new PackingFile(bytes, jarEntry));
151 }
152 }
153
154
155 if (!keepFileOrder) {
156 reorderPackingFiles(packingFileList);
157 }
158 return packingFileList;
159 }
160
161 public static List<PackingFile> getPackingFileListFromJar(final JarInputStream jarInputStream, final boolean keepFileOrder) throws IOException {
162 final List<PackingFile> packingFileList = new ArrayList<>();
163
164
165 final Manifest manifest = jarInputStream.getManifest();
166 if (manifest != null) {
167 final ByteArrayOutputStream baos = new ByteArrayOutputStream();
168 manifest.write(baos);
169 packingFileList.add(new PackingFile(JarFile.MANIFEST_NAME, baos.toByteArray(), 0));
170 }
171
172
173 JarEntry jarEntry;
174 byte[] bytes;
175 while ((jarEntry = jarInputStream.getNextJarEntry()) != null) {
176 bytes = readJarEntry(jarEntry, new BufferedInputStream(jarInputStream));
177 packingFileList.add(new PackingFile(bytes, jarEntry));
178 }
179
180
181 if (!keepFileOrder) {
182 reorderPackingFiles(packingFileList);
183 }
184 return packingFileList;
185 }
186
187 public static void log(final String message) {
188 packingLogger.log(Level.INFO, message);
189 }
190
191 private static byte[] readJarEntry(final JarEntry jarEntry, final InputStream inputStream) throws IOException {
192 long size = jarEntry.getSize();
193 if (size > Integer.MAX_VALUE) {
194
195 throw new IllegalArgumentException("Large Class!");
196 }
197 if (size < 0) {
198 size = 0;
199 }
200 final byte[] bytes = new byte[(int) size];
201 if (inputStream.read(bytes) != size) {
202 throw new IllegalArgumentException("Error reading from stream");
203 }
204 return bytes;
205 }
206
207 private static void reorderPackingFiles(final List<PackingFile> packingFileList) {
208 final Iterator<PackingFile> iterator = packingFileList.iterator();
209 while (iterator.hasNext()) {
210 final PackingFile packingFile = iterator.next();
211 if (packingFile.isDirectory()) {
212
213 iterator.remove();
214 }
215 }
216
217
218
219 packingFileList.sort((arg0, arg1) -> {
220 final String fileName0 = arg0.getName();
221 final String fileName1 = arg1.getName();
222 if (fileName0.equals(fileName1)) {
223 return 0;
224 }
225 if (JarFile.MANIFEST_NAME.equals(fileName0)) {
226 return -1;
227 }
228 if (JarFile.MANIFEST_NAME.equals(fileName1)) {
229 return 1;
230 }
231 return fileName0.compareTo(fileName1);
232 });
233 }
234
235 }