A Practical Solution for the Deployment of JavaServer Pages
Written by Alexis Grandemange p.84

Download files assoicated with this article

Listing 1: Apache implementation of _jspService and jspInit
public final void init(ServletConfig config)
  throws ServletException {
  this.config = config;
  jspInit();
}
public final void destroy() {
  jspDestroy();
}
public final void service(
  HttpServletRequest request,
  HttpServletResponse response)
  throws ServletException, IOException {
  _jspService(request, response);
}

Listing 2: JSPservlet web.xml
<!DOCTYPE web-app PUBLIC "-//Sun Microsystems, -
Inc.//DTD Web Application 1.2//EN"
"http://java.sun.com/j2ee/dtds/web-app_2_2.dtd">

<web-app>
  <servlet>
    <servlet-name>JDJloader</servlet-name>
    <servlet-class>JDJloader.JSPservlet
    </servlet-class>
    <init-param>
      <param-name>cachePath</param-name>
      <param-value>C:/temp</param-value>
      <description>local cache</description>
    </init-param>
    <init-param>
      <param-name>remoteLocations</param-name>
      <param-value>C:/temp/jdj.properties</param-value>
      <description>jar remote location</description>
    </init-param>
  </servlet>
  <servlet-mapping>
    <servlet-name>JDJloader</servlet-name>
    <url-pattern>/</url-pattern>
  </servlet-mapping>
</web-app>

Listing 3: JSPservlet code
public class JSPservlet extends HttpServlet {
  public static HashMap JSPhandlers = null;
  public static final synchronized JSPhandler
    getHandler(ServletConfig sc,
    String contextPath) throws ServletException {
    JSPhandler jh = null;
    if (JSPhandlers == null)
      JSPhandlers = new HashMap();
    else
      jh = (JSPhandler)JSPhandlers.get(
        contextPath);
    if (jh != null)
      return jh;
    jh = new JSPhandler(sc, contextPath);
    JSPhandlers.put(contextPath, jh);
    return jh;
  }
  public void service(HttpServletRequest request,
    HttpServletResponse response)
    throws ServletException, IOException {
    JSPhandler jh = getHandler(getServletConfig(),
      request.getContextPath());
    Servlet srv = jh.get(request.getPathInfo());
    srv.service(request, response);
  }
}

Listing 4: JSPhandler code
public class JSPhandler {
  String cachePath;
  HashMap classEntries = new HashMap();
  Properties remoteLocProp = new Properties();
  ServletConfig servletConfig;
  JSPhandler(ServletConfig sc,String contextPath){
    servletConfig = sc;
    cachePath = sc.getInitParameter("cachePath");
    if (cachePath == null)
      cachePath = "C:/temp";
    String remoteLocFile = sc.getInitParameter(
      "remoteLocations");
    if (remoteLocFile == null)
      remoteLocFile = cachePath + contextPath +
        ".properties";
    File f = new File(remoteLocFile);
    if ((f != null) && f.exists()) {
      try {
        remoteLocProp.load(new DataInputStream(
          new FileInputStream(f)));
      }
      catch(Exception e) {}
    }
  }
  final synchronized Servlet get(String pathInfo)
    throws ServletException {
    String fullName = pathInfo;
    if (pathInfo.startsWith("/"))
      fullName = pathInfo.substring(1);
    int idx = fullName.indexOf('/');
    String jarName = fullName.substring(0, idx);
    String classPath = fullName.substring(idx + 1);
    ClassEntry ce = null;
    if (classEntries.containsKey(jarName)) {
      ce = (ClassEntry)classEntries.get(jarName);
      return ce.get(classPath);
    }
    ce = new ClassEntry(this, jarName);
    classEntries.put(jarName, ce);
    return ce.get(classPath);
  }
}

Listing 5: ClassEntry code
class ClassEntry {
  JSPhandler handler;
  JSPloader jl;
  HashMap servletObjects;
  ClassEntry(JSPhandler jh, String jarName)
    throws ServletException {
    handler = jh;
    String jarURL = (String)
      jh.remoteLocProp.get(jarName);
    jl = new JSPloader(jh, jarName, jarURL);
    servletObjects = new HashMap();
  }
  final Servlet get(String classPath)
    throws ServletException {
    if (servletObjects.containsKey(classPath))
      return (Servlet)
        servletObjects.get(classPath);
    Servlet srv = null;
    try {
      Class jspClass = jl.loadClass(
        classPath.replace('/', '.'));
      srv = (Servlet)jspClass.newInstance();
      srv.init(handler.servletConfig);
      servletObjects.put(classPath, srv);
    }
    catch(Exception e) {
      throw new ServletException("ClassEntry.get("
        + classPath + ") " + e);
    }
    return srv;
  }
}

Listing 6: JSPloader code
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);
  }
}