package other.coreutils; import game.Command; import gui.windows.device.Terminal; import networks.devices.Device; import other.File; import java.io.FileNotFoundException; import java.io.IOException; import java.io.PrintStream; import java.lang.reflect.Method; import java.util.*; /** * An implementation of the file utilities from GNU CoreUtils. * The list of programs included in CoreUtils can be found here https://en.wikipedia.org/wiki/GNU_Core_Utilities * <p/> * I am not going to give documentation of any public methods in here. * Only the CoreUtil programs are public, and they are fully documented on the wiki. * Plus I included their help text in the methods, see that if you don't understand one. * I will try my best to simulate the functionality of them, but I will have to leave out options for some. */ public class FileUtils { public static final Map<String, Method> METHOD_MAP; private final Device device; private final Terminal terminal; private final PrintStream out; public FileUtils(Command command) { this.terminal = command.getTerminal(); this.device = terminal.getDevice(); out = new PrintStream(command.getOutputStream()); } static { Map<String, Method> methodMap = new HashMap<String, Method>(); for (Method m : FileUtils.class.getDeclaredMethods()) { methodMap.put(m.getName(), m); } METHOD_MAP = Collections.unmodifiableMap(methodMap); } /** * Finds the file with the given path on the server. */ private File getFile(String path) throws FileNotFoundException { return device.getFile(path); } /** * Searches for files based on wildcards(*) in the given path. */ private List<File> getFilesStar(String path) throws FileNotFoundException { List<File> Files = new ArrayList<File>(); if (path.contains("*")) { String[] pathArray = path.split("/"); String name = pathArray[pathArray.length - 1]; name = name.replace("*", ".*"); // setting up the regex pathArray[pathArray.length - 1] = ""; String dirPath = "/"; // path to use to find the directory of the files for (String s : pathArray) { dirPath += s + "/"; } File dir = getFile(dirPath); if (dir == null) { throw new FileNotFoundException(); } for (File f : dir.getFileMap().values()) { // search for files matching the regex name if (f.getName().matches(name)) { Files.add(f); } } } return Files; } private List<File> getPathFileList(String path) { String[] pathArray = path.split("/"); List<File> fileList = new ArrayList<File>(); fileList.add(device.getRoot()); for (String fileName : pathArray) { File file = fileList.get(fileList.size() - 1).getFile(fileName); if (file == null) { break; } else if (file.isDirectory()) { fileList.add(file); } } return fileList; } private List<String> getPathStringList(String path) { String[] pathArray = path.split("/"); List<String> pathList = new ArrayList<String>(); pathList.add("/"); for (String fileName : pathArray) { String filePath = pathList.get(pathList.size() - 1) + fileName + "/"; pathList.add(filePath); } return pathList; } public void cp(List<String> parameters, List<String> input) throws IOException { String options; String sourcePath; String targetPath; if (parameters.size() >= 2) { if (parameters.get(0).contains("-")) { options = parameters.get(0); sourcePath = parameters.get(1); targetPath = parameters.get(2); } else { options = ""; sourcePath = parameters.get(0); targetPath = parameters.get(1); } } else if (parameters.get(0).contains("h")) { out.println("cp [-hor] sourcefile targetfile"); out.println("Copy the sourcefile to the target file"); out.println("sourcefile is the file(s) or directory to be copied"); out.println("targetfile is the file or directory to copy to"); out.println(""); out.println("Use a * as a wildcard for specifying multiple source files"); out.println(""); out.println("Options:"); out.println(" -h shows this help text"); out.println(" -o overwrites all matching files"); out.println(" -r recursively find sourcefiles in the sourcefile directory"); return; } else { out.println("cp [-hor] sourcefile targetfile"); return; } if (sourcePath.isEmpty() || targetPath.isEmpty()) { out.println("cp [-hor] sourcefile targetfile"); return; } else if (sourcePath.startsWith("./")) { sourcePath = terminal.getDirectory().getPath() + sourcePath.substring(2); } else if (targetPath.startsWith("./")) { targetPath = terminal.getDirectory().getPath() + targetPath.substring(2); } File targetFile = getFile(targetPath); List<File> sourceFiles = getFilesStar(sourcePath); if (sourceFiles.isEmpty()) { sourceFiles.add(device.getFile(sourcePath)); } if (sourceFiles.size() == 1) { File sourceFile = sourceFiles.get(0); if (sourceFile.isDirectory() && !options.contains("r")) { out.println("Please include -r to copy a directory"); } else if (targetFile == null || !sourceFile.isDirectory()) { File targetDirectory; if (targetFile == null) { String targetDirectoryPath = sourcePath.substring(0, targetPath.lastIndexOf('\\')); targetDirectory = getFile(targetDirectoryPath); } else { targetDirectory = targetFile.getParentDirectory(); targetDirectory.removeFile(targetFile); } targetDirectory.addFile(sourceFile.copy()); } else if (targetFile.isDirectory()) { if (targetFile.getFile(sourceFile.getName()) == null || options.contains("o")) { targetFile.addFile(sourceFile.copy()); } else { throw new IOException("File already exists"); } } else { throw new IOException("Could not be copied"); } } else if (targetFile.isDirectory()) { boolean notAllCopied = false; for (File f : sourceFiles) { if (targetFile.getFile(f.getName()) == null || options.contains("o")) { targetFile.addFile(f.copy()); } else { notAllCopied = true; } } if (notAllCopied) { out.println("Not all files could be copied"); } } else { throw new IOException("Could not copied"); } } public void ls(List<String> parameters, List<String> input) throws IOException { String options; String directoryPath; if (parameters.size() >= 2) { options = parameters.get(0); directoryPath = parameters.get(1); } else if (parameters.size() == 1) { if (parameters.get(0).contains("-")) { options = parameters.get(0); directoryPath = terminal.getDirectory().getPath(); } else { options = ""; directoryPath = parameters.get(0); } } else { options = ""; directoryPath = terminal.getDirectory().getPath(); } if (options.contains("h")) { out.println("ls [-fhlmpQRrSt] [directory]"); out.println("List the files in the directory"); out.println(""); out.println("Options:"); out.println(" -f do not sort the files, default sorts alphabetically"); out.println(" -h shows this help text"); out.println(" -l long format: size, last-modified date and filename"); out.println(" -m separate lines with commas"); out.println(" -p gives the files as a path"); out.println(" -Q enclose entry names in double quotes"); out.println(" -R recursively list files"); out.println(" -r reverse the list of files"); out.println(" -S sort the list of files by size"); out.println(" -t sort the list of files by modification time"); return; } else if (directoryPath.isEmpty()) { directoryPath = terminal.getDirectory().getPath(); } else if (directoryPath.startsWith("./")) { directoryPath = terminal.getDirectory().getPath() + directoryPath.substring(2); } File directory = null; try { directory = getFile(directoryPath); } catch (FileNotFoundException e) { e.printStackTrace(); return; } List<File> fileList; if (options.contains("R")) { fileList = directory.getRecursiveFileList(directory); } else { fileList = new ArrayList<File>(directory.getFileMap().values()); } if (!options.contains("f")) { if (options.contains("S")) { // sort by size Collections.sort(fileList, new Comparator<File>() { @Override public int compare(File file, File file2) { return (file.getSize() + "").compareTo(file2.getSize() + ""); // this probably won't work numarically } }); } else if (options.contains("t")) { // sort by time Collections.sort(fileList, new Comparator<File>() { @Override public int compare(File file, File file2) { return file.getTime().compareTo(file2.getTime()); // maybe sort by miliseconds } }); } else { // sort by name Collections.sort(fileList, new Comparator<File>() { @Override public int compare(File file, File file2) { return file.toString().compareTo(file2.toString()); } }); } } if (options.contains("r")) { Collections.reverse(fileList); } if (options.contains("l")) { for (File f : fileList) { String s = ""; // s += f.getOwner(); TODO s += f.getSize() + " "; s += f.getTime() + " "; s += f.getName() + " "; out.println(s); } } else if (options.contains("p")) { for (File f : fileList) { out.println(f.getPath() + f.getName()); } } else { for (File f : fileList) { out.println(f.getName()); } } } public void mkdir(List<String> parameters, List<String> input) throws IOException { String options = ""; String directoryPath = ""; if (parameters.size() >= 2) { options = parameters.get(0); directoryPath = parameters.get(1); } else if (parameters.size() == 1) { directoryPath = parameters.get(0); } if (options.contains("h")) { out.println("mkdir [-pv] [directory]"); out.println("Creates a directory at the given path"); out.println(""); out.println("Options:"); out.println(" -p will also create all directories leading up to the given directory that do not exist already. If the given directory already exists, ignore the error."); out.println(" -v display each directory that mkdir creates, most often used with -p"); return; } else if (directoryPath.isEmpty()) { out.println("mkdir [-pv] [directory]"); return; } else if (directoryPath.startsWith("./")) { //|| !directoryPath.startsWith("/")) { directoryPath = terminal.getDirectory().getPath() + directoryPath.substring(2); } String name; if (options.contains("p")) { List<String> pathList = getPathStringList(directoryPath); File lastFile = device.getRoot(); for (String dir : pathList) { try { lastFile = device.getFile(dir); } catch (FileNotFoundException e) { // expected String[] names = dir.split("/"); name = names[names.length - 1]; File file = new File(name, null); lastFile.addFile(file); lastFile = file; if (options.contains("v")) { out.println(file.getPath()); } } } } else { String[] names = directoryPath.split("/"); name = names[names.length - 1]; List<File> fileList = getPathFileList(directoryPath); File dir = fileList.get(fileList.size() - 1); File file = new File(name, null); dir.addFile(file); if (options.contains("v") && dir.getFileMap().containsValue(file)) { out.println(file.getPath()); } } } }