Adjust fat jar central directory to account for launch script

An upgrade to Apache Commons Compress allows the build plugins to write
the launch script to the fat jar as a proper preamble, making the file
compatible with more jar and zip tooling.

Fixes gh-22336
This commit is contained in:
Scott Frederick
2021-07-19 15:02:05 -05:00
parent b5ef5a2d90
commit 9f001efa29
11 changed files with 36 additions and 46 deletions

View File

@@ -1,5 +1,5 @@
/*
* Copyright 2012-2020 the original author or authors.
* Copyright 2012-2021 the original author or authors.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
@@ -20,12 +20,7 @@ import java.io.File;
import java.io.FileNotFoundException;
import java.io.FileOutputStream;
import java.io.IOException;
import java.nio.file.Files;
import java.nio.file.Path;
import java.nio.file.attribute.FileTime;
import java.nio.file.attribute.PosixFilePermission;
import java.util.HashSet;
import java.util.Set;
import java.util.zip.ZipEntry;
import java.util.zip.ZipException;
@@ -39,6 +34,7 @@ import org.apache.commons.compress.archivers.jar.JarArchiveOutputStream;
* @author Phillip Webb
* @author Andy Wilkinson
* @author Madhura Bhave
* @author Scott Frederick
* @since 1.0.0
*/
public class JarWriter extends AbstractJarWriter implements AutoCloseable {
@@ -80,28 +76,15 @@ public class JarWriter extends AbstractJarWriter implements AutoCloseable {
*/
public JarWriter(File file, LaunchScript launchScript, FileTime lastModifiedTime)
throws FileNotFoundException, IOException {
FileOutputStream fileOutputStream = new FileOutputStream(file);
this.jarOutputStream = new JarArchiveOutputStream(new FileOutputStream(file));
if (launchScript != null) {
fileOutputStream.write(launchScript.toByteArray());
setExecutableFilePermission(file);
this.jarOutputStream.writePreamble(launchScript.toByteArray());
file.setExecutable(true);
}
this.jarOutputStream = new JarArchiveOutputStream(fileOutputStream);
this.jarOutputStream.setEncoding("UTF-8");
this.lastModifiedTime = lastModifiedTime;
}
private void setExecutableFilePermission(File file) {
try {
Path path = file.toPath();
Set<PosixFilePermission> permissions = new HashSet<>(Files.getPosixFilePermissions(path));
permissions.add(PosixFilePermission.OWNER_EXECUTE);
Files.setPosixFilePermissions(path, permissions);
}
catch (Throwable ex) {
// Ignore and continue creating the jar
}
}
@Override
protected void writeToArchive(ZipEntry entry, EntryWriter entryWriter) throws IOException {
JarArchiveEntry jarEntry = asJarArchiveEntry(entry);

View File

@@ -1,5 +1,5 @@
/*
* Copyright 2012-2020 the original author or authors.
* Copyright 2012-2021 the original author or authors.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
@@ -49,6 +49,7 @@ import static org.assertj.core.api.Assertions.assertThatIllegalArgumentException
* @author Phillip Webb
* @author Andy Wilkinson
* @author Madhura Bhave
* @author Scott Frederick
*/
class RepackagerTests extends AbstractPackagerTests<Repackager> {
@@ -159,6 +160,9 @@ class RepackagerTests extends AbstractPackagerTests<Repackager> {
assertThat(new String(bytes)).startsWith("ABC");
assertThat(hasLauncherClasses(source)).isFalse();
assertThat(hasLauncherClasses(this.destination)).isTrue();
try (ZipFile zipFile = new ZipFile(this.destination)) {
assertThat(zipFile.getEntries().hasMoreElements()).isTrue();
}
try {
assertThat(Files.getPosixFilePermissions(this.destination.toPath()))
.contains(PosixFilePermission.OWNER_EXECUTE);