/** * Copyright (c) 2009 - 2010 AppWork UG(haftungsbeschränkt) <e-mail@appwork.org> * * This file is part of org.appwork.utils.zip * * This software is licensed under the Artistic License 2.0, * see the LICENSE file or http://www.opensource.org/licenses/artistic-license-2.0.php * for details */ package org.appwork.utils.zip; import java.io.ByteArrayOutputStream; import java.io.File; import java.io.FileInputStream; import java.io.FileNotFoundException; import java.io.FileOutputStream; import java.io.IOException; import java.io.OutputStream; import java.util.zip.ZipEntry; import java.util.zip.ZipOutputStream; import org.appwork.utils.Hash; /** * @author daniel * */ public class ZipIOWriter { private ZipOutputStream zipStream = null; private OutputStream fileStream = null; private File zipFile = null; private final byte[] buf = new byte[8192]; public ZipIOWriter(final ByteArrayOutputStream stream) throws FileNotFoundException, ZipIOException { fileStream = stream; zipStream = new ZipOutputStream(fileStream); } /** * constructor for ZipIOWriter * * @param zipFile * zipFile we want create (does not overwrite existing files!) * @throws FileNotFoundException * @throws ZipIOException */ public ZipIOWriter(final File zipFile) throws FileNotFoundException, ZipIOException { this.zipFile = zipFile; openZip(false); } /** * constructor for ZipIOWriter * * @param zipFile * zipFile we want create * @param overwrite * overwrite existing ziFiles? * @throws FileNotFoundException * @throws ZipIOException */ public ZipIOWriter(final File zipFile, final boolean overwrite) throws FileNotFoundException, ZipIOException { this.zipFile = zipFile; openZip(overwrite); } /** * add given File (File or Directory) to this ZipFile * * @param add * File to add * @param compress * compress or store * @param path * customized path * @throws ZipIOException * @throws IOException */ public synchronized void add(final File add, final boolean compress, final String path) throws ZipIOException, IOException { if (add == null || !add.exists()) { throw new ZipIOException("add " + add.getAbsolutePath() + " invalid"); } if (add.isFile()) { addFileInternal(add, compress, path); } else if (add.isDirectory()) { addDirectoryInternal(add, compress, path); } else { throw new ZipIOException("add " + add.getAbsolutePath() + " invalid"); } } public synchronized void addByteArry(final byte[] data, final boolean compress, final String path, final String name) throws IOException, ZipIOException { boolean zipEntryAdded = false; try { if (data == null) { throw new ZipIOException("data array is invalid"); } final ZipEntry zipAdd = new ZipEntry((path != null && path.trim().length() > 0 ? path + "/" : "") + name); zipAdd.setSize(data.length); if (compress) { zipAdd.setMethod(ZipEntry.DEFLATED); } else { zipAdd.setMethod(ZipEntry.STORED); zipAdd.setCompressedSize(data.length); /* STORED must have a CRC32! */ zipAdd.setCrc(Hash.getCRC32(data)); } zipStream.putNextEntry(zipAdd); zipEntryAdded = true; zipStream.write(data, 0, data.length); } finally { if (zipEntryAdded) { zipStream.closeEntry(); } } } /** * add given Directory to this ZipFile * * @param addDirectory * Directory to add * @param compress * compress or store * @param path * customized path * @throws ZipIOException * @throws IOException */ public synchronized void addDirectory(final File addDirectory, final boolean compress, final String path) throws ZipIOException, IOException { addDirectoryInternal(addDirectory, compress, path); } private void addDirectoryInternal(final File addDirectory, final boolean compress, final String path) throws ZipIOException, IOException { if (addDirectory == null || !addDirectory.isDirectory() || !addDirectory.exists()) { throw new ZipIOException("addDirectory " + addDirectory.getAbsolutePath() + " invalid"); } final File[] list = addDirectory.listFiles(); if (list == null) { return; } for (final File add : list) { if (add.isFile()) { addFileInternal(add, compress, (path != null && path.trim().length() > 0 ? path + "/" : "") + addDirectory.getName()); } else if (add.isDirectory()) { addDirectoryInternal(add, compress, (path != null && path.trim().length() > 0 ? path + "/" : "") + addDirectory.getName()); } else { throw new ZipIOException("addDirectory " + addDirectory.getAbsolutePath() + " invalid"); } } } /** * Add file * * @param addFile * @param compress * @param fullPath * full path incl. filename * @throws ZipIOException * @throws IOException * @throws FileNotFoundException */ public void addFile(final File addFile, final boolean compress, final String fullPath) throws ZipIOException, IOException, FileNotFoundException { FileInputStream fin = null; boolean zipEntryAdded = false; try { if (addFile == null || !addFile.isFile() || !addFile.exists()) { throw new ZipIOException("addFile " + addFile.getAbsolutePath() + " invalid"); } final ZipEntry zipAdd = new ZipEntry(fullPath); zipAdd.setSize(addFile.length()); if (compress) { zipAdd.setMethod(ZipEntry.DEFLATED); } else { zipAdd.setMethod(ZipEntry.STORED); zipAdd.setCompressedSize(addFile.length()); /* STORED must have a CRC32! */ zipAdd.setCrc(Hash.getCRC32(addFile)); } fin = new FileInputStream(addFile); zipStream.putNextEntry(zipAdd); zipEntryAdded = true; int len; while ((len = fin.read(buf)) > 0) { zipStream.write(buf, 0, len); } } finally { if (zipEntryAdded) { zipStream.closeEntry(); } if (fin != null) { fin.close(); } } } private void addFileInternal(final File addFile, final boolean compress, final String path) throws ZipIOException, IOException { final String fullPath = (path != null && path.trim().length() > 0 ? path + "/" : "") + addFile.getName(); addFile(addFile, compress, fullPath); } /** * add given File to this ZipFile * * @param addFile * File to add * @param compress * compress or store * @param path * customized path without filename! * @throws ZipIOException * @throws IOException */ public synchronized void addFileToPath(final File addFile, final boolean compress, final String path) throws ZipIOException, IOException { addFileInternal(addFile, compress, path); } /** * closes the ZipFile * * @throws Throwable */ public synchronized void close() throws IOException { Throwable e = null; try { try { zipStream.flush(); } catch (final Throwable e2) { if (e == null) { e = e2; } } try { fileStream.flush(); } catch (final Throwable e2) { if (e == null) { e = e2; } } try { zipStream.close(); } catch (final Throwable e2) { if (e == null) { e = e2; } } try { fileStream.close(); } catch (final Throwable e2) { if (e == null) { e = e2; } } } finally { zipStream = null; fileStream = null; } if (e != null) { throw new IOException(e); } } /** * opens the zipFile for further use * * @param overwrite * overwrite existing zipFiles? * @throws ZipIOException * @throws FileNotFoundException */ private void openZip(final boolean overwrite) throws ZipIOException, FileNotFoundException { if (fileStream != null && zipStream != null) { return; } if (zipFile == null || zipFile.isDirectory()) { throw new ZipIOException("invalid zipFile"); } if (zipFile.exists() && !overwrite) { throw new ZipIOException("zipFile already exists"); } fileStream = new FileOutputStream(zipFile); zipStream = new ZipOutputStream(fileStream); } }