/*
* JBoss, Home of Professional Open Source.
* See the COPYRIGHT.txt file distributed with this work for information
* regarding copyright ownership. Some portions may be licensed
* to Red Hat, Inc. under one or more contributor license agreements.
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
* License as published by the Free Software Foundation; either
* version 2.1 of the License, or (at your option) any later version.
*
* This library is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public
* License along with this library; if not, write to the Free Software
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
* 02110-1301 USA.
*/
package org.teiid.core.util;
import java.io.*;
import java.util.ArrayList;
import java.util.List;
import org.teiid.core.CorePlugin;
import org.teiid.core.TeiidException;
import org.teiid.core.TeiidRuntimeException;
public final class FileUtils {
public interface Constants {
char CURRENT_FOLDER_SYMBOL_CHAR = '.';
char DRIVE_SEPARATOR_CHAR = ':';
char FILE_EXTENSION_SEPARATOR_CHAR = '.';
char FILE_NAME_WILDCARD_CHAR = '*';
String CURRENT_FOLDER_SYMBOL = String.valueOf(CURRENT_FOLDER_SYMBOL_CHAR);
String DRIVE_SEPARATOR = String.valueOf(DRIVE_SEPARATOR_CHAR);
String FILE_EXTENSION_SEPARATOR = String.valueOf(FILE_EXTENSION_SEPARATOR_CHAR);
String FILE_NAME_WILDCARD = String.valueOf(FILE_NAME_WILDCARD_CHAR);
String PARENT_FOLDER_SYMBOL = ".."; //$NON-NLS-1$
}
public static final char SEPARATOR = '/';
public static int DEFAULT_BUFFER_SIZE = 2048;
public static String TEMP_DIRECTORY;
public static String LINE_SEPARATOR = System.getProperty("line.separator"); //$NON-NLS-1$
public static char[] LINE_SEPARATOR_CHARS = LINE_SEPARATOR.toCharArray();
public final static String JAVA_IO_TEMP_DIR="java.io.tmpdir";//$NON-NLS-1$
public final static char[] SUFFIX_class = ".class".toCharArray(); //$NON-NLS-1$
public final static char[] SUFFIX_CLASS = ".CLASS".toCharArray(); //$NON-NLS-1$
public final static char[] SUFFIX_java = ".java".toCharArray(); //$NON-NLS-1$
public final static char[] SUFFIX_JAVA = ".JAVA".toCharArray(); //$NON-NLS-1$
public final static char[] SUFFIX_jar = ".jar".toCharArray(); //$NON-NLS-1$
public final static char[] SUFFIX_JAR = ".JAR".toCharArray(); //$NON-NLS-1$
public final static char[] SUFFIX_zip = ".zip".toCharArray(); //$NON-NLS-1$
public final static char[] SUFFIX_ZIP = ".ZIP".toCharArray(); //$NON-NLS-1$
static {
String tempDirPath = System.getProperty(JAVA_IO_TEMP_DIR);
TEMP_DIRECTORY = (tempDirPath.endsWith(File.separator) ? tempDirPath : tempDirPath + File.separator);
}
private FileUtils() {}
/**<p>
* Convert the specified file name to end with the specified extension if it doesn't already end with an extension.
* </p>
* @param name
* The file name.
* @param extension
* The extension to append to the file name.
* @return The file name with an extension.
* @since 4.0
*/
public static String toFileNameWithExtension(final String name,
final String extension) {
return toFileNameWithExtension(name, extension, false);
}
/**<p>
* Convert the specified file name to end with the specified extension if it doesn't already end with an extension. If force
* is true, the specified extension will be appended to the name if the name doesn't end with that particular extension.
* </p>
* @param name
* The file name.
* @param extension
* The extension to append to the file name.
* @param force
* Indicates whether to force the specified extension as the extension of the file name.
* @return The file name with an extension.
* @since 4.0
*/
public static String toFileNameWithExtension(final String name,
final String extension,
final boolean force) {
if (name == null) {
final String msg = CorePlugin.Util.getString("FileUtils.The_name_of_the_file_may_not_be_null"); //$NON-NLS-1$
throw new IllegalArgumentException(msg);
}
if (extension == null) {
final String msg = CorePlugin.Util.getString("FileUtils.The_file_extension_may_not_be_null"); //$NON-NLS-1$
throw new IllegalArgumentException(msg);
}
if (name.endsWith(extension)) {
return name;
}
if (!force && name.indexOf(Constants.FILE_EXTENSION_SEPARATOR_CHAR) >= 0) {
return name;
}
final int nameLen = name.length() - 1;
final int extLen = extension.length();
final boolean nameEndsWithExtChr = (nameLen >= 0 && name.charAt(nameLen) == Constants.FILE_EXTENSION_SEPARATOR_CHAR);
final boolean extBeginsWithExtChr = (extLen > 0 && extension.charAt(0) == Constants.FILE_EXTENSION_SEPARATOR_CHAR);
if (nameEndsWithExtChr && extBeginsWithExtChr) {
return name.substring(0, nameLen) + extension;
}
if (!nameEndsWithExtChr && !extBeginsWithExtChr) {
return name + Constants.FILE_EXTENSION_SEPARATOR + extension;
}
return name + extension;
}
/**
* Determine whether the specified name is valid for a file or folder on the current file system.
* @param newName the new name to be checked
* @return true if the name is null or contains no invalid characters for a folder or file, or false otherwise
*/
public static boolean isFilenameValid( String newName ) {
return true; //TODO: just catch an exception when the file is accessed or created
}
/**
* Copy a file. Overwrites the destination file if it exists.
* @param fromFileName
* @param toFileName
* @throws Exception
* @since 4.3
*/
public static void copy(String fromFileName, String toFileName) throws IOException {
copy(fromFileName, toFileName, true);
}
/**
* Copy a file
* @param fromFileName
* @param toFileName
* @param overwrite whether to overwrite the destination file if it exists.
* @throws TeiidException
* @since 4.3
*/
public static void copy(String fromFileName, String toFileName, boolean overwrite) throws IOException {
File toFile = new File(toFileName);
if (toFile.exists()) {
if (overwrite) {
toFile.delete();
} else {
final String msg = CorePlugin.Util.getString("FileUtils.File_already_exists", toFileName); //$NON-NLS-1$
throw new IOException(msg);
}
}
File fromFile = new File(fromFileName);
if (!fromFile.exists()) {
throw new FileNotFoundException(CorePlugin.Util.getString("FileUtils.File_does_not_exist._1", fromFileName)); //$NON-NLS-1$
}
FileInputStream fis = null;
try {
fis = new FileInputStream(fromFile);
write(fis, toFileName);
} finally {
if (fis != null) {
fis.close();
}
}
}
/**
* Copy recursively the contents of <code>sourceDirectory</code> to
* the <code>targetDirectory</code>. Note that <code>sourceDirectory</code>
* will <b>NOT</b> be copied. If <code>targetDirectory</code> does not exist, it will be created.
* @param sourceDirectory The source directory to copy
* @param targetDirectory The target directory to copy to
* @throws Exception If the source directory does not exist.
* @since 4.3
*/
public static void copyDirectoryContentsRecursively(File sourceDirectory, File targetDirectory) throws Exception {
copyRecursively(sourceDirectory, targetDirectory, false);
}
/**
* Copy file from orginating directory to the destination directory.
*
* @param orginDirectory
* @param destDirectory
* @param fileName
* @throws Exception
* @since 4.4
*/
public static void copyFile(String orginDirectory,
String destDirectory,
String fileName) throws Exception {
copyFile(orginDirectory, fileName, destDirectory, fileName);
}
/**
* Copy file from orginating directory to the destination directory.
*
* @param orginDirectory
* @param orginFileName
* @param destDirectory
* @param destFileName
* @throws Exception
* @since 4.4
*/
public static void copyFile(String orginDirectory,
String orginFileName,
String destDirectory,
String destFileName) throws Exception {
FileUtils.copy(orginDirectory + File.separator + orginFileName, destDirectory + File.separator + destFileName);
}
/**
* Copy recursively the <code>sourceDirectory</code> and all its contents
* to the <code>targetDirectory</code>. If <code>targetDirectory</code>
* does not exist, it will be created.
* @param sourceDirectory The source directory to copy
* @param targetDirectory The target directory to copy to
* @throws Exception If the source directory does not exist.
* @since 4.3
*/
public static void copyDirectoriesRecursively(File sourceDirectory, File targetDirectory) throws Exception {
copyRecursively(sourceDirectory, targetDirectory, true);
}
/**
* Copy recursively from the <code>sourceDirectory</code> all its contents
* to the <code>targetDirectory</code>. if
* <code>includeSourceRoot<code> == <code>true</code>, copy <code>sourceDirectory</code>
* itself, else only copy <code>sourceDirectory</code>'s contents.
* If <code>targetDirectory</code> does not exist, it will be created.
* @param sourceDirectory
* @param targetDirectory
* @throws FileNotFoundException
* @throws Exception
* @since 4.3
*/
private static void copyRecursively(File sourceDirectory,
File targetDirectory,
boolean includeSourceRoot) throws FileNotFoundException,
Exception {
if (!sourceDirectory.exists()) {
throw new FileNotFoundException(CorePlugin.Util.getString("FileUtils.File_does_not_exist._1",sourceDirectory)); //$NON-NLS-1$
}
if (!sourceDirectory.isDirectory()) {
throw new FileNotFoundException(CorePlugin.Util.getString("FileUtils.Not_a_directory",sourceDirectory)); //$NON-NLS-1$
}
File targetDir = new File(targetDirectory.getAbsolutePath() + File.separatorChar + sourceDirectory.getName());
if (includeSourceRoot) {
// copy source directory
targetDir.mkdir();
} else {
// copy only source directory contents
targetDir = new File(targetDirectory.getAbsolutePath() + File.separatorChar);
}
File[] sourceFiles = sourceDirectory.listFiles();
for (int i = 0; i < sourceFiles.length; i++) {
File srcFile = sourceFiles[i];
if (srcFile.isDirectory()) {
File childTargetDir = new File(targetDir.getAbsolutePath());
copyRecursively(srcFile, childTargetDir, true);
} else {
copy(srcFile.getAbsolutePath(), targetDir.getAbsolutePath() + File.separatorChar + srcFile.getName());
}
}
}
/**
* Write an InputStream to a file.
*/
public static void write(InputStream is, String fileName) throws IOException {
File f = new File(fileName);
write(is,f);
}
/**
* Write an InputStream to a file.
*/
public static void write(InputStream is, File f) throws IOException {
write(is, f, DEFAULT_BUFFER_SIZE);
}
/**
* Write an InputStream to a file.
*/
public static void write(InputStream is, File f, int bufferSize) throws IOException {
f.delete();
final File parentDir = f.getParentFile();
if (parentDir !=null) {
parentDir.mkdirs();
}
FileOutputStream fio = null;
BufferedOutputStream bos = null;
try {
fio = new FileOutputStream(f);
bos = new BufferedOutputStream(fio);
if (bufferSize > 0) {
byte[] buff = new byte[bufferSize];
int bytesRead;
// Simple read/write loop.
while(-1 != (bytesRead = is.read(buff, 0, buff.length))) {
bos.write(buff, 0, bytesRead);
}
}
bos.flush();
} finally {
if (bos != null) {
bos.close();
}
if (fio != null) {
fio.close();
}
}
}
/**
* Write an File to an OutputStream
* Note: this will not close the outputStream;
*/
public static void write(File f, OutputStream outputStream) throws IOException {
write(f, outputStream, DEFAULT_BUFFER_SIZE);
}
/**
* Write an File to an OutputStream
* Note: this will not close the outputStream;
*/
public static void write(File f, OutputStream outputStream, int bufferSize) throws IOException {
FileInputStream fis = null;
try {
fis = new FileInputStream(f);
write(fis, outputStream, bufferSize);
} finally {
if (fis != null) {
fis.close();
}
}
}
/**
* Write the given input stream to outputstream
* Note: this will not close in/out streams
*/
public static void write(InputStream fis, OutputStream outputStream, int bufferSize) throws IOException {
byte[] buff = new byte[bufferSize];
int bytesRead;
// Simple read/write loop.
while(-1 != (bytesRead = fis.read(buff, 0, buff.length))) {
outputStream.write(buff, 0, bytesRead);
}
outputStream.flush();
}
/**
* Write a byte array to a file.
*/
public static void write(byte[] data, String fileName) throws IOException {
ByteArrayInputStream bais = null;
InputStream is = null;
try {
bais = new ByteArrayInputStream(data);
is = new BufferedInputStream(bais);
write(is, fileName);
} finally {
if (is != null) {
is.close();
}
if (bais != null) {
bais.close();
}
}
}
/**
* Write a byte array to a file.
*/
public static void write(byte[] data, File file) throws IOException {
ByteArrayInputStream bais = null;
InputStream is = null;
try {
bais = new ByteArrayInputStream(data);
is = new BufferedInputStream(bais);
write(is, file);
} finally {
if (is != null) {
is.close();
}
if (bais != null) {
bais.close();
}
}
}
/**
* Returns a <code>File</code> array that will contain all the files that
* exist in the specified directory or any nested directories
* @return File[] of files in the directory
*/
public static File[] findAllFilesInDirectoryRecursively(final String dir) {
// Recursively navigate through the contents of this directory
// gathering up all the files
List allFiles = new ArrayList();
File directory = new File(dir);
addFilesInDirectoryRecursively(directory, allFiles);
return (File[])allFiles.toArray(new File[allFiles.size()]);
}
private static void addFilesInDirectoryRecursively(final File directory, final List allFiles) {
File[] files = directory.listFiles();
if (files != null) {
for (int i=0; i < files.length; i++) {
File file = files[i];
if (file.isDirectory()) {
addFilesInDirectoryRecursively(file, allFiles);
} else {
allFiles.add(file);
}
}
}
}
/**
* Returns a <code>File</code> array that will contain all the files that exist in the directory
*
* @return File[] of files in the directory
*/
public static File[] findAllFilesInDirectory(String dir) {
// Find all files in the specified directory
File modelsDirFile = new File(dir);
FileFilter fileFilter = new FileFilter() {
public boolean accept(File file) {
if (file.isDirectory()) {
return false;
}
String fileName = file.getName();
if (fileName == null || fileName.length() == 0) {
return false;
}
return true;
}
};
File[] modelFiles = modelsDirFile.listFiles(fileFilter);
return modelFiles;
}
/**
* @param string
* @return
*/
public static String getFilenameWithoutExtension( final String filename ) {
if ( filename == null || filename.length() == 0 ) {
return filename;
}
final int extensionIndex = filename.lastIndexOf(Constants.FILE_EXTENSION_SEPARATOR_CHAR);
if ( extensionIndex == -1 ) {
return filename; // not found
}
if ( extensionIndex == 0 ) {
return ""; //$NON-NLS-1$
}
return filename.substring(0,extensionIndex);
}
public static String getBaseFileNameWithoutExtension(String path) {
return StringUtil.getFirstToken(StringUtil.getLastToken(path, "/"), "."); //$NON-NLS-1$ //$NON-NLS-2$
}
/**
* Obtains the file extension of the specified <code>File</code>. The extension is considered to be all the
* characters after the last occurrence of {@link Constants#FILE_EXTENSION_SEPARATOR_CHAR} in the pathname
* of the input.
* @param theFile the file whose extension is being requested
* @return the extension or <code>null</code> if not found
* @since 4.2
*/
public static String getExtension(File theFile) {
return getExtension(theFile.getPath());
}
/**
* Obtains the file extension of the specified file name. The extension is considered to be all the
* characters after the last occurrence of {@link Constants#FILE_EXTENSION_SEPARATOR_CHAR}.
* @param theFileName the file whose extension is being requested
* @return the extension or <code>null</code> if not found
* @since 4.2
*/
public static String getExtension(String theFileName) {
String result = null;
final int index = theFileName.lastIndexOf(Constants.FILE_EXTENSION_SEPARATOR_CHAR);
// make sure extension char is found and is not the last char in the path
if ((index != -1) && ((index + 1) != theFileName.length())) {
result = theFileName.substring(index + 1);
}
return result;
}
/**
* Returns true iff str.toLowerCase().endsWith(".jar") || str.toLowerCase().endsWith(".zip")
* implementation is not creating extra strings.
*/
public final static boolean isArchiveFileName(String name) {
int nameLength = name == null ? 0 : name.length();
int suffixLength = SUFFIX_JAR.length;
if (nameLength < suffixLength) return false;
// try to match as JAR file
for (int i = 0; i < suffixLength; i++) {
char c = name.charAt(nameLength - i - 1);
int suffixIndex = suffixLength - i - 1;
if (c != SUFFIX_jar[suffixIndex] && c != SUFFIX_JAR[suffixIndex]) {
// try to match as ZIP file
suffixLength = SUFFIX_ZIP.length;
if (nameLength < suffixLength) return false;
for (int j = 0; j < suffixLength; j++) {
c = name.charAt(nameLength - j - 1);
suffixIndex = suffixLength - j - 1;
if (c != SUFFIX_zip[suffixIndex] && c != SUFFIX_ZIP[suffixIndex]) return false;
}
return true;
}
}
return true;
}
/**
* Returns true iff str.toLowerCase().endsWith(".class")
* implementation is not creating extra strings.
*/
public final static boolean isClassFileName(String name) {
int nameLength = name == null ? 0 : name.length();
int suffixLength = SUFFIX_CLASS.length;
if (nameLength < suffixLength) return false;
for (int i = 0; i < suffixLength; i++) {
char c = name.charAt(nameLength - i - 1);
int suffixIndex = suffixLength - i - 1;
if (c != SUFFIX_class[suffixIndex] && c != SUFFIX_CLASS[suffixIndex]) return false;
}
return true;
}
/**
* Returns true iff str.toLowerCase().endsWith(".java")
* implementation is not creating extra strings.
*/
public final static boolean isJavaFileName(String name) {
int nameLength = name == null ? 0 : name.length();
int suffixLength = SUFFIX_JAVA.length;
if (nameLength < suffixLength) return false;
for (int i = 0; i < suffixLength; i++) {
char c = name.charAt(nameLength - i - 1);
int suffixIndex = suffixLength - i - 1;
if (c != SUFFIX_java[suffixIndex] && c != SUFFIX_JAVA[suffixIndex]) return false;
}
return true;
}
public static File convertByteArrayToFile(final byte[] contents, final String parentDirectoryPath, final String fileName) {
if (contents != null) {
FileOutputStream os = null;
try {
final File temp = new File(parentDirectoryPath,fileName);
os = new FileOutputStream(temp);
os.write(contents);
return temp;
} catch (Exception e) {
throw new TeiidRuntimeException(CorePlugin.Event.TEIID10024, e);
} finally {
if (os != null) {
try {
os.close();
} catch (IOException e1) {
// do nothing
}
}
}
}
return null;
}
public static void removeDirectoryAndChildren(File directory) {
removeChildrenRecursively(directory);
if(!directory.delete()) {
directory.deleteOnExit();
}
}
public static void removeChildrenRecursively(File directory) {
File[] files = directory.listFiles();
if(files != null) {
for(int i=0; i < files.length; i++) {
File file = files[i];
if (file.isDirectory()) {
removeDirectoryAndChildren(file);
} else {
if(!file.delete()) {
file.deleteOnExit();
}
}
}
}
}
/**
* Builds a file directory path from a physical location and a location that needs
* to be appended to the physical. This is used so that the correct File.separator
* is used and that no additional separator is added when not needed.
* @param physicalDirectory
* @param appendLocation
* @return
* @since 4.3
*/
public static String buildDirectoryPath(String[] paths) {
// String physicalDirectory, String appendLocation) {
if (paths == null || paths.length == 0) {
return ""; //$NON-NLS-1$
}
if (paths.length == 1) {
return (paths[0]!=null?paths[0]:"");//$NON-NLS-1$
}
int l = paths.length;
StringBuffer sb = new StringBuffer();
for (int cur=0;cur<l; cur++) {
int next = cur+1;
String value = paths[cur]!=null?paths[cur]:"";//$NON-NLS-1$
if (value.equals("")) {//$NON-NLS-1$
continue;
}
sb.append(value);
if (next < l) {
String nextValue = paths[next]!=null?paths[next]:"";//$NON-NLS-1$
if (value.endsWith(File.separator)) {
} else if (!nextValue.startsWith(File.separator)) {
sb.append(File.separator);
}
}
}
return sb.toString();
}
/**
* Rename a file.
* @param oldFilePath
* @param newFilePath
* @param overwrite If true, overwrite the old file if it exists. If false, throw an exception if the old file exists.
* @throws TeiidException
* @since 4.3
*/
public static void rename(String oldFilePath, String newFilePath, boolean overwrite) throws IOException {
File oldFile = new File(oldFilePath);
File newFile = new File(newFilePath);
if (newFile.exists()) {
if (overwrite) {
newFile.delete();
} else {
final String msg = CorePlugin.Util.getString("FileUtils.File_already_exists", newFilePath); //$NON-NLS-1$
throw new IOException(msg);
}
}
boolean renamed = oldFile.renameTo(newFile);
//Sometimes file.renameTo will silently fail, for example attempting to rename from different UNIX partitions.
//Try to copy instead.
if (!renamed) {
copy(oldFilePath, newFilePath);
oldFile.delete();
}
}
public static void remove(File file) {
if (file.exists()) {
file.delete();
}
}
public static void remove(String filePath) throws IOException {
File file = new File(filePath);
if (file.exists()) {
file.delete();
}
}
}