Java tutorial
/* * To change this license header, choose License Headers in Project Properties. * To change this template file, choose Tools | Templates * and open the template in the editor. */ package com.skynetcomputing.skynetclient.persistence; import com.google.gson.Gson; import com.skynetcomputing.api.jobs.TaskInfo; import com.skynetcomputing.api.jobs.data.TaskData; import com.skynetcomputing.serializable.SrzData; import com.skynetcomputing.serializable.SrzJar; import com.skynetcomputing.serializable.SrzTask; import com.skynetcomputing.utils.MiscUtils; import org.apache.commons.io.FileUtils; import org.apache.commons.io.FilenameUtils; import org.json.simple.JSONArray; import org.json.simple.JSONObject; import org.json.simple.parser.JSONParser; import org.json.simple.parser.ParseException; import java.io.*; import java.nio.file.Files; import java.nio.file.Paths; import java.nio.file.StandardCopyOption; import java.util.ArrayList; import java.util.HashMap; import java.util.List; import java.util.Map; import java.util.logging.Level; import java.util.logging.Logger; /** * * @author Kargathia */ public class PersistenceManager { private final String rootDir; /** * Directory structure: * */ private final static String TASK_DIR = "CurrentTask" + File.separator; private final static String JAR_DIR = "Jars" + File.separator; private final static String DATA_DIR = "Data" + File.separator; /** * Starts a new PersistenceManager, using provided directory path as root. * <br> * Files are saved in the following file system order: * <blockquote><pre> * root\ * Jars\ * (jar_name)_(jar_version).jar * CurrentTask\ * (task_id).task * Data\ * (data_id).data * * </pre></blockquote> * * @param rootDir */ public PersistenceManager(String rootDir) throws IOException { rootDir = rootDir.replace("\\", File.separator).replace("/", File.separator); if (!rootDir.endsWith(File.separator)) { rootDir = rootDir + File.separator; } this.rootDir = rootDir; String propertyKey = MiscUtils.getProperty("resetDatabase"); if (propertyKey != null) { String strReset = MiscUtils.getPropertyOrDefault("resetDatabase", "false"); boolean reset = strReset.equalsIgnoreCase("true"); if (reset) { FileUtils.deleteDirectory(new File(rootDir, JAR_DIR)); } } // Recursively creates all directories if they don't exist. FileUtils.forceMkdir(new File(rootDir, JAR_DIR)); FileUtils.forceMkdir(new File(rootDir, TASK_DIR)); FileUtils.forceMkdir(new File(rootDir, TASK_DIR + DATA_DIR)); } /** * Removes current task / data files, and re-makes their directories * * @throws IOException */ public void clearTask() throws IOException { File taskDir = new File(rootDir + TASK_DIR); FileUtils.deleteDirectory(taskDir); taskDir.mkdirs(); File dataDir = new File(taskDir, DATA_DIR); FileUtils.deleteDirectory(dataDir); dataDir.mkdirs(); } /** * Reads task file and initiates new task. Wipes current task directory. * TaskInfo is saved to file, and from now on can be retrieved with * getCurrentTask() * * @param inputFile * @return * @throws IOException * @throws ClassNotFoundException * @throws ParseException */ public SrzTask saveTaskFile(File inputFile) throws IOException, ClassNotFoundException, ParseException { clearTask(); SrzTask task = readTaskFile(inputFile); File outputFile = new File(rootDir + TASK_DIR + task.getID() + SrzTask.EXT); Files.copy(inputFile.toPath(), outputFile.toPath(), StandardCopyOption.REPLACE_EXISTING); return task; } /** * Reads given file into a task. Does not save the task to the file system. * * @param taskFile * @return * @throws IOException */ public SrzTask readTaskFile(File taskFile) throws IOException { if (taskFile == null || taskFile.length() <= 0) { return null; } Gson gson = new Gson(); SrzTask output = null; try (BufferedReader br = new BufferedReader(new FileReader(taskFile))) { output = gson.fromJson(br, SrzTask.class); } return output; } /** * Saves given SrzData to file. Will overwrite any previous data file with * same ID. * * @param data * @return * @throws IOException */ public File saveData(SrzData data) throws IOException { File dataDir = new File(rootDir + TASK_DIR + DATA_DIR); dataDir.mkdirs(); File output = new File(dataDir, data.getID() + SrzData.EXT); Gson gson = new Gson(); try (BufferedWriter bw = new BufferedWriter(new FileWriter(output))) { gson.toJson(data, bw); } catch (IOException ex) { output.delete(); output = null; throw ex; } return output; } /** * Saves given data file to file system, and returns the SrzData object. * * @param dataFile * @return * @throws IOException */ public SrzData saveDataFile(File dataFile) throws IOException { File dataDir = new File(rootDir + TASK_DIR + DATA_DIR); dataDir.mkdirs(); SrzData output = readDataFile(dataFile); File outputFile = new File( String.format("%s%s%s%d%s", rootDir, TASK_DIR, DATA_DIR, output.getID(), SrzData.EXT)); Files.copy(dataFile.toPath(), outputFile.toPath(), StandardCopyOption.REPLACE_EXISTING); return output; } /** * Reads given task data file into a SrzData object. <br> * File is not saved to worker file system. * * @param dataFile * @return * @throws IOException */ public SrzData readDataFile(File dataFile) throws IOException { if (dataFile == null || dataFile.length() <= 0) { return null; } Gson gson = new Gson(); SrzData output = null; try (BufferedReader br = new BufferedReader(new FileReader(dataFile))) { output = gson.fromJson(br, SrzData.class); } return output; } /** * Reads data object for current task with given ID from file system. * * @param ID * @return * @throws IOException */ public SrzData getData(int ID) throws IOException { SrzData output = null; File dataFile = new File(rootDir + TASK_DIR + DATA_DIR + ID + SrzData.EXT); if (dataFile.length() > 0) { output = readDataFile(dataFile); } return output; } /** * Saves jar file to file system. Name is its MD5 checksum * * @param jarFile * @return * @throws IOException */ public File saveJar(File jarFile) throws IOException { File outputFile = null; try (FileInputStream fis = new FileInputStream(jarFile)) { String md5 = org.apache.commons.codec.digest.DigestUtils.md5Hex(fis); outputFile = new File(String.format("%s%s%s%s", rootDir, JAR_DIR, md5, SrzJar.EXT)); Files.copy(jarFile.toPath(), outputFile.toPath(), StandardCopyOption.REPLACE_EXISTING); } return outputFile; } /** * * @param task * @return */ public File getJarFile(SrzTask task) { File jarFile = new File(String.format("%s%s%s%s", rootDir, JAR_DIR, task.getJar().getHash(), SrzJar.EXT)); if (jarFile.length() <= 0) { return null; } return jarFile; } /** * * @return @throws IOException */ public SrzTask getCurrentTask() throws IOException { File taskDir = new File(rootDir + TASK_DIR); File taskFile = null; for (File f : taskDir.listFiles()) { if (f.isFile() && FilenameUtils.getExtension(f.getPath()) // includes double backslash to escape . special char for regex .equals(SrzTask.EXT.replaceAll("\\.", ""))) { taskFile = f; break; } } return readTaskFile(taskFile); } /** * * @param input * @return */ public boolean isAllDataPresent(SrzTask input) { Map<String, Boolean> presentData = new HashMap<>(); File dataDir = new File(rootDir + TASK_DIR + DATA_DIR); for (File f : dataDir.listFiles()) { presentData.put(f.getName(), true); } for (Integer i : input.getDependencies()) { if (presentData.get(i + SrzData.EXT) == null) { return false; } } return true; } }