Hi Dain,

I wrote a servlet (attached) and it looks like it will simplify
things.

It effectively replaces WebService and WebServer (WebService
simply wraps WebServer). WebClassLoader doesn't have a dependency on
WebServ* so it can operate as normal. I ran the DynLoadingUnitTestCase
and it passes. Funnily enough it passes if it succeeds with
./build.sh -Dtest=jrmp tests-client-unit
but fails with
./build.sh -Dtest=jrmp test
I think this is how it's supposed to be called at any rate.

A couple of points:

1. I didn't implement addClassLoader - AFAIK Scott said we will use the
servlets class loader to retrieve all classes. Removing addClassLoader
doesn't appear to cause a problem.
2. The WebServ* classes should be removed.
3. run.sh/run.bat will have to be updated with
-Djava.rmi.server.codebase=http://localhost:8080/class-loader/
4. Do we need to have a jmx service for this?

I've been working on the 3.2 branch but it should work with 4.0. I have
been using my own xdoclet ant script to build it as a .war - do you want
me to use another deployment script as a template?

I'll have some time over the next couple of days to write a compliant build script and make any other changes you may want.

James

Dain Sundstrom wrote:
We have a small project open for a volunteer. In Jboss 2 and 3 we have a custom lightweight web server (port 8083) that returns java class files from the classLoader.getResouceAsStream to RMI clients (this is how remote class loading happens). I talked to Scott at JBoss Boot Camp and we think it is a good idea to replace this with a plain old Servlet for JBoss 4.0 so it can work with regular security, pooling and such. This is a fairly simple piece of code and shouldn't take longer then a day or two. If you are interested the code can be found in jboss-head/server/src/main/org/jboss/web/WebServer.java

-dain



-------------------------------------------------------
This SF.NET email is sponsored by:
SourceForge Enterprise Edition + IBM + LinuxWorld = Something 2 See!
http://www.vasoftware.com
_______________________________________________
Jboss-development mailing list
[EMAIL PROTECTED]
https://lists.sourceforge.net/lists/listinfo/jboss-development



/* JBoss, the OpenSource J2EE webOS
 *
 * Distributable under LGPL license.
 * See terms of license at gnu.org.
 */

package org.jboss.web;

import javax.servlet.ServletException;
import javax.servlet.ServletConfig;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;
import java.io.InputStream;
import org.jboss.logging.Logger;
import org.jboss.util.stream.Streams;

/**
 * The HTTPClassLoader Servlet's primary purpose is to simplify dynamic class-loading 
in RMI.
 *
 * It can serve any file that is available, including class-files.
 * This is a replacement for the WebServer class in this package. 
 * 
 * @web.servlet
 *     display-name="JBoss HTTPClassLoaderServlet"
 *     load-on-startup="1"
 *     name="HTTPClassLoaderServlet"
 *
 * @web.servlet-mapping
 *     url-pattern="/*"
 *
 * @link org.jboss.test.jrmp.test.DynLoadingUnitTestCase
 * @see http://java.sun.com/j2se/1.4/docs/guide/rmi/codebase.html
 *
 * @author  <a href="mailto:[EMAIL PROTECTED]";>James Cooley</a>
 */

public class HTTPClassLoaderServlet extends HttpServlet
{
  
   // Constants -----------------------------------------------------
   
   // Attributes ----------------------------------------------------
   private static Logger log = Logger.getLogger(HTTPClassLoaderServlet.class);

   public static final String CONTENT_TYPE = "application/binary";


   public void init(ServletConfig conf) throws ServletException
   {
      super.init(conf);
   }
   
   /**
    * Called by the server (via the service method) to allow a servlet to handle a 
POST request.
    * The HTTP POST method allows the client to send data of unlimited length to the 
Web server
    * a single time and is useful when posting information such as credit card numbers.
    */
   public void doPost(HttpServletRequest request, HttpServletResponse response)
      throws IOException, ServletException
   {
      log.trace("post called");
      doGet(request, response);
   }

   public void doGet(HttpServletRequest request, HttpServletResponse response) throws 
ServletException
   {   
      String filePath = null;
      boolean traceOn = log.isTraceEnabled();
      response.setContentType(CONTENT_TYPE);
      try
      {
         String servletRoot = request.getContextPath(); 
         int startOfFilePath = servletRoot.length() + 1; // +1 to get the trailing "/"
         String rawPath = request.getRequestURI().substring(startOfFilePath);
         boolean usesJBossProtocol = rawPath.indexOf(']') > 0;
         if(usesJBossProtocol)
            filePath = extractClassName(rawPath);
         else
            filePath = rawPath;
         
         if (traceOn)
         {
            log.trace("servletRoot("+servletRoot+")");
            log.trace("rawPath("+rawPath+")");
            log.trace("filePath("+ filePath+")");
         }

         if(filePath == null)
         {
            response.sendError(HttpServletResponse.SC_NOT_FOUND, "Requested class name 
set to null!");
            return;
         }
         
         InputStream classStream = 
Thread.currentThread().getContextClassLoader().getResourceAsStream(filePath);
         if(classStream != null)
         {
            long bytes = Streams.copy(classStream, response.getOutputStream());
            if(log.isTraceEnabled())
               log.trace("copied " + bytes + " bytes");
         }
      }
      catch(IOException ioex)
      {
         // this will send back the correct HTTP error code
         try
         {
            response.sendError(HttpServletResponse.SC_NOT_FOUND, "Could not find " + 
filePath);
         }
         catch(IOException ioexOops)
         {
            log.fatal(ioexOops);
         }
      }
   }



   /**
    *
    * This is to support a JBoss proprietary class loading protocol.
    * We do not use the class loader key as we don't support the
    * addition of classloaders. The rest of this comment describes
    * the protocol.
    * 
    * Parse the path into the class loader key and file path.
    *
    * The class loader key is a string whose format is 
    * "ClassName[oid]",  where the oid substring may contain '/'
    * chars. The expected form of the raw path is:
    *
    *     "SomeClassName[some/object/id]/some/file/path"
    *
    * The class loader key is "SomeClassName[some/object/id]"
    * and the file path is "some/file/path"
    *
    * @param request a <code>HttpServletRequest</code> value
    * @return a <code>String</code> value - the filePath that was found
    * @exception IOException if an error occurs
    */
   protected String extractClassName(String rawPath)
   {
      int endOfKey = rawPath.indexOf(']');
      String filePath = rawPath.substring(endOfKey+2);
      String loaderKey = rawPath.substring(0, endOfKey+1);
      log.trace("loaderKey = "+loaderKey);
      log.trace("filePath = "+filePath);
      return filePath;
   }
   
}

Reply via email to