private java.nio.ByteBuffer readElevations(Object source) throws java.io.IOException {
    if (!(source instanceof java.io.File) && !(source instanceof java.net.URL)) {
      String message = Logging.getMessage("DataRaster.CannotRead", source);
      Logging.logger().severe(message);
      throw new java.io.IOException(message);
    }

    if (source instanceof java.io.File) {
      java.io.File file = (java.io.File) source;

      // handle .bil.zip, .bil16.zip, and .bil32.gz files
      if (file.getName().toLowerCase().endsWith(".zip")) {
        return WWIO.readZipEntryToBuffer(file, null);
      }
      // handle bil.gz, bil16.gz, and bil32.gz files
      else if (file.getName().toLowerCase().endsWith(".gz")) {
        return WWIO.readGZipFileToBuffer(file);
      } else if (!this.isMapLargeFiles() || (this.getLargeFileThreshold() > file.length())) {
        return WWIO.readFileToBuffer(file);
      } else {
        return WWIO.mapFile(file);
      }
    } else // (source instanceof java.net.URL)
    {
      java.net.URL url = (java.net.URL) source;
      return WWIO.readURLContentToBuffer(url);
    }
  }
  protected String[] doListFileNames(
      String pathName, FileStoreFilter filter, boolean recurse, boolean exitBranchOnFirstMatch) {
    java.util.ArrayList<String> nameList = null;

    for (StoreLocation location : this.readLocations) {
      // If the path name is null, then just search from the root of each location. Otherwise search
      // from the
      // named cache path.
      java.io.File dir = location.getFile();
      if (pathName != null) dir = new java.io.File(makeAbsolutePath(dir, pathName));

      // Either the location does not exists, or the speciifed path does not exist under that
      // location. In either
      // case we skip searching this location.
      if (!dir.exists()) continue;

      // Lazily initialize the list of file names. If no location contains the specified path, then
      // the list is
      // not created, and this method will return null.
      if (nameList == null) nameList = new java.util.ArrayList<String>();

      this.doListFileNames(location, dir, filter, recurse, exitBranchOnFirstMatch, nameList);
    }

    if (nameList == null) return null;

    String[] names = new String[nameList.size()];
    nameList.toArray(names);
    return names;
  }
  protected void doListFileNames(
      StoreLocation location,
      java.io.File dir,
      FileStoreFilter filter,
      boolean recurse,
      boolean exitBranchOnFirstMatch,
      java.util.Collection<String> names) {
    java.util.ArrayList<java.io.File> subDirs = new java.util.ArrayList<java.io.File>();

    // Search the children of the specified directory. If the child is a directory, append it to the
    // list of sub
    // directories to search later. Otherwise, try to list the file as a match. If the file is a
    // match and
    // exitBranchOnFirstMatch is true, then exit this branch without considering any other files.
    // This has the
    // effect of choosing files closest to the search root.
    for (java.io.File childFile : dir.listFiles()) {
      if (childFile == null) continue;

      if (childFile.isDirectory()) {
        subDirs.add(childFile);
      } else {
        if (this.listFile(location, childFile, filter, names) && exitBranchOnFirstMatch) return;
      }
    }

    if (!recurse) return;

    // Recursively search each sub-directory. If exitBranchOnFirstMatch is true, then we did not
    // find a match under
    // this directory.
    for (java.io.File childDir : subDirs) {
      this.doListFileNames(location, childDir, filter, recurse, exitBranchOnFirstMatch, names);
    }
  }
  /**
   * @param url the "file:" URL of the file to remove from the file store. Only files in the
   *     writable World Wind disk cache or temp file directory are removed by this method.
   * @throws IllegalArgumentException if <code>url</code> is null
   */
  @SuppressWarnings({"ResultOfMethodCallIgnored"})
  public void removeFile(java.net.URL url) {
    if (url == null) {
      String msg = Logging.getMessage("nullValue.URLIsNull");
      Logging.logger().severe(msg);
      throw new IllegalArgumentException(msg);
    }

    try {
      java.io.File file = new java.io.File(url.toURI());

      // This block of code must be synchronized for proper operation. A thread may check that the
      // file exists,
      // and become immediately suspended. A second thread may then delete that file. When the first
      // thread
      // wakes up, file.delete() fails.
      synchronized (this.fileLock) {
        if (file.exists()) {
          // Don't remove files outside the cache or temp directory.
          String parent = file.getParent();
          if (!(parent.startsWith(this.getWriteLocation().getPath())
              || parent.startsWith(Configuration.getSystemTempDirectory()))) return;

          file.delete();
        }
      }
    } catch (java.net.URISyntaxException e) {
      Logging.logger()
          .log(
              Level.SEVERE,
              Logging.getMessage("FileStore.ExceptionRemovingFile", url.toString()),
              e);
    }
  }
  /**
   * @param fileName the name to give the newly created file
   * @return a handle to the newly created file if it could be created and added to the file store,
   *     otherwise null
   * @throws IllegalArgumentException if <code>fileName</code> is null
   */
  public java.io.File newFile(String fileName) {
    if (fileName == null) {
      String message = Logging.getMessage("nullValue.FilePathIsNull");
      Logging.logger().severe(message);
      throw new IllegalArgumentException(message);
    }

    if (this.writeLocation != null) {
      String fullPath = makeAbsolutePath(this.writeLocation.getFile(), fileName);
      java.io.File file = new java.io.File(fullPath);
      boolean canCreateFile = false;

      // This block of code must be synchronized for proper operation. A thread may check that
      // file.getParentFile() does not exist, and become immediately suspended. A second thread may
      // then create
      // the parent and ancestor directories. When the first thread wakes up,
      // file.getParentFile().mkdirs()
      // fails, resulting in an erroneous log message: The log reports that the file cannot be
      // created.
      synchronized (this.fileLock) {
        if (file.getParentFile().exists()) canCreateFile = true;
        else if (file.getParentFile().mkdirs()) canCreateFile = true;
      }

      if (canCreateFile) return file;
      else {
        String msg = Logging.getMessage("generic.CannotCreateFile", fullPath);
        Logging.logger().severe(msg);
      }
    }

    return null;
  }
  protected StoreLocation storeLocationFor(String path) {
    java.io.File file = new java.io.File(path);

    for (StoreLocation location : this.readLocations) {
      if (file.equals(location.getFile())) return location;
    }

    return null;
  }
  public boolean containsFile(String fileName) {
    if (fileName == null) return false;

    for (StoreLocation location : this.readLocations) {
      java.io.File dir = location.getFile();
      java.io.File file;

      if (fileName.startsWith(dir.getAbsolutePath())) file = new java.io.File(fileName);
      else file = makeAbsoluteFile(dir, fileName);

      if (file.exists()) return true;
    }

    return false;
  }
  protected static String storePathForFile(StoreLocation location, java.io.File file) {
    String path = file.getPath();

    if (location != null) {
      String locationPath = location.getFile().getPath();
      if (path.startsWith(locationPath))
        path = path.substring(locationPath.length(), path.length());
    }

    return path;
  }
  @SuppressWarnings({"ResultOfMethodCallIgnored"})
  protected void buildWritePaths(org.w3c.dom.Node dataFileCacheNode) {
    javax.xml.xpath.XPathFactory pathFactory = javax.xml.xpath.XPathFactory.newInstance();
    javax.xml.xpath.XPath pathFinder = pathFactory.newXPath();

    try {
      org.w3c.dom.NodeList locationNodes =
          (org.w3c.dom.NodeList)
              pathFinder.evaluate(
                  "/dataFileStore/writeLocations/location",
                  dataFileCacheNode.getFirstChild(),
                  javax.xml.xpath.XPathConstants.NODESET);
      for (int i = 0; i < locationNodes.getLength(); i++) {
        org.w3c.dom.Node location = locationNodes.item(i);
        String prop = pathFinder.evaluate("@property", location);
        String wwDir = pathFinder.evaluate("@wwDir", location);
        String append = pathFinder.evaluate("@append", location);
        String create = pathFinder.evaluate("@create", location);

        String path = buildLocationPath(prop, append, wwDir);
        if (path == null) {
          Logging.logger()
              .log(
                  Level.WARNING,
                  "FileStore.LocationInvalid",
                  prop != null ? prop : Logging.getMessage("generic.Unknown"));
          continue;
        }

        Logging.logger().log(Level.FINER, "FileStore.AttemptingWriteDir", path);
        java.io.File pathFile = new java.io.File(path);
        if (!pathFile.exists()
            && create != null
            && (create.contains("t") || create.contains("T"))) {
          Logging.logger().log(Level.FINER, "FileStore.MakingDirsFor", path);
          pathFile.mkdirs();
        }

        if (pathFile.isDirectory() && pathFile.canWrite() && pathFile.canRead()) {
          Logging.logger().log(Level.FINER, "FileStore.WriteLocationSuccessful", path);
          this.writeLocation = new StoreLocation(pathFile);

          // Remove the writable location from search path if it already exists.
          StoreLocation oldLocation = this.storeLocationFor(path);
          if (oldLocation != null) this.readLocations.remove(oldLocation);

          // Writable location is always first in search path.
          this.readLocations.add(0, this.writeLocation);

          break; // only need one
        }
      }
    } catch (javax.xml.xpath.XPathExpressionException e) {
      String message = Logging.getMessage("FileStore.ExceptionReadingConfigurationFile");
      Logging.logger().severe(message);
      throw new IllegalStateException(message, e);
    }
  }
  @SuppressWarnings({"ResultOfMethodCallIgnored"})
  protected static void markFileUsed(java.io.File file) {
    if (file == null) return;

    long currentTime = System.currentTimeMillis();

    if (file.canWrite()) file.setLastModified(currentTime);

    if (file.isDirectory()) return;

    java.io.File parent = file.getParentFile();
    if (parent != null && parent.canWrite()) parent.setLastModified(currentTime);
  }
  /**
   * @param fileName the name of the file to find
   * @param checkClassPath if <code>true</code>, the class path is first searched for the file,
   *     otherwise the class path is not searched unless it's one of the explicit paths in the cache
   *     search directories
   * @return a handle to the requested file if it exists in the cache, otherwise null
   * @throws IllegalArgumentException if <code>fileName</code> is null
   */
  public java.net.URL findFile(String fileName, boolean checkClassPath) {
    if (fileName == null) {
      String message = Logging.getMessage("nullValue.FilePathIsNull");
      Logging.logger().severe(message);
      throw new IllegalArgumentException(message);
    }

    if (checkClassPath) {
      java.net.URL url = this.getClass().getClassLoader().getResource(fileName);
      if (url != null) return url;

      // Check for a thread context class loader. This allows the file store to find resources in a
      // case
      // in which different parts of the application are handled by different class loaders.
      ClassLoader tccl = Thread.currentThread().getContextClassLoader();
      if (tccl != null) {
        url = tccl.getResource(fileName);
        if (url != null) return url;
      }
    }

    for (StoreLocation location : this.readLocations) {
      java.io.File dir = location.getFile();
      if (!dir.exists()) continue;

      java.io.File file = new java.io.File(makeAbsolutePath(dir, fileName));
      if (file.exists()) {
        try {
          if (location.isMarkWhenUsed()) markFileUsed(file);
          else markFileUsed(file.getParentFile());

          return file.toURI().toURL();
        } catch (java.net.MalformedURLException e) {
          Logging.logger()
              .log(
                  Level.SEVERE,
                  Logging.getMessage("FileStore.ExceptionCreatingURLForFile", file.getPath()),
                  e);
        }
      }
    }

    return null;
  }
 protected static String makeAbsolutePath(java.io.File dir, String fileName) {
   return dir.getAbsolutePath() + "/" + fileName;
 }
 protected static java.io.File makeAbsoluteFile(java.io.File file, String fileName) {
   return new java.io.File(file.getAbsolutePath() + "/" + fileName);
 }
  protected void buildReadPaths(org.w3c.dom.Node dataFileStoreNode) {
    javax.xml.xpath.XPathFactory pathFactory = javax.xml.xpath.XPathFactory.newInstance();
    javax.xml.xpath.XPath pathFinder = pathFactory.newXPath();

    try {
      org.w3c.dom.NodeList locationNodes =
          (org.w3c.dom.NodeList)
              pathFinder.evaluate(
                  "/dataFileStore/readLocations/location",
                  dataFileStoreNode.getFirstChild(),
                  javax.xml.xpath.XPathConstants.NODESET);
      for (int i = 0; i < locationNodes.getLength(); i++) {
        org.w3c.dom.Node location = locationNodes.item(i);
        String prop = pathFinder.evaluate("@property", location);
        String wwDir = pathFinder.evaluate("@wwDir", location);
        String append = pathFinder.evaluate("@append", location);
        String isInstall = pathFinder.evaluate("@isInstall", location);
        String isMarkWhenUsed = pathFinder.evaluate("@isMarkWhenUsed", location);

        String path = buildLocationPath(prop, append, wwDir);
        if (path == null) {
          Logging.logger()
              .log(
                  Level.WARNING,
                  "FileStore.LocationInvalid",
                  prop != null ? prop : Logging.getMessage("generic.Unknown"));
          continue;
        }

        StoreLocation oldStore = this.storeLocationFor(path);
        if (oldStore != null) // filter out duplicates
        continue;

        // Even paths that don't exist or are otherwise problematic are added to the list because
        // they may
        // become readable during the session. E.g., removable media. So add them to the search
        // list.

        java.io.File pathFile = new java.io.File(path);
        if (pathFile.exists() && !pathFile.isDirectory()) {
          Logging.logger().log(Level.WARNING, "FileStore.LocationIsFile", pathFile.getPath());
        }

        boolean pathIsInstall =
            isInstall != null && (isInstall.contains("t") || isInstall.contains("T"));
        StoreLocation newStore = new StoreLocation(pathFile, pathIsInstall);

        // If the input parameter "markWhenUsed" is null or empty, then the StoreLocation should
        // keep its
        // default value. Otherwise the store location value is set to true when the input parameter
        // contains
        // "t", and is set to false otherwise.
        if (isMarkWhenUsed != null && isMarkWhenUsed.length() > 0)
          newStore.setMarkWhenUsed(isMarkWhenUsed.toLowerCase().contains("t"));

        this.readLocations.add(newStore);
      }
    } catch (javax.xml.xpath.XPathExpressionException e) {
      String message = Logging.getMessage("FileStore.ExceptionReadingConfigurationFile");
      Logging.logger().severe(message);
      throw new IllegalStateException(message, e);
    }
  }