![JAR search and dependency download from the Maven repository](/logo.png)
uk.ac.liv.pgb.analytica.lib.wrappedr.FileSystem Maven / Gradle / Ivy
Go to download
Show more of this group Show more artifacts with this name
Show all versions of analytica-lib Show documentation
Show all versions of analytica-lib Show documentation
Library allowing generation of plots and data from proteomics and
metabolomics mass spectrometry data through the use of R and java
methods.
The newest version!
package uk.ac.liv.pgb.analytica.lib.wrappedr;
import java.io.File;
import java.io.FileNotFoundException;
import java.io.IOException;
import java.io.OutputStream;
import java.io.PrintStream;
import java.lang.reflect.Field;
import java.util.Arrays;
import java.util.Collections;
import java.util.HashMap;
import java.util.HashSet;
import java.util.LinkedList;
import java.util.List;
import java.util.Map;
import java.util.Map.Entry;
import java.util.Optional;
import java.util.Set;
import java.util.logging.Level;
import java.util.logging.Logger;
import java.util.prefs.Preferences;
import java.util.stream.StreamSupport;
/**
* Utility class to help to find files/executables and to manipulate
* environments.
*
* @author sperkins
*/
public final class FileSystem {
/**
* Map of found commands/executables from their names.
*/
private static final Map PREVIOUS_FIND_COMMAND_RESULTS = new HashMap<>();
/**
* Set of directories that commands/executables were found in.
*/
private static final Set PREVIOUS_FIND_COMMAND_DIRECTORIES = new HashSet<>();
/**
* Map of found files from their names.
*/
private static final Map PREVIOUS_FIND_FILE_RESULTS = new HashMap<>();
/**
* Type of the operating system.
*/
private static SystemType systemType = null;
/**
* Whether the JVM is running in administrator mode or not.
*/
private static final boolean ADMIN_MODE = isAdmin();
/**
* Private constructor to prevent instantiation.
*/
private FileSystem() {
}
/**
* Recursively deletes the path represented by the given file..
*
* @param path The path represented by a file.
* @return True if the path is successfully deleted.
* @throws FileNotFoundException Thrown if the path does not exist.
*/
public static boolean deleteRecursive(final File path) throws FileNotFoundException {
if (!path.exists()) {
throw new FileNotFoundException(path.getAbsolutePath());
}
File[] children = path.listFiles();
if (children == null) {
return path.delete();
}
return Arrays.stream(children).parallel().map(child -> {
if (child.isFile()) {
return child.delete();
} else if (child.isDirectory()) {
try {
return deleteRecursive(child);
} catch (FileNotFoundException ex) {
return false;
}
}
return true;
}).allMatch(deleted -> deleted) ? path.delete() : false;
}
/**
* Finds a executable/command from its name.
*
* @param command Executable/command name.
* @return The command/executable represented by a file.
*/
public static File findExecutionCommand(final String command) {
return findExecutionCommand(command, Collections.emptyList());
}
/**
* Finds a executable/command from its name, given some location hints.
*
* @param command Executable/command name.
* @param locationHints Hints to the location of the command/executable.
* @return The command/executable represented by a file.
*/
public static File findExecutionCommand(final String command, final Iterable locationHints) {
// First let's see if we have seen this command before in this session.
if (PREVIOUS_FIND_COMMAND_RESULTS.containsKey(command)) {
return PREVIOUS_FIND_COMMAND_RESULTS.get(command);
}
// We haven't seen it before, so let's see if the command is on the system path.
// We use the 'where' command for windows, and the 'which' command for linux.
SystemType type = getSystemType();
CommandExecutor exec = null;
switch (type) {
case WIN32:
case WIN64:
exec = new CommandExecutor(findFile("where.exe", Arrays.asList(File.listRoots())));
break;
case LINUX32:
case LINUX64:
exec = new CommandExecutor(findFile("which", Arrays.asList(File.listRoots())));
default:
break;
}
if (exec != null) {
try {
exec.execute(Collections.singletonList(command));
} catch (InterruptedException ex) {
}
List output = exec.getOutput();
if (output != null) {
for (String outputLine : output) {
if (!outputLine.startsWith("INFO") && !outputLine.startsWith("JINKIES")) {
File file = new File(outputLine.trim());
PREVIOUS_FIND_COMMAND_RESULTS.put(command, file);
PREVIOUS_FIND_COMMAND_DIRECTORIES.add(file.getParentFile());
try {
return file.getCanonicalFile();
} catch (IOException ex) {
}
}
}
}
}
// Command wasn't in the path, so let's check the location hints.
File foundFile = findFile(command, locationHints);
if (foundFile != null) {
PREVIOUS_FIND_COMMAND_RESULTS.put(command, foundFile);
PREVIOUS_FIND_COMMAND_DIRECTORIES.add(foundFile.getParentFile());
return foundFile;
}
// Command wasn't in the hinted locations, so we have to be more inventive.
foundFile = findFile(command, PREVIOUS_FIND_COMMAND_DIRECTORIES);
if (foundFile != null) {
PREVIOUS_FIND_COMMAND_RESULTS.put(command, foundFile);
PREVIOUS_FIND_COMMAND_DIRECTORIES.add(foundFile.getParentFile());
return foundFile;
}
// Command wasn't in the most recent directories that other commands where found in.
// Let's look through the file system. This is very expensive, should not normally be triggered.
System.out.println("Warning: searching file systems for '" + command + "'");
foundFile = findFile(command, Arrays.asList(File.listRoots()));
if (foundFile != null) {
PREVIOUS_FIND_COMMAND_RESULTS.put(command, foundFile);
PREVIOUS_FIND_COMMAND_DIRECTORIES.add(foundFile.getParentFile());
return foundFile;
}
// If we ever get to this point the command was nowhere to be found, so return null;
return null;
}
/**
* Finds a file from its name in the given directories.
*
* @param fileName The file name.
* @param directories Directories in which to look for the file.
* @return The found file.
*/
private static File findFile(final String fileName, final Iterable directories) {
return findFile(fileName, directories, false);
}
/**
* Finds a file from its name in the given directories..
*
* @param fileName The file name.
* @param directories Directories in which to look for the file.
* @param skipSystemLocationCheck Whether to skip looking in system
* locations.
* @return The found file.
*/
private static File findFile(final String fileName, final Iterable directories, final boolean skipSystemLocationCheck) {
Optional foundFileOptional = StreamSupport.stream(directories.spliterator(), true).filter(p -> p.isDirectory()).map(p -> {
return findFile(fileName, p, skipSystemLocationCheck, false);
}).filter(p -> p != null).findAny();
return foundFileOptional.isPresent() ? foundFileOptional.get() : null;
}
/**
* Finds a file from its name in the given directories..
*
* @param fileName The file name.
* @param rootDirectory The directory in which to look for the file.
* @return The found file.
*/
public static File findFile(final String fileName, final File rootDirectory) {
return findFile(fileName, rootDirectory, false, false);
}
/**
* Finds a file from its name in the given directories..
*
* @param fileName The file name.
* @param rootDirectory The directory in which to look for the file.
* @param skipSystemLocationCheck Whether to skip looking in system
* locations.
* @param isDirectory Whether the file we are looking for is in fact a
* directory.
* @return The found file.
*/
public static File findFile(final String fileName, final File rootDirectory, final boolean skipSystemLocationCheck, final boolean isDirectory) {
if (PREVIOUS_FIND_FILE_RESULTS.containsKey(fileName)) {
return PREVIOUS_FIND_FILE_RESULTS.get(fileName);
}
if (!skipSystemLocationCheck) {
File systemLocationsFile = findFile(fileName, Arrays.asList(new File[]{new File("c:\\Windows\\System32"), new File("//usr/bin")}), true);
if (systemLocationsFile != null) {
return systemLocationsFile;
}
}
if (rootDirectory == null || !rootDirectory.exists() || !rootDirectory.isDirectory()) {
return null;
}
File[] children = rootDirectory.listFiles();
if (children == null) {
return null;
}
// Speed up finding object if it in the top level directory.
Optional topDirectoryOptional = Arrays.stream(children).filter(child -> {
if ((child.isDirectory() && isDirectory) || (child.isFile() && !isDirectory)) {
if (getSystemType().equals(SystemType.WIN32) || getSystemType().equals(SystemType.WIN64)) {
if (child.getName().toUpperCase().equals(fileName.toUpperCase())) {
PREVIOUS_FIND_FILE_RESULTS.put(fileName, child);
return true;
}
} else if (child.getName().equals(fileName)) {
PREVIOUS_FIND_FILE_RESULTS.put(fileName, child);
return true;
}
}
return false;
}).findAny();
if (topDirectoryOptional.isPresent()) {
return topDirectoryOptional.get();
}
// Don't need to scan current directory level as we have just done it above.
Optional subDirectoryOptional = Arrays.stream(children).parallel().filter(p -> p.isDirectory()).map(child -> {
File foundFile = findFile(fileName, child, true, isDirectory);
return foundFile;
}).filter(p -> p != null).findAny();
return subDirectoryOptional.isPresent() ? subDirectoryOptional.get() : null;
}
/**
* Add a folder to the permanent path variable.
*
* @param folder Folder to add to the path permanently.
* @return True if there was no error setting the path.
*/
public static boolean addFolderToPathPermanent(final File folder) {
throw new UnsupportedOperationException();
}
/**
* Add a folder to the path variable for the session, in a few places.
*
* @param folder Folder to add to the path for the session.
* @return True if there was no error setting the path.
*/
public static boolean addFolderToPathForJavaSession(final File folder) {
String existingPath = System.getProperty("java.library.path");
if (existingPath.endsWith(".")) {
existingPath = existingPath.substring(0, existingPath.length() - 1);
}
System.setProperty("java.library.path", existingPath + folder.getAbsolutePath() + File.separator + File.pathSeparator);
try {
Field fieldSysPath = ClassLoader.class.getDeclaredField("sys_paths");
fieldSysPath.setAccessible(true);
fieldSysPath.set(null, null);
} catch (NoSuchFieldException | SecurityException | IllegalArgumentException | IllegalAccessException ex) {
return false;
}
try {
Class> theClass = Class.forName("java.lang.ProcessEnvironment");
Field field1 = theClass.getDeclaredField("theEnvironment");
field1.setAccessible(true);
Map theEnvironment = (Map) field1.get(null);
Field field2 = theClass.getDeclaredField("theCaseInsensitiveEnvironment");
field2.setAccessible(true);
Map caseInsensitiveEnvironment = (Map) field1.get(null);
Optional> paths1 = theEnvironment.entrySet().stream().filter(p -> p.getKey().equalsIgnoreCase("PATH")).findFirst();
if (paths1.isPresent()) {
paths1.get().setValue(paths1.get().getValue() + ";" + folder.getAbsolutePath());
}
Optional> paths2 = caseInsensitiveEnvironment.entrySet().stream().filter(p -> p.getKey().equalsIgnoreCase("PATH")).findFirst();
if (paths2.isPresent()) {
paths2.get().setValue(paths2.get().getValue() + ";" + folder.getAbsolutePath());
}
} catch (ClassNotFoundException | NoSuchFieldException | SecurityException | IllegalArgumentException | IllegalAccessException ex) {
return false;
}
return true;
}
/**
* Set an environment variable permanently. If running in administrator
* mode, a system-level variable will be set, otherwise a a user-level
* variable.
*
* @param name The environment variable name.
* @param value The environment variable value.
* @return True if there was no error setting the environment variable.
*/
public static boolean setEnvironmentVariablePermanent(final String name, final String value) {
if (systemType == SystemType.WIN32 || systemType == SystemType.WIN64) {
File setxCommand = findExecutionCommand("setx");
if (setxCommand == null) {
return false;
}
CommandExecutor executor = new CommandExecutor(setxCommand);
List arguments = new LinkedList<>();
arguments.add(name);
arguments.add(value);
if (ADMIN_MODE) {
arguments.add("/M");
}
try {
executor.execute(arguments);
} catch (InterruptedException ex) {
return false;
}
} else if (systemType == SystemType.LINUX32 || systemType == SystemType.LINUX64) {
if (ADMIN_MODE) {
File profileD = new File("/etc/profile.d");
if (profileD.exists() && profileD.isDirectory()) {
// Let's add a script to the profile.d directory to make the environment variable change permanent.
throw new UnsupportedOperationException("Not yet implemented.");
} else {
File profile = new File("/etc/profile");
if (profile.exists() && profile.isFile()) {
// Let's edit the profile file directly to make the environment variable change permanent.
throw new UnsupportedOperationException("Not yet implemented.");
}
}
}
} else {
// System type was not one of the four we support, so we cannot set the environment variable.
return false;
}
return true;
}
/**
* Set an environment variable for the session.
*
* @param name The environment variable name.
* @param value The environment variable value.
* @return True if there was no error setting the environment variable.
*/
public static boolean setEnvironmentVariableForJavaSession(final String name, final String value) {
try {
Class> theClass = Class.forName("java.lang.ProcessEnvironment");
Field field1 = theClass.getDeclaredField("theEnvironment");
field1.setAccessible(true);
Map theEnvironment = (Map) field1.get(null);
theEnvironment.put(name, value);
Field field2 = theClass.getDeclaredField("theCaseInsensitiveEnvironment");
field2.setAccessible(true);
Map caseInsensitiveEnvironment = (Map) field1.get(null);
caseInsensitiveEnvironment.put(name, value);
} catch (ClassNotFoundException | NoSuchFieldException | SecurityException | IllegalArgumentException | IllegalAccessException ex) {
return false;
}
return true;
}
/**
* Checks whether the JVM was started with administrator privileges.
*
* @return True if the JVM was started with administrator privileges.
*/
private static boolean isAdmin() {
Preferences prefs = Preferences.systemRoot();
PrintStream systemErr = System.err;
synchronized (systemErr) {
System.setErr(new PrintStream(new OutputStream() {
@Override
public void write(int i) throws IOException {
}
}));
try {
// SecurityException on windows if not admin.
prefs.put("foo", "bar");
prefs.remove("foo");
// BackingStoreException in linux if not admin.
prefs.flush();
return true;
} catch (Exception ex) {
return false;
} finally {
System.setErr(systemErr);
}
}
}
/**
* Gets the system type.
*
* @return The system type.
*/
public static SystemType getSystemType() {
if (systemType != null) {
return systemType;
}
String operatingSystemType = System.getProperty("os.name");
if (operatingSystemType.startsWith("Windows")) {
if (System.getenv("ProgramFiles(x86)") != null) {
systemType = SystemType.WIN64;
} else {
systemType = SystemType.WIN32;
}
} else {
CommandExecutor exec = new CommandExecutor(findFile("uname.sh", Arrays.asList(File.listRoots())));
try {
exec.execute(Collections.singletonList("-a"));
} catch (InterruptedException ex) {
}
systemType = SystemType.LINUX32;
List output = exec.getOutput();
for (String outputLine : output) {
if (outputLine.contains("x86_64")
|| outputLine.contains("ia64")) {
systemType = SystemType.LINUX64;
break;
}
}
}
return systemType;
}
/**
* The system type.
*/
public enum SystemType {
/**
* 32-bit windows system.
*/
WIN32,
/**
* 64-bit windows system.
*/
WIN64,
/**
* 32-bit linux system.
*/
LINUX32,
/**
* 64-bit linux system.
*/
LINUX64
}
}
© 2015 - 2025 Weber Informatics LLC | Privacy Policy