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
This commit is contained in:
Phillip Webb 2020-06-11 12:24:04 -07:00
parent 29f5468ada
commit 8a249daf1a
2 changed files with 282 additions and 218 deletions

View File

@ -29,9 +29,11 @@ import java.net.URLDecoder;
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 @@ public class PropertiesLauncher extends Launcher {
}
@Override
protected ClassLoader createClassLoader(List<Archive> archives) throws Exception {
Set<URL> urls = new LinkedHashSet<>(archives.size());
for (Archive archive : archives) {
urls.add(archive.getUrl());
protected ClassLoader createClassLoader(Iterator<Archive> archives) throws Exception {
String customLoaderClassName = getProperty("loader.classLoader");
if (customLoaderClassName == null) {
return super.createClassLoader(archives);
}
Set<URL> urls = new LinkedHashSet<>();
while (archives.hasNext()) {
urls.add(archives.next().getUrl());
}
ClassLoader loader = new LaunchedURLClassLoader(urls.toArray(NO_URLS), getClass().getClassLoader());
debug("Classpath: " + urls);
String customLoaderClassName = getProperty("loader.classLoader");
if (customLoaderClassName != null) {
loader = wrapWithCustomClassLoader(loader, customLoaderClassName);
debug("Using custom class loader: " + customLoaderClassName);
}
debug("Classpath for custom loader: " + urls);
loader = wrapWithCustomClassLoader(loader, customLoaderClassName);
debug("Using custom class loader: " + customLoaderClassName);
return loader;
}
@ -449,153 +454,12 @@ public class PropertiesLauncher extends Launcher {
@Override
protected Iterator<Archive> getClassPathArchivesIterator() throws Exception {
List<Archive> lib = new ArrayList<>();
for (String path : this.paths) {
for (Archive archive : getClassPathArchives(path)) {
if (archive instanceof ExplodedArchive) {
List<Archive> 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();
}
private List<Archive> getClassPathArchives(String path) throws Exception {
String root = cleanupPath(handleUrl(path));
List<Archive> 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<Archive> 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 new JarFileArchive(file);
}
return null;
}
private boolean isNestedArchivePath(File file) {
return file.getPath().contains(NESTED_ARCHIVE_SEPARATOR);
}
private List<Archive> 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<Archive> 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 void addNestedEntries(List<Archive> 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<Archive> archives = this.parent.getNestedArchives(null, JarLauncher.NESTED_ARCHIVE_ENTRY_FILTER);
while (archives.hasNext()) {
lib.add(archives.next());
}
}
catch (IOException ex) {
// Ignore
}
}
private String cleanupPath(String path) {
path = path.trim();
// No need for current dir path
if (path.startsWith("./")) {
path = path.substring(2);
}
String lowerCasePath = path.toLowerCase(Locale.ENGLISH);
if (lowerCasePath.endsWith(".jar") || lowerCasePath.endsWith(".zip")) {
return path;
}
if (path.endsWith("/*")) {
path = path.substring(0, path.length() - 1);
}
else {
// It's a directory
if (!path.endsWith("/") && !path.equals(".")) {
path = path + "/";
}
}
return path;
}
private List<Archive> asList(Iterator<Archive> iterator) {
List<Archive> list = new ArrayList<>();
while (iterator.hasNext()) {
list.add(iterator.next());
}
return list;
return classPathArchives.iterator();
}
public static void main(String[] args) throws Exception {
@ -629,6 +493,200 @@ public class PropertiesLauncher extends Launcher {
}
}
private String cleanupPath(String path) {
path = path.trim();
// No need for current dir path
if (path.startsWith("./")) {
path = path.substring(2);
}
String lowerCasePath = path.toLowerCase(Locale.ENGLISH);
if (lowerCasePath.endsWith(".jar") || lowerCasePath.endsWith(".zip")) {
return path;
}
if (path.endsWith("/*")) {
path = path.substring(0, path.length() - 1);
}
else {
// It's a directory
if (!path.endsWith("/") && !path.equals(".")) {
path = path + "/";
}
}
return path;
}
void close() throws Exception {
if (this.classPathArchives != null) {
this.classPathArchives.close();
}
if (this.parent != null) {
this.parent.close();
}
}
/**
* An iterable collection of the classpath archives.
*/
private class ClassPathArchives implements Iterable<Archive> {
private final List<Archive> classPathArchives;
private final Map<File, JarFileArchive> 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<Archive> getClassPathArchives(String path) throws Exception {
String root = cleanupPath(handleUrl(path));
List<Archive> 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<Archive> 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;
}
private boolean isNestedArchivePath(File file) {
return file.getPath().contains(NESTED_ARCHIVE_SEPARATOR);
}
private List<Archive> 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<Archive> 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 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<Archive> 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<Archive> asList(Iterator<Archive> iterator) {
List<Archive> 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<Archive> iterator() {
return this.classPathArchives.iterator();
}
void close() throws IOException {
for (JarFileArchive archive : this.jarFileArchives.values()) {
archive.close();
}
}
}
/**
* Convenience class for finding nested archives that have a prefix in their file path
* (e.g. "lib/").

View File

@ -65,6 +65,8 @@ class PropertiesLauncherTests {
@TempDir
File tempDir;
private PropertiesLauncher launcher;
private ClassLoader contextClassLoader;
private CapturedOutput output;
@ -88,6 +90,9 @@ class PropertiesLauncherTests {
System.clearProperty("loader.system");
System.clearProperty("loader.classLoader");
clearHandlerCache();
if (this.launcher != null) {
this.launcher.close();
}
}
@SuppressWarnings("unchecked")
@ -105,16 +110,16 @@ class PropertiesLauncherTests {
@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 @@ class PropertiesLauncherTests {
@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<Archive> 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 @@ class PropertiesLauncherTests {
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 @@ class PropertiesLauncherTests {
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<Archive> 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 @@ class PropertiesLauncherTests {
@Test
void testUserSpecifiedRootOfJarPathWithDot() throws Exception {
System.setProperty("loader.path", "nested-jars/app.jar!/./");
PropertiesLauncher launcher = new PropertiesLauncher();
this.launcher = new PropertiesLauncher();
List<Archive> 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 @@ class PropertiesLauncherTests {
@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<Archive> 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 @@ class PropertiesLauncherTests {
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<Archive> 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 @@ class PropertiesLauncherTests {
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<Archive> 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 @@ class PropertiesLauncherTests {
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 @@ class PropertiesLauncherTests {
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 @@ class PropertiesLauncherTests {
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 @@ class PropertiesLauncherTests {
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 @@ class PropertiesLauncherTests {
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 @@ class PropertiesLauncherTests {
@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 @@ class PropertiesLauncherTests {
try (FileOutputStream manifestStream = new FileOutputStream(manifestFile)) {
manifest.write(manifestStream);
}
PropertiesLauncher launcher = new PropertiesLauncher();
assertThat((List<String>) ReflectionTestUtils.getField(launcher, "paths")).containsExactly("/foo.jar", "/bar/");
this.launcher = new PropertiesLauncher();
assertThat((List<String>) 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 @@ class PropertiesLauncherTests {
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<Archive> 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 @@ class PropertiesLauncherTests {
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) {
}