/* * * ConfigManager * * This class is the central configuration file manager for all other classes and acts as a utility class for other classes to use. * It is typical to define this class as a general object (not static instance) for each class in single-threaded actions. If you need * a special function or action from this class; it is recommended to add it to this class and not make your own. * * */ package jesse.keeblarcraft.ConfigMgr; import java.io.FileWriter; import java.io.File; import java.io.FileNotFoundException; import java.io.IOException; import java.nio.file.Paths; import com.google.common.base.Charsets; import com.google.common.io.Files; import com.google.gson.Gson; import com.google.gson.GsonBuilder; import com.google.gson.JsonIOException; import com.google.gson.JsonSyntaxException; import java.util.List; import org.apache.commons.io.FileUtils; import java.util.ArrayList; import java.util.HashMap; import jesse.keeblarcraft.Keeblarcraft; import net.minecraft.nbt.NbtCompound; import net.minecraft.nbt.NbtIo; import net.minecraft.nbt.NbtList; public class ConfigManager { // Pedantic empty constructor private static final String GLOBAL_CONFIG = "config/keeblarcraft/"; public ConfigManager() {} // Get a File reference to a file that is created on disk private File GetFile(String confFile) { File file = null; try { file = new File(GLOBAL_CONFIG + confFile); } catch (Exception e) {} return file; } // Returns the parent path to a given input. // Ex: /home/Downloads/file.txt will return /home/Downloads/ // Ex: /home/Downloads will return /home/ // Ex: / will return / private String GetPathOfFile(String file) { String pathToFile = ""; if (file != null) { for (int i = file.length() - 1; i >= 0; i--) { if (file.charAt(i) != File.separatorChar) { continue; } else { // Trim and break pathToFile = file.substring(0, i); break; } } } System.out.println("PathOfFile: " + pathToFile); return pathToFile; } // Creates a directory and all necessary parent directories listed in dirname (under global config area) public Boolean CreateDirectory(String dirName) { Boolean success = false; File directory = GetFile(dirName); try { if (directory != null) { if (!directory.exists()) { success = directory.mkdirs(); } else if (directory.isDirectory()) { success = true; } else { System.out.println("Directory " + dirName + " is an already existing file!"); } } } catch (Exception e) { System.out.println("Failed to create directory with name " + dirName); e.printStackTrace(); } return success; } // Create a file on the disk public Boolean CreateFile(String fileName) { Boolean success = false; File file = GetFile(fileName); String parentDir = GetPathOfFile(fileName); // CreateDirectory will verify that the parent directories exist & at least the parent directory is in fact a directory if (file != null && !file.exists() && CreateDirectory(parentDir)) { try { success = file.createNewFile(); } catch (Exception e) { System.out.println("Failed to create file " + fileName); e.printStackTrace(); } } else { System.out.println("CreateFile failed to finish. File may have been null (empty string input, unlikely), or parent directories could not be created/have overlapped name"); success = false; } return success; } public Boolean DeleteFile(String fileName) { Boolean success = false; File file = GetFile(fileName); success = !file.exists(); if (!success) { try { success = file.delete(); } catch (Exception e) { System.out.println("Failed to delete file " + fileName); e.printStackTrace(); } } return success; } ///////////////////////////////////////////////////////////////////////////// /// @fn WriteNbtListToFile /// /// @param[in] fileName is the file location to write to /// /// @param[in] key is the compound key type to store /// /// @param[in] data is the NbtList to write /// /// @brief Writes NbtList data to disk ///////////////////////////////////////////////////////////////////////////// public void WriteNbtListToFile(String fileName, String key, NbtList data) { // fileName = "config/keeblarcraft/" + fileName; File file = GetFile(fileName); if (!file.exists()) { file.getParentFile().mkdirs(); } try { NbtCompound compound = new NbtCompound(); compound.put(key, data); NbtIo.writeCompressed(compound, file); } catch (Exception e) { e.printStackTrace(); } } ///////////////////////////////////////////////////////////////////////////// /// @fn ReadAllNbtListFromDirectory /// /// @param[in] dir is the directory path to read from /// /// @param[in] listType is the NBT Compound list type /// /// @brief Reads in NBTList data from a directory; using file names as key. /// If a file is read in correctly, the file is deleted /// /// @return A map of NbtList data with the key being the file name (minus ext) ///////////////////////////////////////////////////////////////////////////// public HashMap ReadAllNbtListFromDirectory(String dir, int listType) { HashMap list = new HashMap(); // dir = "config/keeblarcraft/" + dir; File directory = GetFile(dir); File[] files = directory.listFiles(); if (files != null) { for (File file : files) { String key = file.getName().substring(0, file.getName().length() - 4); NbtList nbtList = ReadNbtListFromFile(file, key, listType); if (nbtList != null) { // Subtract out '.nbt' from name list.put(key, nbtList); file.delete(); } } } return list; } ///////////////////////////////////////////////////////////////////////////// /// @fn ReadNbtListFromFile /// /// @param[in] file handler object to read nbt list data from /// /// @param[in] key for the nbt compound object /// /// @param[in] listType is the NBT Compound list type /// /// @brief Reads in NBTList data from a single file /// /// @return NbtList data ///////////////////////////////////////////////////////////////////////////// public NbtList ReadNbtListFromFile(File file, String key, int listType) { NbtList list = null; try { NbtCompound c = NbtIo.readCompressed(file); list = c.getList(key, listType); } catch (Exception e) { e.printStackTrace(); } return list; } // WriteToFile // // Will write or append to file (valid modes: "w" or "a") if file is available. Returns false if not public Boolean WriteToFile(String fileName, String data, String mode) { Boolean ret = false; FileWriter file; try { file = new FileWriter(GetFile(fileName)); switch(mode) { case "w": file.write(data); ret = true; break; case "a": file.append(data); ret = true; break; default: Keeblarcraft.LOGGER.debug("Invalid mode to WriteToFile!!"); break; } file.close(); } catch (IOException e) { e.printStackTrace(); Keeblarcraft.LOGGER.error("Could not open file " + fileName + " to write to it! Possible permissions issue??"); } return ret; } // WriteToJsonFile // // Will write to or append to a json file. It will search if the key exists first & update the field; // or add a new entry. It should be noted that json objects *can* be buried inside each other. It is // considered best (and only) practice to call the "GetJsonStringFromFile" function first from this // class and simply iterate to what you would need and then update the entire entry alongside the // top-level key. // // NOTE: THIS DOES NOT SAFE UPDATE THE KEY OBJECT. PRE-EXISTING DATA WILL BE DELETED FOREVER public void WriteToJsonFile(String fileName, Object data) { Gson gson = new GsonBuilder().setPrettyPrinting().create(); try { // The FileWriter cannot create objects; so we create parent directories before writing. This may be // changed in the future File parent = GetFile(fileName).getParentFile(); if (!parent.exists()) { parent.mkdirs(); } FileWriter writer = new FileWriter(GetFile(fileName)); gson.toJson(data, writer); writer.flush(); writer.close(); } catch (JsonIOException | IOException e) { Keeblarcraft.LOGGER.error("Could not successfully write to json file ["+fileName+"]"); e.printStackTrace(); } } // GetJsonStringFromFile // // Retrieves json file and converts to desired object. Returns JsonSyntaxException if file could not be fitted to class input public T GetJsonObjectFromFile(String fileName, Class classToConvertTo) throws JsonSyntaxException { Gson gson = new Gson(); String ret = ""; // hot fix: Not sure how to return "false" for invalid conversion when I'm forced to convert or just catch... Look into a better // return value in the future - but for now throw JsonSyntaxException no matter what exception is caught try { File file = GetFile(fileName); ret = FileUtils.readFileToString(file, "UTF-8"); } catch (Exception e) { e.printStackTrace(); System.out.println("Caught an exception in retrieving JSON Object from file " + fileName); // throw new JsonSyntaxException(""); } return gson.fromJson(ret, classToConvertTo); } public Boolean DoesFileExist(String fileName) { return GetFile(fileName).exists(); } public Boolean DoesDirectoryExist(String dirName) { File file = GetFile(dirName); return file != null && file.isDirectory(); } public Boolean DeleteDirectory(String dirName) { return DeleteFile(dirName); } // GetFile // // Returns a file as an arraylist of all the lines in the file. Generally only used for testing // // NOTE: Returns UTF-8 Encoding of file public List GetFileLines(String fileName) { List ret = new ArrayList(); try { return Files.readLines(GetFile(fileName), Charsets.UTF_8); } catch (IOException e) { ret.clear(); } return ret; } }