package org.eclipse.buckminster.jarprocessor; import java.io.File; import java.io.FileInputStream; import java.io.FileOutputStream; import java.io.IOException; import java.io.InputStream; import java.io.OutputStream; import java.util.List; import java.util.Map; import java.util.jar.JarFile; import java.util.zip.ZipEntry; import java.util.zip.ZipInputStream; import java.util.zip.ZipOutputStream; import org.eclipse.buckminster.core.helpers.BMProperties; import org.eclipse.buckminster.runtime.Buckminster; import org.eclipse.buckminster.runtime.BuckminsterException; import org.eclipse.buckminster.runtime.IOUtils; import org.eclipse.buckminster.runtime.Logger; import org.eclipse.core.runtime.CoreException; public class RecursiveConditioner extends RecursivePack200 { private static void emitEclipseInf(ZipOutputStream jarOut, JarInfo jarInfo, ZipEntry entry) throws IOException { jarOut.putNextEntry(entry); Map<String, String> eclipseInf = jarInfo.getEclipseInf(); eclipseInf.put(JarInfo.PROP_PACK200_CONDITIONED, "true"); //$NON-NLS-1$ BMProperties.store(eclipseInf, jarOut, "Processed using Jarprocessor"); //$NON-NLS-1$ } public RecursiveConditioner(File tempDir, List<String> defaultArgs) { super(tempDir, defaultArgs); } public boolean condition(File jarFile, File conditionedJarFile) throws CoreException { Logger log = Buckminster.getLogger(); InputStream input = null; OutputStream output = null; String fileName = jarFile.getAbsolutePath(); try { input = new ZipInputStream(new FileInputStream(jarFile)); JarInfo jarInfo = JarInfo.getJarInfo(null, fileName, (ZipInputStream) input); IOUtils.close(input); boolean condition = true; if (jarInfo.isConditioned()) { log.debug("Conditioner: skipping %s, it is already conditioned", fileName); //$NON-NLS-1$ condition = false; } else if (jarInfo.isSigned()) { log.debug("Conditioner: skipping %s, it is already signed", fileName); //$NON-NLS-1$ condition = false; } else if (jarInfo.isExcludeSign()) { log.debug("Conditioner: skipping %s, it is excluded from signing", fileName); //$NON-NLS-1$ condition = false; } else if (!(jarInfo.hasClasses() || (jarInfo.isNested() && !jarInfo.isExcludeChildrenSign()))) { log.debug("Conditioner: skipping %s, it has no classes and has no nested jars eligable for signing", fileName); //$NON-NLS-1$ condition = false; } input = new FileInputStream(jarFile); output = new FileOutputStream(conditionedJarFile); if (condition) nestedConditioning(input, jarInfo, output); else IOUtils.copy(input, output, null); return condition; } catch (IOException e) { throw BuckminsterException.fromMessage(e, "Unable to condition %s", fileName); //$NON-NLS-1$ } finally { IOUtils.close(input); IOUtils.close(output); } } private void nestedConditioning(final InputStream input, final JarInfo jarInfo, OutputStream conditioned) throws CoreException { final ProducerThread jarPumper = new ProducerThread("Pack200 jarPumper") //$NON-NLS-1$ { @Override protected void internalRun(OutputStream writer) throws Exception { ZipOutputStream jarOut = new ZipOutputStream(writer); ZipInputStream jarIn = new ZipInputStream(input); boolean metaAddingDone = false; boolean hasEclipseInf = false; ZipEntry entry; while ((entry = jarIn.getNextEntry()) != null) { String name = entry.getName(); entry = createEntry(entry); if (name.equals(META_INF + ECLIPSE_INF)) { if (hasEclipseInf) continue; emitEclipseInf(jarOut, jarInfo, entry); hasEclipseInf = true; continue; } if (entry.isDirectory()) { jarOut.putNextEntry(entry); continue; } if (name.endsWith(JAR_SUFFIX) && !jarInfo.isExcludeChildrenSign()) { JarInfo nested = jarInfo.getNestedInfo(name); if (nested != null && !(nested.isConditioned() || nested.isSigned() || nested.isExcludeSign())) { Buckminster.getLogger().debug("Conditioner: Recursive conditioning of %s", name); //$NON-NLS-1$ jarOut.putNextEntry(entry); nestedConditioning(jarIn, nested, jarOut); continue; } } jarOut.putNextEntry(entry); IOUtils.copy(jarIn, jarOut, null); if (!metaAddingDone && name.equals(JarFile.MANIFEST_NAME)) { metaAddingDone = true; if (!jarInfo.hasEclipseInf()) { // Create the eclipse.inf here so that it ends up Buckminster.getLogger().debug("Conditioner: Adding " + META_INF + ECLIPSE_INF); //$NON-NLS-1$ emitEclipseInf(jarOut, jarInfo, new ZipEntry(META_INF + ECLIPSE_INF)); hasEclipseInf = true; } } } jarOut.finish(); } }; jarPumper.start(); ProducerThread packPumper = new ProducerThread("Pack200 packPumper") //$NON-NLS-1$ { @Override protected void internalRun(OutputStream writer) throws Exception { try { pack(jarInfo, jarPumper.getReaderStream(), writer); } catch (IOException e) { jarPumper.drain(jarInfo, e); } jarPumper.drain(jarInfo, null); } }; packPumper.start(); try { unpack(new NonClosingInputStream(packPumper.getReaderStream()), conditioned); } catch (IOException e) { packPumper.drain(jarInfo, e); } packPumper.drain(jarInfo, null); } }