/* * The MIT License * * Copyright 2015 Neil McAlister. * * Permission is hereby granted, free of charge, to any person obtaining a copy * of this software and associated documentation files (the "Software"), to deal * in the Software without restriction, including without limitation the rights * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell * copies of the Software, and to permit persons to whom the Software is * furnished to do so, subject to the following conditions: * * The above copyright notice and this permission notice shall be included in * all copies or substantial portions of the Software. * * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN * THE SOFTWARE. */ package dotaSoundEditor.Helpers; import dotaSoundEditor.UserPrefs; import info.ata4.vpk.VPKArchive; import info.ata4.vpk.VPKEntry; import info.ata4.vpk.VPKException; import java.io.*; import java.net.URISyntaxException; import java.nio.file.Paths; import java.util.HashMap; import java.util.Properties; public class CacheManager { private Properties scriptsProperties = new Properties(); private HashMap<String, Long> sessionCrcs = new HashMap<>(); private VPKEntry cachedEntry = null; private String relativePath; private final String SCRIPTS_FILE_NAME = "scripts.properties"; private final String PATH_SEP = "_path"; private final String SESSION_CRC_SEP = "_latestcrc"; public CacheManager() { try { relativePath = getClass().getProtectionDomain().getCodeSource().getLocation().getPath(); relativePath = relativePath.substring(0, relativePath.lastIndexOf("/")); relativePath = relativePath.replaceAll("%20"," "); } catch (Exception ex) { ex.printStackTrace(); return; } if(System.getProperty("os.name").toUpperCase().contains("WINDOWS")) { //Kill the leading slash for Windows systems, windows paths don't start with / relativePath = relativePath.substring(1); } File propsFile = Paths.get(relativePath, SCRIPTS_FILE_NAME).toFile(); try { if (!propsFile.isFile()) { propsFile.getParentFile().mkdirs(); propsFile.createNewFile(); } FileInputStream fis = new FileInputStream(propsFile); try { scriptsProperties.load(fis); } catch (IOException ex) { System.out.println("Could not load cache file."); ex.printStackTrace(); } } catch (IOException ex) { System.out.println("Could not load cache file."); ex.printStackTrace(); } } /** * @param scriptKey The filename of the script file. This will be used as * the key of the script's CRC32 in the cache. * @param scriptPath The vpk-internal file path of the script file. (i.e. * dota/scripts/game_sounds_heroes/game_sounds_lina.txt) * @return The old CRC value of the script that was just updated, or null if * it was just added. */ public String putScript(String scriptKey, String scriptPath, long crc) { String oldCrc = scriptsProperties.setProperty(scriptKey, Long.toString(crc)) == null ? null : scriptsProperties.setProperty(scriptKey, Long.toString(crc)).toString(); putScriptPath(scriptKey, scriptPath); sessionCrcs.put(scriptKey + SESSION_CRC_SEP, crc); return oldCrc; } public void putScriptPath(String scriptKey, String scriptPath) { scriptsProperties.setProperty(scriptKey + PATH_SEP, scriptPath); } public String removeScript(String scriptKey) { Object removed = scriptsProperties.remove(scriptKey); if (removed != null) { scriptsProperties.remove(scriptKey + PATH_SEP); sessionCrcs.remove(scriptKey + SESSION_CRC_SEP); } return removed.toString(); } /** * @param scriptKey The filename of the script whose CRC you want. * @param internalCrc The CRC of the up-to-date, internal script. * @return True if the CRC saved in cache is equal to the internal CRC. * False otherwise. * */ public boolean isUpToDate(String scriptKey, long internalCrc) { long cachedCrc; Object value = scriptsProperties.getProperty(scriptKey); if (value == null) { return false; } cachedCrc = Long.parseLong(value.toString()); return cachedCrc == internalCrc; } /** * @param scriptKey The filename of the script whose CRC you want. * @return The CRC value of the session-cached script. These values are * retrieved and stored the first time a script is validated against cache, * and cleared again on program exit. Returns 0 on failure. * */ public long getSessionCrc(String scriptKey) { //check local table first if (sessionCrcs.containsKey(scriptKey + SESSION_CRC_SEP)) { return sessionCrcs.get(scriptKey + SESSION_CRC_SEP); } String vpkPath = UserPrefs.getInstance().getVPKPath(); VPKArchive vpk = new VPKArchive(); long internalCrc = 0; try { vpk.load(new File(vpkPath)); String scriptPath = scriptsProperties.getProperty(scriptKey + PATH_SEP); VPKEntry scriptEntry = vpk.getEntry(scriptPath); if (scriptEntry != null) { internalCrc = scriptEntry.getCRC32(); } else { throw new ScriptNotFoundException("Unable to locate VPKEntry at " + scriptPath); } cachedEntry = scriptEntry; } catch (ScriptNotFoundException | VPKException ex) { System.out.println("Failed to load VPK in CacheManager. Details: " + ex.getMessage()); ex.printStackTrace(); } catch (IOException ioe) { System.out.println("Failed to load VPK in CacheManager. Details: " + ioe.getMessage()); ioe.printStackTrace(); } finally { sessionCrcs.put(scriptKey + SESSION_CRC_SEP, internalCrc); return internalCrc; } } /** * Returns the VPKEntry that corresponds to file whose CRC32 was most recently checked in * getSessionCrc. * @return The VPKEntry of the most recently looked-up file. */ public VPKEntry getCachedVpkEntry() { return cachedEntry; } public void saveCache() throws IOException, URISyntaxException, SecurityException, NullPointerException { File outFile = Paths.get(relativePath, SCRIPTS_FILE_NAME).toFile(); OutputStream os = new FileOutputStream(outFile); scriptsProperties.store(os, null); } }