From 8a249daf1af737ba71386c7af793fcb564e793e5 Mon Sep 17 00:00:00 2001 From: Phillip Webb Date: Thu, 11 Jun 2020 12:24:04 -0700 Subject: [PATCH] Refactor PropertiesLauncher so jars can be closed Refactor the internals of `PropertiesLauncher` so that opened jar files are tracked and can be closed after a test completes. See gh-21575 --- .../boot/loader/PropertiesLauncher.java | 342 ++++++++++-------- .../boot/loader/PropertiesLauncherTests.java | 128 +++---- 2 files changed, 267 insertions(+), 203 deletions(-) diff --git a/spring-boot-project/spring-boot-tools/spring-boot-loader/src/main/java/org/springframework/boot/loader/PropertiesLauncher.java b/spring-boot-project/spring-boot-tools/spring-boot-loader/src/main/java/org/springframework/boot/loader/PropertiesLauncher.java index 5481457d2d5e..a726dc4f1775 100755 --- a/spring-boot-project/spring-boot-tools/spring-boot-loader/src/main/java/org/springframework/boot/loader/PropertiesLauncher.java +++ b/spring-boot-project/spring-boot-tools/spring-boot-loader/src/main/java/org/springframework/boot/loader/PropertiesLauncher.java @@ -29,9 +29,11 @@ import java.util.ArrayList; import java.util.Collections; import java.util.Iterator; +import java.util.LinkedHashMap; import java.util.LinkedHashSet; import java.util.List; import java.util.Locale; +import java.util.Map; import java.util.Properties; import java.util.Set; import java.util.jar.Manifest; @@ -144,7 +146,9 @@ public class PropertiesLauncher extends Launcher { private final Properties properties = new Properties(); - private Archive parent; + private final Archive parent; + + private volatile ClassPathArchives classPathArchives; public PropertiesLauncher() { try { @@ -346,18 +350,19 @@ protected String getMainClass() throws Exception { } @Override - protected ClassLoader createClassLoader(List archives) throws Exception { - Set urls = new LinkedHashSet<>(archives.size()); - for (Archive archive : archives) { - urls.add(archive.getUrl()); - } - ClassLoader loader = new LaunchedURLClassLoader(urls.toArray(NO_URLS), getClass().getClassLoader()); - debug("Classpath: " + urls); + protected ClassLoader createClassLoader(Iterator archives) throws Exception { String customLoaderClassName = getProperty("loader.classLoader"); - if (customLoaderClassName != null) { - loader = wrapWithCustomClassLoader(loader, customLoaderClassName); - debug("Using custom class loader: " + customLoaderClassName); + if (customLoaderClassName == null) { + return super.createClassLoader(archives); } + Set urls = new LinkedHashSet<>(); + while (archives.hasNext()) { + urls.add(archives.next().getUrl()); + } + ClassLoader loader = new LaunchedURLClassLoader(urls.toArray(NO_URLS), getClass().getClassLoader()); + debug("Classpath for custom loader: " + urls); + loader = wrapWithCustomClassLoader(loader, customLoaderClassName); + debug("Using custom class loader: " + customLoaderClassName); return loader; } @@ -449,122 +454,42 @@ private String getProperty(String propertyKey, String manifestKey, String defaul @Override protected Iterator getClassPathArchivesIterator() throws Exception { - List lib = new ArrayList<>(); - for (String path : this.paths) { - for (Archive archive : getClassPathArchives(path)) { - if (archive instanceof ExplodedArchive) { - List nested = asList(archive.getNestedArchives(null, new ArchiveEntryFilter())); - nested.add(0, archive); - lib.addAll(nested); - } - else { - lib.add(archive); - } - } + ClassPathArchives classPathArchives = this.classPathArchives; + if (classPathArchives == null) { + classPathArchives = new ClassPathArchives(); + this.classPathArchives = classPathArchives; } - addNestedEntries(lib); - return lib.iterator(); + return classPathArchives.iterator(); } - private List getClassPathArchives(String path) throws Exception { - String root = cleanupPath(handleUrl(path)); - List lib = new ArrayList<>(); - File file = new File(root); - if (!"/".equals(root)) { - if (!isAbsolutePath(root)) { - file = new File(this.home, root); - } - if (file.isDirectory()) { - debug("Adding classpath entries from " + file); - Archive archive = new ExplodedArchive(file, false); - lib.add(archive); - } - } - Archive archive = getArchive(file); - if (archive != null) { - debug("Adding classpath entries from archive " + archive.getUrl() + root); - lib.add(archive); - } - List nestedArchives = getNestedArchives(root); - if (nestedArchives != null) { - debug("Adding classpath entries from nested " + root); - lib.addAll(nestedArchives); - } - return lib; - } - - private boolean isAbsolutePath(String root) { - // Windows contains ":" others start with "/" - return root.contains(":") || root.startsWith("/"); + public static void main(String[] args) throws Exception { + PropertiesLauncher launcher = new PropertiesLauncher(); + args = launcher.getArgs(args); + launcher.launch(args); } - private Archive getArchive(File file) throws IOException { - if (isNestedArchivePath(file)) { + public static String toCamelCase(CharSequence string) { + if (string == null) { return null; } - String name = file.getName().toLowerCase(Locale.ENGLISH); - if (name.endsWith(".jar") || name.endsWith(".zip")) { - return new JarFileArchive(file); + StringBuilder builder = new StringBuilder(); + Matcher matcher = WORD_SEPARATOR.matcher(string); + int pos = 0; + while (matcher.find()) { + builder.append(capitalize(string.subSequence(pos, matcher.end()).toString())); + pos = matcher.end(); } - return null; - } - - private boolean isNestedArchivePath(File file) { - return file.getPath().contains(NESTED_ARCHIVE_SEPARATOR); + builder.append(capitalize(string.subSequence(pos, string.length()).toString())); + return builder.toString(); } - private List getNestedArchives(String path) throws Exception { - Archive parent = this.parent; - String root = path; - if (!root.equals("/") && root.startsWith("/") || parent.getUrl().toURI().equals(this.home.toURI())) { - // If home dir is same as parent archive, no need to add it twice. - return null; - } - int index = root.indexOf('!'); - if (index != -1) { - File file = new File(this.home, root.substring(0, index)); - if (root.startsWith("jar:file:")) { - file = new File(root.substring("jar:file:".length(), index)); - } - parent = new JarFileArchive(file); - root = root.substring(index + 1); - while (root.startsWith("/")) { - root = root.substring(1); - } - } - if (root.endsWith(".jar")) { - File file = new File(this.home, root); - if (file.exists()) { - parent = new JarFileArchive(file); - root = ""; - } - } - if (root.equals("/") || root.equals("./") || root.equals(".")) { - // The prefix for nested jars is actually empty if it's at the root - root = ""; - } - EntryFilter filter = new PrefixMatchingArchiveFilter(root); - List archives = asList(parent.getNestedArchives(null, filter)); - if (("".equals(root) || ".".equals(root)) && !path.endsWith(".jar") && parent != this.parent) { - // You can't find the root with an entry filter so it has to be added - // explicitly. But don't add the root of the parent archive. - archives.add(parent); - } - return archives; + private static String capitalize(String str) { + return Character.toUpperCase(str.charAt(0)) + str.substring(1); } - private void addNestedEntries(List lib) { - // The parent archive might have "BOOT-INF/lib/" and "BOOT-INF/classes/" - // directories, meaning we are running from an executable JAR. We add nested - // entries from there with low priority (i.e. at end). - try { - Iterator archives = this.parent.getNestedArchives(null, JarLauncher.NESTED_ARCHIVE_ENTRY_FILTER); - while (archives.hasNext()) { - lib.add(archives.next()); - } - } - catch (IOException ex) { - // Ignore + private void debug(String message) { + if (Boolean.getBoolean(DEBUG)) { + System.out.println(message); } } @@ -590,43 +515,176 @@ private String cleanupPath(String path) { return path; } - private List asList(Iterator iterator) { - List list = new ArrayList<>(); - while (iterator.hasNext()) { - list.add(iterator.next()); + void close() throws Exception { + if (this.classPathArchives != null) { + this.classPathArchives.close(); + } + if (this.parent != null) { + this.parent.close(); } - return list; } - public static void main(String[] args) throws Exception { - PropertiesLauncher launcher = new PropertiesLauncher(); - args = launcher.getArgs(args); - launcher.launch(args); - } + /** + * An iterable collection of the classpath archives. + */ + private class ClassPathArchives implements Iterable { - public static String toCamelCase(CharSequence string) { - if (string == null) { + private final List classPathArchives; + + private final Map jarFileArchives = new LinkedHashMap<>(); + + ClassPathArchives() throws Exception { + this.classPathArchives = new ArrayList<>(); + for (String path : PropertiesLauncher.this.paths) { + for (Archive archive : getClassPathArchives(path)) { + addClassPathArchive(archive); + } + } + addNestedEntries(); + } + + private void addClassPathArchive(Archive archive) throws IOException { + if (!(archive instanceof ExplodedArchive)) { + this.classPathArchives.add(archive); + return; + } + this.classPathArchives.add(archive); + this.classPathArchives.addAll(asList(archive.getNestedArchives(null, new ArchiveEntryFilter()))); + } + + private List getClassPathArchives(String path) throws Exception { + String root = cleanupPath(handleUrl(path)); + List lib = new ArrayList<>(); + File file = new File(root); + if (!"/".equals(root)) { + if (!isAbsolutePath(root)) { + file = new File(PropertiesLauncher.this.home, root); + } + if (file.isDirectory()) { + debug("Adding classpath entries from " + file); + Archive archive = new ExplodedArchive(file, false); + lib.add(archive); + } + } + Archive archive = getArchive(file); + if (archive != null) { + debug("Adding classpath entries from archive " + archive.getUrl() + root); + lib.add(archive); + } + List nestedArchives = getNestedArchives(root); + if (nestedArchives != null) { + debug("Adding classpath entries from nested " + root); + lib.addAll(nestedArchives); + } + return lib; + } + + private boolean isAbsolutePath(String root) { + // Windows contains ":" others start with "/" + return root.contains(":") || root.startsWith("/"); + } + + private Archive getArchive(File file) throws IOException { + if (isNestedArchivePath(file)) { + return null; + } + String name = file.getName().toLowerCase(Locale.ENGLISH); + if (name.endsWith(".jar") || name.endsWith(".zip")) { + return getJarFileArchive(file); + } return null; } - StringBuilder builder = new StringBuilder(); - Matcher matcher = WORD_SEPARATOR.matcher(string); - int pos = 0; - while (matcher.find()) { - builder.append(capitalize(string.subSequence(pos, matcher.end()).toString())); - pos = matcher.end(); + + private boolean isNestedArchivePath(File file) { + return file.getPath().contains(NESTED_ARCHIVE_SEPARATOR); } - builder.append(capitalize(string.subSequence(pos, string.length()).toString())); - return builder.toString(); - } - private static String capitalize(String str) { - return Character.toUpperCase(str.charAt(0)) + str.substring(1); - } + private List getNestedArchives(String path) throws Exception { + Archive parent = PropertiesLauncher.this.parent; + String root = path; + if (!root.equals("/") && root.startsWith("/") + || parent.getUrl().toURI().equals(PropertiesLauncher.this.home.toURI())) { + // If home dir is same as parent archive, no need to add it twice. + return null; + } + int index = root.indexOf('!'); + if (index != -1) { + File file = new File(PropertiesLauncher.this.home, root.substring(0, index)); + if (root.startsWith("jar:file:")) { + file = new File(root.substring("jar:file:".length(), index)); + } + parent = getJarFileArchive(file); + root = root.substring(index + 1); + while (root.startsWith("/")) { + root = root.substring(1); + } + } + if (root.endsWith(".jar")) { + File file = new File(PropertiesLauncher.this.home, root); + if (file.exists()) { + parent = getJarFileArchive(file); + root = ""; + } + } + if (root.equals("/") || root.equals("./") || root.equals(".")) { + // The prefix for nested jars is actually empty if it's at the root + root = ""; + } + EntryFilter filter = new PrefixMatchingArchiveFilter(root); + List archives = asList(parent.getNestedArchives(null, filter)); + if (("".equals(root) || ".".equals(root)) && !path.endsWith(".jar") + && parent != PropertiesLauncher.this.parent) { + // You can't find the root with an entry filter so it has to be added + // explicitly. But don't add the root of the parent archive. + archives.add(parent); + } + return archives; + } - private void debug(String message) { - if (Boolean.getBoolean(DEBUG)) { - System.out.println(message); + private void addNestedEntries() { + // The parent archive might have "BOOT-INF/lib/" and "BOOT-INF/classes/" + // directories, meaning we are running from an executable JAR. We add nested + // entries from there with low priority (i.e. at end). + try { + Iterator archives = PropertiesLauncher.this.parent.getNestedArchives(null, + JarLauncher.NESTED_ARCHIVE_ENTRY_FILTER); + while (archives.hasNext()) { + this.classPathArchives.add(archives.next()); + } + } + catch (IOException ex) { + // Ignore + } + } + + private List asList(Iterator iterator) { + List list = new ArrayList<>(); + while (iterator.hasNext()) { + list.add(iterator.next()); + } + return list; + } + + private JarFileArchive getJarFileArchive(File file) throws IOException { + JarFileArchive archive = this.jarFileArchives.get(file); + if (archive == null) { + archive = new JarFileArchive(file); + this.jarFileArchives.put(file, archive); + } + return archive; + } + + @Override + public Iterator iterator() { + return this.classPathArchives.iterator(); } + + void close() throws IOException { + for (JarFileArchive archive : this.jarFileArchives.values()) { + archive.close(); + } + } + } /** diff --git a/spring-boot-project/spring-boot-tools/spring-boot-loader/src/test/java/org/springframework/boot/loader/PropertiesLauncherTests.java b/spring-boot-project/spring-boot-tools/spring-boot-loader/src/test/java/org/springframework/boot/loader/PropertiesLauncherTests.java index aa0b94977988..936783ae64e9 100644 --- a/spring-boot-project/spring-boot-tools/spring-boot-loader/src/test/java/org/springframework/boot/loader/PropertiesLauncherTests.java +++ b/spring-boot-project/spring-boot-tools/spring-boot-loader/src/test/java/org/springframework/boot/loader/PropertiesLauncherTests.java @@ -65,6 +65,8 @@ class PropertiesLauncherTests { @TempDir File tempDir; + private PropertiesLauncher launcher; + private ClassLoader contextClassLoader; private CapturedOutput output; @@ -88,6 +90,9 @@ void close() throws Exception { System.clearProperty("loader.system"); System.clearProperty("loader.classLoader"); clearHandlerCache(); + if (this.launcher != null) { + this.launcher.close(); + } } @SuppressWarnings("unchecked") @@ -105,16 +110,16 @@ private void clearHandlerCache() throws Exception { @Test void testDefaultHome() { System.clearProperty("loader.home"); - PropertiesLauncher launcher = new PropertiesLauncher(); - assertThat(launcher.getHomeDirectory()).isEqualTo(new File(System.getProperty("user.dir"))); + this.launcher = new PropertiesLauncher(); + assertThat(this.launcher.getHomeDirectory()).isEqualTo(new File(System.getProperty("user.dir"))); } @Test void testAlternateHome() throws Exception { System.setProperty("loader.home", "src/test/resources/home"); - PropertiesLauncher launcher = new PropertiesLauncher(); - assertThat(launcher.getHomeDirectory()).isEqualTo(new File(System.getProperty("loader.home"))); - assertThat(launcher.getMainClass()).isEqualTo("demo.HomeApplication"); + this.launcher = new PropertiesLauncher(); + assertThat(this.launcher.getHomeDirectory()).isEqualTo(new File(System.getProperty("loader.home"))); + assertThat(this.launcher.getMainClass()).isEqualTo("demo.HomeApplication"); } @Test @@ -126,40 +131,40 @@ void testNonExistentHome() { @Test void testUserSpecifiedMain() throws Exception { - PropertiesLauncher launcher = new PropertiesLauncher(); - assertThat(launcher.getMainClass()).isEqualTo("demo.Application"); + this.launcher = new PropertiesLauncher(); + assertThat(this.launcher.getMainClass()).isEqualTo("demo.Application"); assertThat(System.getProperty("loader.main")).isNull(); } @Test void testUserSpecifiedConfigName() throws Exception { System.setProperty("loader.config.name", "foo"); - PropertiesLauncher launcher = new PropertiesLauncher(); - assertThat(launcher.getMainClass()).isEqualTo("my.Application"); - assertThat(ReflectionTestUtils.getField(launcher, "paths").toString()).isEqualTo("[etc/]"); + this.launcher = new PropertiesLauncher(); + assertThat(this.launcher.getMainClass()).isEqualTo("my.Application"); + assertThat(ReflectionTestUtils.getField(this.launcher, "paths").toString()).isEqualTo("[etc/]"); } @Test void testRootOfClasspathFirst() throws Exception { System.setProperty("loader.config.name", "bar"); - PropertiesLauncher launcher = new PropertiesLauncher(); - assertThat(launcher.getMainClass()).isEqualTo("my.BarApplication"); + this.launcher = new PropertiesLauncher(); + assertThat(this.launcher.getMainClass()).isEqualTo("my.BarApplication"); } @Test void testUserSpecifiedDotPath() { System.setProperty("loader.path", "."); - PropertiesLauncher launcher = new PropertiesLauncher(); - assertThat(ReflectionTestUtils.getField(launcher, "paths").toString()).isEqualTo("[.]"); + this.launcher = new PropertiesLauncher(); + assertThat(ReflectionTestUtils.getField(this.launcher, "paths").toString()).isEqualTo("[.]"); } @Test void testUserSpecifiedSlashPath() throws Exception { System.setProperty("loader.path", "jars/"); - PropertiesLauncher launcher = new PropertiesLauncher(); - assertThat(ReflectionTestUtils.getField(launcher, "paths").toString()).isEqualTo("[jars/]"); + this.launcher = new PropertiesLauncher(); + assertThat(ReflectionTestUtils.getField(this.launcher, "paths").toString()).isEqualTo("[jars/]"); List archives = new ArrayList<>(); - launcher.getClassPathArchivesIterator().forEachRemaining(archives::add); + this.launcher.getClassPathArchivesIterator().forEachRemaining(archives::add); assertThat(archives).areExactly(1, endingWith("app.jar")); } @@ -167,9 +172,9 @@ void testUserSpecifiedSlashPath() throws Exception { void testUserSpecifiedWildcardPath() throws Exception { System.setProperty("loader.path", "jars/*"); System.setProperty("loader.main", "demo.Application"); - PropertiesLauncher launcher = new PropertiesLauncher(); - assertThat(ReflectionTestUtils.getField(launcher, "paths").toString()).isEqualTo("[jars/]"); - launcher.launch(new String[0]); + this.launcher = new PropertiesLauncher(); + assertThat(ReflectionTestUtils.getField(this.launcher, "paths").toString()).isEqualTo("[jars/]"); + this.launcher.launch(new String[0]); waitFor("Hello World"); } @@ -177,20 +182,20 @@ void testUserSpecifiedWildcardPath() throws Exception { void testUserSpecifiedJarPath() throws Exception { System.setProperty("loader.path", "jars/app.jar"); System.setProperty("loader.main", "demo.Application"); - PropertiesLauncher launcher = new PropertiesLauncher(); - assertThat(ReflectionTestUtils.getField(launcher, "paths").toString()).isEqualTo("[jars/app.jar]"); - launcher.launch(new String[0]); + this.launcher = new PropertiesLauncher(); + assertThat(ReflectionTestUtils.getField(this.launcher, "paths").toString()).isEqualTo("[jars/app.jar]"); + this.launcher.launch(new String[0]); waitFor("Hello World"); } @Test void testUserSpecifiedRootOfJarPath() throws Exception { System.setProperty("loader.path", "jar:file:./src/test/resources/nested-jars/app.jar!/"); - PropertiesLauncher launcher = new PropertiesLauncher(); - assertThat(ReflectionTestUtils.getField(launcher, "paths").toString()) + this.launcher = new PropertiesLauncher(); + assertThat(ReflectionTestUtils.getField(this.launcher, "paths").toString()) .isEqualTo("[jar:file:./src/test/resources/nested-jars/app.jar!/]"); List archives = new ArrayList<>(); - launcher.getClassPathArchivesIterator().forEachRemaining(archives::add); + this.launcher.getClassPathArchivesIterator().forEachRemaining(archives::add); assertThat(archives).areExactly(1, endingWith("foo.jar!/")); assertThat(archives).areExactly(1, endingWith("app.jar")); } @@ -198,9 +203,9 @@ void testUserSpecifiedRootOfJarPath() throws Exception { @Test void testUserSpecifiedRootOfJarPathWithDot() throws Exception { System.setProperty("loader.path", "nested-jars/app.jar!/./"); - PropertiesLauncher launcher = new PropertiesLauncher(); + this.launcher = new PropertiesLauncher(); List archives = new ArrayList<>(); - launcher.getClassPathArchivesIterator().forEachRemaining(archives::add); + this.launcher.getClassPathArchivesIterator().forEachRemaining(archives::add); assertThat(archives).areExactly(1, endingWith("foo.jar!/")); assertThat(archives).areExactly(1, endingWith("app.jar")); } @@ -208,9 +213,9 @@ void testUserSpecifiedRootOfJarPathWithDot() throws Exception { @Test void testUserSpecifiedRootOfJarPathWithDotAndJarPrefix() throws Exception { System.setProperty("loader.path", "jar:file:./src/test/resources/nested-jars/app.jar!/./"); - PropertiesLauncher launcher = new PropertiesLauncher(); + this.launcher = new PropertiesLauncher(); List archives = new ArrayList<>(); - launcher.getClassPathArchivesIterator().forEachRemaining(archives::add); + this.launcher.getClassPathArchivesIterator().forEachRemaining(archives::add); assertThat(archives).areExactly(1, endingWith("foo.jar!/")); } @@ -218,9 +223,9 @@ void testUserSpecifiedRootOfJarPathWithDotAndJarPrefix() throws Exception { void testUserSpecifiedJarFileWithNestedArchives() throws Exception { System.setProperty("loader.path", "nested-jars/app.jar"); System.setProperty("loader.main", "demo.Application"); - PropertiesLauncher launcher = new PropertiesLauncher(); + this.launcher = new PropertiesLauncher(); List archives = new ArrayList<>(); - launcher.getClassPathArchivesIterator().forEachRemaining(archives::add); + this.launcher.getClassPathArchivesIterator().forEachRemaining(archives::add); assertThat(archives).areExactly(1, endingWith("foo.jar!/")); assertThat(archives).areExactly(1, endingWith("app.jar")); } @@ -229,9 +234,9 @@ void testUserSpecifiedJarFileWithNestedArchives() throws Exception { void testUserSpecifiedNestedJarPath() throws Exception { System.setProperty("loader.path", "nested-jars/app.jar!/foo.jar"); System.setProperty("loader.main", "demo.Application"); - PropertiesLauncher launcher = new PropertiesLauncher(); + this.launcher = new PropertiesLauncher(); List archives = new ArrayList<>(); - launcher.getClassPathArchivesIterator().forEachRemaining(archives::add); + this.launcher.getClassPathArchivesIterator().forEachRemaining(archives::add); assertThat(archives).hasSize(1).areExactly(1, endingWith("foo.jar!/")); } @@ -239,8 +244,8 @@ void testUserSpecifiedNestedJarPath() throws Exception { 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]); + this.launcher = new PropertiesLauncher(); + this.launcher.launch(new String[0]); waitFor("Hello World"); } @@ -248,9 +253,9 @@ void testUserSpecifiedDirectoryContainingJarFileWithNestedArchives() throws Exce void testUserSpecifiedJarPathWithDot() throws Exception { System.setProperty("loader.path", "./jars/app.jar"); System.setProperty("loader.main", "demo.Application"); - PropertiesLauncher launcher = new PropertiesLauncher(); - assertThat(ReflectionTestUtils.getField(launcher, "paths").toString()).isEqualTo("[jars/app.jar]"); - launcher.launch(new String[0]); + this.launcher = new PropertiesLauncher(); + assertThat(ReflectionTestUtils.getField(this.launcher, "paths").toString()).isEqualTo("[jars/app.jar]"); + this.launcher.launch(new String[0]); waitFor("Hello World"); } @@ -258,9 +263,9 @@ void testUserSpecifiedJarPathWithDot() throws Exception { void testUserSpecifiedClassLoader() throws Exception { System.setProperty("loader.path", "jars/app.jar"); System.setProperty("loader.classLoader", URLClassLoader.class.getName()); - PropertiesLauncher launcher = new PropertiesLauncher(); - assertThat(ReflectionTestUtils.getField(launcher, "paths").toString()).isEqualTo("[jars/app.jar]"); - launcher.launch(new String[0]); + this.launcher = new PropertiesLauncher(); + assertThat(ReflectionTestUtils.getField(this.launcher, "paths").toString()).isEqualTo("[jars/app.jar]"); + this.launcher.launch(new String[0]); waitFor("Hello World"); } @@ -268,18 +273,18 @@ void testUserSpecifiedClassLoader() throws Exception { void testUserSpecifiedClassPathOrder() throws Exception { System.setProperty("loader.path", "more-jars/app.jar,jars/app.jar"); System.setProperty("loader.classLoader", URLClassLoader.class.getName()); - PropertiesLauncher launcher = new PropertiesLauncher(); - assertThat(ReflectionTestUtils.getField(launcher, "paths").toString()) + this.launcher = new PropertiesLauncher(); + assertThat(ReflectionTestUtils.getField(this.launcher, "paths").toString()) .isEqualTo("[more-jars/app.jar, jars/app.jar]"); - launcher.launch(new String[0]); + this.launcher.launch(new String[0]); waitFor("Hello Other World"); } @Test void testCustomClassLoaderCreation() throws Exception { System.setProperty("loader.classLoader", TestLoader.class.getName()); - PropertiesLauncher launcher = new PropertiesLauncher(); - ClassLoader loader = launcher.createClassLoader(archives()); + this.launcher = new PropertiesLauncher(); + ClassLoader loader = this.launcher.createClassLoader(archives()); assertThat(loader).isNotNull(); assertThat(loader.getClass().getName()).isEqualTo(TestLoader.class.getName()); } @@ -311,15 +316,15 @@ private Archive archive(String url) throws IOException { void testUserSpecifiedConfigPathWins() throws Exception { System.setProperty("loader.config.name", "foo"); System.setProperty("loader.config.location", "classpath:bar.properties"); - PropertiesLauncher launcher = new PropertiesLauncher(); - assertThat(launcher.getMainClass()).isEqualTo("my.BarApplication"); + this.launcher = new PropertiesLauncher(); + assertThat(this.launcher.getMainClass()).isEqualTo("my.BarApplication"); } @Test void testSystemPropertySpecifiedMain() throws Exception { System.setProperty("loader.main", "foo.Bar"); - PropertiesLauncher launcher = new PropertiesLauncher(); - assertThat(launcher.getMainClass()).isEqualTo("foo.Bar"); + this.launcher = new PropertiesLauncher(); + assertThat(this.launcher.getMainClass()).isEqualTo("foo.Bar"); } @Test @@ -332,8 +337,8 @@ void testSystemPropertiesSet() { @Test void testArgsEnhanced() throws Exception { System.setProperty("loader.args", "foo"); - PropertiesLauncher launcher = new PropertiesLauncher(); - assertThat(Arrays.asList(launcher.getArgs("bar")).toString()).isEqualTo("[foo, bar]"); + this.launcher = new PropertiesLauncher(); + assertThat(Arrays.asList(this.launcher.getArgs("bar")).toString()).isEqualTo("[foo, bar]"); } @SuppressWarnings("unchecked") @@ -348,15 +353,16 @@ void testLoadPathCustomizedUsingManifest() throws Exception { try (FileOutputStream manifestStream = new FileOutputStream(manifestFile)) { manifest.write(manifestStream); } - PropertiesLauncher launcher = new PropertiesLauncher(); - assertThat((List) ReflectionTestUtils.getField(launcher, "paths")).containsExactly("/foo.jar", "/bar/"); + this.launcher = new PropertiesLauncher(); + assertThat((List) ReflectionTestUtils.getField(this.launcher, "paths")).containsExactly("/foo.jar", + "/bar/"); } @Test void testManifestWithPlaceholders() throws Exception { System.setProperty("loader.home", "src/test/resources/placeholders"); - PropertiesLauncher launcher = new PropertiesLauncher(); - assertThat(launcher.getMainClass()).isEqualTo("demo.FooApplication"); + this.launcher = new PropertiesLauncher(); + assertThat(this.launcher.getMainClass()).isEqualTo("demo.FooApplication"); } @Test @@ -364,9 +370,9 @@ void encodedFileUrlLoaderPathIsHandledCorrectly() throws Exception { File loaderPath = new File(this.tempDir, "loader path"); loaderPath.mkdir(); System.setProperty("loader.path", loaderPath.toURI().toURL().toString()); - PropertiesLauncher launcher = new PropertiesLauncher(); + this.launcher = new PropertiesLauncher(); List archives = new ArrayList<>(); - launcher.getClassPathArchivesIterator().forEachRemaining(archives::add); + this.launcher.getClassPathArchivesIterator().forEachRemaining(archives::add); assertThat(archives.size()).isEqualTo(1); File archiveRoot = (File) ReflectionTestUtils.getField(archives.get(0), "root"); assertThat(archiveRoot).isEqualTo(loaderPath); @@ -378,9 +384,9 @@ void loadResourceFromJarFile() throws Exception { TestJarCreator.createTestJar(jarFile); System.setProperty("loader.home", this.tempDir.getAbsolutePath()); System.setProperty("loader.path", "app.jar"); - PropertiesLauncher launcher = new PropertiesLauncher(); + this.launcher = new PropertiesLauncher(); try { - launcher.launch(new String[0]); + this.launcher.launch(new String[0]); } catch (Exception ex) { }