/*******************************************************************************
* Copyright (c) 2011 GigaSpaces Technologies Ltd. All rights reserved
*
* Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with
* the License. You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on
* an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the
* specific language governing permissions and limitations under the License.
*******************************************************************************/
package org.cloudifysource.dsl.internal.packaging;
import java.io.Closeable;
import java.io.File;
import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
import java.net.URI;
import java.util.Enumeration;
import java.util.Stack;
import java.util.zip.ZipEntry;
import java.util.zip.ZipFile;
import java.util.zip.ZipOutputStream;
/*********
* Static utility methods for using zip and unzip.
*
* @author barakme
* @since 1.0
*
*/
public final class ZipUtils {
private static final int BUFFER_SIZE = 1024;
private ZipUtils() {
}
/***********
* Zips a single source file into the given file.
*
* @param sourceFile
* the file to zip.
* @param zipfile
* the zip file to create.
* @throws IOException
* in case of an error.
*/
public static void zipSingleFile(final File sourceFile, final File zipfile)
throws IOException {
if (!sourceFile.exists()) {
throw new FileNotFoundException("Could not find: " + sourceFile);
}
if (!sourceFile.isFile()) {
throw new IllegalArgumentException(sourceFile + " is not a file!");
}
final File toZip = new File(zipfile, "");
toZip.setWritable(true);
final ZipOutputStream zout = new ZipOutputStream(new FileOutputStream(toZip));
try {
final String name = sourceFile.getName();
zout.putNextEntry(new ZipEntry(name));
copy(sourceFile, zout);
zout.closeEntry();
} finally {
zout.close();
}
}
/***********
* Zips a directory into the given file.
*
* @param directory
* the directory to zip.
* @param zipfile
* the zip file to create.
* @throws IOException
* in case of an error.
*/
public static void zip(final File directory, final File zipfile)
throws IOException {
final URI base = directory.toURI();
final File toZip = new File(zipfile, "");
toZip.setWritable(true);
final Stack<File> stack = new Stack<File>();
stack.push(directory);
final OutputStream out = new FileOutputStream(toZip);
Closeable res = out;
try {
final ZipOutputStream zout = new ZipOutputStream(out);
res = zout;
while (!stack.isEmpty()) {
final File currentDirectory = stack.pop();
for (final File kid : currentDirectory.listFiles()) {
String name = base.relativize(kid.toURI()).getPath();
if (kid.isDirectory()) {
stack.push(kid);
name = name.endsWith("/") ? name : name + "/";
zout.putNextEntry(new ZipEntry(name));
} else {
zout.putNextEntry(new ZipEntry(name));
copy(kid, zout);
zout.closeEntry();
}
}
}
} finally {
res.close();
}
}
/*************
* Unzip the given zip file into the specified directory.
*
* @param zipfile
* the zip file.
* @param directory
* the target directory.
* @throws IOException .
*/
public static void unzip(final File zipfile, final File directory)
throws IOException {
final ZipFile zfile = new ZipFile(zipfile);
try {
final Enumeration<? extends ZipEntry> entries = zfile.entries();
while (entries.hasMoreElements()) {
final ZipEntry entry = entries.nextElement();
final File file = new File(directory, entry.getName());
if (entry.isDirectory()) {
final boolean mkdirs = file.mkdirs();
if (!mkdirs) {
zfile.close();
throw new IllegalStateException("cant create dir" + file.getAbsolutePath());
}
} else {
if (!file.getParentFile().exists()) {
final boolean mkdirs = file.getParentFile().mkdirs();
if (!mkdirs) {
zfile.close();
throw new IllegalStateException("cant create dir" + file.getParentFile().getAbsolutePath());
}
}
final InputStream in = zfile.getInputStream(entry);
try {
copy(in, file);
} finally {
in.close();
}
}
}
} finally {
zfile.close();
}
}
/***************
* Unzips a specific entry from a zip file to a temporary directory.
*
* @param zipfile
* the zip file.
* @param entryName
* the entry to unzip.
* @param fileName
* the file name of the created file, which will be placed in a directory.
* @return the unzipped file matching the entry, or null if the entry name was not found.
* @throws IOException
* if an error occured.
*
*/
public static File unzipEntry(final File zipfile, final String entryName, final String fileName)
throws IOException {
final ZipFile zfile = new ZipFile(zipfile);
final ZipEntry entry = zfile.getEntry(entryName);
if (entry == null) {
return null;
}
final InputStream in = zfile.getInputStream(entry);
final File entryDirectory = File.createTempFile("cloudConfiguFile", ".tmp");
entryDirectory.delete();
entryDirectory.mkdirs();
final File entryFile = new File(entryDirectory, fileName);
entryFile.deleteOnExit();
entryDirectory.deleteOnExit();
try {
copy(in, entryFile);
} finally {
in.close();
}
return entryFile;
}
private static void copy(final InputStream in, final OutputStream out)
throws IOException {
final byte[] buffer = new byte[BUFFER_SIZE];
while (true) {
final int readCount = in.read(buffer);
if (readCount < 0) {
break;
}
out.write(buffer, 0, readCount);
}
}
private static void copy(final File file, final OutputStream out)
throws IOException {
final InputStream in = new FileInputStream(file);
try {
copy(in, out);
} finally {
in.close();
}
}
private static void copy(final InputStream in, final File file)
throws IOException {
final OutputStream out = new FileOutputStream(file);
try {
copy(in, out);
} finally {
out.close();
}
}
}