blob: b44fd464acc5fae3b069a10659fb68c635987b5d [file] [log] [blame]
/*
* Copyright (C) 2016 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.android.compatibility.common.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.io.InputStream;
import java.io.OutputStream;
import java.util.LinkedList;
import java.util.List;
import java.util.zip.ZipEntry;
import java.util.zip.ZipOutputStream;
public class ZipUtil {
/**
* Utility method to create a zip file containing the given directory and
* all its contents.
*
* @param dir the directory to zip
* @param zipFile the zip file to create - it should not already exist
* @throws IOException if failed to create zip file
*/
public static void createZip(File dir, File zipFile) throws IOException {
ZipOutputStream out = null;
try {
FileOutputStream fileStream = new FileOutputStream(zipFile);
out = new ZipOutputStream(new BufferedOutputStream(fileStream));
addToZip(out, dir, new LinkedList<String>());
} catch (IOException e) {
zipFile.delete();
throw e;
} catch (RuntimeException e) {
zipFile.delete();
throw e;
} finally {
out.close();
}
}
/**
* Recursively adds given file and its contents to ZipOutputStream
*
* @param out the {@link ZipOutputStream}
* @param file the {@link File} to add to the stream
* @param relativePathSegs the relative path of file, including separators
* @throws IOException if failed to add file to zip
*/
public static void addToZip(ZipOutputStream out, File file, List<String> relativePathSegs)
throws IOException {
relativePathSegs.add(file.getName());
if (file.isDirectory()) {
// note: it appears even on windows, ZipEntry expects '/' as a path separator
relativePathSegs.add("/");
}
ZipEntry zipEntry = new ZipEntry(buildPath(relativePathSegs));
out.putNextEntry(zipEntry);
if (file.isFile()) {
writeToStream(file, out);
}
out.closeEntry();
if (file.isDirectory()) {
// recursively add contents
File[] subFiles = file.listFiles();
if (subFiles == null) {
throw new IOException(String.format("Could not read directory %s",
file.getAbsolutePath()));
}
for (File subFile : subFiles) {
addToZip(out, subFile, relativePathSegs);
}
// remove the path separator
relativePathSegs.remove(relativePathSegs.size()-1);
}
// remove the last segment, added at beginning of method
relativePathSegs.remove(relativePathSegs.size()-1);
}
/**
* Builds a file system path from a stack of relative path segments
*
* @param relativePathSegs the list of relative paths
* @return a {@link String} containing all relativePathSegs
*/
private static String buildPath(List<String> relativePathSegs) {
StringBuilder pathBuilder = new StringBuilder();
for (String segment : relativePathSegs) {
pathBuilder.append(segment);
}
return pathBuilder.toString();
}
/**
* Helper method to write input file contents to output stream.
*
* @param file the input {@link File}
* @param out the {@link OutputStream}
*
* @throws IOException
*/
private static void writeToStream(File file, OutputStream out) throws IOException {
InputStream inputStream = null;
try {
inputStream = new BufferedInputStream(new FileInputStream(file));
StreamUtil.copyStreams(inputStream, out);
} finally {
inputStream.close();
}
}
}