Ensure that fat jars and wars do not corrupt UTF-8 entry names

Previously, both Repackager and the Grade plugin used the JRE's
standard ZipOutputStream when creating a fat jar or war file. This
resulted in entry names that needed UTF-8 encoding to become
corrupted.

This commit updates both to use Commons Compress'
ZipArchiveOutputStream and to configure the stream's encoding and
each entry's Unix mode. This ensures that names are encoded using
UTF-8 and can be read back in correctly by common zip tools.

Closes gh-9405
This commit is contained in:
Andy Wilkinson
2017-06-22 07:39:50 -07:00
parent 885e29934b
commit f0b7e7cf56
11 changed files with 137 additions and 54 deletions

View File

@@ -27,6 +27,8 @@ import java.util.List;
import java.util.jar.JarEntry;
import java.util.jar.JarFile;
import org.apache.commons.compress.archivers.zip.ZipArchiveEntry;
import org.apache.commons.compress.archivers.zip.ZipFile;
import org.gradle.api.Project;
import org.gradle.api.tasks.bundling.AbstractArchiveTask;
import org.gradle.api.tasks.bundling.Jar;
@@ -306,6 +308,27 @@ public abstract class AbstractBootArchiveTests<T extends Jar & BootArchive> {
}
}
@Test
public void allEntriesUseUnixPlatformAndUtf8NameEncoding() throws IOException {
this.task.setMainClass("com.example.Main");
this.task.setMetadataCharset("UTF-8");
File classpathFolder = this.temp.newFolder();
File resource = new File(classpathFolder, "some-resource.xml");
resource.getParentFile().mkdirs();
resource.createNewFile();
this.task.classpath(classpathFolder);
this.task.execute();
File archivePath = this.task.getArchivePath();
try (ZipFile zip = new ZipFile(archivePath)) {
Enumeration<ZipArchiveEntry> entries = zip.getEntries();
while (entries.hasMoreElements()) {
ZipArchiveEntry entry = entries.nextElement();
assertThat(entry.getPlatform()).isEqualTo(ZipArchiveEntry.PLATFORM_UNIX);
assertThat(entry.getGeneralPurposeBit().usesUTF8ForNames()).isTrue();
}
}
}
private T configure(T task) throws IOException {
AbstractArchiveTask archiveTask = task;
archiveTask.setBaseName("test");

View File

@@ -30,6 +30,7 @@ import javax.xml.xpath.XPathExpression;
import javax.xml.xpath.XPathFactory;
import io.spring.gradle.dependencymanagement.DependencyManagementPlugin;
import org.apache.commons.compress.archivers.ArchiveEntry;
import org.gradle.testkit.runner.BuildResult;
import org.gradle.testkit.runner.GradleRunner;
import org.junit.rules.TemporaryFolder;
@@ -114,7 +115,8 @@ public class GradleBuild implements TestRule {
+ absolutePath("build/resources/main") + ","
+ pathOfJarContaining(LaunchScript.class) + ","
+ pathOfJarContaining(ClassVisitor.class) + ","
+ pathOfJarContaining(DependencyManagementPlugin.class);
+ pathOfJarContaining(DependencyManagementPlugin.class) + ","
+ pathOfJarContaining(ArchiveEntry.class);
}
private String absolutePath(String path) {