blob: 603728f8cf35281afb169d2442909a07a3e5e80d [file] [log] [blame]
//------------------------------------------------------------------------------
// Copyright (c) 2005, 2006 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 implementation
//------------------------------------------------------------------------------
package org.eclipse.epf.common.utils;
import java.io.File;
import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.io.FileOutputStream;
import java.io.FileWriter;
import java.io.IOException;
import java.io.InputStream;
import java.io.InputStreamReader;
import java.io.OutputStream;
import java.io.OutputStreamWriter;
import java.io.PrintWriter;
import java.net.URL;
import java.nio.CharBuffer;
import java.nio.MappedByteBuffer;
import java.nio.channels.FileChannel;
import java.nio.channels.FileLock;
import java.nio.channels.OverlappingFileLockException;
import java.nio.charset.Charset;
import java.nio.charset.CharsetDecoder;
import java.util.ArrayList;
import java.util.List;
import java.util.Locale;
import org.eclipse.epf.common.CommonPlugin;
/**
* Utility class for managing directories and files.
*
* @author Kelvin Low
* @author Jinhua Xi
* @since 1.0
*/
public class FileUtil {
/**
* Platform-specific line separator.
*/
public static final String LINE_SEP = System.getProperty("line.separator"); //$NON-NLS-1$
/**
* Platform-specific file separator.
*/
public static final String FILE_SEP = System.getProperty("file.separator"); //$NON-NLS-1$
/**
* Platform-specific line separator length.
*/
public static final int LINE_SEP_LENGTH = LINE_SEP.length();
/**
* UNC path prefix.
*/
public static final String UNC_PATH_PREFIX = "\\\\"; //$NON-NLS-1$
/**
* UNC path prefix length.
*/
public static final int UNC_PATH_PREFIX_LENGTH = UNC_PATH_PREFIX.length();
/**
* ISO-8859-1 encoding.
*/
public static final String ENCODING_ISO_8859_1 = "ISO-8859-1"; //$NON-NLS-1$
/**
* UTF-8 encoding.
*/
public static final String ENCODING_UTF_8 = "UTF-8";//$NON-NLS-1$
/**
* Private constructor to prevent this class from being instantiated. All
* methods in this class should be static.
*/
private FileUtil() {
}
/**
* Returns the absolute path for the given file or directory.
*
* @param file
* The given file or directory.
* @return The absolute path of the given file or directory.
*/
public static String getAbsolutePath(File file) {
return file.getAbsolutePath().replace('\\', '/');
}
/**
* Returns the absolute path for the given file or directory.
*
* @param file
* The given file or directory name.
* @return The absolute path of the given file or directory.
*/
public static String getAbsolutePath(String file) {
return getAbsolutePath(new File(file));
}
/**
* Returns the absolute path for the given URL.
*
* @param url
* The given URL.
* @return The absolute path of the given URL.
*/
public static String getAbsolutePath(URL url) {
String pathName = url.getFile().substring(1);
String result = NetUtil.decodeUrl(pathName, null);
return result;
}
/**
* Returns the parent directory of the given path.
*
* @param path
* The path name.
* @return The name of the parent directory.
*/
public static String getParentDirectory(String path) {
return (new File(path)).getParent();
}
/**
* Returns the file name and extension from the given path.
*
* @param path
* The path name.
* @return The file name and the file extension.
*/
public static String getFileName(String path) {
return getFileName(path, true);
}
/**
* Returns the file name from the given path, with or without the file
* extension.
*
* @param path
* The path name.
* @param withExtension
* If true, include the file extension in the result.
* @return The file name with or without the file extension.
*/
public static String getFileName(String path, boolean withExtension) {
String normalizedPath = path.replace('\\', '/');
int prefixLength = 0;
if (normalizedPath.startsWith(NetUtil.FILE_URI_PREFIX)) {
prefixLength = NetUtil.FILE_URI_PREFIX_LENGTH;
} else if (normalizedPath.startsWith(NetUtil.HTTP_URI_PREFIX)) {
prefixLength = NetUtil.HTTP_URI_PREFIX_LENGTH;
}
String fileName;
int index = normalizedPath.lastIndexOf("/"); //$NON-NLS-1$
if (index < prefixLength) {
fileName = normalizedPath.substring(prefixLength);
} else {
fileName = path.substring(index + 1);
}
if (withExtension) {
return fileName;
}
index = fileName.indexOf("."); //$NON-NLS-1$
return (index > 0) ? fileName.substring(0, index) : fileName;
}
/**
* Returns the relative path for the target path from the base path.
*
* @param path
* The target path.
* @param basePath
* The base path.
* @return The relative path.
*/
public static String getRelativePathToBase(File path, File basePath) {
try {
String dir = path.toURL().toExternalForm();
String baseDir = basePath.toURL().toExternalForm();
StringBuffer result = new StringBuffer();
if (dir.indexOf(baseDir) == 0) {
String delta = dir.substring(baseDir.length());
for (int i = 0; i < delta.length(); i++) {
if (delta.charAt(i) == '/') {
result.append("../"); //$NON-NLS-1$
}
}
}
return result.toString();
} catch (Exception e) {
return ""; //$NON-NLS-1$
}
}
public static String getRelativePath(File path, File basePath) {
try {
String dir = path.toURL().toExternalForm();
String baseDir = appendSeparator(basePath.toURL().toExternalForm(),
"/"); //$NON-NLS-1$
StringBuffer result = new StringBuffer();
while (dir.indexOf(baseDir) == -1) {
basePath = basePath.getParentFile();
baseDir = appendSeparator(basePath.toURL().toExternalForm(),
"/"); //$NON-NLS-1$
result.append("../"); //$NON-NLS-1$
}
if (dir.indexOf(baseDir) == 0) {
String delta = dir.substring(baseDir.length());
result.append(delta);
}
return result.toString();
} catch (Exception e) {
return ""; //$NON-NLS-1$
}
}
/**
* Appends the platform specific path separator to the end of the given
* path.
*
* @param path
* The path name.
* @return The path name appended with the platform specific path separator.
*/
public static String appendSeparator(String path) {
return appendSeparator(path, File.separator);
}
/**
* Appends the given path separator to the end of the given path.
*
* @param path
* The path name.
* @param separator
* The path separator.
* @return The path name appended with the given separator.
*/
public static String appendSeparator(String path, String separator) {
return path.endsWith(separator) ? path : path + separator;
}
/**
* Removes the ending path separator from the given path.
*
* @param path
* The path name.
* @return The path name minus the platform specific path separator.
*/
public static String removeSeparator(String path) {
return path.endsWith(File.separator) ? path.substring(0,
path.length() - 1) : path;
}
/**
* Removes the ending path separator from the given path.
*
* @param path
* The path name.
* @return The path name minus the path separator "\\" or "/".
*/
public static String removeAllSeparator(String path) {
return path.endsWith("/") || path.endsWith("\\") ? path.substring(0, path.length() - 1) : path; //$NON-NLS-1$ //$NON-NLS-2$
}
/**
* Removes the ending path separator from the given path.
*
* @param path
* The path name.
* @param separator
* The path separator.
* @return The path name minus the separator.
*/
public static String removeSeparator(String path, String separator) {
return path.endsWith(separator) ? path.substring(0, path.length() - 1)
: path;
}
/**
* Replaces the file name with another in the given path.
*
* @param path
* The path name.
* @param oldFileName
* The old file name.
* @param newFileName
* The new file name.
* @return The new path name with the new file name.
*/
public static String replaceFileName(String path, String oldFileName,
String newFileName) {
int index = path.lastIndexOf(oldFileName);
return path.substring(0, index) + newFileName;
}
/**
* Replaces the file extension with another in the given path.
*
* @param path
* The path name.
* @param oldFileExt
* The old file extension.
* @param newFileExt
* The new file extension.
* @return The new path with the new file extension.
*/
public static String replaceExtension(String path, String oldExt,
String newExt) {
int index = path.lastIndexOf(oldExt);
return path.substring(0, index) + newExt;
}
/**
* Returns the locale-specific path of a base path.
*
* @param path
* The base path name.
* @param localeStr
* The locale string.
* @return The locale-specific path.
*/
public static String getLocalePath(String path, String localeStr) {
if (StrUtil.isBlank(localeStr)) {
return path;
}
String fileName = getFileName(path);
return replaceFileName(path, fileName, localeStr + "/" + fileName); //$NON-NLS-1$
}
/**
* Returns the locale-specific path of a base path.
*
* @param path
* The base path name.
* @param locale
* The locale object.
* @return The locale-specific path.
*/
public static String getLocalePath(String path, Locale locale) {
return locale == null ? path : getLocalePath(path, locale.toString());
}
/**
* Writes the given text to a text file.
*
* @param fileName
* The target file name.
* @param text
* The text to write.
* @return true if the given text is written successfully to file.
*/
public static boolean writeFile(String filename, String text) {
FileWriter writer = null;
try {
writer = new FileWriter(filename);
writer.write(text);
writer.flush();
} catch (IOException e) {
} finally {
if (writer != null) {
try {
writer.close();
return true;
} catch (Exception e) {
}
}
}
return false;
}
/**
* Write the given text to a file with UTF-8 encoding.
*
* @param fileName
* The target file name.
* @param text
* The text to write.
* @param append ture to append to the end of the file, false to override the file
* @return true if the given text is written successfully to file.
*/
public static boolean writeUTF8File(String filename, String text) {
return writeUTF8File(filename, text, false);
}
/**
* Write the given text to a file with UTF-8 encoding.
*
* @param fileName
* The target file name.
* @param text
* The text to write.
* @param append ture to append to the end of the file, false to override the file
* @return true if the given text is written successfully to file.
*/
public static boolean writeUTF8File(String filename, String text, boolean append) {
OutputStreamWriter writer = null;
FileOutputStream fileOut = null;
try {
fileOut = new FileOutputStream(filename, append);
writer = new OutputStreamWriter(fileOut, ENCODING_UTF_8);
writer.write(text);
writer.flush();
fileOut.flush();
} catch (IOException e) {
e.printStackTrace();
} finally {
if (writer != null) {
try {
writer.close();
return true;
} catch (Exception e) {
}
}
if (fileOut != null) {
try {
fileOut.close();
return true;
} catch (Exception e) {
}
}
}
return false;
}
/**
* Write the content of the given URI to the given output stream.
*
* @param uri
* The source URI.
* @param output
* The output stream.
*/
public static void writeFile(String uri, OutputStream output)
throws IOException {
if (uri == null) {
return;
}
InputStream input = null;
try {
input = NetUtil.getInputStream(uri);
int bytesRead;
byte[] buf = new byte[4096];
while ((bytesRead = input.read(buf, 0, 4096)) > 0) {
output.write(buf, 0, bytesRead);
}
output.flush();
} finally {
if (input != null) {
try {
input.close();
} catch (Exception e) {
}
}
}
}
/**
* Write the content of the given URI to the given PrintWriter.
*
* @param uri
* The source URI.
* @param writer
* The PrintWriter obejct.
*/
public static void writeFile(String uri, PrintWriter pw) throws IOException {
if (uri == null) {
return;
}
InputStreamReader input = null;
try {
input = new InputStreamReader(NetUtil.getInputStream(uri));
int charsRead;
char[] buf = new char[4096];
while ((charsRead = input.read(buf, 0, 4096)) > 0) {
pw.write(buf, 0, charsRead);
}
pw.flush();
} finally {
if (input != null) {
try {
input.close();
} catch (Exception e) {
}
}
}
}
/**
* Recursively delete all sub-directories and files in the given directory.
* Does not delete the given directory.
*
* @param dir
* The directory containing the sub-directories and files.
* @return boolean true if delete successful
*/
public static boolean deleteAllFiles(String dir) {
boolean ret = true;
File targetDir = new File(dir);
File[] files = targetDir.listFiles();
if (files != null) {
for (int i = 0; i < files.length; i++) {
if (files[i].isDirectory()) {
ret = ret && deleteAllFiles(files[i].getAbsolutePath());
}
ret = ret && files[i].delete();
}
}
return ret;
}
/**
* Copies the content of the source file to the target file.
*
* @param srcFile
* The source file or path.
* @param tgtFile
* The target file or path.
*/
public static void copyFile(File srcFile, File tgtFile) throws IOException {
if (srcFile.equals(tgtFile))
return;
if (!srcFile.exists() || !srcFile.canRead()) {
return;
}
if (tgtFile.exists() && !tgtFile.canWrite()) {
return;
}
if (!srcFile.isFile()) {
File[] files = srcFile.listFiles();
if (files != null) {
for (int i = 0; i < files.length; i++) {
copyFile(files[i], tgtFile);
}
}
return;
}
FileInputStream src = null;
FileOutputStream tgt = null;
try {
src = new FileInputStream(srcFile);
if (tgtFile.isFile()) {
tgt = new FileOutputStream(tgtFile);
} else {
String srcPath = srcFile.toURL().toString();
int index = srcPath.lastIndexOf("/"); //$NON-NLS-1$
String srcFileName = srcPath.substring(index + 1);
String srcCanonicalPath = srcFile.getCanonicalPath();
String tgtCanonicalPath = new File(tgtFile, srcFileName).getCanonicalPath();
if (srcCanonicalPath.equals(tgtCanonicalPath)) {
return;
}
tgt = new FileOutputStream(new File(tgtFile, srcFileName));
}
byte[] buffer = new byte[4096];
int bytes_read;
while ((bytes_read = src.read(buffer)) != -1) {
tgt.write(buffer, 0, bytes_read);
}
} finally {
if (src != null) {
try {
src.close();
} catch (Exception e) {
}
}
if (tgt != null) {
try {
tgt.close();
} catch (Exception e) {
}
}
tgtFile.setLastModified(srcFile.lastModified());
}
}
/**
* Copies the content of the source file to the target file.
*
* @param srcFileName
* The source file name.
* @param tgtFileName
* The target file name.
*/
public static void copyFile(String srcFileName, String tgtFileName)
throws IOException {
copyFile(new File(srcFileName), new File(tgtFileName));
}
/**
* Copies the content of a directory to another directory.
*
* @param srcDirName
* The source directory name.
* @param tgtDirName
* The target directory name.
*/
public static void copyDir(String srcDirName, String tgtDirName)
throws IOException {
copyFile(new File(srcDirName), new File(tgtDirName));
}
/**
* Copies one file to another - operates ONLY on files, not on directories.
*
* @param source
* @param dest
* @throws IOException
*/
public static void copyfile(File source, File dest) throws IOException {
if (source.equals(dest))
return;
FileInputStream input = null;
FileOutputStream output = null;
try {
input = new FileInputStream(source);
FileChannel in = input.getChannel();
if (!dest.exists()) {
dest.getParentFile().mkdirs();
}
output = new FileOutputStream(dest);
FileChannel out = output.getChannel();
out.transferFrom(in, 0, source.length());
} finally {
if (input != null) {
try {
input.close();
} catch (IOException e) {
}
}
if (output != null) {
try {
output.close();
} catch (IOException e) {
}
}
}
}
public static void copydirectory(File sourceDir, File destDir)
throws IOException {
if (!sourceDir.exists() || !destDir.exists()) {
return;
}
if (!sourceDir.isDirectory() || !destDir.isDirectory()) {
return;
}
File[] files = sourceDir.listFiles();
if (files != null) {
for (int i = 0; i < files.length; i++) {
// calc destination name
String destName = destDir
+ File.separator
+ files[i].getAbsolutePath().substring(
sourceDir.getAbsolutePath().length() + 1);
if (files[i].isFile()) {
// copy the file
copyfile(files[i], new File(destName));
} else if (files[i].isDirectory()) {
// copy directory recursively
File destFile = new File(destName);
destFile.mkdirs();
copydirectory(files[i], destFile);
}
}
}
}
// for some reason, this guy locks the file, if you try to update the file,
// got the following exception
// java.io.FileNotFoundException:
// (The requested operation cannot be performed on a file with a user-mapped
// section open)
// need to handle later
public static CharBuffer readFile(File file) throws IOException {
FileInputStream input = null;
CharBuffer charBuffer = null;
try {
input = new FileInputStream(file);
FileChannel inChannel = input.getChannel();
int length = (int) inChannel.size();
MappedByteBuffer byteBuffer = inChannel.map(
FileChannel.MapMode.READ_ONLY, 0, length);
Charset charset = Charset.forName(ENCODING_ISO_8859_1);
CharsetDecoder decoder = charset.newDecoder();
charBuffer = decoder.decode(byteBuffer);
} finally {
if (input != null) {
try {
input.close();
} catch (IOException e) {
}
}
}
return charBuffer;
}
public static StringBuffer readFile(File file, String encoding)
throws IOException {
StringBuffer result = new StringBuffer();
FileInputStream fis = null;
InputStreamReader reader = null;
try {
char[] buffer = new char[1024];
fis = new FileInputStream(file);
reader = new InputStreamReader(fis, encoding);
int size;
while ((size = reader.read(buffer, 0, 1024)) > 0) {
result.append(buffer, 0, size);
}
} finally {
if (fis != null) {
fis.close();
}
if (reader != null) {
reader.close();
}
}
return result;
}
/**
* Uses Java 1.4's FileLock class to test for a file lock
*
* @param file
* @return
*/
public static boolean isFileLocked(File file) {
boolean isLocked = false;
FileOutputStream input = null;
FileLock lock = null;
if (!file.exists()) {
return false;
}
try {
input = new FileOutputStream(file);
FileChannel fileChannel = input.getChannel();
lock = fileChannel.tryLock();
if (lock == null)
isLocked = true;
else
lock.release();
} catch (Exception e) {
if (e instanceof SecurityException)
// Can't write to file.
isLocked = true;
else if (e instanceof FileNotFoundException)
isLocked = false;
else if (e instanceof IOException)
isLocked = true;
// OverlappingFileLockException means that this JVM has it locked
// therefore it is not locked to us
else if (e instanceof OverlappingFileLockException)
isLocked = false;
// Could not get a lock for some other reason.
else
isLocked = true;
} finally {
if (input != null) {
try {
input.close();
} catch (Exception ex) {
}
}
}
return isLocked;
}
/**
* Locks a file for the current JVM. Will create the file if it does not
* exist
*
* @param file
* @return a FileLock object, or null if file could not be locked
*/
public static FileLock lockFile(File file) {
FileOutputStream input = null;
FileLock lock = null;
try {
input = new FileOutputStream(file);
FileChannel fileChannel = input.getChannel();
lock = fileChannel.tryLock();
if (lock.isValid())
return lock;
} catch (Exception e) {
// Could not get a lock for some reason.
return null;
} finally {
try {
if (input != null && (lock == null || !lock.isValid())) {
input.close();
}
} catch (Exception ex) {
}
}
return null;
}
/**
* get all files in the specified path
* @param path, absolute path of a folder
* @param fileList List the list to collect the Files
* @param recursive boolean, if true find the files in sub folders as well
*/
public static void getAllFiles(File path, List fileList, boolean recursive)
{
// get all files in the specified folder
if (path.isDirectory())
{
File[] files = path.listFiles();
if (files != null)
{
for (int i = 0; i < files.length; i++)
{
if ( files[i].isFile() )
{
fileList.add(files[i]);
}
else if (recursive)
{
getAllFiles(files[i], fileList, recursive);
}
}
}
}
}
/**
* given a directory and extension, returns all files (recursively) whose
* extension startsWith the given extension
*
* @param f
* @param extension
* @return
*/
public static List fileList(File f, String extension) {
extension = extension.toUpperCase();
List returnList = new ArrayList();
try {
if (f.isDirectory()) { // if dir then recurse
String[] flist = f.list();
for (int i = 0; i < flist.length; ++i) {
File fc = new File(f.getPath(), flist[i]);
returnList.addAll(fileList(fc, extension));
}
} else { // ordinary file
if (extension != null) {
String name = f.getName().toUpperCase();
if (name.lastIndexOf(".") != -1) //$NON-NLS-1$
if (name
.substring(name.lastIndexOf(".") + 1).startsWith(extension)) { //$NON-NLS-1$
returnList.add(f);
}
} else
returnList.add(f);
}
} catch (Exception ex) {
ex.printStackTrace();
}
return returnList;
}
/**
* given a directory and extension, returns all files (recursively)whose
* extension does not startsWith the given extension
*
* @param f
* @param extension
* @return
*/
public static List fileListExcludeExt(File f, String extension) {
List returnList = new ArrayList();
try {
if (f.isDirectory()) { // if dir then recurse
String[] flist = f.list();
for (int i = 0; i < flist.length; ++i) {
File fc = new File(f.getPath(), flist[i]);
returnList.addAll(fileListExcludeExt(fc, extension));
}
} else { // ordinary file
if (extension != null) {
String name = f.getName();
if (name.lastIndexOf(".") != -1) //$NON-NLS-1$
if (!(name.substring(name.lastIndexOf(".") + 1).startsWith(extension))) { //$NON-NLS-1$
returnList.add(f);
}
} else
returnList.add(f);
}
} catch (Exception ex) {
ex.printStackTrace();
}
return returnList;
}
/**
* get all file paths in the specified path
* @param path, absolute path of a folder
* @param recursive boolean, if true find the files in sub folders as well
*/
public static ArrayList getAllFileAbsolutePaths(File path, boolean recursive) {
ArrayList files = new ArrayList();
getAllFiles(path, files, recursive);
ArrayList paths = new ArrayList();
for (int i=0; i<files.size(); i++) {
String absPath = ((File) files.get(i)).getAbsolutePath();
paths.add(absPath);
}
return paths;
}
/**
* Moves a file
*
* Attempts to rename the file first. If that fails,
* will copy the sourceFile to destFile and delete the sourceFile.
* @param sourceFile
* @param destFile
* @return
*/
public static boolean moveFile(File sourceFile, File destFile) {
try {
// first try the renameTo method
if (sourceFile.renameTo(destFile)) {
return true;
}
else {
// try to copy file, delete original
copyfile(sourceFile, destFile);
sourceFile.delete();
return true;
}
} catch (Exception t) {
CommonPlugin.getDefault().getLogger().logError(t);
return false;
}
}
}