Java tutorial
/* * 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.jboss.bqt.core.util; import java.io.BufferedInputStream; import java.io.BufferedOutputStream; import java.io.ByteArrayInputStream; import java.io.File; import java.io.FileFilter; import java.io.FileInputStream; import java.io.FileNotFoundException; import java.io.FileOutputStream; import java.io.IOException; import java.io.InputStream; import java.io.OutputStream; import java.util.ArrayList; import java.util.List; import org.apache.commons.lang.StringUtils; import org.jboss.bqt.core.CorePlugin; import org.jboss.bqt.core.exception.FrameworkException; import org.jboss.bqt.core.exception.FrameworkRuntimeException; 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$ private static final String TEMP_FILE = "delete.me"; //$NON-NLS-1$ private static final String TEMP_FILE_RENAMED = "delete.me.old"; //$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 IOException * @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 IOException * @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 * @param includeSourceRoot * @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. * @param is * @param fileName * @throws IOException */ public static void write(InputStream is, String fileName) throws IOException { File f = new File(fileName); write(is, f); } /** * Write an InputStream to a file. * @param is * @param f * @throws IOException */ public static void write(InputStream is, File f) throws IOException { write(is, f, DEFAULT_BUFFER_SIZE); } /** * Write an InputStream to a file. * @param is * @param f * @param bufferSize * @throws IOException */ 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; * @param f * @param outputStream * @throws IOException */ 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; * @param f * @param outputStream * @param bufferSize * @throws IOException */ 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 * @param fis * @param outputStream * @param bufferSize * @throws IOException */ 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. * @param data * @param fileName * @throws IOException */ 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. * @param data * @param file * @throws IOException */ 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 * @param dir * * @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 * @param dir * * @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; } /** * Returns a <code>File</code> array that will contain all the files that * exist in the directory that have the specified extension. * @param dir * @param extension * * @return File[] of files having a certain extension */ public static File[] findAllFilesInDirectoryHavingExtension(String dir, final String extension) { // Find all files in that directory that end in XML and attempt to // load them into the runtime metadata database. 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; } // here we check to see if the file is an .xml file... int index = fileName.lastIndexOf("."); //$NON-NLS-1$ if (index < 0 || index == fileName.length()) { return false; } if (fileName.substring(index, fileName.length()).equalsIgnoreCase(extension)) { return true; } return false; } }; File[] modelFiles = modelsDirFile.listFiles(fileFilter); return modelFiles; } /** * @param filename * @return String */ 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) { String name = StringUtils.substringAfterLast(path, File.separator); if (name == null || name.length() == 0) name = path; return StringUtils.substringBefore(name, "."); } /** * 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. * @param name * @return boolean */ 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. * @param name * @return boolean */ 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. * @param name * @return boolean */ 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 FrameworkRuntimeException(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 paths * @return String * * @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(); } /** * Test whether it's possible to read and write files in the specified * directory. * * @param dirPath * Name of the directory to test * @throws FrameworkException * @since 4.3 */ public static void testDirectoryPermissions(String dirPath) throws FrameworkException { // try to create a file File tmpFile = new File(dirPath + File.separatorChar + TEMP_FILE); boolean success = false; try { success = tmpFile.createNewFile(); } catch (IOException e) { } if (!success) { final String msg = CorePlugin.Util.getString("FileUtils.Unable_to_create_file_in", dirPath); //$NON-NLS-1$ throw new FrameworkException(msg); } // test if file can be written to if (!tmpFile.canWrite()) { final String msg = CorePlugin.Util.getString("FileUtils.Unable_to_write_file_in", dirPath); //$NON-NLS-1$ throw new FrameworkException(msg); } // test if file can be read if (!tmpFile.canRead()) { final String msg = CorePlugin.Util.getString("FileUtils.Unable_to_read_file_in", dirPath); //$NON-NLS-1$ throw new FrameworkException(msg); } // test if file can be renamed File newFile = new File(dirPath + File.separatorChar + TEMP_FILE_RENAMED); success = false; try { success = tmpFile.renameTo(newFile); } catch (Exception e) { } if (!success) { final String msg = CorePlugin.Util.getString("FileUtils.Unable_to_rename_file_in", dirPath); //$NON-NLS-1$ throw new FrameworkException(msg); } // test if file can be deleted success = false; try { success = newFile.delete(); } catch (Exception e) { } if (!success) { final String msg = CorePlugin.Util.getString("FileUtils.Unable_to_delete_file_in", dirPath); //$NON-NLS-1$ throw new FrameworkException(msg); } } /** * 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 IOException * @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(String filePath) throws IOException { File file = new File(filePath); if (file.exists()) { file.delete(); } } }