Merge branch '2.4.x' into 2.5.x
Closes gh-27056
This commit is contained in:
@@ -30,7 +30,7 @@ import java.util.Collection;
|
||||
import java.util.Enumeration;
|
||||
import java.util.HashSet;
|
||||
import java.util.Set;
|
||||
import java.util.function.Predicate;
|
||||
import java.util.function.Function;
|
||||
import java.util.jar.JarEntry;
|
||||
import java.util.jar.JarFile;
|
||||
import java.util.jar.JarInputStream;
|
||||
@@ -89,24 +89,33 @@ public abstract class AbstractJarWriter implements LoaderClassesWriter {
|
||||
* Write all entries from the specified jar file.
|
||||
* @param jarFile the source jar file
|
||||
* @throws IOException if the entries cannot be written
|
||||
* @deprecated since 2.4.8 for removal in 2.6.0
|
||||
*/
|
||||
@Deprecated
|
||||
public void writeEntries(JarFile jarFile) throws IOException {
|
||||
writeEntries(jarFile, EntryTransformer.NONE, UnpackHandler.NEVER, (name) -> false);
|
||||
writeEntries(jarFile, EntryTransformer.NONE, UnpackHandler.NEVER, (entry) -> null);
|
||||
}
|
||||
|
||||
final void writeEntries(JarFile jarFile, EntryTransformer entryTransformer, UnpackHandler unpackHandler,
|
||||
Predicate<String> libraryPredicate) throws IOException {
|
||||
Function<JarEntry, Library> libraryLookup) throws IOException {
|
||||
Enumeration<JarEntry> entries = jarFile.entries();
|
||||
while (entries.hasMoreElements()) {
|
||||
JarArchiveEntry entry = new JarArchiveEntry(entries.nextElement());
|
||||
setUpEntry(jarFile, entry);
|
||||
try (ZipHeaderPeekInputStream inputStream = new ZipHeaderPeekInputStream(jarFile.getInputStream(entry))) {
|
||||
EntryWriter entryWriter = new InputStreamEntryWriter(inputStream);
|
||||
JarArchiveEntry transformedEntry = entryTransformer.transform(entry);
|
||||
if (transformedEntry != null) {
|
||||
boolean updateLayerIndex = !libraryPredicate.test(entry.getName());
|
||||
writeEntry(transformedEntry, entryWriter, unpackHandler, updateLayerIndex);
|
||||
}
|
||||
JarEntry entry = entries.nextElement();
|
||||
Library library = libraryLookup.apply(entry);
|
||||
if (library == null || library.isIncluded()) {
|
||||
writeEntry(jarFile, entryTransformer, unpackHandler, new JarArchiveEntry(entry), library);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private void writeEntry(JarFile jarFile, EntryTransformer entryTransformer, UnpackHandler unpackHandler,
|
||||
JarArchiveEntry entry, Library library) throws IOException {
|
||||
setUpEntry(jarFile, entry);
|
||||
try (ZipHeaderPeekInputStream inputStream = new ZipHeaderPeekInputStream(jarFile.getInputStream(entry))) {
|
||||
EntryWriter entryWriter = new InputStreamEntryWriter(inputStream);
|
||||
JarArchiveEntry transformedEntry = entryTransformer.transform(entry);
|
||||
if (transformedEntry != null) {
|
||||
writeEntry(transformedEntry, library, entryWriter, unpackHandler);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -160,15 +169,7 @@ public abstract class AbstractJarWriter implements LoaderClassesWriter {
|
||||
entry.setTime(getNestedLibraryTime(library));
|
||||
new CrcAndSize(library::openStream).setupStoredEntry(entry);
|
||||
try (InputStream inputStream = library.openStream()) {
|
||||
writeEntry(entry, new InputStreamEntryWriter(inputStream), new LibraryUnpackHandler(library), false);
|
||||
updateLayerIndex(entry.getName(), library);
|
||||
}
|
||||
}
|
||||
|
||||
private void updateLayerIndex(String name, Library library) {
|
||||
if (this.layers != null) {
|
||||
Layer layer = this.layers.getLayer(library);
|
||||
this.layersIndex.add(layer, name);
|
||||
writeEntry(entry, library, new InputStreamEntryWriter(inputStream), new LibraryUnpackHandler(library));
|
||||
}
|
||||
}
|
||||
|
||||
@@ -249,20 +250,20 @@ public abstract class AbstractJarWriter implements LoaderClassesWriter {
|
||||
}
|
||||
|
||||
private void writeEntry(JarArchiveEntry entry, EntryWriter entryWriter) throws IOException {
|
||||
writeEntry(entry, entryWriter, UnpackHandler.NEVER, true);
|
||||
writeEntry(entry, null, entryWriter, UnpackHandler.NEVER);
|
||||
}
|
||||
|
||||
/**
|
||||
* Perform the actual write of a {@link JarEntry}. All other write methods delegate to
|
||||
* this one.
|
||||
* @param entry the entry to write
|
||||
* @param library the library for the entry or {@code null}
|
||||
* @param entryWriter the entry writer or {@code null} if there is no content
|
||||
* @param unpackHandler handles possible unpacking for the entry
|
||||
* @param updateLayerIndex if the layer index should be updated
|
||||
* @throws IOException in case of I/O errors
|
||||
*/
|
||||
private void writeEntry(JarArchiveEntry entry, EntryWriter entryWriter, UnpackHandler unpackHandler,
|
||||
boolean updateLayerIndex) throws IOException {
|
||||
private void writeEntry(JarArchiveEntry entry, Library library, EntryWriter entryWriter,
|
||||
UnpackHandler unpackHandler) throws IOException {
|
||||
String name = entry.getName();
|
||||
writeParentDirectoryEntries(name);
|
||||
if (this.writtenEntries.add(name)) {
|
||||
@@ -273,16 +274,14 @@ public abstract class AbstractJarWriter implements LoaderClassesWriter {
|
||||
entry.setSize(entryWriter.size());
|
||||
}
|
||||
entryWriter = addUnpackCommentIfNecessary(entry, entryWriter, unpackHandler);
|
||||
if (updateLayerIndex) {
|
||||
updateLayerIndex(entry);
|
||||
}
|
||||
updateLayerIndex(entry, library);
|
||||
writeToArchive(entry, entryWriter);
|
||||
}
|
||||
}
|
||||
|
||||
private void updateLayerIndex(JarArchiveEntry entry) {
|
||||
private void updateLayerIndex(JarArchiveEntry entry, Library library) {
|
||||
if (this.layers != null && !entry.getName().endsWith("/")) {
|
||||
Layer layer = this.layers.getLayer(entry.getName());
|
||||
Layer layer = (library != null) ? this.layers.getLayer(library) : this.layers.getLayer(entry.getName());
|
||||
this.layersIndex.add(layer, entry.getName());
|
||||
}
|
||||
}
|
||||
@@ -294,7 +293,7 @@ public abstract class AbstractJarWriter implements LoaderClassesWriter {
|
||||
while (parent.lastIndexOf('/') != -1) {
|
||||
parent = parent.substring(0, parent.lastIndexOf('/'));
|
||||
if (!parent.isEmpty()) {
|
||||
writeEntry(new JarArchiveEntry(parent + "/"), null, UnpackHandler.NEVER, false);
|
||||
writeEntry(new JarArchiveEntry(parent + "/"), null, null, UnpackHandler.NEVER);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -42,7 +42,7 @@ public class JarModeLibrary extends Library {
|
||||
}
|
||||
|
||||
public JarModeLibrary(LibraryCoordinates coordinates) {
|
||||
super(getJarName(coordinates), null, LibraryScope.RUNTIME, coordinates, false);
|
||||
super(getJarName(coordinates), null, LibraryScope.RUNTIME, coordinates, false, false, true);
|
||||
}
|
||||
|
||||
private static LibraryCoordinates createCoordinates(String artifactId) {
|
||||
|
||||
@@ -43,11 +43,16 @@ public class Library {
|
||||
|
||||
private final boolean local;
|
||||
|
||||
private final boolean included;
|
||||
|
||||
/**
|
||||
* Create a new {@link Library}.
|
||||
* @param file the source file
|
||||
* @param scope the scope of the library
|
||||
* @deprecated since 2.4.8 for removal in 2.6.0 in favor of
|
||||
* {@link #Library(String, File, LibraryScope, LibraryCoordinates, boolean, boolean, boolean)}
|
||||
*/
|
||||
@Deprecated
|
||||
public Library(File file, LibraryScope scope) {
|
||||
this(file, scope, false);
|
||||
}
|
||||
@@ -57,7 +62,10 @@ public class Library {
|
||||
* @param file the source file
|
||||
* @param scope the scope of the library
|
||||
* @param unpackRequired if the library needs to be unpacked before it can be used
|
||||
* @deprecated since 2.4.8 for removal in 2.6.0 in favor of
|
||||
* {@link #Library(String, File, LibraryScope, LibraryCoordinates, boolean, boolean, boolean)}
|
||||
*/
|
||||
@Deprecated
|
||||
public Library(File file, LibraryScope scope, boolean unpackRequired) {
|
||||
this(null, file, scope, unpackRequired);
|
||||
}
|
||||
@@ -69,7 +77,10 @@ public class Library {
|
||||
* @param file the source file
|
||||
* @param scope the scope of the library
|
||||
* @param unpackRequired if the library needs to be unpacked before it can be used
|
||||
* @deprecated since 2.4.8 for removal in 2.6.0 in favor of
|
||||
* {@link #Library(String, File, LibraryScope, LibraryCoordinates, boolean, boolean, boolean)}
|
||||
*/
|
||||
@Deprecated
|
||||
public Library(String name, File file, LibraryScope scope, boolean unpackRequired) {
|
||||
this(name, file, scope, null, unpackRequired);
|
||||
}
|
||||
@@ -82,7 +93,10 @@ public class Library {
|
||||
* @param scope the scope of the library
|
||||
* @param coordinates the library coordinates or {@code null}
|
||||
* @param unpackRequired if the library needs to be unpacked before it can be used
|
||||
* @deprecated since 2.4.8 for removal in 2.6.0 in favor of
|
||||
* {@link #Library(String, File, LibraryScope, LibraryCoordinates, boolean, boolean, boolean)}
|
||||
*/
|
||||
@Deprecated
|
||||
public Library(String name, File file, LibraryScope scope, LibraryCoordinates coordinates, boolean unpackRequired) {
|
||||
this(name, file, scope, coordinates, unpackRequired, false);
|
||||
}
|
||||
@@ -98,15 +112,37 @@ public class Library {
|
||||
* @param local if the library is local (part of the same build) to the application
|
||||
* that is being packaged
|
||||
* @since 2.4.0
|
||||
* @deprecated since 2.4.8 for removal in 2.6.0 in favor of
|
||||
* {@link #Library(String, File, LibraryScope, LibraryCoordinates, boolean, boolean, boolean)}
|
||||
*/
|
||||
@Deprecated
|
||||
public Library(String name, File file, LibraryScope scope, LibraryCoordinates coordinates, boolean unpackRequired,
|
||||
boolean local) {
|
||||
this(name, file, scope, coordinates, unpackRequired, local, true);
|
||||
}
|
||||
|
||||
/**
|
||||
* Create a new {@link Library}.
|
||||
* @param name the name of the library as it should be written or {@code null} to use
|
||||
* the file name
|
||||
* @param file the source file
|
||||
* @param scope the scope of the library
|
||||
* @param coordinates the library coordinates or {@code null}
|
||||
* @param unpackRequired if the library needs to be unpacked before it can be used
|
||||
* @param local if the library is local (part of the same build) to the application
|
||||
* that is being packaged
|
||||
* @param included if the library is included in the fat jar
|
||||
* @since 2.4.8
|
||||
*/
|
||||
public Library(String name, File file, LibraryScope scope, LibraryCoordinates coordinates, boolean unpackRequired,
|
||||
boolean local, boolean included) {
|
||||
this.name = (name != null) ? name : file.getName();
|
||||
this.file = file;
|
||||
this.scope = scope;
|
||||
this.coordinates = coordinates;
|
||||
this.unpackRequired = unpackRequired;
|
||||
this.local = local;
|
||||
this.included = included;
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -172,4 +208,12 @@ public class Library {
|
||||
return this.local;
|
||||
}
|
||||
|
||||
/**
|
||||
* Return if the library is included in the fat jar.
|
||||
* @return if the library is included
|
||||
*/
|
||||
public boolean isIncluded() {
|
||||
return this.included;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@@ -25,7 +25,9 @@ import java.util.List;
|
||||
import java.util.Map;
|
||||
import java.util.Map.Entry;
|
||||
import java.util.concurrent.TimeUnit;
|
||||
import java.util.function.Function;
|
||||
import java.util.jar.Attributes;
|
||||
import java.util.jar.JarEntry;
|
||||
import java.util.jar.JarFile;
|
||||
import java.util.jar.Manifest;
|
||||
import java.util.stream.Collectors;
|
||||
@@ -191,14 +193,18 @@ public abstract class Packager {
|
||||
|
||||
protected final void write(JarFile sourceJar, Libraries libraries, AbstractJarWriter writer) throws IOException {
|
||||
Assert.notNull(libraries, "Libraries must not be null");
|
||||
WritableLibraries writeableLibraries = new WritableLibraries(libraries);
|
||||
write(sourceJar, writer, new PackagedLibraries(libraries));
|
||||
}
|
||||
|
||||
private void write(JarFile sourceJar, AbstractJarWriter writer, PackagedLibraries libraries) throws IOException {
|
||||
if (isLayered()) {
|
||||
writer.useLayers(this.layers, this.layersIndex);
|
||||
}
|
||||
writer.writeManifest(buildManifest(sourceJar));
|
||||
writeLoaderClasses(writer);
|
||||
writer.writeEntries(sourceJar, getEntityTransformer(), writeableLibraries, writeableLibraries::containsEntry);
|
||||
writeableLibraries.write(writer);
|
||||
writer.writeEntries(sourceJar, getEntityTransformer(), libraries.getUnpackHandler(),
|
||||
libraries.getLibraryLookup());
|
||||
libraries.write(writer);
|
||||
if (isLayered()) {
|
||||
writeLayerIndex(writer);
|
||||
}
|
||||
@@ -451,11 +457,15 @@ public abstract class Packager {
|
||||
* An {@link UnpackHandler} that determines that an entry needs to be unpacked if a
|
||||
* library that requires unpacking has a matching entry name.
|
||||
*/
|
||||
private final class WritableLibraries implements UnpackHandler {
|
||||
private final class PackagedLibraries {
|
||||
|
||||
private final Map<String, Library> libraries = new LinkedHashMap<>();
|
||||
|
||||
WritableLibraries(Libraries libraries) throws IOException {
|
||||
private final UnpackHandler unpackHandler;
|
||||
|
||||
private final Function<JarEntry, Library> libraryLookup;
|
||||
|
||||
PackagedLibraries(Libraries libraries) throws IOException {
|
||||
libraries.doWithLibraries((library) -> {
|
||||
if (isZip(library::openStream)) {
|
||||
addLibrary(library);
|
||||
@@ -464,6 +474,8 @@ public abstract class Packager {
|
||||
if (isLayered() && Packager.this.includeRelevantJarModeJars) {
|
||||
addLibrary(JarModeLibrary.LAYER_TOOLS);
|
||||
}
|
||||
this.unpackHandler = new PackagedLibrariesUnpackHandler();
|
||||
this.libraryLookup = this::lookup;
|
||||
}
|
||||
|
||||
private void addLibrary(Library library) {
|
||||
@@ -475,41 +487,57 @@ public abstract class Packager {
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean requiresUnpack(String name) {
|
||||
Library library = this.libraries.get(name);
|
||||
return library != null && library.isUnpackRequired();
|
||||
private Library lookup(JarEntry entry) {
|
||||
return this.libraries.get(entry.getName());
|
||||
}
|
||||
|
||||
@Override
|
||||
public String sha1Hash(String name) throws IOException {
|
||||
Library library = this.libraries.get(name);
|
||||
Assert.notNull(library, () -> "No library found for entry name '" + name + "'");
|
||||
return Digest.sha1(library::openStream);
|
||||
UnpackHandler getUnpackHandler() {
|
||||
return this.unpackHandler;
|
||||
}
|
||||
|
||||
boolean containsEntry(String name) {
|
||||
return this.libraries.containsKey(name);
|
||||
Function<JarEntry, Library> getLibraryLookup() {
|
||||
return this.libraryLookup;
|
||||
}
|
||||
|
||||
private void write(AbstractJarWriter writer) throws IOException {
|
||||
void write(AbstractJarWriter writer) throws IOException {
|
||||
List<String> writtenPaths = new ArrayList<>();
|
||||
for (Entry<String, Library> entry : this.libraries.entrySet()) {
|
||||
String path = entry.getKey();
|
||||
Library library = entry.getValue();
|
||||
String location = path.substring(0, path.lastIndexOf('/') + 1);
|
||||
writer.writeNestedLibrary(location, library);
|
||||
if (library.isIncluded()) {
|
||||
String location = path.substring(0, path.lastIndexOf('/') + 1);
|
||||
writer.writeNestedLibrary(location, library);
|
||||
writtenPaths.add(path);
|
||||
}
|
||||
}
|
||||
if (Packager.this.layout instanceof RepackagingLayout) {
|
||||
writeClasspathIndex(getLayout(), writer);
|
||||
if (getLayout() instanceof RepackagingLayout) {
|
||||
writeClasspathIndex(writtenPaths, (RepackagingLayout) getLayout(), writer);
|
||||
}
|
||||
}
|
||||
|
||||
private void writeClasspathIndex(Layout layout, AbstractJarWriter writer) throws IOException {
|
||||
List<String> names = this.libraries.keySet().stream().map((path) -> "- \"" + path + "\"")
|
||||
.collect(Collectors.toList());
|
||||
private void writeClasspathIndex(List<String> paths, RepackagingLayout layout, AbstractJarWriter writer)
|
||||
throws IOException {
|
||||
List<String> names = paths.stream().map((path) -> "- \"" + path + "\"").collect(Collectors.toList());
|
||||
writer.writeIndexFile(layout.getClasspathIndexFileLocation(), names);
|
||||
}
|
||||
|
||||
private class PackagedLibrariesUnpackHandler implements UnpackHandler {
|
||||
|
||||
@Override
|
||||
public boolean requiresUnpack(String name) {
|
||||
Library library = PackagedLibraries.this.libraries.get(name);
|
||||
return library != null && library.isUnpackRequired();
|
||||
}
|
||||
|
||||
@Override
|
||||
public String sha1Hash(String name) throws IOException {
|
||||
Library library = PackagedLibraries.this.libraries.get(name);
|
||||
Assert.notNull(library, () -> "No library found for entry name '" + name + "'");
|
||||
return Digest.sha1(library::openStream);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@@ -197,9 +197,9 @@ abstract class AbstractPackagerTests<P extends Packager> {
|
||||
libJarFile.setLastModified(JAN_1_1980);
|
||||
P packager = createPackager();
|
||||
execute(packager, (callback) -> {
|
||||
callback.library(new Library(libJarFile, LibraryScope.COMPILE));
|
||||
callback.library(new Library(libJarFileToUnpack, LibraryScope.COMPILE, true));
|
||||
callback.library(new Library(libNonJarFile, LibraryScope.COMPILE));
|
||||
callback.library(newLibrary(libJarFile, LibraryScope.COMPILE, false));
|
||||
callback.library(newLibrary(libJarFileToUnpack, LibraryScope.COMPILE, true));
|
||||
callback.library(newLibrary(libNonJarFile, LibraryScope.COMPILE, false));
|
||||
});
|
||||
assertThat(hasPackagedEntry("BOOT-INF/lib/" + libJarFile.getName())).isTrue();
|
||||
assertThat(hasPackagedEntry("BOOT-INF/lib/" + libJarFileToUnpack.getName())).isTrue();
|
||||
@@ -226,9 +226,9 @@ abstract class AbstractPackagerTests<P extends Packager> {
|
||||
File file = this.testJarFile.getFile();
|
||||
P packager = createPackager(file);
|
||||
execute(packager, (callback) -> {
|
||||
callback.library(new Library(libJarFile1, LibraryScope.COMPILE));
|
||||
callback.library(new Library(libJarFile2, LibraryScope.COMPILE));
|
||||
callback.library(new Library(libJarFile3, LibraryScope.COMPILE));
|
||||
callback.library(newLibrary(libJarFile1, LibraryScope.COMPILE, false));
|
||||
callback.library(newLibrary(libJarFile2, LibraryScope.COMPILE, false));
|
||||
callback.library(newLibrary(libJarFile3, LibraryScope.COMPILE, false));
|
||||
});
|
||||
assertThat(hasPackagedEntry("BOOT-INF/classpath.idx")).isTrue();
|
||||
String index = getPackagedEntryContent("BOOT-INF/classpath.idx");
|
||||
@@ -258,9 +258,9 @@ abstract class AbstractPackagerTests<P extends Packager> {
|
||||
packager.setLayers(layers);
|
||||
packager.setIncludeRelevantJarModeJars(false);
|
||||
execute(packager, (callback) -> {
|
||||
callback.library(new Library(libJarFile1, LibraryScope.COMPILE));
|
||||
callback.library(new Library(libJarFile2, LibraryScope.COMPILE));
|
||||
callback.library(new Library(libJarFile3, LibraryScope.COMPILE));
|
||||
callback.library(newLibrary(libJarFile1, LibraryScope.COMPILE, false));
|
||||
callback.library(newLibrary(libJarFile2, LibraryScope.COMPILE, false));
|
||||
callback.library(newLibrary(libJarFile3, LibraryScope.COMPILE, false));
|
||||
});
|
||||
assertThat(hasPackagedEntry("BOOT-INF/classpath.idx")).isTrue();
|
||||
String classpathIndex = getPackagedEntryContent("BOOT-INF/classpath.idx");
|
||||
@@ -316,8 +316,8 @@ abstract class AbstractPackagerTests<P extends Packager> {
|
||||
this.testJarFile.addClass("a/b/C.class", ClassWithMainMethod.class);
|
||||
P packager = createPackager();
|
||||
assertThatIllegalStateException().isThrownBy(() -> execute(packager, (callback) -> {
|
||||
callback.library(new Library(libJarFile, LibraryScope.COMPILE, false));
|
||||
callback.library(new Library(libJarFile, LibraryScope.COMPILE, false));
|
||||
callback.library(newLibrary(libJarFile, LibraryScope.COMPILE, false));
|
||||
callback.library(newLibrary(libJarFile, LibraryScope.COMPILE, false));
|
||||
})).withMessageContaining("Duplicate library");
|
||||
}
|
||||
|
||||
@@ -334,7 +334,7 @@ abstract class AbstractPackagerTests<P extends Packager> {
|
||||
given(layout.getLibraryLocation(anyString(), eq(scope))).willReturn("test/");
|
||||
given(layout.getLibraryLocation(anyString(), eq(LibraryScope.COMPILE))).willReturn("test-lib/");
|
||||
packager.setLayout(layout);
|
||||
execute(packager, (callback) -> callback.library(new Library(libJarFile, scope)));
|
||||
execute(packager, (callback) -> callback.library(newLibrary(libJarFile, scope, false)));
|
||||
assertThat(hasPackagedEntry("test/" + libJarFile.getName())).isTrue();
|
||||
assertThat(getPackagedManifest().getMainAttributes().getValue("Spring-Boot-Lib")).isEqualTo("test-lib/");
|
||||
assertThat(getPackagedManifest().getMainAttributes().getValue("Main-Class")).isEqualTo("testLauncher");
|
||||
@@ -351,7 +351,7 @@ abstract class AbstractPackagerTests<P extends Packager> {
|
||||
LibraryScope scope = mock(LibraryScope.class);
|
||||
given(layout.getLauncherClassName()).willReturn("testLauncher");
|
||||
packager.setLayout(layout);
|
||||
execute(packager, (callback) -> callback.library(new Library(libJarFile, scope)));
|
||||
execute(packager, (callback) -> callback.library(newLibrary(libJarFile, scope, false)));
|
||||
assertThat(getPackagedManifest().getMainAttributes().getValue("Spring-Boot-Lib")).isNull();
|
||||
assertThat(getPackagedManifest().getMainAttributes().getValue("Main-Class")).isEqualTo("testLauncher");
|
||||
}
|
||||
@@ -405,7 +405,7 @@ abstract class AbstractPackagerTests<P extends Packager> {
|
||||
this.testJarFile.addFile("test/nested.jar", nestedFile);
|
||||
this.testJarFile.addClass("A.class", ClassWithMainMethod.class);
|
||||
P packager = createPackager();
|
||||
execute(packager, (callback) -> callback.library(new Library(nestedFile, LibraryScope.COMPILE)));
|
||||
execute(packager, (callback) -> callback.library(newLibrary(nestedFile, LibraryScope.COMPILE, false)));
|
||||
assertThat(getPackagedEntry("BOOT-INF/lib/" + nestedFile.getName()).getMethod()).isEqualTo(ZipEntry.STORED);
|
||||
assertThat(getPackagedEntry("BOOT-INF/classes/test/nested.jar").getMethod()).isEqualTo(ZipEntry.STORED);
|
||||
}
|
||||
@@ -419,7 +419,7 @@ abstract class AbstractPackagerTests<P extends Packager> {
|
||||
this.testJarFile.addFile(name, nested.getFile());
|
||||
this.testJarFile.addClass("A.class", ClassWithMainMethod.class);
|
||||
P packager = createPackager();
|
||||
execute(packager, (callback) -> callback.library(new Library(nestedFile, LibraryScope.COMPILE, true)));
|
||||
execute(packager, (callback) -> callback.library(newLibrary(nestedFile, LibraryScope.COMPILE, true)));
|
||||
assertThat(getPackagedEntry(name).getComment()).startsWith("UNPACK:");
|
||||
}
|
||||
|
||||
@@ -437,7 +437,7 @@ abstract class AbstractPackagerTests<P extends Packager> {
|
||||
File toZip = new File(this.tempDir, "to-zip");
|
||||
toZip.createNewFile();
|
||||
ZipUtil.packEntry(toZip, nestedFile);
|
||||
callback.library(new Library(nestedFile, LibraryScope.COMPILE));
|
||||
callback.library(newLibrary(nestedFile, LibraryScope.COMPILE, false));
|
||||
});
|
||||
assertThat(getPackagedEntry("BOOT-INF/lib/" + nestedFile.getName()).getSize()).isEqualTo(sourceLength);
|
||||
}
|
||||
@@ -498,14 +498,14 @@ abstract class AbstractPackagerTests<P extends Packager> {
|
||||
@Test
|
||||
void loaderIsWrittenFirstThenApplicationClassesThenLibraries() throws IOException {
|
||||
this.testJarFile.addClass("com/example/Application.class", ClassWithMainMethod.class);
|
||||
File libraryOne = createLibrary();
|
||||
File libraryTwo = createLibrary();
|
||||
File libraryThree = createLibrary();
|
||||
File libraryOne = createLibraryJar();
|
||||
File libraryTwo = createLibraryJar();
|
||||
File libraryThree = createLibraryJar();
|
||||
P packager = createPackager();
|
||||
execute(packager, (callback) -> {
|
||||
callback.library(new Library(libraryOne, LibraryScope.COMPILE, false));
|
||||
callback.library(new Library(libraryTwo, LibraryScope.COMPILE, true));
|
||||
callback.library(new Library(libraryThree, LibraryScope.COMPILE, false));
|
||||
callback.library(newLibrary(libraryOne, LibraryScope.COMPILE, false));
|
||||
callback.library(newLibrary(libraryTwo, LibraryScope.COMPILE, true));
|
||||
callback.library(newLibrary(libraryThree, LibraryScope.COMPILE, false));
|
||||
});
|
||||
assertThat(getPackagedEntryNames()).containsSubsequence("org/springframework/boot/loader/",
|
||||
"BOOT-INF/classes/com/example/Application.class", "BOOT-INF/lib/" + libraryOne.getName(),
|
||||
@@ -514,12 +514,12 @@ abstract class AbstractPackagerTests<P extends Packager> {
|
||||
|
||||
@Test
|
||||
void existingEntryThatMatchesUnpackLibraryIsMarkedForUnpack() throws IOException {
|
||||
File library = createLibrary();
|
||||
File library = createLibraryJar();
|
||||
this.testJarFile.addClass("WEB-INF/classes/com/example/Application.class", ClassWithMainMethod.class);
|
||||
this.testJarFile.addFile("WEB-INF/lib/" + library.getName(), library);
|
||||
P packager = createPackager(this.testJarFile.getFile("war"));
|
||||
packager.setLayout(new Layouts.War());
|
||||
execute(packager, (callback) -> callback.library(new Library(library, LibraryScope.COMPILE, true)));
|
||||
execute(packager, (callback) -> callback.library(newLibrary(library, LibraryScope.COMPILE, true)));
|
||||
assertThat(getPackagedEntryNames()).containsSubsequence("org/springframework/boot/loader/",
|
||||
"WEB-INF/classes/com/example/Application.class", "WEB-INF/lib/" + library.getName());
|
||||
ZipEntry unpackLibrary = getPackagedEntry("WEB-INF/lib/" + library.getName());
|
||||
@@ -536,7 +536,7 @@ abstract class AbstractPackagerTests<P extends Packager> {
|
||||
Layout layout = mock(Layout.class);
|
||||
LibraryScope scope = mock(LibraryScope.class);
|
||||
packager.setLayout(layout);
|
||||
execute(packager, (callback) -> callback.library(new Library(libJarFile, scope)));
|
||||
execute(packager, (callback) -> callback.library(newLibrary(libJarFile, scope, false)));
|
||||
assertThat(getPackagedEntryNames()).containsExactly("META-INF/", "META-INF/MANIFEST.MF", "a/", "a/b/",
|
||||
"a/b/C.class");
|
||||
}
|
||||
@@ -583,12 +583,39 @@ abstract class AbstractPackagerTests<P extends Packager> {
|
||||
assertThat(getPackagedEntry("BOOT-INF/classes/META-INF/test.kotlin_module")).isNotNull();
|
||||
}
|
||||
|
||||
private File createLibrary() throws IOException {
|
||||
@Test
|
||||
void entryFiltering() throws Exception {
|
||||
File webLibrary = createLibraryJar();
|
||||
File libraryOne = createLibraryJar();
|
||||
File libraryTwo = createLibraryJar();
|
||||
this.testJarFile.addClass("WEB-INF/classes/com/example/Application.class", ClassWithMainMethod.class);
|
||||
this.testJarFile.addFile("WEB-INF/lib/" + webLibrary.getName(), webLibrary);
|
||||
P packager = createPackager(this.testJarFile.getFile("war"));
|
||||
packager.setLayout(new Layouts.War());
|
||||
execute(packager, (callback) -> {
|
||||
callback.library(newLibrary(webLibrary, LibraryScope.COMPILE, false, false));
|
||||
callback.library(newLibrary(libraryOne, LibraryScope.COMPILE, false, false));
|
||||
callback.library(newLibrary(libraryTwo, LibraryScope.COMPILE, false, true));
|
||||
});
|
||||
Collection<String> packagedEntryNames = getPackagedEntryNames();
|
||||
packagedEntryNames.removeIf((name) -> !name.endsWith(".jar"));
|
||||
assertThat(packagedEntryNames).containsExactly("WEB-INF/lib/" + libraryTwo.getName());
|
||||
}
|
||||
|
||||
private File createLibraryJar() throws IOException {
|
||||
TestJarFile library = new TestJarFile(this.tempDir);
|
||||
library.addClass("com/example/library/Library.class", ClassWithoutMainMethod.class);
|
||||
return library.getFile();
|
||||
}
|
||||
|
||||
private Library newLibrary(File file, LibraryScope scope, boolean unpackRequired) {
|
||||
return new Library(null, file, scope, null, unpackRequired, false, true);
|
||||
}
|
||||
|
||||
private Library newLibrary(File file, LibraryScope scope, boolean unpackRequired, boolean included) {
|
||||
return new Library(null, file, scope, null, unpackRequired, false, included);
|
||||
}
|
||||
|
||||
protected final P createPackager() throws IOException {
|
||||
return createPackager(this.testJarFile.getFile());
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user