Skip to content

Commit

Permalink
Merge branch '3.2.x' into 3.3.x
Browse files Browse the repository at this point in the history
Closes gh-41970
  • Loading branch information
scottfrederick committed Aug 20, 2024
2 parents 3ac141e + 21b1555 commit 0451cb8
Show file tree
Hide file tree
Showing 9 changed files with 135 additions and 89 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -16,16 +16,12 @@

package org.springframework.boot.loader.launch;

import java.io.IOException;
import java.net.URL;
import java.util.ArrayList;
import java.util.Collection;
import java.util.Set;
import java.util.jar.Attributes;
import java.util.jar.Manifest;

import org.springframework.boot.loader.launch.Archive.Entry;

/**
* Base class for a {@link Launcher} backed by an executable archive.
*
Expand All @@ -41,14 +37,8 @@ public abstract class ExecutableArchiveLauncher extends Launcher {

private static final String START_CLASS_ATTRIBUTE = "Start-Class";

protected static final String BOOT_CLASSPATH_INDEX_ATTRIBUTE = "Spring-Boot-Classpath-Index";

protected static final String DEFAULT_CLASSPATH_INDEX_FILE_NAME = "classpath.idx";

private final Archive archive;

private final ClassPathIndexFile classPathIndex;

public ExecutableArchiveLauncher() throws Exception {
this(Archive.create(Launcher.class));
}
Expand All @@ -58,21 +48,6 @@ protected ExecutableArchiveLauncher(Archive archive) throws Exception {
this.classPathIndex = getClassPathIndex(this.archive);
}

ClassPathIndexFile getClassPathIndex(Archive archive) throws IOException {
if (!archive.isExploded()) {
return null; // Regular archives already have a defined order
}
String location = getClassPathIndexFileLocation(archive);
return ClassPathIndexFile.loadIfPossible(archive.getRootDirectory(), location);
}

private String getClassPathIndexFileLocation(Archive archive) throws IOException {
Manifest manifest = archive.getManifest();
Attributes attributes = (manifest != null) ? manifest.getMainAttributes() : null;
String location = (attributes != null) ? attributes.getValue(BOOT_CLASSPATH_INDEX_ATTRIBUTE) : null;
return (location != null) ? location : getEntryPathPrefix() + DEFAULT_CLASSPATH_INDEX_FILE_NAME;
}

@Override
protected ClassLoader createClassLoader(Collection<URL> urls) throws Exception {
if (this.classPathIndex != null) {
Expand Down Expand Up @@ -102,13 +77,6 @@ protected Set<URL> getClassPathUrls() throws Exception {
return this.archive.getClassPathUrls(this::isIncludedOnClassPathAndNotIndexed, this::isSearchedDirectory);
}

private boolean isIncludedOnClassPathAndNotIndexed(Entry entry) {
if (!isIncludedOnClassPath(entry)) {
return false;
}
return (this.classPathIndex == null) || !this.classPathIndex.containsEntry(entry.name());
}

/**
* Determine if the specified directory entry is a candidate for further searching.
* @param entry the entry to check
Expand All @@ -119,18 +87,4 @@ protected boolean isSearchedDirectory(Archive.Entry entry) {
&& !isIncludedOnClassPath(entry);
}

/**
* Determine if the specified entry is a nested item that should be added to the
* classpath.
* @param entry the entry to check
* @return {@code true} if the entry is a nested item (jar or directory)
*/
protected abstract boolean isIncludedOnClassPath(Archive.Entry entry);

/**
* Return the path prefix for relevant entries in the archive.
* @return the entry path prefix
*/
protected abstract String getEntryPathPrefix();

}
Original file line number Diff line number Diff line change
Expand Up @@ -36,24 +36,6 @@ protected JarLauncher(Archive archive) throws Exception {
super(archive);
}

@Override
protected boolean isIncludedOnClassPath(Archive.Entry entry) {
return isLibraryFileOrClassesDirectory(entry);
}

@Override
protected String getEntryPathPrefix() {
return "BOOT-INF/";
}

static boolean isLibraryFileOrClassesDirectory(Archive.Entry entry) {
String name = entry.name();
if (entry.isDirectory()) {
return name.equals("BOOT-INF/classes/");
}
return name.startsWith("BOOT-INF/lib/");
}

public static void main(String[] args) throws Exception {
new JarLauncher().launch(args);
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -16,12 +16,16 @@

package org.springframework.boot.loader.launch;

import java.io.IOException;
import java.io.UncheckedIOException;
import java.lang.reflect.Method;
import java.net.URL;
import java.util.Collection;
import java.util.Set;
import java.util.jar.Attributes;
import java.util.jar.Manifest;

import org.springframework.boot.loader.launch.Archive.Entry;
import org.springframework.boot.loader.net.protocol.Handlers;

/**
Expand All @@ -30,12 +34,19 @@
*
* @author Phillip Webb
* @author Dave Syer
* @author Scott Frederick
* @since 3.2.0
*/
public abstract class Launcher {

private static final String JAR_MODE_RUNNER_CLASS_NAME = JarModeRunner.class.getName();

protected static final String BOOT_CLASSPATH_INDEX_ATTRIBUTE = "Spring-Boot-Classpath-Index";

protected static final String DEFAULT_CLASSPATH_INDEX_FILE_NAME = "classpath.idx";

protected ClassPathIndexFile classPathIndex;

/**
* Launch the application. This method is the initial entry point that should be
* called by a subclass {@code public static void main(String[] args)} method.
Expand Down Expand Up @@ -102,6 +113,21 @@ protected boolean isExploded() {
return (archive != null) && archive.isExploded();
}

ClassPathIndexFile getClassPathIndex(Archive archive) throws IOException {
if (!archive.isExploded()) {
return null; // Regular archives already have a defined order
}
String location = getClassPathIndexFileLocation(archive);
return ClassPathIndexFile.loadIfPossible(archive.getRootDirectory(), location);
}

private String getClassPathIndexFileLocation(Archive archive) throws IOException {
Manifest manifest = archive.getManifest();
Attributes attributes = (manifest != null) ? manifest.getMainAttributes() : null;
String location = (attributes != null) ? attributes.getValue(BOOT_CLASSPATH_INDEX_ATTRIBUTE) : null;
return (location != null) ? location : getEntryPathPrefix() + DEFAULT_CLASSPATH_INDEX_FILE_NAME;
}

/**
* Return the archive being launched or {@code null} if there is no archive.
* @return the launched archive
Expand All @@ -122,4 +148,37 @@ protected boolean isExploded() {
*/
protected abstract Set<URL> getClassPathUrls() throws Exception;

/**
* Return the path prefix for relevant entries in the archive.
* @return the entry path prefix
*/
protected String getEntryPathPrefix() {
return "BOOT-INF/";
}

/**
* Determine if the specified entry is a nested item that should be added to the
* classpath.
* @param entry the entry to check
* @return {@code true} if the entry is a nested item (jar or directory)
*/
protected boolean isIncludedOnClassPath(Archive.Entry entry) {
return isLibraryFileOrClassesDirectory(entry);
}

protected boolean isLibraryFileOrClassesDirectory(Archive.Entry entry) {
String name = entry.name();
if (entry.isDirectory()) {
return name.equals("BOOT-INF/classes/");
}
return name.startsWith("BOOT-INF/lib/");
}

protected boolean isIncludedOnClassPathAndNotIndexed(Entry entry) {
if (!isIncludedOnClassPath(entry)) {
return false;
}
return (this.classPathIndex == null) || !this.classPathIndex.containsEntry(entry.name());
}

}
Original file line number Diff line number Diff line change
Expand Up @@ -70,6 +70,7 @@
* @author Janne Valkealahti
* @author Andy Wilkinson
* @author Phillip Webb
* @author Scott Frederick
* @since 3.2.0
*/
public class PropertiesLauncher extends Launcher {
Expand Down Expand Up @@ -148,6 +149,7 @@ public PropertiesLauncher() throws Exception {
this.homeDirectory = getHomeDirectory();
initializeProperties();
this.paths = getPaths();
this.classPathIndex = getClassPathIndex(this.archive);
}

protected File getHomeDirectory() throws Exception {
Expand Down Expand Up @@ -330,6 +332,10 @@ private String cleanupPath(String path) {
@Override
protected ClassLoader createClassLoader(Collection<URL> urls) throws Exception {
String loaderClassName = getProperty("loader.classLoader");
if (this.classPathIndex != null) {
urls = new ArrayList<>(urls);
urls.addAll(this.classPathIndex.getUrls());
}
if (loaderClassName == null) {
return super.createClassLoader(urls);
}
Expand Down Expand Up @@ -537,9 +543,9 @@ private Set<URL> getClassPathUrlsForNested(String path) throws Exception {
}
}

private Set<URL> getClassPathUrlsForRoot() throws IOException {
private Set<URL> getClassPathUrlsForRoot() throws Exception {
debug.log("Adding classpath entries from root archive %s", this.archive);
return this.archive.getClassPathUrls(JarLauncher::isLibraryFileOrClassesDirectory);
return this.archive.getClassPathUrls(this::isIncludedOnClassPathAndNotIndexed, Archive.ALL_ENTRIES);
}

private Predicate<Entry> includeByPrefix(String prefix) {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -35,17 +35,13 @@ protected WarLauncher(Archive archive) throws Exception {
super(archive);
}

@Override
public boolean isIncludedOnClassPath(Archive.Entry entry) {
return isLibraryFileOrClassesDirectory(entry);
}

@Override
protected String getEntryPathPrefix() {
return "WEB-INF/";
}

static boolean isLibraryFileOrClassesDirectory(Archive.Entry entry) {
@Override
protected boolean isLibraryFileOrClassesDirectory(Archive.Entry entry) {
String name = entry.name();
if (entry.isDirectory()) {
return name.equals("WEB-INF/classes/");
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -24,6 +24,7 @@
import java.io.Writer;
import java.net.MalformedURLException;
import java.net.URL;
import java.net.URLClassLoader;
import java.nio.charset.StandardCharsets;
import java.util.Collections;
import java.util.Enumeration;
Expand All @@ -40,13 +41,13 @@
import org.springframework.util.FileCopyUtils;

/**
* Base class for testing {@link ExecutableArchiveLauncher} implementations.
* Base class for testing {@link Launcher} implementations.
*
* @author Andy Wilkinson
* @author Madhura Bhave
* @author Scott Frederick
*/
abstract class AbstractExecutableArchiveLauncherTests {
abstract class AbstractLauncherTests {

@TempDir
File tempDir;
Expand Down Expand Up @@ -133,4 +134,8 @@ protected final URL toUrl(File file) {
}
}

protected URLClassLoader createClassLoader(Launcher launcher) throws Exception {
return (URLClassLoader) launcher.createClassLoader(launcher.getClassPathUrls());
}

}
Original file line number Diff line number Diff line change
Expand Up @@ -49,7 +49,7 @@
* @author Phillip Webb
*/
@AssertFileChannelDataBlocksClosed
class JarLauncherTests extends AbstractExecutableArchiveLauncherTests {
class JarLauncherTests extends AbstractLauncherTests {

@Test
void explodedJarHasOnlyBootInfClassesAndContentsOfBootInfLibOnClasspath() throws Exception {
Expand Down Expand Up @@ -115,10 +115,6 @@ void explodedJarDefinedPackagesIncludeManifestAttributes() {
}));
}

private URLClassLoader createClassLoader(JarLauncher launcher) throws Exception {
return (URLClassLoader) launcher.createClassLoader(launcher.getClassPathUrls());
}

private URL[] getExpectedFileUrls(File explodedRoot) {
return getExpectedFiles(explodedRoot).stream().map(this::toUrl).toArray(URL[]::new);
}
Expand Down
Loading

0 comments on commit 0451cb8

Please sign in to comment.