Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -54,6 +54,13 @@ class IndexedJarStructure implements JarStructure {
private static final Set<String> ENTRY_IGNORE_LIST = Set.of("META-INF/", "META-INF/MANIFEST.MF",
"META-INF/services/java.nio.file.spi.FileSystemProvider");

/**
* Location of provided-scope dependencies in an executable war. Only
* {@code Spring-Boot-Lib} is recorded in the manifest, but the classpath index of a
* war also references this directory, as {@code WarLauncher} does when running one.
*/
private static final String WAR_PROVIDED_LIB_LOCATION = "WEB-INF/lib-provided/";

private final Manifest originalManifest;

private final String libLocation;
Expand Down Expand Up @@ -130,8 +137,13 @@ public Manifest createLauncherManifest(UnaryOperator<String> libraryTransformer)
}

private String toStructureDependency(String libEntryName) {
Assert.state(libEntryName.startsWith(this.libLocation), () -> "Invalid library location " + libEntryName);
return libEntryName.substring(this.libLocation.length());
if (libEntryName.startsWith(this.libLocation)) {
return libEntryName.substring(this.libLocation.length());
}
if (libEntryName.startsWith(WAR_PROVIDED_LIB_LOCATION)) {
return libEntryName.substring(WAR_PROVIDED_LIB_LOCATION.length());
}
throw new IllegalStateException("Invalid library location " + libEntryName);
}

private static String getMandatoryAttribute(Manifest manifest, String attribute) {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -53,6 +53,24 @@ void shouldResolveLibraryEntry() throws IOException {
assertThat(entry.type()).isEqualTo(Type.LIBRARY);
}

@Test
void shouldResolveLibraryEntryFromWarProvidedLocation() throws IOException {
IndexedJarStructure structure = createWarStructure();
Entry entry = structure.resolve("WEB-INF/lib-provided/tomcat-embed-core-10.1.19.jar");
assertThat(entry).isNotNull();
assertThat(entry.location()).isEqualTo("tomcat-embed-core-10.1.19.jar");
assertThat(entry.originalLocation()).isEqualTo("WEB-INF/lib-provided/tomcat-embed-core-10.1.19.jar");
assertThat(entry.type()).isEqualTo(Type.LIBRARY);
}

@Test
void shouldCreateLauncherManifestForWarWithProvidedLibraries() throws IOException {
IndexedJarStructure structure = createWarStructure();
Manifest manifest = structure.createLauncherManifest(UnaryOperator.identity());
assertThat(getAttributes(manifest)).containsEntry("Class-Path",
"spring-webmvc-6.1.4.jar tomcat-embed-core-10.1.19.jar");
}

@Test
void shouldResolveApplicationEntry() throws IOException {
IndexedJarStructure structure = createStructure();
Expand Down Expand Up @@ -123,6 +141,23 @@ private IndexedJarStructure createStructure() throws IOException {
return new IndexedJarStructure(createManifest(), createIndexFile());
}

private IndexedJarStructure createWarStructure() throws IOException {
Manifest manifest = new Manifest(new ByteArrayInputStream("""
Manifest-Version: 1.0
Main-Class: org.springframework.boot.loader.launch.WarLauncher
Start-Class: org.springframework.boot.jarmode.tools.IndexedJarStructureTests
Spring-Boot-Version: 3.3.0-SNAPSHOT
Spring-Boot-Classes: WEB-INF/classes/
Spring-Boot-Lib: WEB-INF/lib/
Spring-Boot-Classpath-Index: WEB-INF/classpath.idx
""".getBytes(StandardCharsets.UTF_8)));
String indexFile = """
- "WEB-INF/lib/spring-webmvc-6.1.4.jar"
- "WEB-INF/lib-provided/tomcat-embed-core-10.1.19.jar"
""";
return new IndexedJarStructure(manifest, indexFile);
}

private String createIndexFile() {
return """
- "BOOT-INF/lib/spring-webmvc-6.1.4.jar"
Expand Down
Loading