/** Returns the path to be used as the servlet name. */
  private Path getPagePath(String pathName) {
    Path rootDir = _webApp.getRootDirectory();
    String realPath = _webApp.getRealPath(pathName);
    Path path = rootDir.lookupNative(realPath);

    if (path.isFile() && path.canRead()) return path;

    java.net.URL url;
    ClassLoader loader = _webApp.getClassLoader();
    if (loader != null) {
      url = _webApp.getClassLoader().getResource(pathName);

      String name = url != null ? url.toString() : null;

      path = null;
      if (url != null && (name.endsWith(".jar") || name.endsWith(".zip")))
        path = JarPath.create(Vfs.lookup(url.toString())).lookup(pathName);
      else if (url != null) path = Vfs.lookup(url.toString());

      if (path != null && path.isFile() && path.canRead()) return path;
    }

    url = ClassLoader.getSystemResource(pathName);
    String name = url != null ? url.toString() : null;

    path = null;
    if (url != null && (name.endsWith(".jar") || name.endsWith(".zip")))
      path = JarPath.create(Vfs.lookup(url.toString())).lookup(pathName);
    else if (url != null) path = Vfs.lookup(url.toString());

    if (path != null && path.isFile() && path.canRead()) return path;
    else return null;
  }
  /** Returns the code source. */
  public CodeSource getCodeSource(String path) {
    try {
      Path jarPath = _jarPath.lookup(path);

      Certificate[] certificates = jarPath.getCertificates();

      URL url = new URL(_jarPath.getContainer().getURL());

      return new CodeSource(url, certificates);
    } catch (Exception e) {
      log.log(Level.WARNING, e.toString(), e);

      return null;
    }
  }
  /** Reads the jar's manifest. */
  private void loadManifest() {
    if (_isManifestRead) return;

    synchronized (this) {
      if (_isManifestRead) return;

      try {
        _manifest = _jarPath.getManifest();
        if (_manifest == null) return;

        Attributes attr = _manifest.getMainAttributes();
        if (attr != null) addManifestPackage("", attr);

        Map<String, Attributes> entries = _manifest.getEntries();

        for (Map.Entry<String, Attributes> entry : entries.entrySet()) {
          String pkg = entry.getKey();

          attr = entry.getValue();
          if (attr == null) continue;

          addManifestPackage(pkg, attr);
        }
      } catch (IOException e) {
        log.log(Level.WARNING, e.toString(), e);
      } finally {
        _isManifestRead = true;
      }
    }
  }
  /** Sets the resource directory. */
  public void setPath(Path path) {
    if (path.getPath().endsWith(".jar") || path.getPath().endsWith(".zip")) {
      path = JarPath.create(path);
    }

    _path = path;
  }
  /** Tests for equality. */
  @Override
  public boolean equals(Object o) {
    if (!(o instanceof JarEntry)) return false;

    JarEntry entry = (JarEntry) o;

    return _jarPath.equals(entry._jarPath);
  }
  /** Validates the jar. */
  public void validate() throws ConfigException {
    loadManifest();

    if (_manifest != null) validateManifest(_jarPath.getContainer().getURL(), _manifest);
  }