예제 #1
1
  /**
   * 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);
    }
  }
예제 #2
0
  /** Loads all existing repository infos from persisent storage. */
  private void preload() {
    try {
      File[] files = getWorkingDir().listFiles(new ExtensionFilter(EXT_REPOSITORY));
      long now = System.currentTimeMillis();

      /** @todo make user configurable */
      long delta = 1000 * 60 * 60 * 24 * 15;

      for (int i = 0; i < files.length; i++) {
        ClassRepositoryEntry.Info info = loadInfo(files[i]);
        _infos.add(info);

        if ((files[i].lastModified() + delta) < now) {
          // remove repository file not used for a long time
          if (!files[i].delete()) {
            Object[] args = {files[i]};
            Loggers.IO.l7dlog(Level.INFO, "IMPORT_DELETE_UNUSED_ERR", args, null);
          }
        }
      }
    } catch (Throwable ex) {
      _infos.clear();
      Loggers.IO.warn("Error preloading the class repository, no import optimizaton available", ex);
    }
  }
예제 #3
0
  /**
   * 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);
    }
  }
예제 #4
0
  /**
   * 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);
    }
  }
예제 #5
0
  /**
   * 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);
    }
  }
예제 #6
0
  /**
   * Loads the entry from the given location.
   *
   * @param location location where the entry is stored.
   * @return the entry. Returns <code>null</code> if the entry is up-to-date.
   * @throws IOException if the entry could not be loaded.
   */
  private ClassRepositoryEntry loadEntry(File location) throws IOException {
    // either the user has deleted/renamed the .jar since the first
    // initialization or the project was newly created
    if (!location.exists()) {
      if (location.getName().endsWith(".jar") || location.getName().endsWith(".zip")) {
        // for .jars this always means an error
        throw new IOException("File not found -- " + location);
      }

      if (!location.mkdirs()) {
        throw new IOException("Directory not found -- " + location);
      }

      if (Loggers.IO.isDebugEnabled()) {
        Loggers.IO.debug("ClassRepository: Created new directory: " + location);
      }
    }

    ClassRepositoryEntry.Info template = new ClassRepositoryEntry.Info(location);
    ClassRepositoryEntry.Info info = template;
    ClassRepositoryEntry entry = null;

    // location already registered
    if (_infos.contains(template)) {
      info = (ClassRepositoryEntry.Info) _infos.get(_infos.indexOf(template));

      if (Loggers.IO.isDebugEnabled()) {
        Loggers.IO.debug("ClassRepository: Already registered: " + info);
      }

      // already loaded in memory
      if (info.isLoaded()) {
        if (Loggers.IO.isDebugEnabled()) {
          Loggers.IO.debug("ClassRepository: Alread loaded: " + info);
        }

        // always rescan directories as the contents might have changed
        if (location.isDirectory()) {
          if (Loggers.IO.isDebugEnabled()) {
            Loggers.IO.debug("ClassRepository: Create new: " + info);
            Loggers.IO.debug("ClassRepository: Save to disk: " + info);
          }

          entry = createEntry(info);

          saveToDisk(entry);
        } else {
          if (location.lastModified() == info.getLocation().lastModified()) {
            if (Loggers.IO.isDebugEnabled()) {
              Loggers.IO.debug("ClassRepository: Up to date: " + info);
            }

            // no changes detected, nothing to do
            return entry;
          }

          if (Loggers.IO.isDebugEnabled()) {
            Loggers.IO.debug("ClassRepository: Create new: " + info);
            Loggers.IO.debug("ClassRepository: Save to disk: " + info);
          }

          entry = createEntry(info);

          saveToDisk(entry);
        }
      } else {
        // always rescan directories as the contents might have changed
        if (location.isDirectory()) {
          if (Loggers.IO.isDebugEnabled()) {
            Loggers.IO.debug("ClassRepository: Create new: " + info);
            Loggers.IO.debug("ClassRepository: Save to disk: " + info);
          }

          entry = createEntry(info);

          saveToDisk(entry);
        } else {
          if (Loggers.IO.isDebugEnabled()) {
            Loggers.IO.debug("ClassRepository: Load from disk: " + info);
          }

          // load from persistent storage
          entry = loadFromDisk(new File(getWorkingDir() + File.separator + info.getFilename()));
        }
      }
    } else {
      _infos.add(template);

      if (Loggers.IO.isDebugEnabled()) {
        Loggers.IO.debug("ClassRepository: Create new: " + info);
        Loggers.IO.debug("ClassRepository: Save to disk: " + info);
      }

      entry = createEntry(template);

      saveToDisk(entry);
    }

    info = (ClassRepositoryEntry.Info) _infos.get(_infos.indexOf(template));
    info.setLoaded(true);

    return entry;
  }
예제 #7
0
  /**
   * Creates a new entry.
   *
   * @param location location of the package to add.
   * @param path path to add.
   * @param types the package types.
   * @param verify if <code>true</code> the package root check will be performed.
   * @return if <code>verify == true</code> returns <code>true</code> when the given location could
   *     be verified, <code>false</code> if the given location is no package root; otherwise always
   *     returns <code>true</code>.
   */
  private static boolean createEntryImpl(
      File location, String path, final Set types, boolean verify) {
    // strip extension
    path = path.substring(0, path.lastIndexOf('.'));

    int pos = path.lastIndexOf('$');

    // is this an inner class?
    if (pos > -1) {
      String className = path.substring(pos + 1);

      // skip anonymous inner classes
      if (StringHelper.isNumber(className)) {
        return true;
      }

      path = path.replace('$', '.');
    } else if (verify) {
      try {
        // we setup a classloader with the given location and check
        // whether the location is indeed a package root
        URL[] url = new URL[] {location.toURL()};
        ClassLoader loader = new URLClassLoader(url, ClassRepository.class.getClassLoader());
        loader.loadClass(path.replace(File.separatorChar, '.'));
      } catch (ClassNotFoundException ex) {
        Object[] args = {path, location};
        Loggers.IO.l7dlog(Level.WARN, "REPOSITORY_NOT_PACKAGE_ROOT", args, null);

        return false;
      } catch (Throwable ex) {
        return false;
      }
    }

    String typeName = StringHelper.getClassName(path);

    // HACK skip obfuscated classes
    // this is necessary to make our import declaration expanding working
    // as it could easily be, that an identifier reported by the parser
    // would be wrongly taken as a type name:
    //
    //      Database d = new Database();
    //      d.shutdown();
    //      ^
    // 'd' would be reported as an identifier which is perfect but
    // lead to wrong results as there could be a class 'd.class' for
    // obfuscated librarys
    if ((typeName.length() == 1) && Character.isLowerCase(typeName.charAt(0))) {
      return true;
    }

    String packageName = StringHelper.getPackageName(path);

    // we place this marker in front of every subpackage so we know
    // where a package starts (purely for the searching facility in
    // ImportTransformation.java)
    if (!EMPTY_STRING.equals(packageName)) {
      types.add(packageName + '#');
    }

    types.add(path);

    return true;
  }