/*
* Zipper.java
*
*/
package org.smartly.commons.util;
import org.smartly.commons.logging.Level;
import org.smartly.commons.logging.Logger;
import org.smartly.commons.logging.util.LoggingUtils;
import java.io.*;
import java.text.SimpleDateFormat;
import java.util.*;
import java.util.zip.*;
/**
* Utility
*/
public class ZipUtils {
private ZipUtils() {
}
public static void zip(final String filename, final List<File> fileList) throws IOException {
zip(filename, fileList, true);
}
public static void zip(final String filename, final List<File> fileList,
final boolean includepaths) throws IOException {
zip(filename, fileList, includepaths, null);
}
public static void zip(final String filename, final List<File> fileList,
final boolean includepaths, final String pathtoremove) throws IOException {
final List<String> fileNames = new ArrayList<String>();
for (final File file : fileList) {
fileNames.add(file.getAbsolutePath());
}
zip(filename,
fileNames.toArray(new String[fileNames.size()]),
includepaths,
pathtoremove);
}
public static void zip(final String filename, final String[] files) throws IOException {
zip(filename, files, true, null);
}
public static void zip(final String filename, final String[] files,
final boolean includepaths) throws IOException {
zip(filename, files, includepaths, null);
}
public static void zip(final String filename, final String[] files,
final boolean includepaths, final String pathtoremove) throws IOException {
// check
final File zip = new File(filename);
if (zip.exists()) {
throw new IOException("File " + filename + " already exist.");
//return;
}
// open out file and write input files
final String[] fileNames = enumAllFilesInDirectory(files, null);
final ZipOutputStream out = new ZipOutputStream(new FileOutputStream(zip));
zip(out, fileNames, includepaths, pathtoremove);
}
public static void unzip(final String source, final String target) throws IOException {
final String targetFolder = PathUtils.isDirectory(target) ? target : PathUtils.getParent(target);
final char sep = File.separatorChar;
byte[] buff = new byte[1024];
int m;
int n;
// for each file in zip
final ZipFile zip = new ZipFile(source);
final Enumeration e = zip.entries();
while (e.hasMoreElements()) {
// get filename using local separator
final ZipEntry entry = (ZipEntry) e.nextElement();
final String entryName = PathUtils.concat(targetFolder, entry.getName());
final StringBuilder fixed = new StringBuilder(entryName);
for (int i = 0; i < fixed.length(); ++i) {
if (fixed.charAt(i) == '/') {
fixed.setCharAt(i, sep);
}
}
final File file = new File(fixed.toString());
// create dir
if (entry.isDirectory()) {
file.mkdirs();
continue;
}
final String dir = file.getParent();
if (dir != null) {
new File(dir).mkdirs();
}
// unzip file
//System.out.println("unzipping: " + file);
final OutputStream out = new FileOutputStream(file);
final InputStream in = zip.getInputStream(entry);
try {
while ((n = in.read(buff, 0, buff.length)) != -1) {
out.write(buff, 0, n);
}
} finally {
out.flush();
out.close();
in.close();
}
}
zip.close();
}
public static StringBuilder list(final String filename) throws IOException {
final StringBuilder result = new StringBuilder();
final ZipFile zip = new ZipFile(filename);
final SimpleDateFormat fmt = new SimpleDateFormat("yyyy.mm.dd hh:mm:ss");
final Enumeration e = zip.entries();
result.append(" Size | Date | Name");
result.append("\n");
result.append("-----------+---------------------+--------------------------");
result.append("\n");
while (e.hasMoreElements()) {
final ZipEntry entry = (ZipEntry) e.nextElement();
String sz = " " + entry.getSize();
sz = sz.substring(sz.length() - 10);
final String tm = fmt.format(new Date(entry.getTime()));
result.append(sz).append(" | ").append(tm).append(" | ").append(entry.getName());
result.append("\n");
}
return result;
}
public static String[] getEntryNames(final String filename) throws IOException {
final List<String> result = new LinkedList<String>();
final ZipFile zip = new ZipFile(filename);
final Enumeration e = zip.entries();
while (e.hasMoreElements()) {
final ZipEntry entry = (ZipEntry) e.nextElement();
result.add(entry.getName());
}
return result.toArray(new String[result.size()]);
}
/**
* Gzip something.
*
* @param in original content
* @return size gzipped content
*/
public static byte[] gzip(byte[] in) throws IOException {
final Logger logger = getLogger();
if (in != null && in.length > 0) {
long tstart = System.currentTimeMillis();
final ByteArrayOutputStream bout = new ByteArrayOutputStream();
GZIPOutputStream gout = new GZIPOutputStream(bout);
gout.write(in);
gout.flush();
gout.close();
if (logger.isLoggable(Level.FINE)) {
logger.log(Level.FINE, "gzipping took {0} msec",
(System.currentTimeMillis() - tstart));
}
return bout.toByteArray();
}
return new byte[0];
}
public static InputStream gzip(final InputStream in) throws IOException {
final ByteArrayOutputStream out = new ByteArrayOutputStream();
final GZIPOutputStream gout = new GZIPOutputStream(out);
int c;
while ((c = in.read()) != -1) {
gout.write(c);
}
in.close();
gout.close();
byte[] data = out.toByteArray();
return new ByteArrayInputStream(data);
}
public static byte[] gunzip(byte[] in) throws IOException {
final Logger logger = getLogger();
if (in != null && in.length > 0) {
long tstart = System.currentTimeMillis();
final ByteArrayOutputStream bout = new ByteArrayOutputStream();
final ByteArrayInputStream bin = new ByteArrayInputStream(in);
final GZIPInputStream gzipInputStream = new GZIPInputStream(bin);
byte[] buf = new byte[1024]; //size can be changed according to programmer's need.
int len;
while ((len = gzipInputStream.read(buf)) > 0) {
bout.write(buf, 0, len);
}
bout.flush();
bout.close();
if (logger.isLoggable(Level.FINE)) {
logger.log(Level.FINE, "gzipping took {0} msec",
(System.currentTimeMillis() - tstart));
}
return bout.toByteArray();
}
return new byte[0];
}
public static InputStream gunzip(final InputStream in) throws IOException {
return new GZIPInputStream(in);
}
// ------------------------------------------------------------------------
// p r i v a t e
// ------------------------------------------------------------------------
private static Logger getLogger() {
return LoggingUtils.getLogger(ZipUtils.class);
}
/**
* Enum recursively all files in directory and sub directory.
*
* @return return an array of filenames with full path.
*/
private static String[] enumAllFilesInDirectory(final String[] files, final String dir) {
final char sep = File.separatorChar;
final List<String> v = new LinkedList<String>();
for (int i = 0; i < files.length; ++i) {
final String filename = dir == null ? files[i] : dir + sep + files[i];
final File file = new File(filename);
v.add(filename);
if (file.isDirectory()) {
final String[] res = enumAllFilesInDirectory(file.list(), filename);
for (int j = 0; j < res.length; ++j) {
v.add(res[j]);
}
}
}
final String[] res = v.toArray(new String[v.size()]);
return res;
}
private static void zip(final ZipOutputStream out,
final String[] files,
boolean includepath,
final String pathtoremove) throws IOException {
InputStream in;
int n;
final byte[] buff = new byte[1024];
try {
for (final String fileName : files) {
final File file = new File(fileName);
if (file.isDirectory()) {
continue;
}
final String filePath = getPath(file, includepath, pathtoremove);
final ZipEntry entry = new ZipEntry(filePath);
out.putNextEntry(entry);
in = new FileInputStream(file);
try {
while ((n = in.read(buff, 0, buff.length)) != -1) {
out.write(buff, 0, n);
}
} finally {
try {
if (null != out) {
out.closeEntry();
}
} catch (Throwable t) {
getLogger().log(Level.SEVERE, null, t);
}
try {
if (null != in) {
in.close();
}
} catch (Throwable t) {
getLogger().log(Level.SEVERE, null, t);
}
}
}
} finally {
if (null != out) {
out.finish();
out.flush();
out.close();
}
}
}
private static String getPath(final File file,
boolean includepath,
final String pathtoremove) {
if (includepath) {
return file.getPath();
} else {
if (null == pathtoremove) {
return file.getName();
} else {
return PathUtils.subtract(pathtoremove, file.getPath());
}
}
}
}