org.eclipse.gemini.blueprint.test.internal.util.jar.JarUtils.java Source code

Java tutorial

Introduction

Here is the source code for org.eclipse.gemini.blueprint.test.internal.util.jar.JarUtils.java

Source

/******************************************************************************
 * Copyright (c) 2006, 2010 VMware Inc.
 * All rights reserved. This program and the accompanying materials
 * are made available under the terms of the Eclipse Public License v1.0
 * and Apache License v2.0 which accompanies this distribution. 
 * The Eclipse Public License is available at 
 * http://www.eclipse.org/legal/epl-v10.html and the Apache License v2.0
 * is available at http://www.opensource.org/licenses/apache2.0.php.
 * You may elect to redistribute this code under either of these licenses. 
 * 
 * Contributors:
 *   VMware Inc.
 *****************************************************************************/

package org.eclipse.gemini.blueprint.test.internal.util.jar;

import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
import java.util.Iterator;
import java.util.Map;
import java.util.jar.JarEntry;
import java.util.jar.JarInputStream;
import java.util.jar.JarOutputStream;
import java.util.jar.Manifest;
import java.util.zip.Deflater;
import java.util.zip.ZipEntry;

import org.springframework.core.io.Resource;

/**
 * Utility class for Jar files. As opposed to {@link JarCreator}, this class is
 * stateless and contains only static methods (hence the abstract qualifier).
 * 
 * @author Costin Leau
 * 
 */
public abstract class JarUtils {

    private static final int DEFAULT_BUFFER_SIZE = 1024 * 4;

    private static final String MANIFEST_JAR_LOCATION = "/META-INF/MANIFEST.MF";

    static final String SLASH = "/";

    /**
     * Dumps the entries of a jar and return them as a String. This method can
     * be memory expensive depending on the jar size.
     * 
     * @param jis
     * @return
     * @throws Exception
     */
    public static String dumpJarContent(JarInputStream jis) {
        StringBuilder buffer = new StringBuilder();

        try {
            JarEntry entry;
            while ((entry = jis.getNextJarEntry()) != null) {
                buffer.append(entry.getName());
                buffer.append("\n");
            }
        } catch (IOException ioException) {
            buffer.append("reading from stream failed");
        } finally {
            closeStream(jis);
        }

        return buffer.toString();
    }

    /**
     * Dump the entries of a jar and return them as a String. This method can be
     * memory expensive depending on the jar size.
     * 
     * @param resource
     * @return
     */
    public static String dumpJarContent(Resource resource) {
        try {
            return dumpJarContent(new JarInputStream(resource.getInputStream()));
        } catch (IOException ex) {
            return "reading from stream failed" + ex;
        }
    }

    /**
     * Writes a resource content to a jar.
     * 
     * @param res
     * @param entryName
     * @param jarStream
     * @return the number of bytes written to the jar file
     * @throws Exception
     */
    public static int writeToJar(Resource res, String entryName, JarOutputStream jarStream) throws IOException {
        return writeToJar(res, entryName, jarStream, DEFAULT_BUFFER_SIZE);
    }

    /**
     * 
     * Writes a resource content to a jar.
     * 
     * @param res
     * @param entryName
     * @param jarStream
     * @param bufferSize
     * @return the number of bytes written to the jar file
     * @throws Exception
     */
    public static int writeToJar(Resource res, String entryName, JarOutputStream jarStream, int bufferSize)
            throws IOException {
        byte[] readWriteJarBuffer = new byte[bufferSize];

        // remove leading / if present.
        if (entryName.charAt(0) == '/')
            entryName = entryName.substring(1);

        jarStream.putNextEntry(new ZipEntry(entryName));
        InputStream entryStream = res.getInputStream();

        int numberOfBytes;

        // read data into the buffer which is later on written to the jar.
        while ((numberOfBytes = entryStream.read(readWriteJarBuffer)) != -1) {
            jarStream.write(readWriteJarBuffer, 0, numberOfBytes);
        }
        return numberOfBytes;
    }

    /**
     * Read the manifest for a given stream. The stream will be wrapped in a
     * JarInputStream and closed after the manifest was read.
     * 
     * @param stream
     * @return
     */
    public static Manifest getManifest(InputStream stream) {
        JarInputStream myStream = null;
        try {
            myStream = new JarInputStream(stream);
            return myStream.getManifest();
        } catch (IOException ioex) {
            // just ignore it
        } finally {
            closeStream(myStream);
        }

        // return (man != null ? man : new Manifest());
        return null;
    }

    /**
     * Convenience method for reading a manifest from a given resource. Will
     * assume the resource points to a jar.
     * 
     * @param resource
     * @return
     */
    public static Manifest getManifest(Resource resource) {
        try {
            return getManifest(resource.getInputStream());
        } catch (IOException ex) {
            // ignore
        }
        return null;
    }

    /**
     * Creates a jar based on the given entries and manifest. This method will
     * always close the given output stream.
     * 
     * @param manifest jar manifest
     * @param entries map of resources keyed by the jar entry named
     * @param outputStream output stream for writing the jar
     * @return number of byte written to the jar
     */
    public static int createJar(Manifest manifest, Map entries, OutputStream outputStream) throws IOException {
        int writtenBytes = 0;

        // load manifest
        // add it to the jar
        JarOutputStream jarStream = null;

        try {
            // add a jar stream on top
            jarStream = (manifest != null ? new JarOutputStream(outputStream, manifest)
                    : new JarOutputStream(outputStream));

            // select fastest level (no compression)
            jarStream.setLevel(Deflater.NO_COMPRESSION);

            // add deps
            for (Iterator iter = entries.entrySet().iterator(); iter.hasNext();) {
                Map.Entry element = (Map.Entry) iter.next();

                String entryName = (String) element.getKey();

                // safety check - all entries must start with /
                if (!entryName.startsWith(SLASH))
                    entryName = SLASH + entryName;

                Resource entryValue = (Resource) element.getValue();

                // skip special/duplicate entries (like MANIFEST.MF)
                if (MANIFEST_JAR_LOCATION.equals(entryName)) {
                    iter.remove();
                } else {
                    // write jar entry
                    writtenBytes += JarUtils.writeToJar(entryValue, entryName, jarStream);
                }
            }
        } finally {
            try {
                jarStream.flush();
            } catch (IOException ex) {
                // ignore
            }
            try {
                jarStream.finish();
            } catch (IOException ex) {
                // ignore
            }

        }

        return writtenBytes;
    }

    private static void closeStream(InputStream stream) {
        if (stream != null)
            try {
                stream.close();
            } catch (IOException ex) {
                // ignore
            }
    }
}