Improve handling of loader.path in PropertiesLauncher

Previously, if loader.path directly specified a jar file that contained
nested archives (.zip or .jar), launching would fail unless those
nested archives were uncompressed. However, if loader.path specified a
directory that contained such a jar file the launch would succeed. This
was because the nested archives within the jar were ignored.

This commit updates PropertiesLauncher so that its behaviour in the
scenarios described above is consistent by not looking for archives
nested with a jar that’s be specified on loader.path. The javadoc for
loader.path has also been updated to make it clear that loader.path
can points to directories or jar files, bringing it into line with
the reference guide.

Closes gh-3701
This commit is contained in:
Andy Wilkinson 2016-03-31 10:33:03 +01:00
parent 313b6f6451
commit 68b83a8f00
2 changed files with 35 additions and 10 deletions

View File

@ -55,9 +55,10 @@ import org.springframework.boot.loader.util.SystemPropertyUtils;
* extracts optional values (which can also be provided overridden as System properties in
* case the file doesn't exist):
* <ul>
* <li>{@code loader.path}: a comma-separated list of directories to append to the
* classpath (containing file resources and/or nested archives in *.jar or *.zip).
* Defaults to {@code BOOT-INF/classes,BOOT-INF/lib} in your application archive</li>
* <li>{@code loader.path}: a comma-separated list of directories (containing file
* resources and/or nested archives in *.jar or *.zip or archives) or archives to append
* to the classpath. {@code BOOT-INF/classes,BOOT-INF/lib} in the application archive are
* always used</li>
* <li>{@code loader.main}: the main method to delegate execution to once the class loader
* is set up. No default, but will fall back to looking for a {@code Start-Class} in a
* {@code MANIFEST.MF}, if there is one in <code>${loader.home}/META-INF</code>.</li>
@ -78,9 +79,9 @@ public class PropertiesLauncher extends Launcher {
public static final String MAIN = "loader.main";
/**
* Properties key for classpath entries (directories possibly containing jars).
* Defaults to "lib/" (relative to {@link #HOME loader home directory}). Multiple
* entries can be specified using a comma-separated list.
* Properties key for classpath entries (directories possibly containing jars or
* jars). Multiple entries can be specified using a comma-separated list. {@code
* BOOT-INF/classes,BOOT-INF/lib} in the application archive are always used.
*/
public static final String PATH = "loader.path";
@ -407,10 +408,15 @@ public class PropertiesLauncher extends Launcher {
List<Archive> lib = new ArrayList<Archive>();
for (String path : this.paths) {
for (Archive archive : getClassPathArchives(path)) {
List<Archive> nested = new ArrayList<Archive>(
archive.getNestedArchives(new ArchiveEntryFilter()));
nested.add(0, archive);
lib.addAll(nested);
if (archive instanceof ExplodedArchive) {
List<Archive> nested = new ArrayList<Archive>(
archive.getNestedArchives(new ArchiveEntryFilter()));
nested.add(0, archive);
lib.addAll(nested);
}
else {
lib.add(archive);
}
}
}
addNestedEntries(lib);

View File

@ -115,6 +115,25 @@ public class PropertiesLauncherTests {
waitFor("Hello World");
}
@Test
public void testUserSpecifiedJarFileWithNestedArchives() throws Exception {
System.setProperty("loader.path", "nested-jars/app.jar");
System.setProperty("loader.main", "demo.Application");
PropertiesLauncher launcher = new PropertiesLauncher();
launcher.launch(new String[0]);
waitFor("Hello World");
}
@Test
public void testUserSpecifiedDirectoryContainingJarFileWithNestedArchives()
throws Exception {
System.setProperty("loader.path", "nested-jars");
System.setProperty("loader.main", "demo.Application");
PropertiesLauncher launcher = new PropertiesLauncher();
launcher.launch(new String[0]);
waitFor("Hello World");
}
@Test
public void testUserSpecifiedJarPathWithDot() throws Exception {
System.setProperty("loader.path", "./jars/app.jar");