2020import java .io .FileInputStream ;
2121import java .io .FileOutputStream ;
2222import java .io .IOException ;
23+ import java .io .InputStream ;
2324import java .io .OutputStream ;
2425import java .io .PrintStream ;
2526import java .io .UncheckedIOException ;
2627import java .nio .file .Files ;
2728import java .nio .file .attribute .BasicFileAttributeView ;
2829import java .nio .file .attribute .FileTime ;
30+ import java .util .Enumeration ;
2931import java .util .List ;
3032import java .util .Locale ;
3133import java .util .Map ;
3234import java .util .Set ;
3335import java .util .jar .JarEntry ;
36+ import java .util .jar .JarFile ;
3437import java .util .jar .JarOutputStream ;
3538import java .util .jar .Manifest ;
3639import java .util .zip .ZipEntry ;
@@ -157,8 +160,8 @@ private void printError(PrintStream out, String message) {
157160 private void extractLibraries (FileResolver fileResolver , JarStructure jarStructure , Map <Option , String > options )
158161 throws IOException {
159162 String librariesDirectory = getLibrariesDirectory (options );
160- extractArchive (fileResolver , (zipEntry ) -> {
161- Entry entry = jarStructure .resolve (zipEntry );
163+ extractArchive (fileResolver , (jarEntry ) -> {
164+ Entry entry = jarStructure .resolve (jarEntry );
162165 if (isType (entry , Type .LIBRARY )) {
163166 return librariesDirectory + entry .location ();
164167 }
@@ -212,22 +215,22 @@ private JarStructure getJarStructure() {
212215 }
213216
214217 private void extractArchive (FileResolver fileResolver ) throws IOException {
215- extractArchive (fileResolver , ZipEntry ::getName );
218+ extractArchive (fileResolver , JarEntry ::getName );
216219 }
217220
218221 private void extractArchive (FileResolver fileResolver , EntryNameTransformer entryNameTransformer )
219222 throws IOException {
220- withZipEntries (this .context .getArchiveFile (), (stream , zipEntry ) -> {
221- if (zipEntry .isDirectory ()) {
223+ withJarEntries (this .context .getArchiveFile (), (stream , jarEntry ) -> {
224+ if (jarEntry .isDirectory ()) {
222225 return ;
223226 }
224- String name = entryNameTransformer .getName (zipEntry );
227+ String name = entryNameTransformer .getName (jarEntry );
225228 if (name == null ) {
226229 return ;
227230 }
228- File file = fileResolver .resolve (zipEntry , name );
231+ File file = fileResolver .resolve (jarEntry , name );
229232 if (file != null ) {
230- extractEntry (stream , zipEntry , file );
233+ extractEntry (stream , jarEntry , file );
231234 }
232235 });
233236 }
@@ -249,11 +252,11 @@ private void createApplication(JarStructure jarStructure, FileResolver fileResol
249252 Manifest manifest = jarStructure .createLauncherManifest ((library ) -> librariesDirectory + library );
250253 mkDirs (file .getParentFile ());
251254 try (JarOutputStream output = new JarOutputStream (new FileOutputStream (file ), manifest )) {
252- withZipEntries (this .context .getArchiveFile (), ((stream , zipEntry ) -> {
253- Entry entry = jarStructure .resolve (zipEntry );
255+ withJarEntries (this .context .getArchiveFile (), ((stream , jarEntry ) -> {
256+ Entry entry = jarStructure .resolve (jarEntry );
254257 if (isType (entry , Type .APPLICATION_CLASS_OR_RESOURCE ) && StringUtils .hasLength (entry .location ())) {
255- JarEntry jarEntry = createJarEntry (entry .location (), zipEntry );
256- output .putNextEntry (jarEntry );
258+ JarEntry newJarEntry = createJarEntry (entry .location (), jarEntry );
259+ output .putNextEntry (newJarEntry );
257260 StreamUtils .copy (stream , output );
258261 output .closeEntry ();
259262 }
@@ -275,51 +278,74 @@ private static boolean isType(Entry entry, Type type) {
275278 return entry .type () == type ;
276279 }
277280
278- private static void extractEntry (ZipInputStream zip , ZipEntry entry , File file ) throws IOException {
281+ private static void extractEntry (InputStream stream , JarEntry entry , File file ) throws IOException {
279282 mkDirs (file .getParentFile ());
280283 try (OutputStream out = new FileOutputStream (file )) {
281- StreamUtils .copy (zip , out );
284+ StreamUtils .copy (stream , out );
282285 }
283286 try {
284287 Files .getFileAttributeView (file .toPath (), BasicFileAttributeView .class )
285- .setTimes (entry . getLastModifiedTime (), entry . getLastAccessTime (), entry . getCreationTime ());
288+ .setTimes (getLastModifiedTime (entry ), getLastAccessTime (entry ), getCreationTime (entry ));
286289 }
287290 catch (IOException ex ) {
288291 // File system does not support setting time attributes. Continue.
289292 }
290293 }
291294
295+ private static FileTime getCreationTime (JarEntry entry ) {
296+ if (entry .getCreationTime () != null ) {
297+ return entry .getCreationTime ();
298+ }
299+ return entry .getLastModifiedTime ();
300+ }
301+
302+ private static FileTime getLastAccessTime (JarEntry entry ) {
303+ if (entry .getLastAccessTime () != null ) {
304+ return entry .getLastAccessTime ();
305+ }
306+ return getLastModifiedTime (entry );
307+ }
308+
309+ private static FileTime getLastModifiedTime (JarEntry entry ) {
310+ if (entry .getLastModifiedTime () != null ) {
311+ return entry .getLastModifiedTime ();
312+ }
313+ return entry .getCreationTime ();
314+ }
315+
292316 private static void mkDirs (File file ) throws IOException {
293317 if (!file .exists () && !file .mkdirs ()) {
294318 throw new IOException ("Unable to create directory " + file );
295319 }
296320 }
297321
298- private static JarEntry createJarEntry (String location , ZipEntry originalEntry ) {
322+ private static JarEntry createJarEntry (String location , JarEntry originalEntry ) {
299323 JarEntry jarEntry = new JarEntry (location );
300- FileTime lastModifiedTime = originalEntry . getLastModifiedTime ();
324+ FileTime lastModifiedTime = getLastModifiedTime (originalEntry );
301325 if (lastModifiedTime != null ) {
302326 jarEntry .setLastModifiedTime (lastModifiedTime );
303327 }
304- FileTime lastAccessTime = originalEntry . getLastAccessTime ();
328+ FileTime lastAccessTime = getLastAccessTime (originalEntry );
305329 if (lastAccessTime != null ) {
306330 jarEntry .setLastAccessTime (lastAccessTime );
307331 }
308- FileTime creationTime = originalEntry . getCreationTime ();
332+ FileTime creationTime = getCreationTime (originalEntry );
309333 if (creationTime != null ) {
310334 jarEntry .setCreationTime (creationTime );
311335 }
312336 return jarEntry ;
313337 }
314338
315- private static void withZipEntries (File file , ThrowingConsumer callback ) throws IOException {
316- try (ZipInputStream stream = new ZipInputStream (new FileInputStream (file ))) {
317- ZipEntry entry = stream .getNextEntry ();
318- while (entry != null ) {
339+ private static void withJarEntries (File file , ThrowingConsumer callback ) throws IOException {
340+ try (JarFile jarFile = new JarFile (file )) {
341+ Enumeration <JarEntry > entries = jarFile .entries ();
342+ while (entries .hasMoreElements ()) {
343+ JarEntry entry = entries .nextElement ();
319344 if (StringUtils .hasLength (entry .getName ())) {
320- callback .accept (stream , entry );
345+ try (InputStream stream = jarFile .getInputStream (entry )) {
346+ callback .accept (stream , entry );
347+ }
321348 }
322- entry = stream .getNextEntry ();
323349 }
324350 }
325351 }
@@ -336,14 +362,14 @@ private static File assertFileIsContainedInDirectory(File directory, File file,
336362 @ FunctionalInterface
337363 private interface EntryNameTransformer {
338364
339- String getName (ZipEntry entry );
365+ String getName (JarEntry entry );
340366
341367 }
342368
343369 @ FunctionalInterface
344370 private interface ThrowingConsumer {
345371
346- void accept (ZipInputStream stream , ZipEntry entry ) throws IOException ;
372+ void accept (InputStream stream , JarEntry entry ) throws IOException ;
347373
348374 }
349375
@@ -356,14 +382,14 @@ private interface FileResolver {
356382 void createDirectories () throws IOException ;
357383
358384 /**
359- * Resolves the given {@link ZipEntry } to a file.
360- * @param entry the zip entry
385+ * Resolves the given {@link JarEntry } to a file.
386+ * @param entry the jar entry
361387 * @param newName the new name of the file
362388 * @return file where the contents should be written or {@code null} if this entry
363389 * should be skipped
364390 * @throws IOException if something went wrong
365391 */
366- default File resolve (ZipEntry entry , String newName ) throws IOException {
392+ default File resolve (JarEntry entry , String newName ) throws IOException {
367393 return resolve (entry .getName (), newName );
368394 }
369395
0 commit comments