Skip to content

Commit cbb7383

Browse files
Merge branch '3.3.x'
Closes gh-41971
2 parents 9bf7d4d + 0451cb8 commit cbb7383

File tree

9 files changed

+135
-89
lines changed

9 files changed

+135
-89
lines changed

spring-boot-project/spring-boot-tools/spring-boot-loader/src/main/java/org/springframework/boot/loader/launch/ExecutableArchiveLauncher.java

Lines changed: 0 additions & 46 deletions
Original file line numberDiff line numberDiff line change
@@ -16,16 +16,12 @@
1616

1717
package org.springframework.boot.loader.launch;
1818

19-
import java.io.IOException;
2019
import java.net.URL;
2120
import java.util.ArrayList;
2221
import java.util.Collection;
2322
import java.util.Set;
24-
import java.util.jar.Attributes;
2523
import java.util.jar.Manifest;
2624

27-
import org.springframework.boot.loader.launch.Archive.Entry;
28-
2925
/**
3026
* Base class for a {@link Launcher} backed by an executable archive.
3127
*
@@ -41,14 +37,8 @@ public abstract class ExecutableArchiveLauncher extends Launcher {
4137

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

44-
protected static final String BOOT_CLASSPATH_INDEX_ATTRIBUTE = "Spring-Boot-Classpath-Index";
45-
46-
protected static final String DEFAULT_CLASSPATH_INDEX_FILE_NAME = "classpath.idx";
47-
4840
private final Archive archive;
4941

50-
private final ClassPathIndexFile classPathIndex;
51-
5242
public ExecutableArchiveLauncher() throws Exception {
5343
this(Archive.create(Launcher.class));
5444
}
@@ -58,21 +48,6 @@ protected ExecutableArchiveLauncher(Archive archive) throws Exception {
5848
this.classPathIndex = getClassPathIndex(this.archive);
5949
}
6050

61-
ClassPathIndexFile getClassPathIndex(Archive archive) throws IOException {
62-
if (!archive.isExploded()) {
63-
return null; // Regular archives already have a defined order
64-
}
65-
String location = getClassPathIndexFileLocation(archive);
66-
return ClassPathIndexFile.loadIfPossible(archive.getRootDirectory(), location);
67-
}
68-
69-
private String getClassPathIndexFileLocation(Archive archive) throws IOException {
70-
Manifest manifest = archive.getManifest();
71-
Attributes attributes = (manifest != null) ? manifest.getMainAttributes() : null;
72-
String location = (attributes != null) ? attributes.getValue(BOOT_CLASSPATH_INDEX_ATTRIBUTE) : null;
73-
return (location != null) ? location : getEntryPathPrefix() + DEFAULT_CLASSPATH_INDEX_FILE_NAME;
74-
}
75-
7651
@Override
7752
protected ClassLoader createClassLoader(Collection<URL> urls) throws Exception {
7853
if (this.classPathIndex != null) {
@@ -102,13 +77,6 @@ protected Set<URL> getClassPathUrls() throws Exception {
10277
return this.archive.getClassPathUrls(this::isIncludedOnClassPathAndNotIndexed, this::isSearchedDirectory);
10378
}
10479

105-
private boolean isIncludedOnClassPathAndNotIndexed(Entry entry) {
106-
if (!isIncludedOnClassPath(entry)) {
107-
return false;
108-
}
109-
return (this.classPathIndex == null) || !this.classPathIndex.containsEntry(entry.name());
110-
}
111-
11280
/**
11381
* Determine if the specified directory entry is a candidate for further searching.
11482
* @param entry the entry to check
@@ -119,18 +87,4 @@ protected boolean isSearchedDirectory(Archive.Entry entry) {
11987
&& !isIncludedOnClassPath(entry);
12088
}
12189

122-
/**
123-
* Determine if the specified entry is a nested item that should be added to the
124-
* classpath.
125-
* @param entry the entry to check
126-
* @return {@code true} if the entry is a nested item (jar or directory)
127-
*/
128-
protected abstract boolean isIncludedOnClassPath(Archive.Entry entry);
129-
130-
/**
131-
* Return the path prefix for relevant entries in the archive.
132-
* @return the entry path prefix
133-
*/
134-
protected abstract String getEntryPathPrefix();
135-
13690
}

spring-boot-project/spring-boot-tools/spring-boot-loader/src/main/java/org/springframework/boot/loader/launch/JarLauncher.java

Lines changed: 0 additions & 18 deletions
Original file line numberDiff line numberDiff line change
@@ -36,24 +36,6 @@ protected JarLauncher(Archive archive) throws Exception {
3636
super(archive);
3737
}
3838

39-
@Override
40-
protected boolean isIncludedOnClassPath(Archive.Entry entry) {
41-
return isLibraryFileOrClassesDirectory(entry);
42-
}
43-
44-
@Override
45-
protected String getEntryPathPrefix() {
46-
return "BOOT-INF/";
47-
}
48-
49-
static boolean isLibraryFileOrClassesDirectory(Archive.Entry entry) {
50-
String name = entry.name();
51-
if (entry.isDirectory()) {
52-
return name.equals("BOOT-INF/classes/");
53-
}
54-
return name.startsWith("BOOT-INF/lib/");
55-
}
56-
5739
public static void main(String[] args) throws Exception {
5840
new JarLauncher().launch(args);
5941
}

spring-boot-project/spring-boot-tools/spring-boot-loader/src/main/java/org/springframework/boot/loader/launch/Launcher.java

Lines changed: 59 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -16,12 +16,16 @@
1616

1717
package org.springframework.boot.loader.launch;
1818

19+
import java.io.IOException;
1920
import java.io.UncheckedIOException;
2021
import java.lang.reflect.Method;
2122
import java.net.URL;
2223
import java.util.Collection;
2324
import java.util.Set;
25+
import java.util.jar.Attributes;
26+
import java.util.jar.Manifest;
2427

28+
import org.springframework.boot.loader.launch.Archive.Entry;
2529
import org.springframework.boot.loader.net.protocol.Handlers;
2630

2731
/**
@@ -30,12 +34,19 @@
3034
*
3135
* @author Phillip Webb
3236
* @author Dave Syer
37+
* @author Scott Frederick
3338
* @since 3.2.0
3439
*/
3540
public abstract class Launcher {
3641

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

44+
protected static final String BOOT_CLASSPATH_INDEX_ATTRIBUTE = "Spring-Boot-Classpath-Index";
45+
46+
protected static final String DEFAULT_CLASSPATH_INDEX_FILE_NAME = "classpath.idx";
47+
48+
protected ClassPathIndexFile classPathIndex;
49+
3950
/**
4051
* Launch the application. This method is the initial entry point that should be
4152
* called by a subclass {@code public static void main(String[] args)} method.
@@ -102,6 +113,21 @@ protected boolean isExploded() {
102113
return (archive != null) && archive.isExploded();
103114
}
104115

116+
ClassPathIndexFile getClassPathIndex(Archive archive) throws IOException {
117+
if (!archive.isExploded()) {
118+
return null; // Regular archives already have a defined order
119+
}
120+
String location = getClassPathIndexFileLocation(archive);
121+
return ClassPathIndexFile.loadIfPossible(archive.getRootDirectory(), location);
122+
}
123+
124+
private String getClassPathIndexFileLocation(Archive archive) throws IOException {
125+
Manifest manifest = archive.getManifest();
126+
Attributes attributes = (manifest != null) ? manifest.getMainAttributes() : null;
127+
String location = (attributes != null) ? attributes.getValue(BOOT_CLASSPATH_INDEX_ATTRIBUTE) : null;
128+
return (location != null) ? location : getEntryPathPrefix() + DEFAULT_CLASSPATH_INDEX_FILE_NAME;
129+
}
130+
105131
/**
106132
* Return the archive being launched or {@code null} if there is no archive.
107133
* @return the launched archive
@@ -122,4 +148,37 @@ protected boolean isExploded() {
122148
*/
123149
protected abstract Set<URL> getClassPathUrls() throws Exception;
124150

151+
/**
152+
* Return the path prefix for relevant entries in the archive.
153+
* @return the entry path prefix
154+
*/
155+
protected String getEntryPathPrefix() {
156+
return "BOOT-INF/";
157+
}
158+
159+
/**
160+
* Determine if the specified entry is a nested item that should be added to the
161+
* classpath.
162+
* @param entry the entry to check
163+
* @return {@code true} if the entry is a nested item (jar or directory)
164+
*/
165+
protected boolean isIncludedOnClassPath(Archive.Entry entry) {
166+
return isLibraryFileOrClassesDirectory(entry);
167+
}
168+
169+
protected boolean isLibraryFileOrClassesDirectory(Archive.Entry entry) {
170+
String name = entry.name();
171+
if (entry.isDirectory()) {
172+
return name.equals("BOOT-INF/classes/");
173+
}
174+
return name.startsWith("BOOT-INF/lib/");
175+
}
176+
177+
protected boolean isIncludedOnClassPathAndNotIndexed(Entry entry) {
178+
if (!isIncludedOnClassPath(entry)) {
179+
return false;
180+
}
181+
return (this.classPathIndex == null) || !this.classPathIndex.containsEntry(entry.name());
182+
}
183+
125184
}

spring-boot-project/spring-boot-tools/spring-boot-loader/src/main/java/org/springframework/boot/loader/launch/PropertiesLauncher.java

Lines changed: 8 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -70,6 +70,7 @@
7070
* @author Janne Valkealahti
7171
* @author Andy Wilkinson
7272
* @author Phillip Webb
73+
* @author Scott Frederick
7374
* @since 3.2.0
7475
*/
7576
public class PropertiesLauncher extends Launcher {
@@ -148,6 +149,7 @@ public PropertiesLauncher() throws Exception {
148149
this.homeDirectory = getHomeDirectory();
149150
initializeProperties();
150151
this.paths = getPaths();
152+
this.classPathIndex = getClassPathIndex(this.archive);
151153
}
152154

153155
protected File getHomeDirectory() throws Exception {
@@ -330,6 +332,10 @@ private String cleanupPath(String path) {
330332
@Override
331333
protected ClassLoader createClassLoader(Collection<URL> urls) throws Exception {
332334
String loaderClassName = getProperty("loader.classLoader");
335+
if (this.classPathIndex != null) {
336+
urls = new ArrayList<>(urls);
337+
urls.addAll(this.classPathIndex.getUrls());
338+
}
333339
if (loaderClassName == null) {
334340
return super.createClassLoader(urls);
335341
}
@@ -537,9 +543,9 @@ private Set<URL> getClassPathUrlsForNested(String path) throws Exception {
537543
}
538544
}
539545

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

545551
private Predicate<Entry> includeByPrefix(String prefix) {

spring-boot-project/spring-boot-tools/spring-boot-loader/src/main/java/org/springframework/boot/loader/launch/WarLauncher.java

Lines changed: 2 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -35,17 +35,13 @@ protected WarLauncher(Archive archive) throws Exception {
3535
super(archive);
3636
}
3737

38-
@Override
39-
public boolean isIncludedOnClassPath(Archive.Entry entry) {
40-
return isLibraryFileOrClassesDirectory(entry);
41-
}
42-
4338
@Override
4439
protected String getEntryPathPrefix() {
4540
return "WEB-INF/";
4641
}
4742

48-
static boolean isLibraryFileOrClassesDirectory(Archive.Entry entry) {
43+
@Override
44+
protected boolean isLibraryFileOrClassesDirectory(Archive.Entry entry) {
4945
String name = entry.name();
5046
if (entry.isDirectory()) {
5147
return name.equals("WEB-INF/classes/");
Lines changed: 7 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -24,6 +24,7 @@
2424
import java.io.Writer;
2525
import java.net.MalformedURLException;
2626
import java.net.URL;
27+
import java.net.URLClassLoader;
2728
import java.nio.charset.StandardCharsets;
2829
import java.util.Collections;
2930
import java.util.Enumeration;
@@ -40,13 +41,13 @@
4041
import org.springframework.util.FileCopyUtils;
4142

4243
/**
43-
* Base class for testing {@link ExecutableArchiveLauncher} implementations.
44+
* Base class for testing {@link Launcher} implementations.
4445
*
4546
* @author Andy Wilkinson
4647
* @author Madhura Bhave
4748
* @author Scott Frederick
4849
*/
49-
abstract class AbstractExecutableArchiveLauncherTests {
50+
abstract class AbstractLauncherTests {
5051

5152
@TempDir
5253
File tempDir;
@@ -133,4 +134,8 @@ protected final URL toUrl(File file) {
133134
}
134135
}
135136

137+
protected URLClassLoader createClassLoader(Launcher launcher) throws Exception {
138+
return (URLClassLoader) launcher.createClassLoader(launcher.getClassPathUrls());
139+
}
140+
136141
}

spring-boot-project/spring-boot-tools/spring-boot-loader/src/test/java/org/springframework/boot/loader/launch/JarLauncherTests.java

Lines changed: 1 addition & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -49,7 +49,7 @@
4949
* @author Phillip Webb
5050
*/
5151
@AssertFileChannelDataBlocksClosed
52-
class JarLauncherTests extends AbstractExecutableArchiveLauncherTests {
52+
class JarLauncherTests extends AbstractLauncherTests {
5353

5454
@Test
5555
void explodedJarHasOnlyBootInfClassesAndContentsOfBootInfLibOnClasspath() throws Exception {
@@ -115,10 +115,6 @@ void explodedJarDefinedPackagesIncludeManifestAttributes() {
115115
}));
116116
}
117117

118-
private URLClassLoader createClassLoader(JarLauncher launcher) throws Exception {
119-
return (URLClassLoader) launcher.createClassLoader(launcher.getClassPathUrls());
120-
}
121-
122118
private URL[] getExpectedFileUrls(File explodedRoot) {
123119
return getExpectedFiles(explodedRoot).stream().map(this::toUrl).toArray(URL[]::new);
124120
}

0 commit comments

Comments
 (0)