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