From e5b70c10924601940632dc42a7b2e2a6c9bb2996 Mon Sep 17 00:00:00 2001 From: nik Date: Mon, 24 Dec 2012 19:57:46 +0400 Subject: [PATCH] external artifact builder: preserve compression method for entries extracted from one archive and packed into another (to fix problems with Android *.apk artifacts) --- .../artifacts/impl/JarsBuilder.java | 15 ++++-- .../JarBasedArtifactRootDescriptor.java | 6 +-- .../artifacts/ArtifactBuilderTest.java | 46 ++++++++++++++++++- 3 files changed, 57 insertions(+), 10 deletions(-) diff --git a/jps/jps-builders/src/org/jetbrains/jps/incremental/artifacts/impl/JarsBuilder.java b/jps/jps-builders/src/org/jetbrains/jps/incremental/artifacts/impl/JarsBuilder.java index 66d556db7858..2916a6b6b903 100644 --- a/jps/jps-builders/src/org/jetbrains/jps/incremental/artifacts/impl/JarsBuilder.java +++ b/jps/jps-builders/src/org/jetbrains/jps/incremental/artifacts/impl/JarsBuilder.java @@ -246,7 +246,7 @@ public class JarsBuilder { final Ref manifestRef = Ref.create(null); ((JarBasedArtifactRootDescriptor)descriptor).processEntries(new JarBasedArtifactRootDescriptor.EntryProcessor() { @Override - public void process(@Nullable InputStream inputStream, @NotNull String relativePath) throws IOException { + public void process(@Nullable InputStream inputStream, @NotNull String relativePath, ZipEntry entry) throws IOException { if (manifestRef.isNull() && relativePath.equals(manifestPath) && inputStream != null) { manifestRef.set(createManifest(inputStream, descriptor.getRootFile())); } @@ -285,7 +285,7 @@ public class JarsBuilder { final long timestamp = FileSystemUtil.lastModified(root.getRootFile()); root.processEntries(new JarBasedArtifactRootDescriptor.EntryProcessor() { @Override - public void process(@Nullable InputStream inputStream, @NotNull String relativePath) throws IOException { + public void process(@Nullable InputStream inputStream, @NotNull String relativePath, ZipEntry entry) throws IOException { String pathInJar = addParentDirectories(jarOutputStream, writtenPaths, JpsArtifactPathUtil .appendToPath(relativeOutputPath, relativePath)); @@ -293,9 +293,14 @@ public class JarsBuilder { addDirectoryEntry(jarOutputStream, pathInJar + "/", writtenPaths); } else if (writtenPaths.add(pathInJar)) { - ZipEntry entry = new ZipEntry(pathInJar); - entry.setTime(timestamp); - jarOutputStream.putNextEntry(entry); + ZipEntry newEntry = new ZipEntry(pathInJar); + newEntry.setTime(timestamp); + if (entry.getMethod() == ZipEntry.STORED) { + newEntry.setMethod(ZipEntry.STORED); + newEntry.setSize(entry.getSize()); + newEntry.setCrc(entry.getCrc()); + } + jarOutputStream.putNextEntry(newEntry); FileUtil.copy(inputStream, jarOutputStream); jarOutputStream.closeEntry(); } diff --git a/jps/jps-builders/src/org/jetbrains/jps/incremental/artifacts/instructions/JarBasedArtifactRootDescriptor.java b/jps/jps-builders/src/org/jetbrains/jps/incremental/artifacts/instructions/JarBasedArtifactRootDescriptor.java index fb3e525e21c4..7c31153b7058 100644 --- a/jps/jps-builders/src/org/jetbrains/jps/incremental/artifacts/instructions/JarBasedArtifactRootDescriptor.java +++ b/jps/jps-builders/src/org/jetbrains/jps/incremental/artifacts/instructions/JarBasedArtifactRootDescriptor.java @@ -65,7 +65,7 @@ public class JarBasedArtifactRootDescriptor extends ArtifactRootDescriptor { final String name = entry.getName(); if (name.startsWith(prefix)) { String relativePath = name.substring(prefix.length()); - processor.process(entry.isDirectory() ? null : zipFile.getInputStream(entry), relativePath); + processor.process(entry.isDirectory() ? null : zipFile.getInputStream(entry), relativePath, entry); } } } @@ -90,7 +90,7 @@ public class JarBasedArtifactRootDescriptor extends ArtifactRootDescriptor { } processEntries(new EntryProcessor() { @Override - public void process(@Nullable InputStream inputStream, @NotNull String relativePath) throws IOException { + public void process(@Nullable InputStream inputStream, @NotNull String relativePath, ZipEntry entry) throws IOException { final String fullOutputPath = FileUtil.toSystemDependentName(JpsArtifactPathUtil.appendToPath(outputPath, relativePath)); final File outputFile = new File(fullOutputPath); @@ -119,6 +119,6 @@ public class JarBasedArtifactRootDescriptor extends ArtifactRootDescriptor { } public interface EntryProcessor { - void process(@Nullable InputStream inputStream, @NotNull String relativePath) throws IOException; + void process(@Nullable InputStream inputStream, @NotNull String relativePath, ZipEntry entry) throws IOException; } } diff --git a/jps/jps-builders/testSrc/org/jetbrains/jps/incremental/artifacts/ArtifactBuilderTest.java b/jps/jps-builders/testSrc/org/jetbrains/jps/incremental/artifacts/ArtifactBuilderTest.java index b55a0b4a75ad..9179999c9000 100644 --- a/jps/jps-builders/testSrc/org/jetbrains/jps/incremental/artifacts/ArtifactBuilderTest.java +++ b/jps/jps-builders/testSrc/org/jetbrains/jps/incremental/artifacts/ArtifactBuilderTest.java @@ -23,11 +23,17 @@ import org.jetbrains.jps.model.library.JpsLibrary; import org.jetbrains.jps.model.module.JpsModule; import org.jetbrains.jps.util.JpsPathUtil; +import java.io.BufferedOutputStream; import java.io.File; +import java.io.FileOutputStream; import java.io.IOException; import java.util.Enumeration; import java.util.jar.JarEntry; import java.util.jar.JarFile; +import java.util.zip.CRC32; +import java.util.zip.ZipEntry; +import java.util.zip.ZipFile; +import java.util.zip.ZipOutputStream; import static com.intellij.util.io.TestFileSystemBuilder.fs; import static org.jetbrains.jps.incremental.artifacts.LayoutElementTestUtil.archive; @@ -294,8 +300,7 @@ public class ArtifactBuilderTest extends ArtifactBuilderTestCase { .fileCopy(firstFile).fileCopy(manifestFile).fileCopy(lastFile)); buildArtifacts(a); final String jarPath = a.getOutputPath() + "/a.jar"; - assertNotNull(jarPath); - JarFile jarFile = new JarFile(new File(FileUtil.toSystemDependentName(jarPath))); + JarFile jarFile = new JarFile(new File(jarPath)); try { final Enumeration entries = jarFile.entries(); assertTrue(entries.hasMoreElements()); @@ -307,6 +312,43 @@ public class ArtifactBuilderTest extends ArtifactBuilderTestCase { } } + public void testPreserveCompressionMethodForEntryExtractedFromOneArchiveAndPackedIntoAnother() throws IOException { + String path = createFile("data/a.jar"); + ZipOutputStream output = new ZipOutputStream(new BufferedOutputStream(new FileOutputStream(new File(path)))); + try { + ZipEntry entry = new ZipEntry("a.txt"); + byte[] text = "text".getBytes(); + entry.setMethod(ZipEntry.STORED); + entry.setSize(text.length); + CRC32 crc32 = new CRC32(); + crc32.update(text); + entry.setCrc(crc32.getValue()); + output.putNextEntry(entry); + output.write(text); + output.closeEntry(); + } + catch (Exception e) { + e.printStackTrace(); + } + finally { + output.close(); + } + JpsArtifact a = addArtifact(archive("b.jar").extractedDir(path, "")); + buildAll(); + assertOutput(a, fs().archive("b.jar").file("a.txt", "text")); + + final String jarPath = a.getOutputPath() + "/b.jar"; + ZipFile zipFile = new ZipFile(new File(jarPath)); + try { + ZipEntry entry = zipFile.getEntry("a.txt"); + assertNotNull(entry); + assertEquals(ZipEntry.STORED, entry.getMethod()); + } + finally { + zipFile.close(); + } + } + public void testBuildModuleBeforeArtifactIfSomeDirectoryInsideModuleOutputIsCopiedToArtifact() { String src = PathUtil.getParentPath(PathUtil.getParentPath(createFile("src/x/A.java", "package x; class A{}"))); JpsModule module = addModule("m", src);