package games.strategy.engine;
import java.io.File;
import java.io.IOException;
import java.io.UnsupportedEncodingException;
import java.net.URL;
import java.net.URLDecoder;
import java.nio.charset.StandardCharsets;
import java.util.Arrays;
import java.util.List;
import java.util.stream.Collectors;
import games.strategy.debug.ClientLogger;
import games.strategy.engine.config.GameEnginePropertyFileReader;
import games.strategy.engine.framework.GameRunner;
import games.strategy.engine.framework.system.SystemProperties;
import games.strategy.util.Version;
/**
* Pure utility class, final and private constructor to enforce this
* WARNING: do not call ClientContext in this class. ClientContext call this class in turn
* during construction, depending upon ordering this can cause an infinite call loop.
*/
public final class ClientFileSystemHelper {
private ClientFileSystemHelper() {}
public static File getRootFolder() {
final String fileName = getGameRunnerFileLocation(GameRunner.class.getSimpleName() + ".class");
final String tripleaJarName = "triplea.jar!";
if (fileName.contains(tripleaJarName)) {
return getRootFolderRelativeToJar(fileName, tripleaJarName);
}
final String tripleaJarNameWithEngineVersion = getTripleaJarWithEngineVersionStringPath();
if (fileName.contains("triplea_" + tripleaJarNameWithEngineVersion + ".jar!")) {
return getRootFolderRelativeToJar(fileName, tripleaJarNameWithEngineVersion);
}
return getRootRelativeToClassFile(fileName);
}
public static String getGameRunnerFileLocation(final String runnerClassName) {
final URL url = GameRunner.class.getResource(runnerClassName);
String fileName = url.getFile();
try {
// Deal with spaces in the file name which would be url encoded
fileName = URLDecoder.decode(fileName, StandardCharsets.UTF_8.name());
} catch (final UnsupportedEncodingException e) {
ClientLogger.logError("Unsupported encoding of fileName: " + fileName + ", error: " + e.getMessage());
}
return fileName;
}
private static String getTripleaJarWithEngineVersionStringPath() {
// TODO: This is begging for trouble since we call ClientFileSystem during the construction of
// ClientContext. Though, we will at this point already have parsed the game engine version, so it is okay (but
// brittle)
final EngineVersion engine = ClientContext.engineVersion();
final Version version = engine.getVersion();
return "triplea_" + version.toStringFull("_") + ".jar!";
}
private static File getRootFolderRelativeToJar(final String fileName, final String tripleaJarName) {
final String subString = fileName.substring(
"file:/".length() - (SystemProperties.isWindows() ? 0 : 1),
fileName.indexOf(tripleaJarName) - 1);
final File f = new File(subString).getParentFile();
if (!f.exists()) {
throw new IllegalStateException("File not found:" + f);
}
return f;
}
private static File getRootRelativeToClassFile(final String fileName) {
File f = new File(fileName);
// move up one directory for each package
final int moveUpCount = GameRunner.class.getName().split("\\.").length + 1;
for (int i = 0; i < moveUpCount; i++) {
f = f.getParentFile();
}
// keep moving up one directory until we find the game_engine properties file that we expect to be at the root
while (!folderContainsGamePropsFile(f)) {
f = f.getParentFile();
}
if (!f.exists()) {
System.err.println("Could not find root folder, does not exist:" + f);
return new File(System.getProperties().getProperty("user.dir"));
}
return f;
}
private static boolean folderContainsGamePropsFile(final File folder) {
final File[] files = folder.listFiles();
final List<String> fileNames =
Arrays.asList(files).stream().map(file -> file.getName()).collect(Collectors.toList());
return fileNames.contains(GameEnginePropertyFileReader.GAME_ENGINE_PROPERTY_FILE);
}
public static boolean areWeOldExtraJar() {
final URL url = GameRunner.class.getResource(GameRunner.class.getSimpleName() + ".class");
String fileName = url.getFile();
try {
fileName = URLDecoder.decode(fileName, StandardCharsets.UTF_8.name());
} catch (final UnsupportedEncodingException e) {
ClientLogger.logQuietly(e);
}
final String tripleaJarNameWithEngineVersion = getTripleaJarWithEngineVersionStringPath();
if (fileName.contains(tripleaJarNameWithEngineVersion)) {
final String subString = fileName.substring("file:/".length() - (SystemProperties.isWindows() ? 0 : 1),
fileName.indexOf(tripleaJarNameWithEngineVersion) - 1);
final File f = new File(subString);
if (!f.exists()) {
throw new IllegalStateException("File not found:" + f);
}
String path;
try {
path = f.getCanonicalPath();
} catch (final IOException e) {
path = f.getPath();
}
return path.contains("old");
}
return false;
}
public static File getUserRootFolder() {
final File userHome = new File(System.getProperties().getProperty("user.home"));
final File rootDir = new File(new File(userHome, "Documents"), "triplea");
return rootDir.exists() ? rootDir : new File(userHome, "triplea");
}
public static File getUserMapsFolder() {
final String path = ClientContext.folderSettings().getDownloadedMapPath();
final File mapsFolder = new File(path);
if (!mapsFolder.exists()) {
try {
mapsFolder.mkdirs();
} catch (final SecurityException e) {
ClientLogger.logError(e);
}
}
if (!mapsFolder.exists()) {
ClientLogger.logError("Error, downloaded maps folder does not exist: " + mapsFolder.getAbsolutePath());
}
return mapsFolder;
}
/** Create a temporary file, checked exceptions are re-thrown as unchecked. */
public static File createTempFile() {
try {
return File.createTempFile("triplea", "tmp");
} catch (final IOException e) {
throw new IllegalStateException("Failed to create a temporary file", e);
}
}
}