org.eclipse.jubula.tools.internal.utils.ZipUtil.java Source code

Java tutorial

Introduction

Here is the source code for org.eclipse.jubula.tools.internal.utils.ZipUtil.java

Source

/*******************************************************************************
 * Copyright (c) 2004, 2010 BREDEX GmbH.
 * All rights reserved. This program and the accompanying materials
 * are made available under the terms of the Eclipse Public License v1.0
 * which accompanies this distribution, and is available at
 * http://www.eclipse.org/legal/epl-v10.html
 *
 * Contributors:
 *     BREDEX GmbH - initial API and implementation and/or initial documentation
 *******************************************************************************/
package org.eclipse.jubula.tools.internal.utils;

import java.io.BufferedOutputStream;
import java.io.File;
import java.io.FileInputStream;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.util.ArrayList;
import java.util.Enumeration;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.zip.ZipEntry;
import java.util.zip.ZipFile;
import java.util.zip.ZipOutputStream;

import org.apache.commons.lang.StringUtils;

/**
 * This Util class contains methods to ZIP and unzip directories 
 *
 * @author BREDEX GmbH
 * @created 13.08.2010
 */
public class ZipUtil {

    /** file extension for JAR files, in lower case */
    private static final String JAR_FILE_EXT = ".jar"; //$NON-NLS-1$

    /** mapping from a ZIP file to its extracted temporary JAR files */
    private static Map<File, File[]> zipToTempJars = new HashMap<File, File[]>();

    /**
     * 
     * @author BREDEX GmbH
     * @created 23.06.2011
     */
    public static interface IZipEntryFilter {

        /**
         * 
         * @param entry The ZIP entry to filter.
         * @return <code>true</code> if the ZIP entry should be accepted.
         *         Otherwise, <code>false</code>.
         */
        public boolean accept(ZipEntry entry);

    }

    /** to prevent instantiation */
    private ZipUtil() {
        //do nothing
    }

    /**
     * This method converts a directory into a zip file
     * @param directory The directory to zip
     * @param zip The destination zip file
     * @throws IOException
     */
    public static final void zipDirectory(File directory, File zip) throws IOException {
        ZipOutputStream zos = new ZipOutputStream(new FileOutputStream(zip));
        zip(directory, directory, zos);
        zos.close();
    }

    /**
     * This method converts a directory into a zip file
     * @param directory The directory to zip
     * @param base The directory to zip
     * @param zos A ZipOutputStream
     * @throws IOException
     */
    private static final void zip(File directory, File base, ZipOutputStream zos) throws IOException {
        File[] files = directory.listFiles();
        byte[] buffer = new byte[8192];
        int read = 0;
        for (int i = 0, n = files.length; i < n; i++) {
            if (files[i].isDirectory()) {
                zip(files[i], base, zos);
            } else {
                FileInputStream in = new FileInputStream(files[i]);
                ZipEntry entry = new ZipEntry(files[i].getPath().substring(base.getPath().length() + 1));
                zos.putNextEntry(entry);
                while (-1 != (read = in.read(buffer))) {
                    zos.write(buffer, 0, read);
                }
                in.close();
            }
        }
    }

    /**
     * This method unzip's a zip file into a given folder
     * @param zip The zip file
     * @param extractTo The destination folder
     * @throws IOException
     */
    public static final void unzip(File zip, File extractTo) throws IOException {

        unzipFiles(zip, extractTo, new IZipEntryFilter() {
            public boolean accept(ZipEntry entry) {
                return true;
            }
        });
    }

    /**
     * Extracts all JAR files from the given ZIP file into temporary JAR files. 
     * The directory structure of the extracted contents is not maintained.
     * A mapping from ZIP file to extracted JARs is maintained by this class,
     * so multiple calls to this method for a single ZIP file will extract JAR 
     * files once and return references to those files for each subsequent call.
     * The extracted JAR files are deleted on VM exit.
     * @param srcZip The ZIP file to extract.
     * @return all extracted files.
     * @throws IOException
     */
    public static File[] unzipTempJars(File srcZip) throws IOException {

        if (zipToTempJars.containsKey(srcZip)) {
            return zipToTempJars.get(srcZip);
        }

        IZipEntryFilter filter = new IZipEntryFilter() {
            public boolean accept(ZipEntry entry) {
                return entry.getName().toLowerCase().endsWith(JAR_FILE_EXT);
            }
        };
        ZipFile archive = new ZipFile(srcZip);
        Enumeration e = archive.entries();
        List<File> extractedFiles = new ArrayList<File>();
        while (e.hasMoreElements()) {
            ZipEntry entry = (ZipEntry) e.nextElement();
            if (filter.accept(entry)) {
                if (!entry.isDirectory()) {
                    String prefix = entry.getName().substring(entry.getName().lastIndexOf("/") + 1, //$NON-NLS-1$
                            entry.getName().toLowerCase().lastIndexOf(JAR_FILE_EXT));
                    File file = File.createTempFile(StringUtils.rightPad(prefix, 3), JAR_FILE_EXT);
                    extractedFiles.add(file);
                    file.deleteOnExit();
                    unzipFile(archive, file, entry);
                }
            }
        }

        File[] files = extractedFiles.toArray(new File[extractedFiles.size()]);
        zipToTempJars.put(srcZip, files);
        return files;
    }

    /**
     * Unzips the contents of the given zip file into the given directory.
     * 
     * @param srcZip The zip file to extract.
     * @param targetDir The base directory for extracted files.
     * @param filter Only files accepted by this filter will be extracted.
     * @return all extracted files.
     * @throws IOException
     */
    public static File[] unzipFiles(File srcZip, File targetDir, IZipEntryFilter filter) throws IOException {

        ZipFile archive = new ZipFile(srcZip);
        Enumeration e = archive.entries();
        List<File> extractedFiles = new ArrayList<File>();
        while (e.hasMoreElements()) {
            ZipEntry entry = (ZipEntry) e.nextElement();
            if (filter.accept(entry)) {
                File file = new File(targetDir, entry.getName());
                if (entry.isDirectory() && !file.exists()) {
                    file.mkdirs();
                } else {
                    if (!file.getParentFile().exists()) {
                        file.getParentFile().mkdirs();
                    }

                    extractedFiles.add(file);
                    unzipFile(archive, file, entry);
                }
            }
        }

        return (File[]) extractedFiles.toArray();
    }

    /**
     * 
     * @param archive The zip file from which to extract.
     * @param targetFile The file to which the entry contents will be extracted.
     * @param entry The entry to extract.
     * @throws IOException
     */
    private static void unzipFile(ZipFile archive, File targetFile, ZipEntry entry) throws IOException {
        InputStream in = null;
        BufferedOutputStream out = null;
        try {
            in = archive.getInputStream(entry);
            out = new BufferedOutputStream(new FileOutputStream(targetFile));

            byte[] buffer = new byte[8192];
            int read;

            while (-1 != (read = in.read(buffer))) {
                out.write(buffer, 0, read);
            }
        } finally {
            if (in != null) {
                in.close();
            }
            if (out != null) {
                out.close();
            }
        }
    }
}