/**
   * Loads the contents of the given locations into memory.
   *
   * @param locations locations to add (of type {@link java.io.File <File>}).
   * @throws IOException if an I/O error occurred.
   */
  public synchronized void loadAll(List locations) throws IOException {
    if (locations == null) {
      return;
    }

    Set data = new HashSet(1000);

    for (Iterator i = locations.iterator(); i.hasNext(); ) {
      File location = (File) i.next();
      ClassRepositoryEntry entry = loadEntry(location);

      if (entry != null) {
        data.addAll(entry.getData());

        if (Loggers.IO.isDebugEnabled()) {
          Loggers.IO.debug("ClassRepository: Loaded " + data.size() + " classes from " + location);
        }
      }
    }

    if (!data.isEmpty()) {
      data.addAll(Arrays.asList(_content));
      _content = (String[]) data.toArray(EMPTY_STRING_ARRAY);
      Arrays.sort(_content);
    }
  }
  /**
   * Saves the given entry.
   *
   * @param entry the entry to save.
   * @throws IOException if an I/O error occured.
   */
  private void saveToDisk(ClassRepositoryEntry entry) throws IOException {
    ClassRepositoryEntry.Info info = entry.getInfo();
    ObjectOutputStream out =
        new ObjectOutputStream(
            new BufferedOutputStream(
                new FileOutputStream(
                    getWorkingDir() + File.separator + entry.getInfo().getFilename())));

    try {
      // first the metadata
      out.writeObject(info);
      out.writeObject(entry.getData());
    } finally {
      out.close();
    }
  }
  /**
   * Loads the contents of the given location into memory.
   *
   * <p>If the given location is already registered, both persistent storage and memory will be
   * updated. If the location denotes a Java archive (JAR) an update will only be performed if the
   * archive actually changed.
   *
   * <p>Directories will always be updated as there is no easy way to detect changes in such a case.
   * You should perform logic to avoid unnecessary loads in the Plug-in code.
   *
   * <p>If no entry exits for the location, a new entry will be generated and its contents loaded
   * into memory.
   *
   * @param location location to add.
   * @throws IOException if an I/O error occured.
   */
  public synchronized void load(File location) throws IOException {
    ClassRepositoryEntry entry = loadEntry(location);

    if (entry == null) {
      return;
    }

    Set data = entry.getData();
    Set temp = new HashSet(_content.length + data.size());
    temp.addAll(Arrays.asList(_content));
    temp.addAll(data);
    _content = (String[]) temp.toArray(EMPTY_STRING_ARRAY);
    Arrays.sort(_content);

    if (Loggers.IO.isDebugEnabled()) {
      Loggers.IO.debug("ClassRepository: Loaded " + data.size() + " classes from " + location);
    }
  }
  /**
   * Unloads the given locations from memory. If one of the given locations was not registered, it
   * will be ignored.
   *
   * @param locations locations to unload (of type {@link java.io.File &lt;File&gt;}).
   * @throws IOException if an I/O error occurred.
   * @see ClassRepositoryEntry.Info#getLocation
   */
  public synchronized void unloadAll(List locations) throws IOException {
    Set data = new HashSet(1000);

    for (Iterator i = locations.iterator(); i.hasNext(); ) {
      File location = (File) i.next();

      if (location.exists()) {
        ClassRepositoryEntry entry = null;
        ClassRepositoryEntry.Info template = null;

        try {
          template = new ClassRepositoryEntry.Info(location);

          if (!_infos.contains(template)) {
            continue;
          }

          entry = createEntry(template);
          data.addAll(entry.getData());
        } catch (Exception ex) {
          ex.printStackTrace();

          continue;
        }

        // update the info
        ClassRepositoryEntry.Info info =
            (ClassRepositoryEntry.Info) _infos.get(_infos.indexOf(template));
        info.setLoaded(false);

        if (Loggers.IO.isDebugEnabled()) {
          Loggers.IO.debug(
              "ClassRepository: Unloaded " + entry.getData().size() + " entries for " + location);
        }
      }
    }

    if (!data.isEmpty()) {
      Set temp = new HashSet(Arrays.asList(_content));
      temp.removeAll(data);
      _content = (String[]) temp.toArray(EMPTY_STRING_ARRAY);
      Arrays.sort(_content);
    }
  }
  /**
   * Loads the entry stored in the given file.
   *
   * @param file the file where the entry is stored in.
   * @return the loaded entry.
   * @throws IOException if an I/O error occured.
   * @throws ChainingRuntimeException If an error occurs
   */
  private ClassRepositoryEntry loadFromDisk(File file) throws IOException {
    ObjectInputStream in =
        new ObjectInputStream(new BufferedInputStream(new FileInputStream(file)));

    try {
      ClassRepositoryEntry entry = new ClassRepositoryEntry();
      entry.info = (ClassRepositoryEntry.Info) in.readObject();
      entry.data = (Set) in.readObject();
      in.close(); // so we can update the timestamp

      // we use this timestamp as the last access mark
      file.setLastModified(System.currentTimeMillis());

      return entry;
    } catch (ClassNotFoundException ex) {
      throw new ChainingRuntimeException(ex);
    } finally {
      in.close();
    }
  }
  /**
   * Unloads the given file from memory. If the given location was not registered, the call we be
   * safely ignored.
   *
   * @param location location to unload.
   * @throws IOException if an I/O error occurred.
   * @see ClassRepositoryEntry.Info#getLocation
   */
  public synchronized void unload(File location) throws IOException {
    ClassRepositoryEntry.Info template = new ClassRepositoryEntry.Info(location);

    if (!_infos.contains(template)) {
      return;
    }

    ClassRepositoryEntry entry = createEntry(template);
    Set data = entry.getData();
    Set temp = new HashSet(Arrays.asList(_content));
    temp.removeAll(data);
    _content = (String[]) temp.toArray(EMPTY_STRING_ARRAY);
    Arrays.sort(_content);

    // update the info
    ClassRepositoryEntry.Info info =
        (ClassRepositoryEntry.Info) _infos.get(_infos.indexOf(template));
    info.setLoaded(false);

    if (Loggers.IO.isDebugEnabled()) {
      Loggers.IO.debug("ClassRepository: Unloaded " + data.size() + " entries for " + location);
    }
  }