public class JSPloader extends ClassLoader {
  JSPhandler handler;
  String jarURL;
  String jarName;
  HashMap classes = null;
  ClassLoader parent;
  public JSPloader(JSPhandler jh, String jarName,
    String jarURL)
    throws javax.servlet.ServletException {
    super();
    handler = jh;
    this.jarURL = jarURL;
    this.jarName = jarName;
    parent = getParent();
    if (!loadClassDataFS()) {
      if (!loadClassDataURL())
        throw new javax.servlet.ServletException(
        "JSPloader.JSPloader unable to load jar");
    }
  }
  private final boolean parseStream(
    JarInputStream jis, boolean toSave) {
    JarEntry je = null;
    boolean rc = true;
    try {
      JarOutputStream jos = null;
      if (toSave)
        jos = new JarOutputStream(
          new BufferedOutputStream(
          new FileOutputStream(handler.cachePath +
          "/" + jarName + ".jar")));
      while((je = jis.getNextJarEntry()) != null){
        String entryName = je.getName();
        if (entryName.endsWith(".class")) {
          if (toSave)
          jos.putNextEntry((JarEntry)je.clone());
          ByteArrayOutputStream baos =
            new ByteArrayOutputStream();
          BufferedInputStream bis =
            new BufferedInputStream(jis);
          int i;
          while((i = bis.read()) != -1)
            baos.write(i);
          if (classes == null)
            classes = new HashMap(100);
          byte[] buf = baos.toByteArray();
          String k = entryName.substring(0,
  entryName.lastIndexOf('.')).replace('/', '.');
          Class jarCl = defineClass(k, buf, 0,
            buf.length);
          classes.put(k, jarCl);
          if (toSave)
            jos.write(buf, 0, buf.length);
        }
        jis.closeEntry();
      }
      jis.close();
      if (toSave) {
        jos.closeEntry();
        jos.close();
      }
    }
    catch(Exception e) {
      rc = false;
    }
    return rc;
  }
  private final boolean loadClassDataFS() {
    String jarPath = handler.cachePath + "/" +
      jarName + ".jar";
    JarInputStream jis = null;
    try {
      jis = new JarInputStream(
        new FileInputStream(jarPath));
    }
    catch(Exception e) {
      return false;
    }
    return parseStream(jis, false);
  }
  private final boolean loadClassDataURL() {
    JarInputStream jis = null;
    try {
      URL url = new URL(jarURL + "/" + jarName
        + ".jar");
      InputStream is =
        url.openConnection().getInputStream();
      jis = new JarInputStream(is);
    }
    catch(Exception e) {
      return false;
    }
    return parseStream(jis, true);
  }
  private final Class loadForward(String name)
    throws ClassNotFoundException{
    try {
      return findSystemClass(name);
    }
    catch(ClassNotFoundException cnfe) {}

    try {
      return parent.loadClass(name);
    }
    catch(ClassNotFoundException cnfe) {
      throw cnfe;
    }
    catch(Exception e2) {
      throw new ClassNotFoundException(
        e2.toString());
    }
  }
  public synchronized Class loadClass(String name,
    boolean resolve)
    throws ClassNotFoundException {
    if (name.equals("javax.servlet.Servlet") ||
      name.startsWith("java."))
      return loadForward(name);
    if ((classes != null) &&
      (classes.containsKey(name))) {
      Class cl = (Class)classes.get(name);
      if (resolve)
        resolveClass(cl);
      return cl;
    }
    return loadForward(name);
  }
}