diff --git a/spring-boot-tools/spring-boot-loader-tools/src/main/java/org/springframework/boot/loader/tools/JarWriter.java b/spring-boot-tools/spring-boot-loader-tools/src/main/java/org/springframework/boot/loader/tools/JarWriter.java index f2c365ac6e..aa51cfbb00 100644 --- a/spring-boot-tools/spring-boot-loader-tools/src/main/java/org/springframework/boot/loader/tools/JarWriter.java +++ b/spring-boot-tools/spring-boot-loader-tools/src/main/java/org/springframework/boot/loader/tools/JarWriter.java @@ -1,5 +1,5 @@ /* - * Copyright 2012-2013 the original author or authors. + * Copyright 2012-2015 the original author or authors. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -162,6 +162,7 @@ public class JarWriter { throws IOException { File file = library.getFile(); JarEntry entry = new JarEntry(destination + library.getName()); + entry.setTime(getNestedLibraryTime(file)); if (library.isUnpackRequired()) { entry.setComment("UNPACK:" + FileUtils.sha1Hash(file)); } @@ -169,6 +170,28 @@ public class JarWriter { writeEntry(entry, new InputStreamEntryWriter(new FileInputStream(file), true)); } + private long getNestedLibraryTime(File file) { + try { + JarFile jarFile = new JarFile(file); + try { + Enumeration entries = jarFile.entries(); + while (entries.hasMoreElements()) { + JarEntry entry = entries.nextElement(); + if (!entry.isDirectory()) { + return entry.getTime(); + } + } + } + finally { + jarFile.close(); + } + } + catch (Exception ex) { + // Ignore and just use the source file timestamp + } + return file.lastModified(); + } + /** * Write the required spring-boot-loader classes to the JAR. * @throws IOException diff --git a/spring-boot-tools/spring-boot-loader-tools/src/test/java/org/springframework/boot/loader/tools/RepackagerTests.java b/spring-boot-tools/spring-boot-loader-tools/src/test/java/org/springframework/boot/loader/tools/RepackagerTests.java index d7394d8c6e..019d74b8be 100644 --- a/spring-boot-tools/spring-boot-loader-tools/src/test/java/org/springframework/boot/loader/tools/RepackagerTests.java +++ b/spring-boot-tools/spring-boot-loader-tools/src/test/java/org/springframework/boot/loader/tools/RepackagerTests.java @@ -20,6 +20,7 @@ import java.io.File; import java.io.IOException; import java.nio.file.Files; import java.nio.file.attribute.PosixFilePermission; +import java.util.Calendar; import java.util.jar.Attributes; import java.util.jar.JarEntry; import java.util.jar.JarFile; @@ -58,6 +59,17 @@ public class RepackagerTests { } }; + private static final long JAN_1_1980; + private static final long JAN_1_1985; + static { + Calendar calendar = Calendar.getInstance(); + calendar.set(1980, 0, 1, 0, 0, 0); + calendar.set(Calendar.MILLISECOND, 0); + JAN_1_1980 = calendar.getTime().getTime(); + calendar.set(Calendar.YEAR, 1985); + JAN_1_1985 = calendar.getTime().getTime(); + } + @Rule public TemporaryFolder temporaryFolder = new TemporaryFolder(); @@ -275,7 +287,7 @@ public class RepackagerTests { @Test public void libraries() throws Exception { TestJarFile libJar = new TestJarFile(this.temporaryFolder); - libJar.addClass("a/b/C.class", ClassWithoutMainMethod.class); + libJar.addClass("a/b/C.class", ClassWithoutMainMethod.class, JAN_1_1985); final File libJarFile = libJar.getFile(); final File libJarFileToUnpack = libJar.getFile(); final File libNonJarFile = this.temporaryFolder.newFile(); @@ -284,6 +296,7 @@ public class RepackagerTests { this.testJarFile.addFile("lib/" + libJarFileToUnpack.getName(), libJarFileToUnpack); File file = this.testJarFile.getFile(); + libJarFile.setLastModified(JAN_1_1980); Repackager repackager = new Repackager(file); repackager.repackage(new Libraries() { @Override @@ -297,7 +310,9 @@ public class RepackagerTests { assertThat(hasEntry(file, "lib/" + libJarFile.getName()), equalTo(true)); assertThat(hasEntry(file, "lib/" + libJarFileToUnpack.getName()), equalTo(true)); assertThat(hasEntry(file, "lib/" + libNonJarFile.getName()), equalTo(false)); - JarEntry entry = getEntry(file, "lib/" + libJarFileToUnpack.getName()); + JarEntry entry = getEntry(file, "lib/" + libJarFile.getName()); + assertThat(entry.getTime(), equalTo(JAN_1_1985)); + entry = getEntry(file, "lib/" + libJarFileToUnpack.getName()); assertThat(entry.getComment(), startsWith("UNPACK:")); assertThat(entry.getComment().length(), equalTo(47)); } diff --git a/spring-boot-tools/spring-boot-loader-tools/src/test/java/org/springframework/boot/loader/tools/TestJarFile.java b/spring-boot-tools/spring-boot-loader-tools/src/test/java/org/springframework/boot/loader/tools/TestJarFile.java index a20671d726..00cdf10329 100644 --- a/spring-boot-tools/spring-boot-loader-tools/src/test/java/org/springframework/boot/loader/tools/TestJarFile.java +++ b/spring-boot-tools/spring-boot-loader-tools/src/test/java/org/springframework/boot/loader/tools/TestJarFile.java @@ -1,5 +1,5 @@ /* - * Copyright 2012-2013 the original author or authors. + * Copyright 2012-2015 the original author or authors. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -46,11 +46,19 @@ public class TestJarFile { } public void addClass(String filename, Class classToCopy) throws IOException { + addClass(filename, classToCopy, null); + } + + public void addClass(String filename, Class classToCopy, Long time) + throws IOException { File file = getFilePath(filename); file.getParentFile().mkdirs(); InputStream inputStream = getClass().getResourceAsStream( "/" + classToCopy.getName().replace(".", "/") + ".class"); copyToFile(inputStream, file); + if (time != null) { + file.setLastModified(time); + } } public void addFile(String filename, File fileToCopy) throws IOException {