/******************************************************************************
* Copyright (c) 2008-2013, Linagora
*
* 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:
* Linagora - initial API and implementation
*******************************************************************************/
package com.ebmwebsourcing.petals.common.internal.provisional.utils;
import java.io.ByteArrayOutputStream;
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.MalformedURLException;
import java.net.URI;
import org.eclipse.bpel.common.wsdl.helpers.UriAndUrlHelper;
import org.eclipse.core.resources.IFile;
import org.eclipse.core.runtime.IStatus;
import com.ebmwebsourcing.petals.common.internal.PetalsCommonPlugin;
/**
* @author Vincent Zurczak - EBM WebSourcing
*/
public final class IoUtils {
/**
* Private constructor for utility class.
*/
private IoUtils() {
// nothing
}
/**
* Deletes files recursively.
* @param files the files to delete
* @throws IOException if a file could not be deleted
*/
public static void deleteFilesRecursively( File... files ) throws IOException {
if( files == null )
return;
for( File file : files ) {
if( file.exists()) {
if( file.isDirectory())
deleteFilesRecursively( file.listFiles());
if( ! file.delete())
throw new IOException( file.getAbsolutePath() + " could not be deleted." );
}
}
}
/**
* Copies the content from in into os.
* <p>
* Neither <i>in</i> nor <i>os</i> are closed by this method.<br />
* They must be explicitly closed after this method is called.
* </p>
*
* @param in
* @param os
* @throws IOException
*/
public static void copyStream( InputStream in, OutputStream os ) throws IOException {
byte[] buf = new byte[ 1024 ];
int len;
while((len = in.read( buf )) > 0) {
os.write( buf, 0, len );
}
}
/**
* Copies the content from in into outputFile.
* <p>
* <i>in</i> is not closed by this method.<br />
* It must be explicitly closed after this method is called.
* </p>
*
* @param in
* @param outputFile will be created if it does not exist
* @throws IOException
*/
public static void copyStream( InputStream in, File outputFile ) throws IOException {
if( ! outputFile.exists() && ! outputFile.createNewFile())
throw new IOException( "Failed to create " + outputFile.getAbsolutePath() + "." );
OutputStream os = new FileOutputStream( outputFile );
copyStream( in, os );
os.close ();
}
/**
* Copies the content from inputFile into outputFile.
*
* @param inputFile
* @param outputFile will be created if it does not exist
* @throws IOException
*/
public static void copyStream( File inputFile, File outputFile ) throws IOException {
InputStream is = new FileInputStream( inputFile );
copyStream( is, outputFile );
is.close();
}
/**
* Copies the content from inputFile into an output stream.
*
* @param inputFile
* @param os the output stream
* @throws IOException
*/
public static void copyStream( File inputFile, OutputStream os ) throws IOException {
InputStream is = new FileInputStream( inputFile );
copyStream( is, os );
is.close();
}
/**
* Reads a text file content and returns it as a string.
* <p>
* The file is tried to be read with UTF-8 encoding.
* If it fails, the default system encoding is used.
* </p>
*
* @param file the file whose content must be loaded
* @return the file content
* @throws IOException if the file content could not be read
*/
public static String readFileContent( File file ) throws IOException {
String result = null;
ByteArrayOutputStream os = new ByteArrayOutputStream();
IoUtils.copyStream( file, os );
try {
result = os.toString( "UTF-8" );
} catch( Exception e ) {
result = os.toString();
}
return result;
}
/**
* Reads a text file content and returns it as a string.
*
* @param file the file whose content must be loaded
* @return the file content
* @throws IOException if the file content could not be read
*/
public static String readFileContent( IFile file ) throws IOException {
return readFileContent( file.getLocation().toFile());
}
/**
* Return the relative position of <code>file</code> with respect to originFile.
* @param originFile the absolute file which acts as the <i>origin</i>.
* @param file the file whose relative path must be computed with respect to originFile.
* @return the relative path of <code>file</code> with respect to originFile.
* @see UriAndUrlHelper#getRelativeLocationToUri(URI, URI)
*/
public static String getRelativeLocationToFile( File originFile, File file ) {
String result = file.getAbsolutePath();
try {
URI originUri = UriAndUrlHelper.urlToUri( originFile.toURI().toURL());
URI fileUri = UriAndUrlHelper.urlToUri( file.toURI().toURL());
result = UriAndUrlHelper.getRelativeLocationToUri( originUri, fileUri ).toString();
} catch( MalformedURLException e ) {
PetalsCommonPlugin.log( e, IStatus.ERROR );
}
return result;
}
/**
* Copies a file (or a directory) in a directory.
*
* @param source a file or a directory
* <p>
* If source is a directory, this directory will be copied in the target directory.
* </p>
*
* @param targetDirectory the directory in which the file must be copied
* @param deleteSourceAfter true to delete the source file after the copy is done
* @throws IOException if something went wrong
*/
public static void copyFileInDirectory( File source, File targetDirectory, boolean deleteSourceAfter )
throws IOException {
File target = new File( targetDirectory, source.getName());
copyFile( source, target, deleteSourceAfter );
}
/**
* Copies a source file in a target file.
*
* @param source a file or a directory
* <p>
* If source is a directory, only its content is copied in the target directory.
* </p>
*
* @param target a file or a directory (must have the same type than the source: file or directory)
* @param deleteSourceAfter true to delete the source file after the copy is done
* @throws IOException
*/
public static void copyFile( File source, File target, boolean deleteSourceAfter )
throws IOException {
// Copy a directory
if( source.isDirectory()) {
if( ! target.exists() && ! target.mkdir())
throw new IOException( "Could not create the directory " + target.getAbsolutePath());
else if( target.exists() && ! target.isDirectory())
throw new IOException( target + " already exists and is not a directory." );
File[] children = source.listFiles();
for( File sourceChild : children ) {
File destChild = new File( target, sourceChild.getName());
copyFile( sourceChild, destChild, deleteSourceAfter );
}
}
// Copy a file
else {
if( ! target.exists() && ! target.createNewFile())
throw new IOException( "Could not create the file " + target.getAbsolutePath());
else if( target.exists() && ! target.isFile())
throw new IOException( target + " already exists and is not a file." );
copyStream( source, target );
}
if( deleteSourceAfter )
deleteFilesRecursively( source );
}
/**
* Moves a source file (or directory) to another location in a robust way.
* <p>
* Directory handling is classic: the move results from the creation of another directory
* and in which is moved the content from the source directory.
* </p>
* <p>
* Files are tried to be moved using {@link File#renameTo(File)}.<br />
* If it fails, it copies the source file in the target file, before deleting the source.
* </p>
*
* @param source the source file (or directory)
* @param target the target file (or directory)
* @param overwrite true to overwrite the target file
* <p>
* If the target is a file, the content is overwritten.<br />
* If the target is a directory, the directory is deleted before being replaced
* by the moved directory.
* </p>
*
* @throws IOException if something went wrong
*/
public static void moveFileRobustly( File source, File target, boolean overwrite ) throws IOException {
// Move a directory
if( source.isDirectory()) {
// If it exists and needs to be overwritten, delete it with all its contents
if( target.exists()) {
if( ! overwrite )
throw new IOException( target + " already exists (overwrite = false)." );
else if( ! target.isDirectory())
throw new IOException( target + " already exists and is not a directory." );
deleteFilesRecursively( target );
}
if( ! target.mkdir())
throw new IOException( "Could not create " + target.getAbsolutePath());
File[] children = source.listFiles();
for( File sourceChild : children ) {
File targetChild = new File( target, sourceChild.getName());
moveFileRobustly( sourceChild, targetChild, overwrite );
}
deleteFilesRecursively( source );
}
// Move a file
else {
if( target.exists()) {
if( ! overwrite )
throw new IOException( target + " already exists (overwrite = false)." );
else if( ! target.isFile())
throw new IOException( target + " already exists and is not a file." );
copyStream( source, target );
}
else if( ! source.renameTo( target ))
copyFile( source, target, true );
}
}
/**
* Converts an URI into a file.
* <p>
* The returned file might not exist.
* </p>
*
* @param uri any URI
* @return the file if the URI points to a file, null otherwise
*/
public static File convertToFile( String uri ) {
return convertToFile( UriAndUrlHelper.urlToUri( uri ));
}
/**
* Converts an URI into a file.
* <p>
* The returned file might not exist.
* </p>
*
* @param uri any URI
* @return the file if the URI points to a file, null otherwise
*/
public static File convertToFile( URI uri ) {
File result = null;
try {
if( uri != null )
result = new File( uri );
} catch( Exception e ) {
PetalsCommonPlugin.log( e, IStatus.WARNING );
}
return result;
}
/**
* Closes a stream quietly.
* @param is an input stream
*/
public static void closeQuietly( InputStream is ) {
try {
if( is != null )
is.close();
} catch( IOException e ) {
// nothing
}
}
/**
* Closes a stream quietly.
* @param os an output stream
*/
public static void closeQuietly( OutputStream os ) {
try {
if( os != null )
os.close();
} catch( IOException e ) {
// nothing
}
}
}