/******************************************************************************* * Copyright 2013 Geoscience Australia * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. ******************************************************************************/ package au.gov.ga.earthsci.ant; import java.io.BufferedOutputStream; import java.io.File; import java.io.FileOutputStream; import java.io.IOException; import java.io.OutputStream; import java.util.Vector; import java.util.jar.JarFile; 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.GZIPOutputStream; import org.apache.tools.ant.BuildException; import org.apache.tools.ant.DirectoryScanner; import org.apache.tools.ant.Task; import org.apache.tools.ant.types.FileSet; /** * Ant task used to (re)pack200 JAR files. Repacking means packing and then * immediately unpacking. This is useful if you need to sign a JAR before * packing (as packing it changes the signature of the JAR file). * * @author Michael de Hoog (michael.dehoog@ga.gov.au) */ public class JarPack200 extends Task { private Vector<FileSet> filesets = new Vector<FileSet>(); private String todir; private boolean repack = false; private boolean preservelastmodified = true; private boolean force = false; public void addFileset(FileSet fileset) { filesets.add(fileset); } public void setTodir(String todir) { this.todir = todir; } public void setRepack(boolean repack) { this.repack = repack; } public void setPreservelastmodified(boolean preservelastmodified) { this.preservelastmodified = preservelastmodified; } public void setForce(boolean force) { this.force = force; } @Override public void execute() throws BuildException { Packer packer = Pack200.newPacker(); Unpacker unpacker = Pack200.newUnpacker(); File outputDir = todir == null || todir.length() == 0 ? null : new File(todir); if (outputDir != null) { outputDir.mkdirs(); } try { for (FileSet fileset : filesets) { DirectoryScanner directoryScanner = fileset.getDirectoryScanner(getProject()); String[] includedFiles = directoryScanner.getIncludedFiles(); for (String filename : includedFiles) { filename = filename.replace('\\', '/'); File base = directoryScanner.getBasedir(); File file = new File(base, filename); File parent = outputDir == null ? file.getParentFile() : outputDir; File packFile = new File(parent, getPackFilename(file)); File repackFile = new File(parent, file.getName()); File output = repack ? repackFile : packFile; long lastModified = file.lastModified(); boolean sameFile = file.equals(output); if (!force && !sameFile && output.exists() && output.lastModified() >= lastModified) { //not modified, skip continue; } System.out.println((repack ? "Re" : "") + "Pack200ing JAR: " + file + (sameFile ? "" : " to " + output)); pack(packer, file, packFile, !repack); if (repack) { unpack(unpacker, packFile, repackFile); packFile.delete(); } if (preservelastmodified) { output.setLastModified(lastModified); } } } } catch (IOException e) { throw new BuildException(e); } } private void pack(Packer packer, File input, File output, boolean gzip) throws IOException { JarFile jarFile = null; OutputStream os = null; try { jarFile = new JarFile(input); os = new FileOutputStream(output); if (gzip) { os = new GZIPOutputStream(os); } os = new BufferedOutputStream(os); packer.pack(jarFile, os); } finally { if (jarFile != null) { jarFile.close(); } if (os != null) { os.close(); } } } private void unpack(Unpacker unpacker, File input, File output) throws IOException { JarOutputStream jos = null; try { jos = new JarOutputStream(new FileOutputStream(output)); unpacker.unpack(input, jos); } finally { if (jos != null) { jos.close(); } } } private String getPackFilename(File jarFile) { String suffix = repack ? ".pack" : ".pack.gz"; return jarFile.getName() + suffix; } }