/**
  * 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;
 }