Polish loader and loader-tools
Polish and refactor `spring-boot-loader` and `spring-boot-loader-tools` to make it easier to add indexing and layering support. Closes gh-19766
This commit is contained in:
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright 2012-2019 the original author or authors.
|
||||
* Copyright 2012-2020 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.
|
||||
@@ -32,6 +32,8 @@ import org.springframework.boot.loader.archive.Archive;
|
||||
*/
|
||||
public abstract class ExecutableArchiveLauncher extends Launcher {
|
||||
|
||||
private static final String START_CLASS_ATTRIBUTE = "Start-Class";
|
||||
|
||||
private final Archive archive;
|
||||
|
||||
public ExecutableArchiveLauncher() {
|
||||
@@ -44,11 +46,12 @@ public abstract class ExecutableArchiveLauncher extends Launcher {
|
||||
}
|
||||
|
||||
protected ExecutableArchiveLauncher(Archive archive) {
|
||||
this.archive = archive;
|
||||
}
|
||||
|
||||
protected final Archive getArchive() {
|
||||
return this.archive;
|
||||
try {
|
||||
this.archive = archive;
|
||||
}
|
||||
catch (Exception ex) {
|
||||
throw new IllegalStateException(ex);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
@@ -56,7 +59,7 @@ public abstract class ExecutableArchiveLauncher extends Launcher {
|
||||
Manifest manifest = this.archive.getManifest();
|
||||
String mainClass = null;
|
||||
if (manifest != null) {
|
||||
mainClass = manifest.getMainAttributes().getValue("Start-Class");
|
||||
mainClass = manifest.getMainAttributes().getValue(START_CLASS_ATTRIBUTE);
|
||||
}
|
||||
if (mainClass == null) {
|
||||
throw new IllegalStateException("No 'Start-Class' manifest entry specified in " + this);
|
||||
@@ -125,4 +128,12 @@ public abstract class ExecutableArchiveLauncher extends Launcher {
|
||||
return this.archive.supportsNestedJars();
|
||||
}
|
||||
|
||||
/**
|
||||
* Return the root archive.
|
||||
* @return the root archive
|
||||
*/
|
||||
protected final Archive getArchive() {
|
||||
return this.archive;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright 2012-2019 the original author or authors.
|
||||
* Copyright 2012-2020 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.
|
||||
@@ -77,7 +77,9 @@ public abstract class Launcher {
|
||||
protected ClassLoader createClassLoader(Iterator<Archive> archives) throws Exception {
|
||||
List<URL> urls = new ArrayList<>(50);
|
||||
while (archives.hasNext()) {
|
||||
urls.add(archives.next().getUrl());
|
||||
Archive archive = archives.next();
|
||||
urls.add(archive.getUrl());
|
||||
archive.close();
|
||||
}
|
||||
return createClassLoader(urls.toArray(new URL[0]));
|
||||
}
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright 2012-2019 the original author or authors.
|
||||
* Copyright 2012-2020 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.
|
||||
@@ -23,7 +23,7 @@ import java.io.IOException;
|
||||
import java.net.MalformedURLException;
|
||||
import java.net.URL;
|
||||
import java.util.Enumeration;
|
||||
import java.util.HashSet;
|
||||
import java.util.LinkedHashSet;
|
||||
import java.util.List;
|
||||
import java.util.Set;
|
||||
import java.util.jar.JarEntry;
|
||||
@@ -53,7 +53,15 @@ public abstract class AbstractExecutableArchiveLauncherTests {
|
||||
jarOutputStream.putNextEntry(new JarEntry(entryPrefix + "/"));
|
||||
jarOutputStream.putNextEntry(new JarEntry(entryPrefix + "/classes/"));
|
||||
jarOutputStream.putNextEntry(new JarEntry(entryPrefix + "/lib/"));
|
||||
JarEntry libFoo = new JarEntry(entryPrefix + "/lib/foo.jar");
|
||||
addNestedJars(entryPrefix, "/lib/foo.jar", jarOutputStream);
|
||||
addNestedJars(entryPrefix, "/lib/bar.jar", jarOutputStream);
|
||||
addNestedJars(entryPrefix, "/lib/baz.jar", jarOutputStream);
|
||||
jarOutputStream.close();
|
||||
return archive;
|
||||
}
|
||||
|
||||
private void addNestedJars(String entryPrefix, String lib, JarOutputStream jarOutputStream) throws IOException {
|
||||
JarEntry libFoo = new JarEntry(entryPrefix + lib);
|
||||
libFoo.setMethod(ZipEntry.STORED);
|
||||
ByteArrayOutputStream fooJarStream = new ByteArrayOutputStream();
|
||||
new JarOutputStream(fooJarStream).close();
|
||||
@@ -63,8 +71,6 @@ public abstract class AbstractExecutableArchiveLauncherTests {
|
||||
libFoo.setCrc(crc32.getValue());
|
||||
jarOutputStream.putNextEntry(libFoo);
|
||||
jarOutputStream.write(fooJarStream.toByteArray());
|
||||
jarOutputStream.close();
|
||||
return archive;
|
||||
}
|
||||
|
||||
protected File explode(File archive) throws IOException {
|
||||
@@ -87,11 +93,20 @@ public abstract class AbstractExecutableArchiveLauncherTests {
|
||||
}
|
||||
|
||||
protected Set<URL> getUrls(List<Archive> archives) throws MalformedURLException {
|
||||
Set<URL> urls = new HashSet<>(archives.size());
|
||||
Set<URL> urls = new LinkedHashSet<>(archives.size());
|
||||
for (Archive archive : archives) {
|
||||
urls.add(archive.getUrl());
|
||||
}
|
||||
return urls;
|
||||
}
|
||||
|
||||
protected final URL toUrl(File file) {
|
||||
try {
|
||||
return file.toURI().toURL();
|
||||
}
|
||||
catch (MalformedURLException ex) {
|
||||
throw new IllegalStateException(ex);
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright 2012-2019 the original author or authors.
|
||||
* Copyright 2012-2020 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.
|
||||
@@ -42,9 +42,7 @@ class JarLauncherTests extends AbstractExecutableArchiveLauncherTests {
|
||||
JarLauncher launcher = new JarLauncher(new ExplodedArchive(explodedRoot, true));
|
||||
List<Archive> archives = new ArrayList<>();
|
||||
launcher.getClassPathArchivesIterator().forEachRemaining(archives::add);
|
||||
assertThat(archives).hasSize(2);
|
||||
assertThat(getUrls(archives)).containsOnly(new File(explodedRoot, "BOOT-INF/classes").toURI().toURL(),
|
||||
new File(explodedRoot, "BOOT-INF/lib/foo.jar").toURI().toURL());
|
||||
assertThat(getUrls(archives)).containsExactlyInAnyOrder(getExpectedFileUrls(explodedRoot));
|
||||
for (Archive archive : archives) {
|
||||
archive.close();
|
||||
}
|
||||
@@ -57,14 +55,29 @@ class JarLauncherTests extends AbstractExecutableArchiveLauncherTests {
|
||||
JarLauncher launcher = new JarLauncher(archive);
|
||||
List<Archive> classPathArchives = new ArrayList<>();
|
||||
launcher.getClassPathArchivesIterator().forEachRemaining(classPathArchives::add);
|
||||
assertThat(classPathArchives).hasSize(2);
|
||||
assertThat(classPathArchives).hasSize(4);
|
||||
assertThat(getUrls(classPathArchives)).containsOnly(
|
||||
new URL("jar:" + jarRoot.toURI().toURL() + "!/BOOT-INF/classes!/"),
|
||||
new URL("jar:" + jarRoot.toURI().toURL() + "!/BOOT-INF/lib/foo.jar!/"));
|
||||
new URL("jar:" + jarRoot.toURI().toURL() + "!/BOOT-INF/lib/foo.jar!/"),
|
||||
new URL("jar:" + jarRoot.toURI().toURL() + "!/BOOT-INF/lib/bar.jar!/"),
|
||||
new URL("jar:" + jarRoot.toURI().toURL() + "!/BOOT-INF/lib/baz.jar!/"));
|
||||
for (Archive classPathArchive : classPathArchives) {
|
||||
classPathArchive.close();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
protected final URL[] getExpectedFileUrls(File explodedRoot) {
|
||||
return getExpectedFiles(explodedRoot).stream().map(this::toUrl).toArray(URL[]::new);
|
||||
}
|
||||
|
||||
protected final List<File> getExpectedFiles(File parent) {
|
||||
List<File> expected = new ArrayList<>();
|
||||
expected.add(new File(parent, "BOOT-INF/classes"));
|
||||
expected.add(new File(parent, "BOOT-INF/lib/foo.jar"));
|
||||
expected.add(new File(parent, "BOOT-INF/lib/bar.jar"));
|
||||
expected.add(new File(parent, "BOOT-INF/lib/baz.jar"));
|
||||
return expected;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright 2012-2019 the original author or authors.
|
||||
* Copyright 2012-2020 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.
|
||||
@@ -42,29 +42,41 @@ class WarLauncherTests extends AbstractExecutableArchiveLauncherTests {
|
||||
WarLauncher launcher = new WarLauncher(new ExplodedArchive(explodedRoot, true));
|
||||
List<Archive> archives = new ArrayList<>();
|
||||
launcher.getClassPathArchivesIterator().forEachRemaining(archives::add);
|
||||
assertThat(archives).hasSize(2);
|
||||
assertThat(getUrls(archives)).containsOnly(new File(explodedRoot, "WEB-INF/classes").toURI().toURL(),
|
||||
new File(explodedRoot, "WEB-INF/lib/foo.jar").toURI().toURL());
|
||||
assertThat(getUrls(archives)).containsExactlyInAnyOrder(getExpectedFileUrls(explodedRoot));
|
||||
for (Archive archive : archives) {
|
||||
archive.close();
|
||||
}
|
||||
}
|
||||
|
||||
@Test
|
||||
void archivedWarHasOnlyWebInfClassesAndContentsOWebInfLibOnClasspath() throws Exception {
|
||||
void archivedWarHasOnlyWebInfClassesAndContentsOfWebInfLibOnClasspath() throws Exception {
|
||||
File jarRoot = createJarArchive("archive.war", "WEB-INF");
|
||||
try (JarFileArchive archive = new JarFileArchive(jarRoot)) {
|
||||
WarLauncher launcher = new WarLauncher(archive);
|
||||
List<Archive> classPathArchives = new ArrayList<>();
|
||||
launcher.getClassPathArchivesIterator().forEachRemaining(classPathArchives::add);
|
||||
assertThat(classPathArchives).hasSize(2);
|
||||
assertThat(getUrls(classPathArchives)).containsOnly(
|
||||
new URL("jar:" + jarRoot.toURI().toURL() + "!/WEB-INF/classes!/"),
|
||||
new URL("jar:" + jarRoot.toURI().toURL() + "!/WEB-INF/lib/foo.jar!/"));
|
||||
new URL("jar:" + jarRoot.toURI().toURL() + "!/WEB-INF/lib/foo.jar!/"),
|
||||
new URL("jar:" + jarRoot.toURI().toURL() + "!/WEB-INF/lib/bar.jar!/"),
|
||||
new URL("jar:" + jarRoot.toURI().toURL() + "!/WEB-INF/lib/baz.jar!/"));
|
||||
for (Archive classPathArchive : classPathArchives) {
|
||||
classPathArchive.close();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
protected final URL[] getExpectedFileUrls(File explodedRoot) {
|
||||
return getExpectedFiles(explodedRoot).stream().map(this::toUrl).toArray(URL[]::new);
|
||||
}
|
||||
|
||||
protected final List<File> getExpectedFiles(File parent) {
|
||||
List<File> expected = new ArrayList<>();
|
||||
expected.add(new File(parent, "WEB-INF/classes"));
|
||||
expected.add(new File(parent, "WEB-INF/lib/foo.jar"));
|
||||
expected.add(new File(parent, "WEB-INF/lib/bar.jar"));
|
||||
expected.add(new File(parent, "WEB-INF/lib/baz.jar"));
|
||||
return expected;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user