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