Skip to content

Commit

Permalink
Properly handle bundled server.jar
Browse files Browse the repository at this point in the history
  • Loading branch information
shartte committed Dec 14, 2024
1 parent cc2a49c commit 3394f98
Showing 1 changed file with 56 additions and 1 deletion.
Original file line number Diff line number Diff line change
Expand Up @@ -14,10 +14,14 @@
import org.gradle.api.tasks.PathSensitive;
import org.gradle.api.tasks.PathSensitivity;
import org.gradle.api.tasks.TaskAction;
import org.jetbrains.annotations.Nullable;

import java.io.BufferedOutputStream;
import java.io.File;
import java.io.FileOutputStream;
import java.io.IOException;
import java.nio.file.Files;
import java.util.ArrayList;
import java.util.HashSet;
import java.util.Set;
import java.util.jar.Attributes;
Expand Down Expand Up @@ -103,7 +107,24 @@ private static void addSourceDistEntries(Set<String> distFiles,
}
}

private static Set<String> getFileIndex(ZipFile zipFile) {
private Set<String> getFileIndex(ZipFile zipFile) throws IOException {
// Support "nested" ZIP-Files as in recent server jars
var embeddedVersionPath = readEmbeddedVersionPath(zipFile);
if (embeddedVersionPath != null) {
// Extract the embedded zip and instead index that
var versionJarEntry = zipFile.getEntry(embeddedVersionPath);
if (versionJarEntry == null) {
throw new IOException("version list in jar file " + zipFile + " refers to missing entry " + embeddedVersionPath);
}
var unbundledFile = new File(getTemporaryDir(), "unpacked.jar");
try (var in = zipFile.getInputStream(versionJarEntry)) {
Files.copy(in, unbundledFile.toPath());
}
try (ZipFile zf = new ZipFile(unbundledFile)) {
return getFileIndex(zf);
}
}

var result = new HashSet<String>(zipFile.size());

var entries = zipFile.entries();
Expand Down Expand Up @@ -134,6 +155,40 @@ private static boolean isSignatureFile(String name) {
);
}

/**
* Server jars support embedding the actual jar file using an indirection via a version listing at
* META-INF/versions.list
* This method will try to read that list and return the path to the actual jar embedded in the bundle jar.
*/
@Nullable
private static String readEmbeddedVersionPath(ZipFile zipFile) throws IOException {
var entry = zipFile.getEntry("META-INF/versions.list");
if (entry == null) {
return null;
}

var entries = new ArrayList<String>();
try (var in = zipFile.getInputStream(entry)) {
for (var line : new String(in.readAllBytes()).split("\n")) {
if (line.isBlank()) {
continue;
}
String[] pts = line.split("\t");
if (pts.length != 3)
throw new IOException("Invalid file list line: " + line + " in " + zipFile);
entries.add(pts[2]);
}
}

if (entries.isEmpty()) {
return null;
} else if (entries.size() == 1) {
return "META-INF/versions/" + entries.get(0);
} else {
throw new IOException("Version file list contains more than one entry in " + zipFile);
}
}

@InputFile
@PathSensitive(PathSensitivity.NONE)
public abstract RegularFileProperty getOriginalJar();
Expand Down

0 comments on commit 3394f98

Please sign in to comment.