/*
* Copyright (C) 2012 The Android Open Source Project
*
* 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 com.motorola.studio.android.logger.collector.util;
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.util.Enumeration;
import java.util.zip.CRC32;
import java.util.zip.ZipEntry;
import java.util.zip.ZipFile;
import java.util.zip.ZipOutputStream;
/**
* Class with useful method to compact (zip) files and directories.
*/
public class ZipUtil
{
/**
* The default buffer.
*/
private static final int BUFFER = 2048;
/**
* The output file.
*/
private File outputFile = null;
/**
* This file represents the current directory.
*/
private File directory = null;
/**
* A ZipOutputStream object.
*/
private ZipOutputStream zos = null;
/**
* The path of current directory.
*/
private final String currentDirectory;
/**
* Class constructor.
*
* @param outputFile The output to create the zip file.
* @param directory The directory that will be compacted.
* @throws IOException
*/
public ZipUtil(String outputFile, String directory) throws IOException
{
this(new File(outputFile), new File(directory));
}
/**
* Class constructor.
*
* @param outputFile The file where the zip file will be created.
* @param directory The directory that will be compacted.
* @throws IOException
*/
public ZipUtil(File outputFile, File directory) throws IOException
{
this.outputFile = outputFile;
this.directory = directory;
this.currentDirectory = directory.getAbsolutePath();
}
/**
* Compact the content.
*
* @throws IOException
*/
public final void zip() throws IOException
{
FileOutputStream fos = null;
try
{
fos = new FileOutputStream(outputFile);
zos = new ZipOutputStream(fos);
zipDir(directory);
zos.flush();
}
finally
{
try
{
zos.close();
fos.close();
}
catch (IOException io)
{
io.printStackTrace();
}
}
}
/**
* Compact directory the content.
*
* @param dir The directory
* @throws IOException
*/
private final void zipDir(File dir) throws IOException
{
if (!dir.getPath().equals(currentDirectory))
{
String entryName = dir.getPath().substring(currentDirectory.length() + 1);
entryName = entryName.replace('\\', '/'); //$NON-NLS-1$ //$NON-NLS-2$
ZipEntry ze = new ZipEntry(entryName + "/"); //$NON-NLS-1$
if ((dir != null) && dir.exists())
{
ze.setTime(dir.lastModified());
}
else
{
ze.setTime(System.currentTimeMillis());
}
ze.setSize(0);
ze.setMethod(ZipEntry.STORED);
ze.setCrc(new CRC32().getValue());
zos.putNextEntry(ze);
}
if (dir.exists() && dir.isDirectory())
{
File[] fileList = dir.listFiles();
for (int i = 0; i < fileList.length; i++)
{
if (fileList[i].isDirectory())
{
zipDir(fileList[i]);
}
if (fileList[i].isFile())
{
zipFile(fileList[i]);
}
}
}
}
/**
* Compact the file content.
*
* @param file The file
* @throws IOException
*/
private void zipFile(File file) throws IOException
{
if (!file.equals(this.outputFile))
{
BufferedInputStream bis = null;
try
{
bis = new BufferedInputStream(new FileInputStream(file), BUFFER);
String entryName = file.getPath().substring(currentDirectory.length() + 1);
entryName = entryName.replace('\\', '/'); //$NON-NLS-1$ //$NON-NLS-2$
ZipEntry fileEntry = new ZipEntry(entryName);
zos.putNextEntry(fileEntry);
byte[] data = new byte[BUFFER];
int byteCount;
while ((byteCount = bis.read(data, 0, BUFFER)) != -1)
{
zos.write(data, 0, byteCount);
}
}
finally
{
bis.close();
}
}
}
/**
* Unpacks a zip file to the target directory.
*
* @param zipFilePath The zip file.
* @param destDirPath The destination directory.
* @throws IOException
*/
public static void unzip(String zipFilePath, String destDirPath) throws IOException
{
try
{
File zipFile = new File(zipFilePath);
File folder = new File(destDirPath);
ZipFile zip = new ZipFile(zipFile);
Enumeration<? extends ZipEntry> entries = zip.entries();
while (entries.hasMoreElements())
{
ZipEntry entry = entries.nextElement();
unzipEntry(zip, entry, folder);
}
}
catch (Exception e)
{
throw new RuntimeException("Error while trying to unzip jar file"); //$NON-NLS-1$
}
}
/**
* Validate and write the stream of file.
*
* @param zipFile The zip file
* @param zipEntry The zip entry
* @param folder The folder
* @throws IOException
*/
private static void unzipEntry(ZipFile zipFile, ZipEntry zipEntry, File folder)
throws IOException
{
if (zipEntry.isDirectory())
{
com.motorola.studio.android.common.utilities.FileUtil.mkdir(new File(folder, zipEntry
.getName()).getPath());
}
else
{
File outputFile = new File(folder, zipEntry.getName());
if (!outputFile.getParentFile().exists())
{
com.motorola.studio.android.common.utilities.FileUtil.mkdir(outputFile
.getParentFile().getPath());
}
BufferedInputStream is = new BufferedInputStream(zipFile.getInputStream(zipEntry));
BufferedOutputStream os = new BufferedOutputStream(new FileOutputStream(outputFile));
try
{
com.motorola.studio.android.common.utilities.FileUtil.copy(
new File(zipFile.getName()), outputFile);
}
finally
{
os.close();
is.close();
}
}
}
}