package edu.kit.pse.ws2013.routekit.util;
import java.io.BufferedReader;
import java.io.File;
import java.io.FileReader;
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.attribute.BasicFileAttributes;
import java.util.regex.Pattern;
import edu.kit.pse.ws2013.routekit.history.History;
public class FileUtil {
/**
* Recursively deletes a directory.
*
* @param directory
* The directory.
* @throws IOException
* If something goes wrong.
*/
public static void rmRf(File directory) throws IOException {
// recursive directory delete:
// http://stackoverflow.com/a/8685959/1420237
Files.walkFileTree(directory.toPath(), new SimpleFileVisitor<Path>() {
@Override
public FileVisitResult visitFile(Path file,
BasicFileAttributes attrs) throws IOException {
Files.delete(file);
return FileVisitResult.CONTINUE;
}
@Override
public FileVisitResult visitFileFailed(Path file, IOException exc)
throws IOException {
Files.delete(file);
return FileVisitResult.CONTINUE;
}
@Override
public FileVisitResult postVisitDirectory(Path dir, IOException exc)
throws IOException {
if (exc == null) {
Files.delete(dir);
return FileVisitResult.CONTINUE;
} else {
throw exc;
}
}
});
}
/**
* Gets the root directory of routeKIT’s saved data (profiles, maps,
* precalculations).
* <ul>
* <li><b>Windows:</b> {@code %APPDATA%/routeKIT}</li>
* <li><b>Mac:</b> {@code $HOME/Library/Application Support/routeKIT}</li>
* <li><b>Unix/Linux:</b> {@code $HOME/.config/routeKIT}</li>
* </ul>
*
* @throws IOException
* If the operating system is neither of the above.
*/
public static File getRootDir() {
String os = System.getProperty("os.name").toUpperCase();
if (os.contains("WIN")) {
return new File(System.getenv("APPDATA"), "routeKIT");
} else if (os.contains("MAC")) {
return new File(new File(new File(System.getProperty("user.home"),
"Library"), "Application Support"), "routeKIT");
} else if (os.matches(".*N[IU]X.*")) {
return new File(
new File(System.getProperty("user.home"), ".config"),
"routeKIT");
} else {
throw new RuntimeException("Unknown operating system " + os);
}
}
/**
* Gets the file in which routeKIT’s {@link History} should be saved.
*/
public static File getHistoryFile() throws IOException {
return new File(getRootDir(), "routeKIT.history");
}
/**
* Gets the tile server from the {@code tileServer.txt} file in the
* {@link #getRootDir() root directory} of the installation.
*
* @return The contents of the file, or {@code null} if it doesn’t exist or
* can’t be read.
*/
public static String getTileServer() {
File file = new File(getRootDir(), "tileServer.txt");
if (file.isFile()) {
try (BufferedReader br = new BufferedReader(new FileReader(file))) {
return br.readLine();
} catch (IOException e) {
e.printStackTrace();
}
}
return null;
}
// @formatter:off – uses bad indentation
private static Pattern illegalNames = Pattern.compile(
// relics from the past
"^CON(\\..*)?$|^PRN(\\..*)?$|^AUX(\\..*)?$|^CLOCK\\$(\\..*)?$|^NUL(\\..*)?$|^COM\\d(\\..*)?$|^LPT\\d(\\..*)?$|"
// other Windows forbidden characters: <>:"/\|?* and 0-31
+ "<|>|:|\"|/|\\\\|\\||\\?|\\*|[\0-\31]|"
// forbidden everywhere: ., .., <empty>
+ "^\\.?\\.?$", Pattern.CASE_INSENSITIVE);
// @formatter:on
/**
* Returns {@code true} iff the given name is a valid map name.
* <p>
* Note that this only checks the general validity of the name; you should
* also verify that there is no other map whose name differs only in casing
* ("MyMap" vs "mymap").
*
* @param name
* The map name.
* @return {@code true} if {@code name} can be used as a map name,
* {@code false} otherwise.
*/
public static boolean checkMapName(String name) {
return !name.startsWith("\t") && !name.contains(" + ")
&& !illegalNames.matcher(name).find();
}
/**
* Returns {@code true} iff the given name is a valid profile name.
* <p>
* Note that this only checks the general validity of the name; you should
* also verify that there is no other profile whose name differs only in
* casing ("MyProfile" vs "myprofile").
*
* @param name
* The profile name.
* @return {@code true} if {@code name} can be used as a profile name,
* {@code false} otherwise.
*/
public static boolean checkProfileName(String name) {
return !name.startsWith(" *") && !illegalNames.matcher(name).find();
}
}