package org.myrobotlab.io;
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.io.InputStream;
import java.io.OutputStream;
import java.net.URISyntaxException;
import java.util.ArrayList;
import java.util.Enumeration;
import java.util.zip.ZipEntry;
import java.util.zip.ZipException;
import java.util.zip.ZipFile;
import java.util.zip.ZipInputStream;
import org.myrobotlab.logging.Level;
import org.myrobotlab.logging.LoggerFactory;
import org.myrobotlab.logging.LoggingFactory;
import org.slf4j.Logger;
public class Zip {
final public static String RESOURCE = "RESOURCE";
final public static String FILE = "FILE";
static int BUFFER_SIZE = 2048;
public final static Logger log = LoggerFactory.getLogger(Zip.class);
public static int countOccurrences(String haystack, char needle) {
int count = 0;
for (int i = 0; i < haystack.length(); i++) {
if (haystack.charAt(i) == needle) {
count++;
}
}
return count;
}
static public void extract(String resourcePath, String targetDirectory, String filter, String resourceType, boolean overwrite) throws IOException {
if (targetDirectory != null) {
if (!"/".equals(targetDirectory.substring(targetDirectory.length() - 1))) {
targetDirectory = targetDirectory + "/";
}
}
log.debug(String.format("extract (%s, %s, %s, %s, %b)", resourcePath, targetDirectory, filter, resourceType, overwrite));
// String filter = "resource/";
InputStream source = null;
if (FILE.equals(resourceType)) {
File check = new File(resourcePath);
if (!check.exists() || check.isDirectory()){
log.error("cannot extract self [{}]", resourcePath);
return;
}
source = new FileInputStream(resourcePath);
} else {
source = ClassLoader.class.getResourceAsStream(resourcePath);
}
File target = new File(targetDirectory);
if (!target.exists() && !target.mkdirs()) {
throw new RuntimeException("Unable to create directory " + target.getAbsolutePath());
}
ZipInputStream in = new ZipInputStream(source);
try {
byte[] buffer = new byte[BUFFER_SIZE];
for (ZipEntry entry = in.getNextEntry(); entry != null; entry = in.getNextEntry()) {
log.info(entry.getName());
if (filter == null || entry.getName().startsWith(filter)) {
String filename = (filter==null)?entry.getName():entry.getName().substring(filter.length());
// File file = new File(target, entry.getName());
File file = new File(target, filename);
log.debug("Extracted Resource = " + entry.getName());
if (entry.isDirectory()) {
file.mkdirs();
} else {
file.getParentFile().mkdirs();
if (!file.exists() || overwrite) {
OutputStream out = new FileOutputStream(file);
try {
int count;
while ((count = in.read(buffer)) > 0) {
out.write(buffer, 0, count);
}
} finally {
out.close();
}
}
in.closeEntry();
}
}
}
} catch (IOException e) {
log.error("", e);
throw e;
} finally {
in.close();
}
}
static public void extractFromFile(String filePath, String targetDirectory) throws IOException {
extractFromFile(filePath, targetDirectory, null);
}
// e.g. Zip.extractFromFile("./myrobotlab.jar", "./", "resource");
static public void extractFromFile(String resourcePath, String targetDirectory, String filter) throws IOException {
extract(resourcePath, targetDirectory, filter, FILE, false);
}
static public void extractFromResource(String resourcePath, String targetDirectory) throws IOException {
extract(resourcePath, targetDirectory, null, RESOURCE, false);
}
static public void extractFromResource(String resourcePath, String targetDirectory, String filter) throws IOException {
extract(resourcePath, targetDirectory, filter, RESOURCE, false);
}
static public void extractFromSelf() throws IOException {
extractFromSelf(".");
}
static public void extractFromSelf(String targetDirectory) throws IOException {
extractFromFile(".", targetDirectory, null);
}
static public void extractFromSelf(String targetDirectory, String filter) throws URISyntaxException, IOException {
// Logic to get currently executing JAR name
String filePath = Zip.class.getProtectionDomain().getCodeSource().getLocation().toURI().toASCIIString();
filePath = filePath.substring(filePath.lastIndexOf("/") + 1, filePath.length());
filePath = "./" + filePath;
extractFromFile(filePath, targetDirectory, filter);
}
public static ArrayList<String> listDirectoryContents(String zipFile, String dir) throws ZipException, IOException {
if (dir.charAt(dir.length() - 1) != '/') {
dir = dir + "/";
}
log.info(String.format("listing %s directory %s", zipFile, dir));
// int BUFFER = 2048;
File file = new File(zipFile);
ArrayList<String> children = new ArrayList<String>();
ZipFile zip = new ZipFile(file);
// String newPath = zipFile.substring(0, zipFile.length() - 4);
ZipEntry zipDir = zip.getEntry(dir);
if (zipDir == null) {
log.error(String.format("%s not found", dir));
// don't leak file handles.
zip.close();
return children;
}
if (!zipDir.isDirectory()) {
log.error(String.format("%s not a directory", dir));
// don't leak file handles.
zip.close();
return children;
}
Enumeration<?> zipFileEntries = zip.entries();
// Process each entry
while (zipFileEntries.hasMoreElements()) {
// grab a zip file entry
ZipEntry entry = (ZipEntry) zipFileEntries.nextElement();
String currentEntry = entry.getName();
if (currentEntry.startsWith(dir)) {
String rest = currentEntry.substring(dir.length());
if (rest.length() > 0) {
// not subfiles of sub directories
if ((!(rest.contains("/") && rest.charAt(rest.length() - 1) != '/')) &&
// and not sub directories of sub directories
(countOccurrences(rest, '/') < 2)) {
// log.info(currentEntry);
children.add(currentEntry.substring(dir.length()));
}
}
}
// !entry.isDirectory()
// make sure we don't leak file handles.
zip.close();
}
return children;
}
public static void main(String[] args) throws ZipException, IOException {
LoggingFactory.init(Level.INFO);
ArrayList<String> files = listDirectoryContents("myrobotlab.jar", "resource/Python/");
for (int i = 0; i < files.size(); ++i) {
log.info(files.get(i));
}
}
static public void unzip(String zipFile, String newPath) throws ZipException, IOException {
log.info(String.format("unzipping %s to %s", zipFile, newPath));
int BUFFER = 2048;
File file = new File(zipFile);
ZipFile zip = new ZipFile(file);
// String newPath = zipFile.substring(0, zipFile.length() - 4);
new File(newPath).mkdir();
Enumeration<?> zipFileEntries = zip.entries();
// Process each entry
while (zipFileEntries.hasMoreElements()) {
// grab a zip file entry
ZipEntry entry = (ZipEntry) zipFileEntries.nextElement();
String currentEntry = entry.getName();
File destFile = new File(newPath, currentEntry);
// destFile = new File(newPath, destFile.getName());
File destinationParent = destFile.getParentFile();
// create the parent directory structure if needed
destinationParent.mkdirs();
if (!entry.isDirectory()) {
BufferedInputStream is = new BufferedInputStream(zip.getInputStream(entry));
int currentByte;
// establish buffer for writing file
byte data[] = new byte[BUFFER];
// write the current file to disk
FileOutputStream fos = new FileOutputStream(destFile);
BufferedOutputStream dest = new BufferedOutputStream(fos, BUFFER);
// read and write until last byte is encountered
while ((currentByte = is.read(data, 0, BUFFER)) != -1) {
dest.write(data, 0, currentByte);
}
dest.flush();
dest.close();
is.close();
} else {
destFile.mkdirs();
}
if (currentEntry.endsWith(".zip")) {
// found a zip file, try to open
unzip(destFile.getAbsolutePath(), "./");
}
}
// don't leak file handles.
zip.close();
}
// public static void main(String[] args) throws ZipException, IOException {
// // TODO Auto-generated method stub
// // extractFolder("ziptest.zip");
// Log.init();
// // extractFromResource("/resource/ziptest.zip", "binx");
// // extractFromFile("./VivaClient.jar", "binx", "resource/");
// extractFromSelf("/resource", "binz");
// log.debug("done");
//
// }
}