/** Saves the content of a given system store to file. */ public static SystemStore save(File file, SystemStore store, boolean clearDir) throws IOException { if (!GRAMMAR.hasExtension(file)) { throw new IOException(String.format("File '%s' does not refer to a production system", file)); } // if the file already exists, rename it // in order to be able to restore if saving fails File newFile = null; if (file.exists()) { newFile = file; do { newFile = new File(newFile.getParent(), "Copy of " + newFile.getName()); } while (newFile.exists()); if (clearDir) { if (!file.renameTo(newFile)) { throw new IOException(String.format("Can't save grammar to existing file '%s'", file)); } } else { Util.copyDirectory(file, newFile, true); } } try { DefaultFileSystemStore result = new DefaultFileSystemStore(file, true); result.reload(); // save properties for (ResourceKind kind : ResourceKind.values()) { if (kind == PROPERTIES) { result.putProperties(store.getProperties()); } else if (kind.isTextBased()) { result.putTexts(kind, store.getTexts(kind)); } else { result.putGraphs(kind, store.getGraphs(kind).values(), false); } } if (newFile != null) { boolean deleted = deleteRecursive(newFile); assert deleted : String.format("Failed to delete '%s'", newFile); } return result; } catch (IOException exc) { file.delete(); // attempt to re-rename previously existing file if (newFile != null) { newFile.renameTo(file); } throw exc; } }
/** * Constructs a store from a given file. The file should be a JAR or ZIP file containing a single * subdirectory with extension {@link FileType#GRAMMAR}. The store is immutable. * * @param file source JAR or ZIP file containing the rule system * @throws IllegalArgumentException if <code>file</code> is not a correct archive */ public DefaultArchiveSystemStore(File file) throws IllegalArgumentException { if (!file.exists()) { throw new IllegalArgumentException(String.format("File '%s' does not exist", file)); } String extendedName; if (!file.isDirectory() && JAR.hasExtension(file)) { extendedName = JAR.stripExtension(file.getName()); } else if (!file.isDirectory() && ZIP.hasExtension(file)) { extendedName = ZIP.stripExtension(file.getName()); } else { throw new IllegalArgumentException(String.format("File '%s' " + NO_JAR_OR_ZIP_SUFFIX, file)); } this.location = file.toString(); this.file = file; this.entryName = extendedName; this.grammarName = GRAMMAR.stripExtension(extendedName); this.url = null; }
/** * Constructs a store from a given URL. The URL should either specify the <code>jar:</code> * protocol, in which case the sub-URL should point to a JAR or ZIP file; or the URL should itself * specify a JAR or ZIP file. Query and reference part of the URL are ignored. The store is * immutable. * * @param url source location of the underlying persistent storage; should refer to a ZIP or JAR * file. * @throws IllegalArgumentException if <code>location</code> does not specify the correct protocol * @throws IOException if the URL has the JAR protocol, but cannot be opened */ public DefaultArchiveSystemStore(URL url) throws IllegalArgumentException, IOException { // first strip query and anchor part try { url = new URL(url.getProtocol(), url.getAuthority(), url.getPath()); } catch (MalformedURLException exc) { assert false : String.format("Stripping URL '%s' throws exception: %s", url, exc); } this.location = url.toString(); // artificially append the jar protocol, if it is not yet there if (!url.getProtocol().equals(JAR_PROTOCOL)) { if (!JAR.hasExtension(url.getPath()) && !ZIP.hasExtension(url.getPath())) { throw new IllegalArgumentException(String.format("URL '%s' is not a JAR or ZIP file", url)); } url = new URL(JAR_PROTOCOL, null, url.toString() + "!/"); } this.entryName = extractEntryName(url); // take the last part of the entry name as grammar name File fileFromEntry = new File(this.entryName); this.grammarName = GRAMMAR.stripExtension(fileFromEntry.getName()); this.url = url; this.file = null; }