/* * 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(); } } }