FileDocCategorySizeDatePackage
jlink.javaAPI DocApache Ant 1.7014941Wed Dec 13 06:16:20 GMT 2006org.apache.tools.ant.taskdefs.optional.jlink

jlink

public class jlink extends Object
jlink links together multiple .jar files.

Fields Summary
private String
outfile
private Vector
mergefiles
private Vector
addfiles
private boolean
compression
byte[]
buffer
Constructors Summary
Methods Summary
public voidaddAddFile(java.lang.String fileToAdd)
Adds a file to be added into the output.

param
fileToAdd the file to add to the output.

        if (fileToAdd == null) {
            return;
        }
        addfiles.addElement(fileToAdd);
    
public voidaddAddFiles(java.lang.String[] filesToAdd)
Adds several file to be added into the output.

param
filesToAdd an array of files to add to the output.

        if (filesToAdd == null) {
            return;
        }
        for (int i = 0; i < filesToAdd.length; i++) {
            addAddFile(filesToAdd[i]);
        }
    
private voidaddDirContents(java.util.zip.ZipOutputStream output, java.io.File dir, java.lang.String prefix, boolean compress)

        String[] contents = dir.list();

        for (int i = 0; i < contents.length; ++i) {
            String name = contents[i];
            File file = new File(dir, name);

            if (file.isDirectory()) {
                addDirContents(output, file, prefix + name + '/", compress);
            } else {
                addFile(output, file, prefix, compress);
            }
        }
    
private voidaddFile(java.util.zip.ZipOutputStream output, java.io.File file, java.lang.String prefix, boolean compress)

        //Make sure file exists
        if (!file.exists()) {
            return;
        }
        ZipEntry entry = new ZipEntry(getEntryName(file, prefix));

        entry.setTime(file.lastModified());
        entry.setSize(file.length());
        if (!compress) {
            entry.setCrc(calcChecksum(file));
        }
        FileInputStream input = new FileInputStream(file);

        addToOutputStream(output, input, entry);
    
public voidaddMergeFile(java.lang.String fileToMerge)
Adds a file to be merged into the output.

param
fileToMerge the file to merge into the output.

        if (fileToMerge == null) {
            return;
        }
        mergefiles.addElement(fileToMerge);
    
public voidaddMergeFiles(java.lang.String[] filesToMerge)
Adds several files to be merged into the output.

param
filesToMerge an array of files to merge into the output.

        if (filesToMerge == null) {
            return;
        }
        for (int i = 0; i < filesToMerge.length; i++) {
            addMergeFile(filesToMerge[i]);
        }
    
private voidaddToOutputStream(java.util.zip.ZipOutputStream output, java.io.InputStream input, java.util.zip.ZipEntry ze)

        try {
            output.putNextEntry(ze);
        } catch (ZipException zipEx) {
            //This entry already exists. So, go with the first one.
            input.close();
            return;
        }

        int numBytes = -1;

        while ((numBytes = input.read(buffer)) > 0) {
            output.write(buffer, 0, numBytes);
        }
        output.closeEntry();
        input.close();
    
private longcalcChecksum(java.io.File f)

        BufferedInputStream in = new BufferedInputStream(new FileInputStream(f));

        return calcChecksum(in);
    
private longcalcChecksum(java.io.InputStream in)

        CRC32 crc = new CRC32();
        int len = buffer.length;
        int count = -1;
        int haveRead = 0;

        while ((count = in.read(buffer, 0, len)) > 0) {
            haveRead += count;
            crc.update(buffer, 0, count);
        }
        in.close();
        return crc.getValue();
    
private java.lang.StringgetEntryName(java.io.File file, java.lang.String prefix)

        String name = file.getName();

        if (!name.endsWith(".class")) {
            // see if the file is in fact a .class file, and determine its actual name.
            InputStream input = null;
            try {
                input = new FileInputStream(file);
                String className = ClassNameReader.getClassName(input);

                if (className != null) {
                    return className.replace('.", '/") + ".class";
                }
            } catch (IOException ioe) {
                //do nothing
            } finally {
                if (input != null) {
                    try {
                        input.close();
                    } catch (IOException e) {
                        //do nothing
                    }
                }
            }
        }
        System.out.println("From " + file.getPath() + " and prefix " + prefix
                           + ", creating entry " + prefix + name);
        return (prefix + name);
    
public voidlink()
Performs the linking of files. Addfiles are added to the output as-is. For example, a jar file is added to the output as a jar file. However, mergefiles are first examined for their type. If it is a jar or zip file, the contents will be extracted from the mergefile and entered into the output. If a zip or jar file is encountered in a subdirectory it will be added, not merged. If a directory is encountered, it becomes the root entry of all the files below it. Thus, you can provide multiple, disjoint directories, as addfiles: they will all be added in a rational manner to outfile.

throws
Exception on error.

        ZipOutputStream output = new ZipOutputStream(new FileOutputStream(outfile));

        if (compression) {
            output.setMethod(ZipOutputStream.DEFLATED);
            output.setLevel(Deflater.DEFAULT_COMPRESSION);
        } else {
            output.setMethod(ZipOutputStream.STORED);
        }

        Enumeration merges = mergefiles.elements();

        while (merges.hasMoreElements()) {
            String path = (String) merges.nextElement();
            File f = new File(path);

            if (f.getName().endsWith(".jar") || f.getName().endsWith(".zip")) {
                //Do the merge
                mergeZipJarContents(output, f);
            } else {
                //Add this file to the addfiles Vector and add it
                //later at the top level of the output file.
                addAddFile(path);
            }
        }

        Enumeration adds = addfiles.elements();

        while (adds.hasMoreElements()) {
            String name = (String) adds.nextElement();
            File f = new File(name);

            if (f.isDirectory()) {
                //System.out.println("in jlink: adding directory contents of " + f.getPath());
                addDirContents(output, f, f.getName() + '/", compression);
            } else {
                addFile(output, f, "", compression);
            }
        }
        if (output != null) {
            try {
                output.close();
            } catch (IOException ioe) {
                //do nothing
            }
        }
    
public static voidmain(java.lang.String[] args)
The command line entry point for jlink.

param
args an array of arguments

        // jlink output input1 ... inputN
        if (args.length < 2) {
            System.out.println("usage: jlink output input1 ... inputN");
            System.exit(1);
        }
        jlink linker = new jlink();

        linker.setOutfile(args[0]);
        // To maintain compatibility with the command-line version,
        // we will only add files to be merged.
        for (int i = 1; i < args.length; i++) {
            linker.addMergeFile(args[i]);
        }
        try {
            linker.link();
        } catch (Exception ex) {
            System.err.print(ex.getMessage());
        }
    
private voidmergeZipJarContents(java.util.zip.ZipOutputStream output, java.io.File f)

        //Check to see that the file with name "name" exists.
        if (!f.exists()) {
            return;
        }
        ZipFile zipf = new ZipFile(f);
        Enumeration entries = zipf.entries();

        while (entries.hasMoreElements()) {
            ZipEntry inputEntry = (ZipEntry) entries.nextElement();
            //Ignore manifest entries.  They're bound to cause conflicts between
            //files that are being merged.  User should supply their own
            //manifest file when doing the merge.
            String inputEntryName = inputEntry.getName();
            int index = inputEntryName.indexOf("META-INF");

            if (index < 0) {
                //META-INF not found in the name of the entry. Go ahead and process it.
                try {
                    output.putNextEntry(processEntry(zipf, inputEntry));
                } catch (ZipException ex) {
                    //If we get here, it could be because we are trying to put a
                    //directory entry that already exists.
                    //For example, we're trying to write "com", but a previous
                    //entry from another mergefile was called "com".
                    //In that case, just ignore the error and go on to the
                    //next entry.
                    String mess = ex.getMessage();

                    if (mess.indexOf("duplicate") >= 0) {
                        //It was the duplicate entry.
                        continue;
                    } else {
                        // I hate to admit it, but we don't know what happened
                        // here.  Throw the Exception.
                        throw ex;
                    }
                }

                InputStream in = zipf.getInputStream(inputEntry);
                int len = buffer.length;
                int count = -1;

                while ((count = in.read(buffer, 0, len)) > 0) {
                    output.write(buffer, 0, count);
                }
                in.close();
                output.closeEntry();
            }
        }
        zipf.close();
    
private java.util.zip.ZipEntryprocessEntry(java.util.zip.ZipFile zip, java.util.zip.ZipEntry inputEntry)

        /*
          First, some notes.
          On MRJ 2.2.2, getting the size, compressed size, and CRC32 from the
          ZipInputStream does not work for compressed (deflated) files.  Those calls return -1.
          For uncompressed (stored) files, those calls do work.
          However, using ZipFile.getEntries() works for both compressed and
          uncompressed files.

          Now, from some simple testing I did, it seems that the value of CRC-32 is
          independent of the compression setting. So, it should be easy to pass this
          information on to the output entry.
        */
        String name = inputEntry.getName();

        if (!(inputEntry.isDirectory() || name.endsWith(".class"))) {
            try {
                InputStream input = zip.getInputStream(zip.getEntry(name));
                String className = ClassNameReader.getClassName(input);

                input.close();
                if (className != null) {
                    name = className.replace('.", '/") + ".class";
                }
            } catch (IOException ioe) {
                //do nothing
            }
        }
        ZipEntry outputEntry = new ZipEntry(name);

        outputEntry.setTime(inputEntry.getTime());
        outputEntry.setExtra(inputEntry.getExtra());
        outputEntry.setComment(inputEntry.getComment());
        outputEntry.setTime(inputEntry.getTime());
        if (compression) {
            outputEntry.setMethod(ZipEntry.DEFLATED);
            //Note, don't need to specify size or crc for compressed files.
        } else {
            outputEntry.setMethod(ZipEntry.STORED);
            outputEntry.setCrc(inputEntry.getCrc());
            outputEntry.setSize(inputEntry.getSize());
        }
        return outputEntry;
    
public voidsetCompression(boolean compress)
Determines whether output will be compressed.

param
compress if true use compression.

        this.compression = compress;
    
public voidsetOutfile(java.lang.String outfile)
The file that will be created by this instance of jlink.

param
outfile the file to create.


    // CheckStyle:VisibilityModifier OFF - bc

                          
        
        if (outfile == null) {
            return;
        }
        this.outfile = outfile;