/*****************************************************************************
* Copyright (c) 2006-2013, Cloudsmith Inc.
* The code, documentation and other materials contained herein have been
* licensed under the Eclipse Public License - v 1.0 by the copyright holder
* listed above, as the Initial Contributor under such license. The text of
* such license is available at www.eclipse.org.
*****************************************************************************/
package org.eclipse.buckminster.runtime;
import java.io.Closeable;
import java.io.File;
import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
import java.io.Reader;
import java.io.Writer;
import java.net.MalformedURLException;
import java.net.URI;
import java.net.URISyntaxException;
import java.net.URL;
import java.util.HashSet;
import java.util.Map;
import org.eclipse.core.runtime.IProgressMonitor;
/**
* Class containing some trivial IO tasks that we don't want to duplicate
* everywhere. Keep this class small. It's not supposed to be a general purpose
* can do it all sort of thing.
*
* @author Thomas Hallgren
*/
public class IOUtils {
private static HashSet<File> foldersToRemove;
/**
* Close but no cigar, sorry no Exception...
*
* @param stream
*/
public static void close(Closeable stream) {
if (stream != null) {
try {
stream.close();
} catch (IOException e) {
}
}
}
/**
* Copies all data read from <code>in</code> to <code>out</code> using a
* byte buffer of size 2048 bytes.
*
* @param in
* The stream to copy from
* @param out
* The stream to copy to
* @throws IOException
*/
public static final void copy(InputStream in, OutputStream out, IProgressMonitor monitor) throws IOException {
MonitorUtils.begin(monitor, IProgressMonitor.UNKNOWN);
try {
byte[] buffer = new byte[2048];
int len;
while ((len = in.read(buffer)) > 0) {
MonitorUtils.worked(monitor, 1);
out.write(buffer, 0, len);
}
} finally {
MonitorUtils.done(monitor);
}
}
/**
* Copies all data read from <code>in</code> to <code>out</code> using a
* char buffer of size 2048 bytes.
*
* @param in
* The stream to copy from
* @param out
* The stream to copy to
* @throws IOException
*/
public static final void copy(Reader in, Writer out, IProgressMonitor monitor) throws IOException {
MonitorUtils.begin(monitor, IProgressMonitor.UNKNOWN);
try {
char[] buffer = new char[1024];
int len;
while ((len = in.read(buffer)) > 0) {
MonitorUtils.worked(monitor, 1);
out.write(buffer, 0, len);
}
} finally {
MonitorUtils.done(monitor);
}
}
/**
* Creates a folder based on an abstract file handle. The folder and all its
* content will be deleted when the process exists. The <code>tmpDir</code>
* directory must not exist when this method is called.
*
* @param tmpDir
* The directory to create
* @throws IOException
* If the directory could not be created.
*/
public static synchronized void createTempFolder(File tmpDir) throws IOException {
if (tmpDir.exists())
throw new IOException("Path already exists: " + tmpDir.getAbsolutePath()); //$NON-NLS-1$
if (!tmpDir.mkdirs())
throw new IOException("Unable to create directory: " + tmpDir.getAbsolutePath()); //$NON-NLS-1$
if (foldersToRemove == null) {
foldersToRemove = new HashSet<File>();
Runtime.getRuntime().addShutdownHook(new Thread() {
@Override
public void run() {
// Prevent that foldersToRemove is updated during the
// remove
//
HashSet<File> folders = new HashSet<File>(foldersToRemove);
foldersToRemove = null;
for (File folder : folders) {
try {
deleteRecursive(folder, null);
} catch (Exception e) {
// We're shutting down so this is ignored
System.err.println("Failed to remove directory " + folder.getAbsolutePath() + " :" + e.toString()); //$NON-NLS-1$ //$NON-NLS-2$
}
}
}
});
}
foldersToRemove.add(tmpDir);
}
/**
* Creates a folder based on a generated name. The folder and all its
* content will be deleted when the process exists.
*/
public static synchronized File createTempFolder(String prefix, String suffix, File directory) throws IOException {
directory.mkdirs();
File tmpFile = File.createTempFile(prefix, suffix, directory);
if (!tmpFile.delete())
throw new IOException("Unable to delete file: " + tmpFile.getAbsolutePath()); //$NON-NLS-1$
createTempFolder(tmpFile);
return tmpFile;
}
public static void deleteRecursive(File file, IProgressMonitor monitor) throws IOException {
MonitorUtils.begin(monitor, 1000);
try {
if (file == null)
return;
File[] list = file.listFiles();
int count = (list == null) ? 0 : list.length;
if (count > 0) {
IProgressMonitor subMon = MonitorUtils.subMonitor(monitor, 900);
MonitorUtils.begin(subMon, count * 100);
try {
if (foldersToRemove != null)
foldersToRemove.remove(file);
while (--count >= 0)
deleteRecursive(list[count], MonitorUtils.subMonitor(subMon, 100));
} finally {
MonitorUtils.done(subMon);
}
} else
MonitorUtils.worked(monitor, 900);
if (!file.delete() && file.exists())
throw new IOException("Unable to delete file: " + file.getAbsolutePath()); //$NON-NLS-1$
MonitorUtils.worked(monitor, 100);
} catch (SecurityException e) {
throw new IOException("Unable to delete file: " + file.getAbsolutePath(), e); //$NON-NLS-1$
} finally {
MonitorUtils.done(monitor);
}
}
public static File getTempRoot(Map<String, String> properties) {
String tempRootStr = properties.get(Buckminster.ACTION_TEMP_ROOT);
File tempRoot;
if (tempRootStr == null)
tempRoot = new File(new File(System.getProperty("java.io.tmpdir")), "buckminster"); //$NON-NLS-1$ //$NON-NLS-2$
else
tempRoot = new File(tempRootStr);
return tempRoot;
}
/**
* Convert an <code>String</code> into a <code>URI</code>.
*
* @param uriStr
* The String to be converted or <code>null</code>.
* @return <code>null</code> if <code>null</code> was passed, otherwise the
* corresponding URI.
* @throws IllegalArgumentException
* if the String could not be converted.
*/
public static URI uri(String uriStr) {
try {
return uriStr == null ? null : new URI(uriStr);
} catch (URISyntaxException e) {
throw new IllegalArgumentException("Unable to convert String into URI: " + uriStr); //$NON-NLS-1$
}
}
/**
* Convert an <code>URL</code> into a <code>URI</code>.
*
* @param url
* The url to be converted or <code>null</code>.
* @return <code>null</code> if <code>null</code> was passed, otherwise the
* corresponding URI.
* @throws IllegalArgumentException
* if the URL could not be converted.
*/
public static URI uri(URL url) {
try {
return url == null ? null : url.toURI();
} catch (URISyntaxException e) {
throw new IllegalArgumentException("Unable to convert URL into URI: " + url); //$NON-NLS-1$
}
}
/**
* Convert an <code>File</code> into a <code>URL</code>.
*
* @param file
* The file to be converted or <code>null</code>.
* @return <code>null</code> if <code>null</code> was passed, otherwise the
* corresponding URL.
* @throws IllegalArgumentException
* if the File could not be converted.
*/
public static URL url(File file) {
return file == null ? null : url(file.toURI());
}
/**
* Convert an <code>URI</code> into a <code>URL</code>.
*
* @param uri
* The uri to be converted or <code>null</code>.
* @return <code>null</code> if <code>null</code> was passed, otherwise the
* corresponding URL.
* @throws IllegalArgumentException
* if the URI could not be converted.
*/
public static URL url(URI uri) {
try {
return uri == null ? null : uri.toURL();
} catch (MalformedURLException e) {
throw new IllegalArgumentException("Unable to convert URI into URL: " + uri); //$NON-NLS-1$
}
}
}