com.redhat.ceylon.common.FileUtil Maven / Gradle / Ivy
package com.redhat.ceylon.common;
import java.io.File;
import java.io.IOException;
import java.nio.file.FileVisitResult;
import java.nio.file.Files;
import java.nio.file.Path;
import java.nio.file.SimpleFileVisitor;
import java.nio.file.StandardCopyOption;
import java.nio.file.attribute.BasicFileAttributes;
import java.util.ArrayList;
import java.util.Collection;
import java.util.Collections;
import java.util.List;
import java.util.regex.Pattern;
public class FileUtil {
/**
* Create a temporary directory
* @param prefix The prefix to use for the directory name
* @return a File pointing to the new directory
* @throws RuntimeException if the directory could not be created
*/
public static File makeTempDir(String prefix){
try {
return Files.createTempDirectory(prefix).toFile();
} catch (IOException e) {
throw new RuntimeException(e);
}
}
/**
* Delete a file or directory
* @param f The file or directory to be deleted
* @throws RuntimeException if the file or directory could not be deleted
*/
public static void delete(File f) {
delete_(f, false);
}
/**
* Try to delete a file or as much of a directory as it can.
* Doesn't throw any errors
* @param f The file or directory to be deleted
*/
public static void deleteQuietly(File f) {
if (!delete_(f, true)) {
// As a last resort
f.deleteOnExit();
}
}
private static boolean delete_(File f, boolean silent) {
boolean ok = true;
if (f.exists()) {
if (f.isDirectory()) {
for (File c : f.listFiles()) {
ok = ok && delete_(c, silent);
}
}
try {
boolean deleted = f.delete();
ok = ok && deleted;
if (!deleted && !silent) {
throw new RuntimeException("Failed to delete file or directory: " + f.getPath());
}
} catch (Exception ex) {
ok = false;
if (!silent) {
throw new RuntimeException("Failed to delete file or directory: " + f.getPath(), ex);
}
}
}
return ok;
}
/**
* Turns the given file into the best absolute representation available
* @param file A file
* @return A canonical or absolute file
*/
public static File absoluteFile(File file) {
if (file != null) {
try {
file = file.getCanonicalFile();
} catch (IOException e) {
file = file.getAbsoluteFile();
}
}
return file;
}
/**
* Given a list of files and a "current working directory"
* returns the list where the files that were relative are
* now absolute after having the "CWD" applied to them
* as their parent directory. Files in the list that were
* already absolute are returned unmodified.
* @param cwd The current working directory
* @param files A list of files
* @return A list of absolute files
*/
public static List applyCwd(File cwd, List files) {
if (files != null) {
List result = new ArrayList(files.size());
for (File f : files) {
result.add(applyCwd(cwd, f));
}
return result;
} else {
return null;
}
}
/**
* Given an Iterable of files and a "current working directory"
* returns an Iterable where the files that were relative are
* now absolute after having the "CWD" applied to them
* as their parent directory. Files in the list that were
* already absolute are returned unmodified.
* @param cwd The current working directory
* @param files An Iterable of files
* @return An Iterable of absolute files
*/
public static Iterable applyCwd(File cwd, Iterable files) {
if (files != null) {
List result = new ArrayList();
for (File f : files) {
result.add(applyCwd(cwd, f));
}
return result;
} else {
return null;
}
}
/**
* Given a file and a "current working directory" returns
* an absolute file after having the "CWD" applied to it
* first as its parent directory. If the file was already
* absolute to begin with it is returned unmodified.
* @param cwd The current working directory
* @param files A file
* @return An absolute file
*/
public static File applyCwd(File cwd, File file) {
if (cwd != null && !cwd.getPath().equals(".") && file != null && !file.isAbsolute()) {
File absCwd = absoluteFile(cwd);
file = new File(absCwd, file.getPath());
}
return file;
}
/**
* Given a file and a possible parent folder returns
* the file relative to the parent. If the file wasn't
* relative to the parent it is returned unmodified.
* @param root A possible parent file
* @param file A file
* @return A file relative to the parent
*/
public static File relativeFile(File root, File file) {
if (root != null && file != null) {
String absRoot = absoluteFile(root).getPath();
String absFile = absoluteFile(file).getPath();
if (absFile.startsWith(absRoot)) {
String path = absFile.substring(absRoot.length());
if (path.startsWith(File.separator)) {
path = path.substring(1);
}
file = new File(path);
}
}
return file;
}
/**
* Turns the given path, if absolute, into a path relative to the
* VM's current working directory and leaves it alone otherwise
* @param f The File to make relative
* @return A relative File
*/
public static File relativeFile(File f) {
if (f.isAbsolute()) {
f = relativeFile(new File("."), f);
}
return f;
}
/**
* The OS-specific directory where global application data can be stored.
* As given by the {@code ceylon.config.dir} system property or the default
* OS-dependent directory if the property doesn't exist. (/etc/ceylon on
* Unix-like systems and %ALLUSERSPROFILE%/ceylon on Windows)
*/
public static File getSystemConfigDir() {
File configDir = null;
String ceylonConfigDir = System.getProperty(Constants.PROP_CEYLON_CONFIG_DIR);
if (ceylonConfigDir != null) {
configDir = new File(ceylonConfigDir);
} else {
if (OSUtil.isWindows()) {
String appDir = System.getenv("ALLUSERSPROFILE");
if (appDir != null) {
configDir = new File(appDir, "ceylon");
}
} else if (OSUtil.isMac()) {
configDir = new File("/etc/ceylon");
} else {
// Assume a "regular" unix OS
configDir = new File("/etc/ceylon");
}
}
return configDir;
}
/**
* The installation directory. As given by the {@code ceylon.home}
* system property
*/
public static File getInstallDir() {
String ceylonHome = System.getProperty(Constants.PROP_CEYLON_HOME_DIR);
if (ceylonHome != null) {
return new File(ceylonHome);
} else {
return null;
}
}
/**
* The default user directory, that is {@code ~/.ceylon}.
*/
public static File getDefaultUserDir() {
String userHome = System.getProperty("user.home");
return new File(userHome, ".ceylon");
}
/**
* The effective user directory, checking the {@code ceylon.user.dir}
* system property then defaulting to {@link getDefaultUserDir}.
*/
public static File getUserDir() {
String ceylonUserDir = System.getProperty(Constants.PROP_CEYLON_USER_DIR);
if (ceylonUserDir != null) {
return new File(ceylonUserDir);
} else {
return getDefaultUserDir();
}
}
/**
* Returns the environment variable {@code PATH} as an array of {@code File}.
* If the value was empty a array of size 0 will be returned.
*/
public static File[] getExecPath() {
String path = System.getenv("PATH");
if (path != null && !path.isEmpty()) {
String[] items = path.split(Pattern.quote(File.pathSeparator));
File[] result = new File[items.length];
for (int i = 0; i < items.length; i++) {
result[i] = new File(items[i]);
}
return result;
} else {
return EMPTY_FILES;
}
}
private static final String[] EMPTY_STRINGS = new String[0];
private static final File[] EMPTY_FILES = new File[0];
public static List pathsToFileList(Collection paths) {
if (paths != null) {
List result = new ArrayList(paths.size());
for (String s : paths) {
result.add(new File(s));
}
return result;
} else {
return Collections.emptyList();
}
}
public static File[] pathsToFileArray(String[] paths) {
if (paths != null) {
File[] result = new File[paths.length];
int idx = 0;
for (String s : paths) {
result[idx++] = new File(s);
}
return result;
} else {
return EMPTY_FILES;
}
}
public static List filesToPathList(Collection files) {
if (files != null) {
List result = new ArrayList(files.size());
for (File f : files) {
result.add(f.getPath());
}
return result;
} else {
return Collections.emptyList();
}
}
public static String[] filesToPathArray(File[] files) {
if (files != null) {
String[] result = new String[files.length];
int idx = 0;
for (File f : files) {
result[idx++] = f.getPath();
}
return result;
} else {
return EMPTY_STRINGS;
}
}
/**
* Given a path to a file and a list of "search paths"
* returns the relative path of the file (relative to the one
* search path that matched)
* @param paths A list of folders
* @param file A path to a file
* @return The relative file path or the original file path if no match was found
*/
public static String relativeFile(Iterable extends File> paths, String file){
// find the matching path prefix
File path = selectPath(paths, file);
// and get the path of the file relative to the prefix
File relFile = relativeFile(path, new File(file));
return relFile.getPath();
}
/**
* Given a path to a file and a list of "search paths" returns
* the search path that matched the path of the file
* @param paths A list of folders
* @param file A path to a file
* @return The search path where the file was located or null
*/
public static File selectPath(Iterable extends File> paths, String file) {
// make sure file is absolute and normalized
file = absoluteFile(new File(file)).getPath();
// find the matching path prefix
int srcDirLength = 0;
File srcDirFile = null;
for (File prefixFile : paths) {
String absPrefix = absoluteFile(prefixFile).getPath() + File.separatorChar;
if (file.startsWith(absPrefix) && absPrefix.length() > srcDirLength) {
srcDirLength = absPrefix.length();
srcDirFile = prefixFile;
}
}
return srcDirFile;
}
/**
* Given a relative file path and a list of "search paths"
* returns the search path where the file was located
* @param paths A list of folders
* @param file A relative path to a file
* @return The search path where the file was located or null
*/
public static File searchPaths(Iterable extends File> paths, String relFile) {
for (File path : paths) {
File f = new File(path, relFile);
if (f.exists()) {
return path;
}
}
return null;
}
/**
* Given a relative file path and a list of "search paths"
* returns the "full" path relative to the current directory
* @param paths A list of folders
* @param file A relative path to a file
* @return The "full" path where the file was located or null
*/
public static File applyPath(Iterable extends File> paths, String relFile) {
File path = searchPaths(paths, relFile);
if (path != null) {
return new File(path, relFile);
}
return null;
}
public static boolean sameFile(File a, File b) {
if(a == null)
return b == null;
if(b == null)
return false;
try {
return Files.isSameFile(a.toPath(), b.toPath());
} catch (IOException e) {
return absoluteFile(a).equals(absoluteFile(b));
}
}
public static boolean containsFile(Collection files, File file) {
for (File f : files) {
if (sameFile(f, file)) {
return true;
}
}
return false;
}
// duplicated in /ceylon-compiler/src/com/redhat/ceylon/ant/Util.java because FileUtil is not in Ant's ClassPath
public static boolean isChildOfOrEquals(File parent, File child){
// doing a single comparison is likely cheaper than walking up to the root
try {
String parentPath = parent.getCanonicalPath();
String childPath = child.getCanonicalPath();
if(parentPath.equals(childPath))
return true;
// make sure we compare with a separator, otherwise /foo would be considered a parent of /foo-bar
if(!parentPath.endsWith(File.separator))
parentPath += File.separator;
return childPath.startsWith(parentPath);
} catch (IOException e) {
return false;
}
}
/**
* Returns true if the specified folder contains at least one regular file
*/
public static boolean containsFile(File dir) {
try {
final boolean[] found = new boolean[1];
found[0] = false;
Files.walkFileTree(dir.toPath(), new SimpleFileVisitor(){
@Override
public FileVisitResult visitFile(Path path, BasicFileAttributes attributes) throws IOException {
if(Files.isRegularFile(path)){
found[0] = true;
return FileVisitResult.TERMINATE;
}
return FileVisitResult.CONTINUE;
}
});
return found[0];
} catch (IOException e) {
throw new RuntimeException(e);
}
}
/**
* Recursively copy every file/folder from root to dest
*/
public static void copyAll(File root, File dest) throws IOException {
if(root.isDirectory()){
for(File child : root.listFiles()){
File childDest = new File(dest, child.getName());
if(child.isDirectory()){
if(!childDest.exists() && !mkdirs(childDest))
throw new IOException("Failed to create dir "+childDest.getPath());
copyAll(child, childDest);
}else{
Files.copy(child.toPath(), childDest.toPath(), StandardCopyOption.COPY_ATTRIBUTES);
}
}
}else{
File childDest = new File(dest, root.getName());
if(!dest.exists() && !mkdirs(dest))
throw new IOException("Failed to create dir "+dest.getPath());
Files.copy(root.toPath(), childDest.toPath(), StandardCopyOption.COPY_ATTRIBUTES);
}
}
/**
* Copy the specified source file given relative to the specified source folder
* to the specified destination file relative to the specified destination folder
*/
public static void copy(File srcDir, File relSrcFile, File destDir, File relDestFile) throws IOException {
File finalSrcFile = (srcDir != null) ? new File(srcDir, relSrcFile.getPath()) : relSrcFile;
File relDestDir = relDestFile.getParentFile();
if (relDestDir != null) {
File finalDestDir = (destDir != null) ? new File(destDir, relDestDir.getPath()) : relDestDir;
mkdirs(finalDestDir);
}
File finalDestFile = new File(destDir, relDestFile.getPath());
Files.copy(finalSrcFile.toPath(), finalDestFile.toPath(), StandardCopyOption.REPLACE_EXISTING, StandardCopyOption.COPY_ATTRIBUTES);
}
/**
* Just a simple wrapper around `java.util.File.mkdirs()` that fails
* when trying to create a folder named "~"
*/
public static boolean mkdirs(File dir) {
String path = dir.getPath().replace('\\', '/');
if (path.equals("~") || path.startsWith("~/") || path.contains("/~/")) {
return false;
}
return dir.mkdirs();
}
}
© 2015 - 2024 Weber Informatics LLC | Privacy Policy