org.kalypso.commons.java.util.zip.ZipUtilities.java Source code

Java tutorial

Introduction

Here is the source code for org.kalypso.commons.java.util.zip.ZipUtilities.java

Source

/*--------------- Kalypso-Header --------------------------------------------------------------------
    
 This file is part of kalypso.
 Copyright (C) 2004, 2005 by:
    
 Technical University Hamburg-Harburg (TUHH)
 Institute of River and coastal engineering
 Denickestr. 22
 21073 Hamburg, Germany
 http://www.tuhh.de/wb
    
 and
    
 Bjoernsen Consulting Engineers (BCE)
 Maria Trost 3
 56070 Koblenz, Germany
 http://www.bjoernsen.de
    
 This library is free software; you can redistribute it and/or
 modify it under the terms of the GNU Lesser General Public
 License as published by the Free Software Foundation; either
 version 2.1 of the License, or (at your option) any later version.
    
 This library is distributed in the hope that it will be useful,
 but WITHOUT ANY WARRANTY; without even the implied warranty of
 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
 Lesser General Public License for more details.
    
 You should have received a copy of the GNU Lesser General Public
 License along with this library; if not, write to the Free Software
 Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
    
 Contact:
    
 E-Mail:
 belger@bjoernsen.de
 schlienger@bjoernsen.de
 v.doemming@tuhh.de
    
 ---------------------------------------------------------------------------------------------------*/
package org.kalypso.commons.java.util.zip;

import java.io.BufferedInputStream;
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.io.OutputStream;
import java.net.URISyntaxException;
import java.net.URL;
import java.util.ArrayList;
import java.util.Enumeration;
import java.util.List;
import java.util.zip.CRC32;
import java.util.zip.ZipEntry;
import java.util.zip.ZipException;
import java.util.zip.ZipFile;
import java.util.zip.ZipInputStream;
import java.util.zip.ZipOutputStream;

import org.apache.commons.io.IOUtils;
import org.apache.commons.io.output.NullOutputStream;
import org.apache.commons.lang3.StringUtils;
import org.apache.tools.ant.types.selectors.SelectorUtils;
import org.eclipse.core.resources.IContainer;
import org.eclipse.core.resources.IFolder;
import org.eclipse.core.resources.IResource;
import org.eclipse.core.runtime.CoreException;
import org.eclipse.core.runtime.IProgressMonitor;
import org.eclipse.core.runtime.IStatus;
import org.eclipse.core.runtime.SubProgressMonitor;
import org.kalypso.commons.KalypsoCommonsPlugin;
import org.kalypso.commons.internal.i18n.Messages;
import org.kalypso.commons.java.io.FileUtilities;
import org.kalypso.contribs.eclipse.core.runtime.StatusUtilities;

/**
 * @author belger
 */
public class ZipUtilities {
    private ZipUtilities() {
        // wird nicht instantiiert
    }

    /**
     * Unzips a stream into a directory using the apache zip classes.
     * 
     * @param zipStream
     *          Is closed after this operation.
     */
    public static void unzipApache(final InputStream zipStream, final File targetDir,
            final boolean overwriteExisting, final String encoding) throws IOException {
        final File file = File.createTempFile("unzipTmpFile", ".zip"); //$NON-NLS-1$ //$NON-NLS-2$
        file.deleteOnExit();

        OutputStream os = null;
        try {
            os = new BufferedOutputStream(new FileOutputStream(file));
            IOUtils.copy(zipStream, os);
            os.close();

            unzipApache(file, targetDir, overwriteExisting, encoding);
        } finally {
            IOUtils.closeQuietly(zipStream);
            IOUtils.closeQuietly(os);

            file.delete();
        }

    }

    /** Unzips a zip archive into a directory using the apache zip classes. */
    public static void unzipApache(final File zip, final File targetDir, final boolean overwriteExisting,
            final String encoding) throws IOException {
        org.apache.tools.zip.ZipFile file = null;
        try {
            file = new org.apache.tools.zip.ZipFile(zip, encoding);

            final Enumeration<?> entries = file.getEntries();
            while (entries.hasMoreElements()) {
                final org.apache.tools.zip.ZipEntry entry = (org.apache.tools.zip.ZipEntry) entries.nextElement();
                if (entry == null)
                    break;

                final File newfile = new File(targetDir, entry.getName());
                if (entry.isDirectory())
                    newfile.mkdirs();
                else {
                    if (!newfile.getParentFile().exists())
                        newfile.getParentFile().mkdirs();

                    OutputStream os = null;
                    InputStream zis = null;
                    try {
                        if (!overwriteExisting && newfile.exists())
                            os = new NullOutputStream();
                        else
                            os = new BufferedOutputStream(new FileOutputStream(newfile));

                        zis = file.getInputStream(entry);
                        IOUtils.copy(zis, os);
                    } finally {
                        IOUtils.closeQuietly(os);
                        IOUtils.closeQuietly(zis);
                    }
                }
            }

            file.close();
        } finally {
            if (file != null)
                file.close();
        }

    }

    public static void unzip(final File zip, final File targetdir) throws ZipException, IOException {
        InputStream zipIS = null;
        try {
            zipIS = new BufferedInputStream(new FileInputStream(zip));
            unzip(zipIS, targetdir);
        } finally {
            IOUtils.closeQuietly(zipIS);
        }
    }

    public static void unzip(final InputStream inputStream, final File targetdir) throws IOException {
        unzip(inputStream, targetdir, true);
    }

    public static void unzip(final InputStream inputStream, final String pattern, final File targetdir,
            final boolean overwriteExisting) throws IOException {
        final ZipInputStream zis = new ZipInputStream(inputStream);
        while (true) {
            final ZipEntry entry = zis.getNextEntry();
            if (entry == null)
                break;

            final String name = entry.getName();

            if (!SelectorUtils.matchPath(pattern, name))
                continue;

            final File newfile = new File(targetdir, name);

            if (entry.isDirectory())
                newfile.mkdirs();
            else {
                if (!newfile.getParentFile().exists())
                    newfile.getParentFile().mkdirs();

                OutputStream os = null;
                try {
                    if (!overwriteExisting && newfile.exists())
                        os = new NullOutputStream();
                    else
                        os = new BufferedOutputStream(new FileOutputStream(newfile));

                    IOUtils.copy(zis, os);
                } finally {
                    IOUtils.closeQuietly(os);
                }
            }
        }
    }

    /**
     * unzips a zip-stream into a target dir.
     * 
     * @param overwriteExisting
     *          if false, existing files will not be overwritten. Folders are always created.
     */
    public static void unzip(final InputStream inputStream, final File targetdir, final boolean overwriteExisting)
            throws IOException {
        final ZipInputStream zis = new ZipInputStream(inputStream);
        while (true) {
            final ZipEntry entry = zis.getNextEntry();
            if (entry == null)
                break;

            final File newfile = new File(targetdir, entry.getName());
            if (entry.isDirectory())
                newfile.mkdirs();
            else {
                if (!newfile.getParentFile().exists())
                    newfile.getParentFile().mkdirs();

                OutputStream os = null;
                try {
                    if (!overwriteExisting && newfile.exists())
                        os = new NullOutputStream();
                    else
                        os = new BufferedOutputStream(new FileOutputStream(newfile));

                    IOUtils.copy(zis, os);
                } finally {
                    IOUtils.closeQuietly(os);
                    zis.closeEntry();
                }
            }
        }
    }

    /**
     * Puts given files into a zip archive.
     * 
     * @param zipfile
     *          Target file. will be created rep. overwritten.
     * @param files
     *          The files to zip
     * @param basedir
     *          If given (i.e. != null) zipentries are genereates as relativ to this basedir (alle files must be within
     *          this dir). If null, alle ZipEntries are create with full path.
     * @throws IOException
     */
    public static void zip(final File zipfile, final File[] files, final File basedir) throws IOException {
        final FileOutputStream os = new FileOutputStream(zipfile);

        zip(os, files, basedir);
    }

    /**
     * Puts given files into a zip archive stream.
     * 
     * @param out
     *          Target output stream. will be created rep. overwritten.
     * @param files
     *          The files to zip
     * @param basedir
     *          If given (i.e. != null) zipentries are genereates as relativ to this basedir (alle files must be within
     *          this dir). If null, alle ZipEntries are create with full path.
     * @throws IOException
     */
    public static void zip(final OutputStream out, final File[] files, final File basedir) throws IOException {
        ZipOutputStream zos = null;
        try {
            zos = new ZipOutputStream(new BufferedOutputStream(out));

            for (final File file : files) {
                final String relativePathTo = FileUtilities.getRelativePathTo(basedir, file);
                writeZipEntry(zos, file, relativePathTo);
            }
        } finally {
            IOUtils.closeQuietly(zos);
        }
    }

    /**
     * @param zipfile
     *          file to write
     * @param dir
     *          dir to archive
     * @throws IOException
     */
    public static void zip(final File zipfile, final File dir) throws IOException {
        final ZipOutputStream zos = new ZipOutputStream(new BufferedOutputStream(new FileOutputStream(zipfile)));
        zip(zos, dir);
    }

    /**
     * Zip a dir into a zip-stream. the streamgets closed by this operation.
     */
    public static void zip(final ZipOutputStream zos, final File dir) throws IOException {
        final ZipFileVisitor visitor = new ZipFileVisitor(zos);
        try {
            visitor.setBasePattern(dir.getAbsolutePath());
            visitor.setBaseReplace(""); //$NON-NLS-1$
            FileUtilities.accept(dir, visitor, true);
        } finally {
            visitor.close();
        }
    }

    /**
     * Writes a single File into a Zip-Stream
     * 
     * @param pathname
     *          The name of the zip entry (relative Path into zip archive).
     */
    public static void writeZipEntry(final ZipOutputStream zos, final File file, final String pathname)
            throws IOException {
        final ZipEntry newEntry = new ZipEntry(pathname);
        zos.putNextEntry(newEntry);

        InputStream contentStream = null;

        try {
            contentStream = new BufferedInputStream(new FileInputStream(file));

            IOUtils.copy(contentStream, zos);
        } finally {
            IOUtils.closeQuietly(contentStream);
        }

        zos.closeEntry();
    }

    public static void unzip(final URL resource, final File targetDir) throws IOException {
        InputStream is = null;
        try {
            is = resource.openStream();
            unzip(is, targetDir);
            is.close();
        } finally {
            IOUtils.closeQuietly(is);
        }
    }

    /**
     * UnZIPs a ZIP archive into a {@link IContainer}.
     * 
     * @see org.eclipse.core.resources.IProjectNature#configure()
     */
    public static void unzip(final URL zipLocation, final IContainer targetContainer,
            final IProgressMonitor monitor) throws CoreException {
        monitor.beginTask(
                Messages.getString("org.kalypso.commons.java.util.zip.ZipUtilities.0") + targetContainer.getName(), //$NON-NLS-1$
                1100);

        final InputStream zipStream = null;
        try {
            /* Ensure that the container exists */
            if (!targetContainer.exists()) {
                if (targetContainer instanceof IFolder) {
                    monitor.subTask(Messages.getString("org.kalypso.commons.java.util.zip.ZipUtilities.1") //$NON-NLS-1$
                            + targetContainer.getName());
                    ((IFolder) targetContainer).create(false, true, new SubProgressMonitor(monitor, 100));
                } else
                    monitor.worked(100);
            }

            monitor.subTask(""); //$NON-NLS-1$

            final File containerDir = targetContainer.getLocation().toFile();

            // REMARK: unzipping files with non UTF-8 filename encoding is really awesome in java.
            // We do use the apache tools, which let us at least set the encoding.
            // Try and error led to use the encoding: "IBM850" for WinZippes .zip's.

            // TODO: It still doesnt work on every machine!!! @gernot: This is a test - I will remove it, if it doesnt work
            // Jessica: The test also doesnt work?!?

            // REMARK: make sure that the .zip was created with WinZIP/PKZIP instead of Eclipse-ZIP?
            ZipUtilities.unzip(zipLocation, containerDir);
            // ZipUtilities.unzipApache( zipInputStream, containerDir, false, "IBM850" );
            monitor.worked(500);
        } catch (final IOException e) {
            final IStatus status = StatusUtilities.statusFromThrowable(e);
            KalypsoCommonsPlugin.getDefault().getLog().log(status);
            throw new CoreException(status);
        } finally {
            try {
                // Never leave the container unsynchronized
                targetContainer.refreshLocal(IResource.DEPTH_INFINITE, new SubProgressMonitor(monitor, 1000));
            } finally {
                IOUtils.closeQuietly(zipStream);

                monitor.done();
            }
        }
    }

    /**
     * returns the {@link InputStream} for the first found file in the given zipped file
     */
    public static InputStream getInputStreamForFirstFile(final URL zipFileURL)
            throws IOException, URISyntaxException {
        return getInputStreamForSingleFile(zipFileURL, null);
    }

    /**
     * returns the {@link InputStream} for the file with given name in the given zipped file
     */
    public static InputStream getInputStreamForSingleFile(final URL zipFileURL, final String zippedFile)
            throws IOException, URISyntaxException {
        final ZipFile zf = new ZipFile(new File(zipFileURL.toURI()));

        final Enumeration<?> entries = zf.entries();
        while (entries.hasMoreElements()) {
            final ZipEntry ze = (ZipEntry) entries.nextElement();
            if (!ze.isDirectory()
                    && (StringUtils.isBlank(zippedFile) || zippedFile.equalsIgnoreCase(ze.getName()))) {
                final long size = ze.getSize();
                // FIXME: why this size check: dubios!
                if (size > 0) {
                    return zf.getInputStream(ze);
                }
            }
        }

        return null;
    }

    /**
     * returns the {@link InputStream} for the file with given name in the given zipped file
     */
    public static List<String> getFilesNamesFromZip(final URL zipFileURL) throws IOException, URISyntaxException {
        final ZipFile zf = new ZipFile(new File(zipFileURL.toURI()));
        List<String> listRes = new ArrayList<>();
        final Enumeration<?> entries = zf.entries();
        while (entries.hasMoreElements()) {
            final ZipEntry ze = (ZipEntry) entries.nextElement();
            if (!ze.isDirectory())
                listRes.add(ze.getName());
        }

        return listRes;
    }

    private static String convertFileName(final File packDir, final File file) {
        final String strPackDir = packDir.getAbsolutePath();
        final String strFileDir = file.getAbsolutePath();

        if (strFileDir.contains(strPackDir)) {
            String string = strFileDir.substring(strPackDir.length() + 1);

            /**
             * openOffice don't like \ in zip archives!!!
             */
            string = string.replaceAll("\\\\", "/"); //$NON-NLS-1$ //$NON-NLS-2$

            return string;
        }

        return file.getName();
    }

    public static void pack(final File archiveTarget, final File packDir) throws ZipException, IOException {
        pack(archiveTarget, packDir, new IFileFilter() {
            @Override
            public boolean accept(final File file) {
                return true;
            }
        });
    }

    public static void pack(final File archiveTarget, final File packDir, final IFileFilter filter)
            throws ZipException, IOException {
        if (!packDir.isDirectory()) {
            return;
        }

        final BufferedOutputStream bos = new BufferedOutputStream(new FileOutputStream(archiveTarget));

        final ZipOutputStream out = new ZipOutputStream(bos);
        out.setMethod(ZipOutputStream.DEFLATED);

        final File[] files = packDir.listFiles();

        for (final File file : files) {
            processFiles(packDir, file, out, filter);
        }
        out.close();

        bos.flush();
        bos.close();
    }

    private static void processFiles(final File packDir, final File file, final ZipOutputStream out,
            final IFileFilter filter) throws IOException {
        if (!filter.accept(file))
            return;

        if (file.isDirectory()) {
            final ZipEntry e = new ZipEntry(convertFileName(packDir, file) + "/"); //$NON-NLS-1$
            out.putNextEntry(e);
            out.closeEntry();

            final File[] files = file.listFiles();
            for (final File f : files) {
                processFiles(packDir, f, out, filter);
            }
        } else {

            final BufferedInputStream bis = new BufferedInputStream(new FileInputStream(file));

            final ZipEntry e = new ZipEntry(convertFileName(packDir, file));
            final CRC32 crc = new CRC32();

            out.putNextEntry(e);

            final byte[] buf = new byte[4096];
            int len = 0;

            while ((len = bis.read(buf)) > 0) {
                out.write(buf, 0, len);
                crc.update(buf, 0, len);
            }
            e.setCrc(crc.getValue());

            out.closeEntry();
            bis.close();

        }
    }

    public static void rmDir(final File dir) {
        if (!dir.isDirectory()) {
            return;
        }

        final File[] files = dir.listFiles();

        for (final File file : files) {
            if (file.isDirectory()) {
                rmDir(file);
            } else {
                file.delete();
            }
        }

        dir.delete();
    }

    private static void saveEntry(final ZipFile zf, final File targetDir, final ZipEntry target)
            throws ZipException, IOException {
        final File file = new File(targetDir.getAbsolutePath() + "/" + target.getName()); //$NON-NLS-1$

        if (target.isDirectory()) {
            file.mkdirs();
        } else {
            final InputStream is = zf.getInputStream(target);
            final BufferedInputStream bis = new BufferedInputStream(is);

            new File(file.getParent()).mkdirs();

            final FileOutputStream fos = new FileOutputStream(file);
            final BufferedOutputStream bos = new BufferedOutputStream(fos);

            final int EOF = -1;

            for (int c; (c = bis.read()) != EOF;) {
                // $ANALYSIS-IGNORE
                bos.write((byte) c);
            }

            bos.close();
            fos.close();
        }
    }

    public static void unpack(final ZipFile zf, final File targetDir) throws ZipException, IOException {
        targetDir.mkdir();

        for (final Enumeration<? extends ZipEntry> e = zf.entries(); e.hasMoreElements();) {
            final ZipEntry target = e.nextElement();
            System.out.print(target.getName() + " ."); //$NON-NLS-1$
            saveEntry(zf, targetDir, target);
            System.out.println(". unpacked"); //$NON-NLS-1$
        }
        zf.close();
    }

}