/* * ProActive Parallel Suite(TM): * The Open Source library for parallel and distributed * Workflows & Scheduling, Orchestration, Cloud Automation * and Big Data Analysis on Enterprise Grids & Clouds. * * Copyright (c) 2007 - 2017 ActiveEon * Contact: contact@activeeon.com * * This library is free software: you can redistribute it and/or * modify it under the terms of the GNU Affero General Public License * as published by the Free Software Foundation: version 3 of * the License. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU Affero General Public License for more details. * * You should have received a copy of the GNU Affero General Public License * along with this program. If not, see <http://www.gnu.org/licenses/>. * * If needed, contact us to obtain a release under GPL Version 2 or 3 * or a different license than the AGPL. */ package org.ow2.proactive_grid_cloud_portal.scheduler.client.utils; import static com.google.common.base.Preconditions.checkNotNull; import java.io.*; import java.nio.file.Path; import java.util.List; import java.util.zip.*; import org.objectweb.proactive.extensions.dataspaces.vfs.selector.FileSelector; import com.google.common.base.Predicate; import com.google.common.base.Strings; import com.google.common.collect.FluentIterable; import com.google.common.collect.ImmutableList; import com.google.common.io.ByteStreams; import com.google.common.io.Closer; import com.google.common.io.Files; public class Zipper { private static byte[] MAGIC = { 'P', 'K', 0x3, 0x4 }; private Zipper() { } public static class GZIP { public static void zip(File file, OutputStream os) throws IOException { checkNotNull(file); checkNotNull(os); GZIP.zip(new FileInputStream(file), os); } public static void zip(InputStream is, OutputStream os) throws IOException { Closer closer = Closer.create(); closer.register(is); try { GZIPOutputStream zos = new GZIPOutputStream(os); closer.register(zos); ByteStreams.copy(is, zos); } catch (IOException ioe) { throw closer.rethrow(ioe); } finally { closer.close(); } } public static void unzip(InputStream is, File file) throws IOException { GZIP.unzip(is, new FileOutputStream(file)); } public static void unzip(InputStream is, OutputStream os) throws IOException { Closer closer = Closer.create(); closer.register(os); try { GZIPInputStream gis = new GZIPInputStream(is); closer.register(gis); ByteStreams.copy(gis, os); } catch (IOException ioe) { throw closer.rethrow(ioe); } finally { closer.close(); } } } public static class ZIP { public static void zip(File root, List<String> includes, List<String> excludes, OutputStream os) throws IOException { checkNotNull(root); checkNotNull(os); FluentIterable<File> fi = Files.fileTreeTraverser().postOrderTraversal(root); ImmutableList<File> fileList = nullOrEmpty(includes) && nullOrEmpty(excludes) ? fi.filter(new FilesOnlyPredicate()) .toList() : fi.filter(new FileSelectionPredicate(root, includes, excludes)) .toList(); zipFiles(fileList, root.getAbsolutePath(), os); } private static boolean nullOrEmpty(List<String> strings) { return strings == null || strings.size() == 0; } private static void zipFiles(List<File> files, String basepath, OutputStream os) throws IOException { Closer closer = Closer.create(); try { ZipOutputStream zos = new ZipOutputStream(os); closer.register(zos); if (files.size() == 1) { File file = files.get(0); writeZipEntry(new ZipEntry(file.getName()), new FileInputStream(file), zos); } else { for (File file : files) { writeZipEntry(zipEntry(basepath, file), new FileInputStream(file), zos); } } } catch (IOException ioe) { throw closer.rethrow(ioe); } finally { closer.close(); } } public static void writeZipEntry(ZipEntry zipEntry, InputStream is, ZipOutputStream zos) throws IOException { Closer closer = Closer.create(); closer.register(is); try { zos.putNextEntry(zipEntry); ByteStreams.copy(is, zos); zos.flush(); } catch (IOException ioe) { throw closer.rethrow(ioe); } finally { closer.close(); } } public static void unzip(InputStream is, File outFile) throws IOException { Closer closer = Closer.create(); try { ZipInputStream zis = new ZipInputStream(is); closer.register(zis); ZipEntry zipEntry = zis.getNextEntry(); while (zipEntry != null) { File entryFile = new File(outFile, zipEntry.getName()); File entryContainer = entryFile.getParentFile(); if (!entryContainer.exists()) { entryContainer.mkdirs(); } if (!entryFile.isDirectory()) { Zipper.ZIP.unzipEntry(zis, new FileOutputStream(entryFile)); } zipEntry = zis.getNextEntry(); } } catch (IOException ioe) { throw closer.rethrow(ioe); } finally { closer.close(); } } public static void unzipEntry(ZipInputStream zis, OutputStream os) throws IOException { Closer closer = Closer.create(); closer.register(os); try { ByteStreams.copy(zis, os); } catch (IOException ioe) { throw closer.rethrow(ioe); } finally { closer.close(); } } private static ZipEntry zipEntry(String basepath, File file) { String name = (Strings.isNullOrEmpty(basepath) || basepath.equals(file.getAbsolutePath())) ? file.getPath() : file.getAbsolutePath() .substring(basepath.length() + 1); return new ZipEntry(name); } } public static boolean isZipFile(File file) throws FileNotFoundException { return isZipFile(new FileInputStream(file)); } public static boolean isZipFile(InputStream is) { if (!is.markSupported()) { is = new BufferedInputStream(is); } boolean isZipStream = true; try { is.mark(MAGIC.length); for (int i = 0; i < MAGIC.length; i++) { if (MAGIC[i] != (byte) is.read()) { isZipStream = false; break; } } is.reset(); } catch (IOException ioe) { isZipStream = false; } return isZipStream; } private static class FilesOnlyPredicate implements Predicate<File> { @Override public boolean apply(File file) { return !file.isDirectory(); } } private static class FileSelectionPredicate implements Predicate<File> { private File root; private List<String> includes; private List<String> excludes; public FileSelectionPredicate(File root, List<String> includes, List<String> excludes) { this.root = root; this.includes = includes; this.excludes = excludes; } @Override public boolean apply(File file) { Path pathRelativeToRoot = root.toPath().relativize(file.toPath()); FileSelector selector = new FileSelector(includes, excludes); return !file.isDirectory() && selector.matches(pathRelativeToRoot); } } }