Skip to content

Commit

Permalink
Add option to repack jars using Pack200. (ceylon/ceylon-compiler#275)
Browse files Browse the repository at this point in the history
  • Loading branch information
tombentley committed May 2, 2014
1 parent be8700e commit e7d43e0
Showing 1 changed file with 49 additions and 0 deletions.
49 changes: 49 additions & 0 deletions impl/src/main/java/com/redhat/ceylon/cmr/util/JarUtils.java
Original file line number Diff line number Diff line change
@@ -1,14 +1,20 @@
package com.redhat.ceylon.cmr.util;

import java.io.File;
import java.io.FileNotFoundException;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
import java.util.Enumeration;
import java.util.Set;
import java.util.jar.JarEntry;
import java.util.jar.JarFile;
import java.util.jar.JarInputStream;
import java.util.jar.JarOutputStream;
import java.util.jar.Pack200;
import java.util.jar.Pack200.Packer;
import java.util.jar.Pack200.Unpacker;
import java.util.zip.ZipEntry;

import com.redhat.ceylon.cmr.api.ArtifactContext;
Expand All @@ -28,6 +34,13 @@ public static void finishUpdatingJar(File originalFile, File outputFile, Artifac
JarOutputStream jarOutputStream, JarEntryFilter filter,
RepositoryManager repoManager, boolean verbose, Logger log,
Set<String> folders) throws IOException {
finishUpdatingJar(originalFile, outputFile, context, jarOutputStream, filter, repoManager, verbose, log, folders, false);
}

public static void finishUpdatingJar(File originalFile, File outputFile, ArtifactContext context,
JarOutputStream jarOutputStream, JarEntryFilter filter,
RepositoryManager repoManager, boolean verbose, Logger log,
Set<String> folders, boolean pack200) throws IOException {
// now copy all previous jar entries
if (originalFile != null) {
JarFile jarFile = new JarFile(originalFile);
Expand Down Expand Up @@ -66,6 +79,11 @@ public static void finishUpdatingJar(File originalFile, File outputFile, Artifac
log.info("[done writing to jar: "+outputFile.getPath()+"]");
//Log.printLines(log.noticeWriter, "[done writing to jar: "+outputFile.getPath()+"]");
}

if (pack200) {
repack(outputFile, log);
}

File sha1File = ShaSigner.sign(outputFile, log, verbose);
try {
context.setForceOperation(true);
Expand All @@ -84,6 +102,37 @@ public static void finishUpdatingJar(File originalFile, File outputFile, Artifac
}
}

/**
* Takes the jar generated file and repacks it using pack200 in an attempt
* to reduce the file size. This is only worth doing on jars containing class files.
*/
private static void repack(File outputFile, Logger log) throws IOException,
FileNotFoundException {
Packer packer = Pack200.newPacker();
packer.properties().put(Packer.EFFORT, "9");
packer.properties().put(Packer.KEEP_FILE_ORDER, Packer.FALSE);
packer.properties().put(Packer.DEFLATE_HINT, Packer.TRUE);
packer.properties().put(Packer.SEGMENT_LIMIT, "-1");
packer.properties().put(Packer.MODIFICATION_TIME, Packer.LATEST);
File tmp = File.createTempFile("ceylon", "pack200", outputFile.getParentFile());
try {
try (OutputStream out = new FileOutputStream(tmp)) {
try (JarFile in = new JarFile(outputFile)) {
packer.pack(in, out);
}
}

try (JarOutputStream outStream = new JarOutputStream(new FileOutputStream(outputFile))) {
outStream.setLevel(9);
Unpacker unpacker = Pack200.newUnpacker();
unpacker.unpack(tmp, outStream);
}
} finally {
tmp.delete();
}
log.debug("[repacked jar: "+outputFile.getPath()+"]");
}

public static String toPlatformIndependentPath(Iterable<? extends File> sourcePaths, String prefixedSourceFile) {
String sourceFile = FileUtil.relativeFile(sourcePaths, prefixedSourceFile);
// zips are UNIX-friendly
Expand Down

3 comments on commit e7d43e0

@FroMage
Copy link
Member

@FroMage FroMage commented on e7d43e0 May 2, 2014

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

There's no way to directly generate the jar file in pack200 format? Rather than make it a second step?

@tombentley
Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Not using the Packer API in the JDK.

@FroMage
Copy link
Member

@FroMage FroMage commented on e7d43e0 May 2, 2014

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

OK.

Please sign in to comment.