package com.applang;
import static com.applang.Util.*;
import static com.applang.Util2.*;
import java.io.*;
import java.util.*;
import java.util.zip.*;
import com.applang.Util.Job;
public class ZipUtil
{
static String basePath(Object path) throws Exception {
return param_File(new File(""), 0, path).getCanonicalPath();
}
static String entryPath(Object file, String base) throws Exception {
return pathDivide(basePath(file), base);
}
public static Object[] iterateFiles(boolean includeDirs, File dir, Job<Object> job, Object...params) throws Exception {
params = reduceDepth(params);
if (dir != null && dir.isDirectory()) {
for (File file : dir.listFiles())
if (file.isDirectory())
iterateFiles(includeDirs, file, job, params);
else if (file.isFile()) {
job.perform(file, params);
Integer n = param_Integer(null, 0, params);
if (n != null)
params[0] = n + 1;
}
if (includeDirs) {
job.perform(dir, params);
Integer n = param_Integer(null, 1, params);
if (n != null)
params[1] = n + 1;
}
}
return params;
}
public static class ZipJob implements Job<Object>
{
public ZipJob(Object base) throws Exception {
this.base = basePath(base);
}
String base;
@Override
public void perform(Object o, Object[] parms) throws Exception {
File file = param_File(null, 0, o);
String path = o.toString();
if (file != null)
path = entryPath(file, base);
ZipOutputStream out = param(null, 1, parms);
ZipEntry entry = new ZipEntry(path);
entry.setTime(file.lastModified());
out.putNextEntry(entry);
// System.out.println(entry);
if (file != null) {
FileInputStream in = new FileInputStream(file);
copyContents(in, out);
in.close();
}
out.closeEntry();
}
};
public static class UnzipJob implements Job<ZipEntry>
{
public UnzipJob(Object base) throws Exception {
path = basePath(base);
}
String path;
@Override
public void perform(ZipEntry entry, Object[] parms) throws Exception {
ZipInputStream in = param(null, 0, parms);
if (in == null)
return;
File file = fileOf(path, entry.getName());
file.getParentFile().mkdirs();
file.createNewFile();
OutputStream out = new FileOutputStream(file);
copyContents(in, out);
out.close();
}
}
public static int zipArchive(Object archive, Object base, Object... params) {
int cnt = 0;
try {
ZipOutputStream out;
if (archive instanceof File)
out = new ZipOutputStream(new FileOutputStream((File)archive));
else if (archive instanceof ZipOutputStream)
out = (ZipOutputStream)archive;
else
throw new Exception("invalid archive");
ZipJob append = new ZipJob(base);
for (Object o : params) {
File file = param_File(null, 0, o);
if (file == null || !file.exists())
continue;
else if (file.isDirectory())
cnt += (Integer)iterateFiles(false, file, append, 0, out)[0];
else {
append.perform(file, new Object[] {0, out});
cnt++;
}
}
out.close();
} catch (Exception e) {
e.printStackTrace();
}
return cnt;
}
public static int unzipArchive(File archive, Job<ZipEntry> extract, boolean exclude, String... names) {
List<String> filter = asList(names);
int cnt = 0;
try {
FileInputStream stream = new FileInputStream(archive);
ZipInputStream in = new ZipInputStream(stream);
ZipEntry entry = null;
while ((entry = in.getNextEntry()) != null) {
String name = entry.getName();
if (filter.size() < 1 ||
(exclude ?
!filter.contains(name) :
filter.contains(name)))
{
extract.perform(entry, new Object[] {in});
cnt++;
}
in.closeEntry();
}
in.close();
stream.close();
} catch (Exception e) {
e.printStackTrace();
}
return cnt;
}
public static int updateArchive(File archive, Object base, int nDelete, Object... params) {
if (nDelete > params.length || nDelete < 0)
return -1;
int cnt = 0;
try {
String path = basePath(base);
ArrayList<String> filter = alist();
for (int i = 0; i < nDelete; i++)
filter.add(entryPath(params[i], path));
File temp = File.createTempFile("zip", ".zip", new File(tempPath()));
final ZipOutputStream out = new ZipOutputStream(new FileOutputStream(temp));
cnt = unzipArchive(archive, new Job<ZipEntry>() {
public void perform(ZipEntry zipEntry, Object[] parms) throws Exception {
ZipInputStream in = param(null, 0, parms);
out.putNextEntry(zipEntry);
if (!zipEntry.isDirectory())
copyContents(in, out);
}
}, true, toStrings(filter));
cnt += zipArchive(out, base,
arrayslice(params, nDelete, params.length - nDelete));
if (archive.delete())
temp.renameTo(archive);
else
throw new Exception(String.format("zip-file '%s' not updated", archive.getPath()));
} catch (Exception e) {
e.printStackTrace();
return -2;
}
return cnt;
}
}