package io.cattle.platform.packaging;
import java.io.ByteArrayInputStream;
import java.io.ByteArrayOutputStream;
import java.io.File;
import java.io.FileInputStream;
import java.io.FileOutputStream;
import java.io.FilterInputStream;
import java.io.IOException;
import java.io.InputStream;
import java.util.jar.Attributes;
import java.util.jar.JarEntry;
import java.util.jar.JarInputStream;
import java.util.jar.JarOutputStream;
import java.util.jar.Manifest;
import java.util.jar.Pack200;
import java.util.jar.Pack200.Packer;
import org.apache.commons.io.FileUtils;
import org.apache.commons.io.IOUtils;
public class Compress {
private static String UUID = System.getProperty("uuid", java.util.UUID.randomUUID().toString());
private static String[] EXCLUDES = new String[] { "mysql-connector-java", "mariadb-java-client" };
private static class NoCloseInputStream extends FilterInputStream {
protected NoCloseInputStream(InputStream in) {
super(in);
}
@Override
public void close() throws IOException {
}
}
protected static boolean containsSha1(Manifest m) {
if (m == null) {
return false;
}
for (Attributes attr : m.getEntries().values()) {
for (Object i : attr.values()) {
i.toString().startsWith("SHA1");
return true;
}
}
return false;
}
public static final void compressJar(InputStream is, JarEntry entry, String output, long mtime) throws IOException {
JarInputStream jis = new JarInputStream(new NoCloseInputStream(is), true);
if (containsSha1(jis.getManifest())) {
ByteArrayOutputStream baos = new ByteArrayOutputStream();
System.out.println("Stripping signature on " + entry.getName());
JarOutputStream jos = new JarOutputStream(baos);
jos.setLevel(0);
try {
JarEntry jarEntry = null;
while ((jarEntry = jis.getNextJarEntry()) != null) {
jos.putNextEntry(new JarEntry(jarEntry.getName()));
IOUtils.copy(jis, jos);
jos.closeEntry();
}
} finally {
IOUtils.closeQuietly(jos);
}
jis = new JarInputStream(new ByteArrayInputStream(baos.toByteArray()));
}
File tempOutputFile = new File(output, entry.getName() + ".pack.tmp");
File outputFile = new File(output, entry.getName() + ".pack");
if (mtime != -1 && outputFile.exists() && outputFile.lastModified() > mtime) {
System.out.println("Already up to date " + outputFile);
return;
}
FileUtils.forceMkdir(tempOutputFile.getParentFile());
System.out.println("Compressing " + entry.getName() + " to " + tempOutputFile);
FileOutputStream fos = new FileOutputStream(tempOutputFile);
try {
Packer packer = Pack200.newPacker();
packer.properties().put(Packer.DEFLATE_HINT, Packer.FALSE);
packer.properties().put(Packer.EFFORT, "9");
packer.pack(jis, fos);
} finally {
IOUtils.closeQuietly(fos);
}
if (!tempOutputFile.renameTo(outputFile)) {
throw new IOException("Failed to rename " + tempOutputFile + " to " + outputFile);
}
}
public static final void compress(String input, String output) throws IOException {
FileUtils.forceMkdir(new File(output));
FileOutputStream fis = new FileOutputStream(new File(output, "id"));
try {
fis.write(UUID.getBytes("UTF-8"));
} finally {
IOUtils.closeQuietly(fis);
}
File outputDir = new File(output);
if (!outputDir.exists() && !outputDir.mkdirs()) {
throw new IOException("Failed to create directory [" + outputDir.getAbsolutePath() + "]");
}
File resourcesFile = new File(output, "resources.jar");
JarInputStream is = new JarInputStream(new FileInputStream(input));
Manifest m = new Manifest(is.getManifest());
m.getMainAttributes().putValue("X-cattle-id", UUID);
JarOutputStream resources = new JarOutputStream(new FileOutputStream(new File(output, "resources.jar")), m);
try {
JarEntry entry = null;
while ((entry = is.getNextJarEntry()) != null) {
String name = entry.getName();
if (!exclude(name) && name.endsWith(".jar")) {
compressJar(is, entry, output, entry.getTime());
} else {
System.out.println("Adding [" + entry.getName() + "] to [" + resourcesFile.getPath() + "]");
resources.putNextEntry(entry);
IOUtils.copy(is, resources);
resources.closeEntry();
}
}
} finally {
IOUtils.closeQuietly(resources);
}
}
protected static boolean exclude(String name) {
for (String exclude : EXCLUDES) {
if (name.contains(exclude)) {
return true;
}
}
return false;
}
public static final void main(String... args) {
try {
compress(args[0], args[1]);
} catch (IOException e) {
e.printStackTrace();
System.exit(1);
}
}
}