blob: e2930374f053e56537f6f5779db044e44e9e7286 [file] [log] [blame]
/*******************************************************************************
* Copyright (c) 2007 IBM Corporation and others.
* All rights reserved. This program and the accompanying materials
* are made available under the terms of the Eclipse Public License v1.0
* which accompanies this distribution, and is available at
* http://www.eclipse.org/legal/epl-v10.html
*
* Contributors:
* IBM Corporation - initial API and implementation
*******************************************************************************/
package org.eclipse.equinox.internal.p2.core.helpers;
import java.io.*;
import java.net.URL;
import java.util.ArrayList;
import java.util.zip.*;
import org.eclipse.core.runtime.*;
import org.eclipse.osgi.util.NLS;
public class FileUtils {
/**
* Unzip from a File to an output directory.
*/
public static File[] unzipFile(File zipFile, File outputDir) throws IOException {
InputStream in = new FileInputStream(zipFile);
try {
return unzipStream(in, zipFile.length(), outputDir, null, null);
} catch (IOException e) {
// add the file name to the message
throw new IOException(NLS.bind(Messages.Util_Error_Unzipping, zipFile, e.getMessage()));
} finally {
in.close();
}
}
/**
* Unzip from a File to an output directory, with progress indication.
* monitor may be null.
*/
public static File[] unzipFile(File zipFile, File outputDir, String taskName, IProgressMonitor monitor) throws IOException {
InputStream in = new FileInputStream(zipFile);
try {
return unzipStream(in, zipFile.length(), outputDir, taskName, monitor);
} catch (IOException e) {
// add the file name to the message
throw new IOException(NLS.bind(Messages.Util_Error_Unzipping, zipFile, e.getMessage()));
} finally {
in.close();
}
}
/**
* Unzip from a URL to an output directory, with progress indication.
* monitor may be null.
*/
public static File[] unzipURL(URL zipURL, File outputDir, String taskName, IProgressMonitor monitor) throws IOException {
int size = zipURL.openConnection().getContentLength();
InputStream in = zipURL.openStream();
try {
return unzipStream(in, size, outputDir, taskName, monitor);
} catch (IOException e) {
// add the URL to the message
throw new IOException(NLS.bind(Messages.Util_Error_Unzipping, zipURL, e.getMessage()));
} finally {
in.close();
}
}
/**
* Unzip from an InputStream to an output directory.
*/
public static File[] unzipStream(InputStream stream, long size, File outputDir, String taskName, IProgressMonitor monitor) throws IOException {
InputStream is = monitor == null ? stream : stream; // new ProgressMonitorInputStream(stream, size, size, taskName, monitor); TODO Commented code
ZipInputStream in = new ZipInputStream(new BufferedInputStream(is));
ZipEntry ze = in.getNextEntry();
if (ze == null) {
// There must be at least one entry in a zip file.
// When there isn't getNextEntry returns null.
in.close();
throw new IOException(Messages.Util_Invalid_Zip_File_Format);
}
ArrayList unzippedFiles = new ArrayList();
do {
File outFile = new File(outputDir, ze.getName());
unzippedFiles.add(outFile);
if (ze.isDirectory()) {
outFile.mkdirs();
} else {
if (outFile.exists()) {
outFile.delete();
} else {
outFile.getParentFile().mkdirs();
}
try {
copyStream(in, false, new FileOutputStream(outFile), true);
} catch (FileNotFoundException e) {
// TEMP: ignore this for now in case we're trying to replace
// a running eclipse.exe
}
outFile.setLastModified(ze.getTime());
}
in.closeEntry();
} while ((ze = in.getNextEntry()) != null);
in.close();
return (File[]) unzippedFiles.toArray(new File[unzippedFiles.size()]);
}
// Delete empty directories under dir, including dir itself.
public static void deleteEmptyDirs(File dir) throws IOException {
File[] files = dir.listFiles();
if (files != null) {
for (int i = 0; i < files.length; i += 1) {
deleteEmptyDirs(files[i]);
}
dir.getCanonicalFile().delete();
}
}
// Delete the given file whether it is a file or a directory
public static void deleteAll(File file) {
if (!file.exists())
return;
if (file.isDirectory()) {
File[] files = file.listFiles();
if (files != null)
for (int i = 0; i < files.length; i++)
deleteAll(files[i]);
}
file.delete();
}
/**
* Copy an input stream to an output stream.
* Optionally close the streams when done.
* Return the number of bytes written.
*/
public static int copyStream(InputStream in, boolean closeIn, OutputStream out, boolean closeOut) throws IOException {
try {
int written = 0;
byte[] buffer = new byte[16 * 1024];
int len;
while ((len = in.read(buffer)) != -1) {
out.write(buffer, 0, len);
written += len;
}
return written;
} finally {
try {
if (closeIn) {
in.close();
}
} finally {
if (closeOut) {
out.close();
}
}
}
}
public static void zip(File[] sourceFiles, File destinationArchive) throws IOException {
zip(sourceFiles, destinationArchive, true);
}
public static void zip(File[] sourceFiles, File destinationArchive, boolean includeRoot) throws IOException {
ZipOutputStream output = new ZipOutputStream(new FileOutputStream(destinationArchive));
try {
for (int i = 0; i < sourceFiles.length; i++)
if (sourceFiles[i].isDirectory())
zipDir(output, sourceFiles[i], includeRoot ? new Path(sourceFiles[i].getName()) : new Path("")); //$NON-NLS-1$
else
zipFile(output, sourceFiles[i], new Path(""));//$NON-NLS-1$
} finally {
try {
// Note! This call will fail miserably if no entries were added to the zip!
// The file is left open after an exception is thrown.
output.close();
} catch (IOException e) {
// ignore
}
}
}
/*
* Zip the contents of the given directory into the zip file represented by
* the given zip stream. Prepend the given prefix to the file paths.
*/
private static void zipDir(ZipOutputStream output, File source, IPath prefix) {
File[] files = source.listFiles();
for (int i = 0; i < files.length; i++) {
try {
if (files[i].isFile())
zipFile(output, files[i], prefix);
else
zipDir(output, files[i], prefix.append(files[i].getName()));
} catch (IOException e) {
e.printStackTrace();
}
}
}
/*
* Add the given file to the zip file represented by the specified stream.
* Prepend the given prefix to the path of the file.
*/
private static void zipFile(ZipOutputStream output, File sourceFile, IPath prefix) throws IOException {
InputStream input = new FileInputStream(sourceFile);
try {
ZipEntry zipEntry = new ZipEntry(prefix.append(sourceFile.getName()).toString());
zipEntry.setTime(sourceFile.lastModified());
output.putNextEntry(zipEntry);
copyStream(input, true, output, false);
} finally {
try {
input.close();
} catch (IOException e) {
// ignore
}
try {
output.closeEntry();
} catch (IOException e) {
// ignore
}
}
}
}