package com.elsealabs.xshot.file; import java.io.File; import java.io.IOException; import java.nio.file.Files; import java.util.ArrayList; import java.util.HashMap; import com.elsea.stone.property.PropertyPool; import com.elsea.stone.property.PropertyPoolReader; import com.elsea.stone.property.PropertyPoolWriter; /** * FileSystem * * Holds information about locations of important directories and * files relevant to the program. It also holds helper methods for * directory and file repair and first time setup. * * @author Connor M. Elsea */ public class FileSystem { public static enum OS { WINDOWS, OSX, LINUX } private OS osType; private String osName; private String userPath; /** * The paths that can be returned by this class' accessor methods * are bound by the PATH enumeration to eliminate the use of magic * String for retrieving paths from the hash map. */ public static enum PATH { PROGRAM_DIR, STONE_FILE, SAVE_DEFAULT_DIR } private HashMap<String, File> files; private File location_programDir; private File location_stoneFile; private File location_saveDefaultDir; /** * When a file system check is performed, issues that are found * are added to the array list of issues. The type of the issues * are bound by the ISSUE enumeration. */ public static enum ISSUE { MISSING_PROGRAM_DIR, MISSING_SAVE_DIR, MISSING_STONE, MALFORMED_STONE } private ArrayList<ISSUE> issues; /** * Various data held by the File System object. */ private PropertyPool pool; /** * Runs all the needed methods for starting up the program and * loading the initial data. */ public void run() { loadPaths(); check(); fix(); } /** * Checks for various problems and if they are present, their * corresponding issue to the arrray list. Loads in Stone data * if it is present and not malformed. */ public void check() { System.out.println("File System: Checking for issues."); if (issues == null) issues = new ArrayList<ISSUE>(); else issues.clear(); if (!getPath(PATH.PROGRAM_DIR).exists()) { issues.add(ISSUE.MISSING_PROGRAM_DIR); } if (!getPath(PATH.SAVE_DEFAULT_DIR).exists()) { issues.add(ISSUE.MISSING_SAVE_DIR); } if (!getPath(PATH.STONE_FILE).exists()) { issues.add(ISSUE.MISSING_STONE); } else { PropertyPoolReader reader = new PropertyPoolReader(); // reader.read(...) returns a boolean indicating whether or not the reader // read in the data correctly. If the data was read in corerctly, set the // read in pool as a member of the File System class. If not, add the // malformed stone issue to the issue array list. if (reader.read(getPath(PATH.STONE_FILE))) { pool = reader.getPropertyPool(); if (pool.search().getGroup("locations") == null) { issues.add(ISSUE.MISSING_STONE); } } else { issues.add(ISSUE.MALFORMED_STONE); } } } /** * Fixes errors if they are present. */ public void fix() { System.out.println("File System: Attempting to fix any issues"); if (!issues.isEmpty()) { if (issues.contains(ISSUE.MISSING_PROGRAM_DIR)) { fix_MissingProgramDir(); } if (issues.contains(ISSUE.MISSING_SAVE_DIR)) { fix_MissingSaveDir(); } if (issues.contains(ISSUE.MISSING_STONE)) { fix_MissingStone(); } if (issues.contains(ISSUE.MALFORMED_STONE)) { fix_MalformedStone(); } issues.clear(); } } public void fix_MissingProgramDir() { System.out.println("Resolve: Attempting to fix missing program directory."); try { Files.createDirectories(getPath(PATH.PROGRAM_DIR).toPath()); } catch (IOException e) { e.printStackTrace(); } } public void fix_MissingSaveDir() { System.out.println("Resolve: Attempting to fix missing save directory."); // TODO: Ask user for new save directory. System.err.println("Error: Missing Save Directory. Cannot fix in current build."); } public void fix_MissingStone() { System.out.println("Resolve: Attempting to fix missing Stone file."); // Get default path generated by File System and put it into // the Stone template. They can change it in the future, but // this is just setting up defaults. String defaultSave = getPath(FileSystem.PATH.SAVE_DEFAULT_DIR).getAbsolutePath(); // Create the Property Pool and fill it with the defaults. pool = new PropertyPool(); pool .group("file") .group("locations") .group("location") .property("name", "Pictures") .property("path", defaultSave) .property("default", "true") .end() .end() .end() .group("actions") .property("autoCopy", "true") .end() ; // Write the Property Pool to the file system PropertyPoolWriter writer = new PropertyPoolWriter(); if (writer.write(pool, getPath(PATH.STONE_FILE))) { System.out.println("Resolve: Wrote Stone file correctly"); } else { System.err.println("Fatal Error: Failed to write Stone file."); } } public void fix_MalformedStone() { System.out.println("Resolve: Attempting to fix malformed stone file."); System.err.println("Errror: Cannot fix malformed stone file."); } /** * Determine the operating system and generate the paths needed by this * program, some of which differ between each operating system. */ public void loadPaths() { System.out.println("File System: Determining paths."); files = new HashMap<String, File>(); osName = System.getProperty("os.name").toLowerCase(); userPath = System.getProperty("user.home"); if (osName.contains("windows")) { osType = OS.WINDOWS; location_programDir = new File(System.getenv("APPDATA") + "\\Capshot"); location_saveDefaultDir = new File(userPath + "\\Pictures"); location_stoneFile = new File(System.getenv("APPDATA") + "\\Capshot\\stone.xml"); } else if (osName.contains("mac")) { osType = OS.OSX; location_programDir = new File(getUserPath() + "/Library/Application Support/Capshot"); } else if (osName.contains("nix") || osName.contains("nux")) { osType = OS.LINUX; location_programDir = new File(getUserPath() + "/Capshot"); } else { osType = OS.WINDOWS; System.err.println("Error: Could not determine OS from os.name = \"" + osName + "\""); System.err.println("Warning: Defaulting OS to WINDOWS."); } System.out.println("File System: Program directory " + location_programDir.getAbsolutePath()); location_stoneFile = new File(location_programDir.getAbsolutePath() + "\\settings.xml"); } /** * Return the File object for the specified pre-defined location * * @param path The pre-defined location * @return The file object for the specified pre-defined location */ public File getPath(PATH path) { switch (path) { case PROGRAM_DIR: return location_programDir; case STONE_FILE: return location_stoneFile; case SAVE_DEFAULT_DIR: return location_saveDefaultDir; default: throw new IllegalArgumentException(); } } public OS getOsType() { return osType; } public String getOsName() { return osName; } public String getUserPath() { return userPath; } }