costin      00/12/13 23:10:58

  Modified:    src/facade22/org/apache/tomcat/facade
                        Servlet22Interceptor.java ServletHandler.java
                        ServletInfo.java WebXmlReader.java
               src/facade22/org/apache/tomcat/modules/facade22
                        JspInterceptor.java LoadOnStartupInterceptor.java
               src/share/org/apache/tomcat/core Handler.java
  Added:       src/share/org/apache/tomcat/util JavaGeneratorTool.java
  Log:
  Major rewrite of JspInterceptor. IMHO what used to be ServletWrapper and
  all related classes are now in a much better shape. That should be the
  last big change - we should start building the first milestone for 3.3
  soon. ( I want to do yet-another review of the core and remove everything
  that is not used or can be simplified before that )
  
  The new code removes few optimizations ( for simplicity ) - most of them
  were part of the initial loading or compilation of JSPs, where the
  compiler is taking most of the time.
  
  There is yet another simplification we can do ( separate the ServletHandler
  and add a JspHanlder ), but so far ServletHandler doesn't seem too complex
  and handling jsps is a very small overhead ( far away from what it used to be).
  
  Revision  Changes    Path
  1.9       +8 -6      
jakarta-tomcat/src/facade22/org/apache/tomcat/facade/Servlet22Interceptor.java
  
  Index: Servlet22Interceptor.java
  ===================================================================
  RCS file: 
/home/cvs/jakarta-tomcat/src/facade22/org/apache/tomcat/facade/Servlet22Interceptor.java,v
  retrieving revision 1.8
  retrieving revision 1.9
  diff -u -r1.8 -r1.9
  --- Servlet22Interceptor.java 2000/12/12 22:32:54     1.8
  +++ Servlet22Interceptor.java 2000/12/14 07:10:56     1.9
  @@ -143,15 +143,17 @@
        if( ct.getHandler() == null ) {
            // we have a container with a valid handler name but without
            // a Handler. Create a ServletWrapper
  -         ServletInfo sw=new ServletInfo();
  -         sw.setServletName( hN );
  -         sw.setContext( ct.getContext() );
  +         ServletHandler handler=new ServletHandler();
  +         handler.setServletClassName( hN );
  +         handler.setName( hN );
  +         handler.setContext( ct.getContext() );
            // *.jsp -> jsp is a legacy default mapping  
  -         if( ! "jsp".equals(hN) ) {
  +         if(debug>0 &&  ! "jsp".equals(hN) ) {
                log( "Create handler " + hN);
            }
  -         ct.setHandler(sw.getHandler());
  -         ct.getContext().addServlet(  sw.getHandler() );
  +         handler.setModule( this );
  +         ct.setHandler(handler);
  +         ct.getContext().addServlet( handler );
        }
            
       }
  
  
  
  1.4       +10 -9     
jakarta-tomcat/src/facade22/org/apache/tomcat/facade/ServletHandler.java
  
  Index: ServletHandler.java
  ===================================================================
  RCS file: 
/home/cvs/jakarta-tomcat/src/facade22/org/apache/tomcat/facade/ServletHandler.java,v
  retrieving revision 1.3
  retrieving revision 1.4
  diff -u -r1.3 -r1.4
  --- ServletHandler.java       2000/12/13 19:57:58     1.3
  +++ ServletHandler.java       2000/12/14 07:10:56     1.4
  @@ -107,7 +107,6 @@
       private ServletInfo sw;
   
       private String servletClassName;
  -    private String path;
       protected Class servletClass;
       protected Servlet servlet;
       protected Context context;
  @@ -155,8 +154,8 @@
        servlet=null; // reset the servlet, if it was set
        servletClass=null;
        this.servletClassName=servletClassName;
  -     if( debug>0 && sw.getPath()!=null)
  -         log( "setServletClassName for " + sw.getPath() +
  +     if( debug>0 && sw.getJspFile()!=null)
  +         log( "setServletClassName for " + sw.getJspFile() +
                 ": " + servletClassName);
       }
   
  @@ -362,7 +361,8 @@
       protected void preInit() throws Exception
       {
        if( debug > 0 )
  -         log( "preInit " + servlet + " " + path + " " + servletClassName);
  +         log( "preInit " + servlet + " " + sw.getJspFile() + " " +
  +              servletClassName);
   
        // Deal with Unavailable errors
        if( ! checkAvailable() ) {
  @@ -432,14 +432,15 @@
        throws Exception
       {
        // <servlet><jsp-file> case
  -     if( path!=null ) {
  -         if( path.startsWith("/"))
  +     String jspFile=sw.getJspFile();
  +     if( jspFile!=null ) {
  +         if( jspFile.startsWith("/"))
                req.setAttribute( "javax.servlet.include.request_uri",
  -                               req.getContext().getPath()  + path );
  +                               req.getContext().getPath()  + jspFile );
            else
                req.setAttribute( "javax.servlet.include.request_uri",
  -                               req.getContext().getPath()  + "/" + path );
  -         req.setAttribute( "javax.servlet.include.servlet_path", path );
  +                               req.getContext().getPath()  + "/" +jspFile );
  +         req.setAttribute( "javax.servlet.include.servlet_path", jspFile );
        }
   
   
  
  
  
  1.3       +18 -7     
jakarta-tomcat/src/facade22/org/apache/tomcat/facade/ServletInfo.java
  
  Index: ServletInfo.java
  ===================================================================
  RCS file: 
/home/cvs/jakarta-tomcat/src/facade22/org/apache/tomcat/facade/ServletInfo.java,v
  retrieving revision 1.2
  retrieving revision 1.3
  diff -u -r1.2 -r1.3
  --- ServletInfo.java  2000/12/13 19:57:58     1.2
  +++ ServletInfo.java  2000/12/14 07:10:56     1.3
  @@ -60,6 +60,7 @@
   
   import org.apache.tomcat.core.*;
   import org.apache.tomcat.util.*;
  +import org.apache.tomcat.util.depend.*;
   import org.apache.tomcat.util.collections.*;
   import java.io.*;
   import java.net.*;
  @@ -100,7 +101,7 @@
       Hashtable initArgs=null;
   
       // should be removed from handler
  -    private String path = null;
  +    private String jspFile = null;
       protected int loadOnStartup=-1;
       protected boolean loadingOnStartup=false;
   
  @@ -115,7 +116,7 @@
       }
   
       public String toString() {
  -     return "SW (" + path + " CN=" +
  +     return "SW (" + jspFile + " CN=" +
            handler.getServletClassName() +  ")";
       }
   
  @@ -248,15 +249,25 @@
   
       // -------------------- Jsp specific code
       
  -    public String getPath() {
  -        return this.path;
  +    public String getJspFile() {
  +        return this.jspFile;
       }
   
  -    public void setPath(String path) {
  -        this.path = path;
  +    public void setJspFile(String path) {
  +        this.jspFile = path;
        if( handler.getName() == null ) 
  -         handler.setName(path);
  +         handler.setName(jspFile);
        // the path will serve as servlet name if not set
  +    }
  +    
  +    Dependency dependency;
  +    
  +    public Dependency getDependency() {
  +     return dependency;
  +    }
  +
  +    public void setDependency(Dependency dep ) {
  +     dependency=dep;
       }
   
       // -------------------- 
  
  
  
  1.9       +2 -1      
jakarta-tomcat/src/facade22/org/apache/tomcat/facade/WebXmlReader.java
  
  Index: WebXmlReader.java
  ===================================================================
  RCS file: 
/home/cvs/jakarta-tomcat/src/facade22/org/apache/tomcat/facade/WebXmlReader.java,v
  retrieving revision 1.8
  retrieving revision 1.9
  diff -u -r1.8 -r1.9
  --- WebXmlReader.java 2000/12/13 19:57:58     1.8
  +++ WebXmlReader.java 2000/12/14 07:10:56     1.9
  @@ -204,7 +204,8 @@
            // remove it from stack when done
            xh.addRule("web-app/servlet/servlet-name", 
xh.methodSetter("setServletName",0) );
            xh.addRule("web-app/servlet/servlet-class", 
xh.methodSetter("setServletClassName",0));
  -         xh.addRule("web-app/servlet/jsp-file",xh.methodSetter("setPath",0));
  +         xh.addRule("web-app/servlet/jsp-file",
  +                    xh.methodSetter("setJspFile",0));
   
            xh.addRule("web-app/servlet/security-role-ref", 
xh.methodSetter("addSecurityMapping", 3) );
            xh.addRule("web-app/servlet/security-role-ref/role-name", 
xh.methodParam(0) );
  
  
  
  1.17      +401 -493  
jakarta-tomcat/src/facade22/org/apache/tomcat/modules/facade22/JspInterceptor.java
  
  Index: JspInterceptor.java
  ===================================================================
  RCS file: 
/home/cvs/jakarta-tomcat/src/facade22/org/apache/tomcat/modules/facade22/JspInterceptor.java,v
  retrieving revision 1.16
  retrieving revision 1.17
  diff -u -r1.16 -r1.17
  --- JspInterceptor.java       2000/12/13 19:57:59     1.16
  +++ JspInterceptor.java       2000/12/14 07:10:57     1.17
  @@ -74,7 +74,7 @@
   import org.apache.jasper.compiler.*;
   import org.apache.jasper.compiler.Compiler;
   import org.apache.tomcat.core.*;
  -import org.apache.tomcat.facade.ServletHandler;
  +import org.apache.tomcat.facade.*;
   
   /**
    * Plug in the JSP engine (a.k.a Jasper)! 
  @@ -84,10 +84,11 @@
    * @author Costin Manolache
    */
   public class JspInterceptor extends BaseInterceptor {
  -    int jspInfoNOTE;
       TomcatOptions options=new TomcatOptions();
   
       static final String JIKES="org.apache.jasper.compiler.JikesJavaCompiler";
  +
  +    // -------------------- Configurable properties --------------------
       
       public void setJavaCompiler( String type ) {
        // shortcut
  @@ -101,40 +102,46 @@
        }
       }
   
  -    public void engineInit(ContextManager cm )
  -     throws TomcatException
  -    {
  -     super.engineInit(cm);
  -     jspInfoNOTE=cm.getNoteId( ContextManager.HANDLER_NOTE,
  -                               "tomcat.jspInfoNote");
  -    }
  +    // -------------------- Hooks --------------------
   
  -    
  +    /**
  +     * Jasper-specific initializations, add work dir to classpath,
  +     *  make sure we have a dependManager.
  +     */
       public void addContext(ContextManager cm, Context ctx)
        throws TomcatException 
       {
  +     // Make sure JspFactory is set ( ? )
        JspFactory.setDefaultFactory(new JspFactoryImpl());
  +
        try {
            URL url=new URL( "file", null,
                             ctx.getWorkDir().getAbsolutePath() + "/");
            ctx.addClassPath( url );
  -         if( debug > 0 ) log( "Added to classpath: " + url );
  +         if( debug > 9 ) log( "Added to classpath: " + url );
        } catch( MalformedURLException ex ) {
        }
  +
  +     DependManager dm=ctx.getDependManager();
  +     if( dm==null ) {
  +         dm=new DependManager();
  +         ctx.setDependManager( dm );
  +     }
       }
   
       /** Set the HttpJspBase classloader before init,
  -     as required by Jasper
  -    */
  +     *  as required by Jasper
  +     */
       public void preServletInit( Context ctx, Handler sw )
        throws TomcatException
       {
        if( ! (sw instanceof ServletHandler) )
            return;
        try {
  +         // requires that everything is compiled
            Servlet theServlet = ((ServletHandler)sw).getServlet();
            if (theServlet instanceof HttpJspBase)  {
  -             if( debug > 0 )
  +             if( debug > 9 )
                    log( "PreServletInit: HttpJspBase.setParentClassLoader" +
                         sw );
                HttpJspBase h = (HttpJspBase) theServlet;
  @@ -145,6 +152,8 @@
        }
       }
   
  +    //-------------------- Main hook - compile the jsp file if needed
  +    
       /** Detect if the request is for a JSP page and if it is find
        the associated servlet name and compile if needed.
   
  @@ -168,206 +177,232 @@
   
        if( wrapper==null )
            return 0;
  -
  -     // That's equivalent with the previous behavior
  -     // of tomcat, where a special "jsp" handler was defined.
   
  -     // we should change that - but we need a way to map
  -     // other extensions, and that is backward compatible
  -
  -     // the condition is: continue if the request is mapped to
  -     // the special "jsp" handler ( as result of *.jsp ) or
  -     // to a named handler that has a path ( <servlet> defined with path)
  -     if( ! ( "jsp".equals( wrapper.getName()) ||
  -             ( wrapper instanceof ServletHandler &&
  -               ((ServletHandler)wrapper).getServletInfo().getPath()
  -               != null)
  -             )) {
  +     // It's not a jsp if it's not "*.jsp" mapped or a servlet
  +     if( (! "jsp".equals( wrapper.getName())) &&
  +         (! (wrapper instanceof ServletHandler)) ) {
            return 0;
        }
   
  -     Context ctx= req.getContext();
  -     DependManager dm=ctx.getDependManager();
  -     if( dm==null ) {
  -         dm=new DependManager();
  -         ctx.setDependManager( dm );
  -     }
  +     ServletHandler handler=null;
  +     String jspFile=null;
   
  -     // If this Wrapper was already used, we have all the info
  -     JspInfo jspInfo=(JspInfo)wrapper.getNote( jspInfoNOTE );
  -     if( jspInfo == null ) {
  -         if( debug>0) log("Handler never processed " + wrapper );
  -         
  -         jspInfo=new JspInfo(req);
  -         if( "jsp".equals(wrapper.getName())) {
  -             wrapper = mapJspPage( ctx, jspInfo );
  -         }
  -         wrapper.setNote( jspInfoNOTE, jspInfo );
  -         dm.addDependency( jspInfo.expireCheck );
  -         ((ServletHandler)wrapper).
  -             setServletClassName( jspInfo.fullClassN );
  -         req.setHandler( wrapper );
  +     // if it's an extension mapped file, construct and map a handler
  +     if( "jsp".equals( wrapper.getName())) {
  +         jspFile=req.getServletPath();
  +         // extension mapped jsp - define a new handler,
  +         // add the exact mapping to avoid future overhead
  +         handler= mapJspPage( req.getContext(), jspFile );
  +         req.setHandler( handler );
  +     } else if( wrapper instanceof ServletHandler) {
  +         // if it's a simple servlet, we don't care about it
  +         handler=(ServletHandler)wrapper;
  +         jspFile=handler.getServletInfo().getJspFile();
  +         if( jspFile==null )
  +             return 0; // not a jsp
        }
  -
  -     if( debug > 3) 
  -         log( "Check if source is up-to-date " +  jspInfo.jspSource + " " + 
  -              jspInfo.jspSource.lastModified()+" "+ jspInfo.compileTime );
  -       
  -     if( jspInfo.expireCheck.isExpired() ) {
  -         //XXX old servlet -  destroy(); 
  -         
  -         // jump version number - the file needs to
  -         // be recompiled, and we don't want a reload
  -         if( debug > 0 ) log( "Before sync block  " + jspInfo );
  -         synchronized( jspInfo ) {
  -             // if still expired ( we may enter the sync block after
  -             // another thread re-compiled )
  -             if( jspInfo.expireCheck.isExpired() ) {
  -                 // reset the handler error, un-initialize the servlet
  -                 wrapper.setErrorException( null );
  -                 jspInfo.setCompileException( null );
  -                 wrapper.setState( Handler.STATE_ADDED );
  -                 
  -                 if( debug > 0 ) log( "Compiling " + jspInfo );
  -                 // Move to the next class name
  -                 jspInfo.nextVersion();
  -
  -                 compile( req, jspInfo );
  -
  -                 // Update the class name in wrapper
  -                 ((ServletHandler)wrapper).
  -                     setServletClassName( jspInfo.fullClassN );
  -
  -                 // set initial exception on the servlet if one is present
  -                 if ( jspInfo.isExceptionPresent() ) {
  -                     wrapper.
  -                         setErrorException(jspInfo.getCompileException());
  -                     wrapper.setState(Handler.STATE_DISABLED);
  -                     // until the jsp cahnges, when it'll be enabled again
  -                 }
  -                 jspInfo.expireCheck.setExpired( false );
  -
  -             }
  -         } 
  +     
  +     Dependency dep= handler.getServletInfo().getDependency();
  +     if( dep!=null && ! dep.isExpired() ) {
  +         // if the jspfile is older than the class - we're ok
  +         return 0;
        }
   
  +     JasperLiaison liasion=new JasperLiaison(getLog(), debug, options);
  +     liasion.processJspFile(req, jspFile, handler);
        return 0;
       }
   
  -    private static final String SERVLET_NAME_PREFIX="tomcat_jsp.";
  +    // -------------------- Utils --------------------
       
  +    private static final String SERVLET_NAME_PREFIX="TOMCAT/JSP";
  +    
       /** Add an exact map that will avoid *.jsp mapping and intermediate
        *  steps. It's equivalent with declaring
  -     *  <servlet-name>tomcat_jsp.uri</>
  -     *  <servlet-mapping><servlet-name>tomcat_jsp.uri</><url-pattern>uri</></>
  +     *  <servlet-name>tomcat.jsp.[uri]</>
  +     *  <servlet-mapping><servlet-name>tomcat.jsp.[uri]</>
  +     *                   <url-pattern>[uri]</></>
        */
  -    Handler mapJspPage( Context ctx, JspInfo jspInfo)
  +    ServletHandler mapJspPage( Context ctx, String uri)
       {
  -     String uri=jspInfo.uri;
        String servletName= SERVLET_NAME_PREFIX + uri;
   
  -     log( "mapJspPage " + ctx + " " + jspInfo + " " + servletName + " " +
  -          uri  );
  +     if( debug>0)
  +         log( "mapJspPage " + ctx + " " + " " + servletName + " " +  uri  );
   
  +     Handler h=ctx.getServletByName( servletName );
  +     if( h!= null ) {
  +         log( "Name already exists " + servletName +
  +              " while mapping " + uri);
  +         return null; // exception ?
  +     }
  +     
  +     ServletHandler wrapper=new ServletHandler();
  +     wrapper.setModule( this );
  +     wrapper.setContext(ctx);
  +     wrapper.setName(servletName);
  +     wrapper.getServletInfo().setJspFile( uri );
  +     
        // add the mapping - it's a "invoker" map ( i.e. it
        // can be removed to keep memory under control.
        // The memory usage is smaller than JspSerlvet anyway, but
        // can be further improved.
        try {
  -         Handler wrapper=ctx.getServletByName( servletName );
  -         
  -         // We may want to replace the class and reset it if changed
  -         
  -         if( wrapper==null ) {
  -             wrapper=new ServletHandler();
  -             wrapper.setModule( this );
  -             ((ServletHandler)wrapper).setContext(ctx);
  -             wrapper.setName(servletName);
  -
  -             ((ServletHandler)wrapper).getServletInfo().
  -                 setPath( uri );
  -             ctx.addServlet( wrapper );
  -             
  -             ctx.addServletMapping( uri ,
  -                                    servletName );
  -             if( debug > 0 )
  -                 log( "Added mapping " + uri +
  -                      " path=" + servletName );
  -         }
  -         return wrapper;
  +         ctx.addServlet( wrapper );
  +         ctx.addServletMapping( uri ,
  +                                servletName );
  +         if( debug > 0 )
  +             log( "Added mapping " + uri + " path=" + servletName );
        } catch( TomcatException ex ) {
            log("mapJspPage: ctx=" + ctx +
  -             ", jspInfo=" + jspInfo +
                ", servletName=" + servletName, ex);
            return null;
        }
  +     return wrapper;
       }
   
  +}
  +
  +// -------------------- The main Jasper Liaison --------------------
  +
  +final class JasperLiaison {
  +    Log log;
  +    final int debug;
  +    Options options;
  +    
  +    JasperLiaison( Log log, int debug, Options options ) {
  +     this.log=log;
  +     this.debug=debug;
  +     this.options=options;
  +    }
  +    
  +    /** Generate mangled names, check for previous versions,
  +     *  generate the .java file, compile it - all the expensive
  +     *  operations. This happens only once ( or when the jsp file
  +     *  changes ). 
  +     */
  +    int processJspFile(Request req, String jspFile,
  +                             ServletHandler handler)
  +    {
  +     // ---------- Expensive part - compile and load
        
  +     // If dep==null, the handler was never used - we need
  +     // to either compile it or find the previous compiled version
  +     // If dep.isExpired() we need to recompile.
  +
  +     if( debug > 10 ) log.log( "Before compile sync  " + jspFile );
  +     synchronized( handler ) {
  +         
  +         // double check - maybe another thread did that for us
  +         Dependency dep= handler.getServletInfo().getDependency();
  +         if( dep!=null && ! dep.isExpired() ) {
  +             // if the jspfile is older than the class - we're ok
  +             return 0;
  +         }
  +
  +         Context ctx=req.getContext();
  +         
  +         // Mangle the names - expensive operation, but nothing
  +         // compared with a compilation :-)
  +         JspMangler mangler=
  +             new JspMangler(ctx.getWorkDir().getAbsolutePath(),
  +                            ctx.getAbsolutePath(),
  +                            jspFile );
  +
  +         // register the handler as dependend of the jspfile 
  +         if( dep==null ) {
  +             dep=setDependency( ctx, mangler, handler );
  +             // update the servlet class name
  +             handler.setServletClassName( mangler.getServletClassName() );
  +
  +             // check again - maybe we just found a compiled class from
  +             // a previous run
  +             if( ! dep.isExpired() )
  +                 return 0;
  +         }
  +
  +         if( debug > 3) 
  +             log.log( "Jsp source changed, recompiling: " + jspFile );
  +         
  +         //XXX old servlet -  destroy(); 
  +         
  +         // jump version number - the file needs to be recompiled
  +         // reset the handler error, un-initialize the servlet
  +         handler.setErrorException( null );
  +         handler.setState( Handler.STATE_ADDED );
  +         
  +         // Move to the next class name
  +         mangler.nextVersion();
  +
  +         // record time of attempted translate-and-compile
  +         // if the compilation fails, we'll not try again
  +         // until the jsp file changes
  +         dep.setLastModified( System.currentTimeMillis() );
  +
  +         // Update the class name in wrapper
  +         log.log( "Update class Name " + mangler.getServletClassName());
  +         handler.setServletClassName( mangler.getServletClassName() );
  +
  +         compile( handler, req, mangler );
  +         
  +         
  +         dep.setExpired( false );
  +         
  +     }
  +
  +     return 0;
  +    }
  +
       /** Convert the .jsp file to a java file, then compile it to class
        */
  -    void compile(Request req, JspInfo jspInfo ) {
  -     if( debug > 0 ) log( "Compiling " + jspInfo.realClassPath);
  +    void compile(Handler wrapper, Request req, JspMangler mangler ) {
  +     if( debug > 0 ) log.log( "Generating " + mangler.getJavaFileName());
        try {
            // make sure we have the directories
  -        File dir;
  -        if (jspInfo.pkgDir!=null)
  -         dir=new File( jspInfo.outputDir + "/" + jspInfo.pkgDir);
  -        else
  -         dir=new File( jspInfo.outputDir);
  -         dir.mkdirs();
  -         JspMangler mangler= new JspMangler(jspInfo);
  -         JspEngineContext1 ctxt = new JspEngineContext1(req, mangler);
  +         String javaFileName=mangler.getJavaFileName();
  +         
  +         File javaFile=new File(javaFileName);
  +         
  +         // make sure the directory is created
  +         new File( javaFile.getParent()).mkdirs();
  +
  +         JspEngineContext1 ctxt = new JspEngineContext1(log,req, mangler);
            ctxt.setOptions( options );
            
            Compiler compiler=new Compiler(ctxt);
            compiler.setMangler( mangler );
  -             
            // we will compile ourself
            compiler.setJavaCompiler( null );
  -
  -         // record time of attempted translate-and-compile
  -         jspInfo.touch();
  -
  -         synchronized ( jspInfo ) {
  +         
  +         
  +         synchronized ( mangler ) {
                compiler.compile();
            }
            if( debug > 0 ) {
                File f = new File( mangler.getJavaFileName());
  -             log( "Created file : " + f +  " " + f.lastModified());
  -
  +             log.log( "Created file : " + f +  " " + f.lastModified());
  +             
            }
            javac( createJavaCompiler( options ), ctxt, mangler );
            
  -         if(debug>0)log( "Compiled to " + jspInfo.realClassPath );
  +         if(debug>0)log.log( "Generated " + mangler.getClassFileName() );
        } catch( Exception ex ) {
  -         log("compile: req="+req+", jspInfo=" + jspInfo, ex);
  -         jspInfo.setCompileException(ex);
  +         log.log("compile: req="+req, ex);
  +         wrapper.setErrorException(ex);
  +         wrapper.setState(Handler.STATE_DISABLED);
  +         // until the jsp cahnges, when it'll be enabled again
  +
        }
       }
       
       String javaEncoding = "UTF8";           // perhaps debatable?
       static String sep = System.getProperty("path.separator");
   
  -    static String getClassPath( Context ctx ) {
  -     URL classP[]=ctx.getClassPath();
  -     String separator = System.getProperty("path.separator", ":");
  -        String cpath = "";
  -     
  -        for(int i=0; i< classP.length; i++ ) {
  -            URL cp = classP[i];
  -            File f = new File( cp.getFile());
  -            if (cpath.length()>0) cpath += separator;
  -            cpath += f;
  -        }
  -     return cpath;
  -    }
  -    
       /** Compile a java to class. This should be moved to util, togheter
        with JavaCompiler - it's a general purpose code, no need to
        keep it part of jasper
       */
  -    public void javac(JavaCompiler javac, JspEngineContext1 ctxt,
  +    void javac(JavaCompiler javac, JspCompilationContext ctxt,
                      Mangler mangler)
        throws JasperException
       {
  @@ -376,14 +411,14 @@
        String cp=System.getProperty("java.class.path")+ sep + 
            ctxt.getClassPath() + sep + ctxt.getOutputDir();
           javac.setClasspath( cp );
  -     if( debug>5) log( "ClassPath " + cp);
  +     if( debug>5) log.log( "ClassPath " + cp);
        
        ByteArrayOutputStream out = new ByteArrayOutputStream (256);
        javac.setOutputDir(ctxt.getOutputDir());
           javac.setMsgOutput(out);
   
        String javaFileName = mangler.getJavaFileName();
  -     if( debug>0) log( "Compiling java file " + javaFileName);
  +     if( debug>0) log.log( "Compiling java file " + javaFileName);
        /**
            * Execute the compiler
            */
  @@ -399,7 +434,7 @@
               throw new JasperException("Unable to compile "
                                         + msg);
           }
  -     if( debug > 0 ) log("Compiled ok");
  +     if( debug > 0 ) log.log("Compiled ok");
       }
   
       /** tool for customizing javac
  @@ -429,295 +464,37 @@
   
        return javac;
       }
  -
  -    // XXX need to implement precompile
  -    private void precompile() {
  -     //         String qString = request.getQueryString();
  -     //          if (qString != null &&
  -     //               (qString.startsWith(Constants.PRECOMPILE) ||
  -     //                qString.indexOf("&" + Constants.PRECOMPILE)
  -     //                != -1))
  -     //             precompile = true;
  -    }
  -
  -}
  -
  -/** Given a URL, generate pkg, class name, etc.
  -    This is an internal ( private ) object, we'll add get/set
  -    later ( after we pass the experimental stage) 
  - */
  -class JspInfo {
  -    Request request;
  -
  -    String jspPath; // real jsp path - if the request URI is mapped to
  -    // a named jsp.
  -    String uri; // path from request URI
  -
  -    int version; // version
  -    int debug=9;
  -    String pkg;
  -    String pkgDir;
  -    String baseClassN;
  -    String fullClassN; // package.classN
  -    String classN; // no package
  -    String ext;
  -
  -    String outputDir;
  -    String javaFilePath; // full path to the generated java file
  -    String realClassPath; // full path to the compiled java class
  -    String mapPath; // In even of server reload, keep last version
  -
  -    File jspSource; // used to avoid File allocation for lastModified
  -    long compileTime;// tstamp of last compile attemp
  -
  -    Exception compileException; // translation/compile exception 
  -    Dependency expireCheck=new Dependency();
  -    
  -    JspInfo( Request req ) {
  -     expireCheck.setLocal( true );
  -     init( req );
  -    }
  -
  -    public String toString() {
  -     return "JSPInfo: " + jspPath + " " + uri +" " + version;
  -    }
  -
  -    /** Update compile time
  -     */
  -    public void touch() {
  -     compileTime=System.currentTimeMillis();
  -    }
  -
  -    /** A change was detected, move to a new class name
  -     */
  -    public void nextVersion() {
  -     version++;
  -     updateVersionedPaths();
  -    }
  -
  -    /** Update all paths that contain version number
  -     */
  -    void updateVersionedPaths() {
  -    if( pkgDir!=null ) {
  -        classN = baseClassN + "_" + version;
  -        realClassPath = outputDir + "/" + pkgDir + "/" + classN + ".class";
  -        javaFilePath = outputDir + "/" + pkgDir + "/" + classN + ".java";
  -        fullClassN = pkg  + "." + classN;
  -    } else {
  -        classN = baseClassN + "_" + version;
  -        realClassPath = outputDir + "/" +  classN + ".class";
  -        javaFilePath = outputDir + "/" + classN + ".java";
  -        fullClassN = classN;
  -    }
  -
  -//   log("ClassN=" + classN +
  -//                      " realClassPath=" + realClassPath +
  -//                      " javaFilePath=" + javaFilePath +
  -//                      " fullClassN =" + fullClassN);
  -     writeVersion();
  -     // save to mapFile
  -    }
  -
  -    private static String [] keywords = {
  -        "abstract", "boolean", "break", "byte",
  -        "case", "catch", "char", "class",
  -        "const", "continue", "default", "do",
  -        "double", "else", "extends", "final",
  -        "finally", "float", "for", "goto",
  -        "if", "implements", "import",
  -        "instanceof", "int", "interface",
  -        "long", "native", "new", "package",
  -        "private", "protected", "public",
  -        "return", "short", "static", "super",
  -        "switch", "synchronized", "this",
  -        "throw", "throws", "transient",
  -        "try", "void", "volatile", "while"
  -    };
  -
  -    /** Mangle Package names to avoid reserver words **/
  -    private String manglePackage(String s){
  -         for (int i = 0; i < keywords.length; i++) {
  -            char fs = File.separatorChar;
  -            int index = s.indexOf(keywords[i]);
  -            if(index == -1 ) continue;
  -            while (index != -1) {
  -                String tmpathName = s.substring (0,index) + "__";
  -                s = tmpathName + s.substring (index);
  -                index = s.indexOf(keywords[i],index+3);
  -            }
  -        }
  -        return(s);
  -    }
   
  -    /** Compute various names used
  -     */
  -    void init(Request req ) {
  -     this.request = req;
  -     compileException = null;
  -     //      String includeUri
  -     //          = (String) req.getAttribute(Constants.INC_SERVLET_PATH);
  -     Handler w=req.getHandler();
  -     uri=req.getServletPath();
  -
  -     if("jsp".equals( w.getName()))
  -         jspPath=uri;
  -     else
  -         jspPath=((ServletHandler)w).getServletInfo().getPath();
  -     Context ctx=req.getContext();
  -     outputDir = ctx.getWorkDir().getAbsolutePath();
  -     String jspFilePath=FileUtil.safePath( ctx.getAbsolutePath(),
  -                                           jspPath); 
  -     jspSource = new File(jspFilePath);
  -     
  -     // extension
  -     int lastComp=jspPath.lastIndexOf(  "/" );
  -     String endUnproc=null;
  -     if( lastComp > 0 ) {
  -         // has package
  -         pkgDir=jspPath.substring( 1, lastComp );
  -         endUnproc=jspPath.substring( lastComp+1 );
  -     } else {
  -         endUnproc=jspPath.substring( 1 );
  -     }
  -
  -     if( pkgDir!=null ) {
  -        pkgDir=manglePackage(pkgDir);
  -         pkgDir=pkgDir.replace('.', '_');
  -         pkg=pkgDir.replace('/', '.');
  -         //      pkgDir=pkgDir.replace('/', File.separator );
  -
  -     }
  -
  -     int extIdx=endUnproc.lastIndexOf( "." );
  -
  -     if( extIdx>=0 ) {
  -         baseClassN=endUnproc.substring( 0, extIdx );
  -         ext=endUnproc.substring( extIdx );
  -     } else {
  -         baseClassN=endUnproc;
  -     }
  -     // XXX insert "mangle" to make names safer
  -     if (pkgDir!=null)
  -         mapPath = outputDir + "/" + pkgDir + "/" + baseClassN + ".ver";
  -     else
  -         mapPath = outputDir + "/" + baseClassN + ".ver";
  -
  -     File mapFile=new File(mapPath);
  -     if( mapFile.exists() ) {
  -         // read version from file
  -         readVersion();
  -         updateVersionedPaths();
  -         updateCompileTime();
  +    private Dependency setDependency( Context ctx, JspMangler mangler,
  +                             ServletHandler handler )
  +    {
  +     ServletInfo info=handler.getServletInfo();
  +     // create a lastModified checker.
  +     if( debug>0) log.log("Registering dependency for " + handler );
  +     Dependency dep=new Dependency();
  +     dep.setOrigin( new File(mangler.getJspFilePath()) );
  +     dep.setTarget( handler );
  +     dep.setLocal( true );
  +     if( mangler.getVersion() > 0 ) {
  +         // it has a previous version
  +         File f=new File( mangler.getClassFileName() );
  +         dep.setLastModified(f.lastModified());
  +         // update the "expired" variable
  +         dep.checkExpiry();
        } else {
  -         version=0;
  -         updateVersionedPaths();
  -         compileTime=0;
  -     }
  -     
  -     expireCheck.setOrigin( jspSource );
  -     expireCheck.setTarget( this );
  -     // if the file has been compiled before, we'll use the
  -     // time of the compilation.
  -     expireCheck.setLastModified( compileTime );
  -     // update isExpired()
  -     expireCheck.checkExpiry();
  -     
  -     if( debug>0  )
  -         log("uri=" + uri +
  -             //" outputDir=" + outputDir +
  -             " jspSource=" + jspSource +
  -             " jspPath=" + jspPath +
  -             " pkgDir=" + pkgDir +
  -             " baseClassN=" + baseClassN +
  -             " ext=" + ext +
  -             " mapPath=" + mapPath +
  -             " version=" + version);
  -
  -
  -    }
  -
  -    /** After startup we try to find if the file was precompiled
  -     before
  -    */
  -    void readVersion() {
  -     File mapFile=new File(mapPath);
  -     version=0;
  -     compileTime=0;
  -     try {
  -         FileInputStream fis=new FileInputStream( mapFile );
  -         version=(int)fis.read();
  -//       log("Version=" + version );
  -         fis.close();
  -     } catch( Exception ex ) {
  -         log("readVersion() mapPath=" + mapPath, ex);
  -     }
  -    }
  -
  -    /** After we compile a page, we save the version in a
  -     file with known name, so we can restore the state when we
  -     restart. Note that this should move to a general-purpose
  -     persist repository ( on my plans for next version of tomcat )
  -    */
  -    void writeVersion() {
  -     File mapFile=new File(mapPath);
  -     try {
  -         File dir=new File(mapFile.getParent());
  -         dir.mkdirs();
  -         FileOutputStream fis=new FileOutputStream( mapFile );
  -         fis.write(version);
  -//       log("WVersion=" + version );
  -         fis.close();
  -     } catch( Exception ex ) {
  -         log("writeVersion() mapPath=" + mapPath, ex);
  +         dep.setLastModified( -1 );
  +         dep.setExpired( true );
        }
  +     ctx.getDependManager().addDependency( dep );
  +     info.setDependency( dep );
  +     return dep;
       }
  +     
   
  -    /** After a startup we read the compile time from the class
  -     file lastModified. No further access to that file is done.
  -     If class file doesn't exist, use java file lastModified if
  -     it exists.  We don't need to re-translate if the java file
  -     has not expired.
  -    */
  -    void updateCompileTime() {
  -     File f=new File( realClassPath );
  -     compileTime=0;
  -     if ( ! f.exists() ) return;
  -     compileTime=f.lastModified();
  -    }
  -
  -    void setCompileException(Exception ex) {
  -     compileException = ex;
  -    }
  -
  -    Exception getCompileException() {
  -     return compileException;
  -    }
  -
  -    boolean isExceptionPresent() {
  -     return ( compileException != null );
  -    }
  -
  -    void log(String s) {
  -     if (request != null && request.getContext() != null) {
  -         request.getContext().log(s);
  -     }
  -     else {
  -         System.err.println(s);
  -     }
  -    }
  -
  -    void log(String s, Exception e) {
  -     if (request != null && request.getContext() != null) {
  -         request.getContext().log(s, e);
  -     }
  -     else {
  -         System.err.println(s);
  -         e.printStackTrace();
  -     }
  -    }
   }
   
  -// XXX add code to set the options
  +// -------------------- Jasper support - options --------------------
  +
   class TomcatOptions implements Options {
       public boolean keepGenerated = true;
       public boolean largeFile = false;
  @@ -785,6 +562,7 @@
       
   }
   
  +// -------------------- Jasper support - JspCompilationContext -------------
   
   class JspEngineContext1 implements JspCompilationContext {
       JspReader reader;
  @@ -803,15 +581,17 @@
       
       Request req;
       Mangler m;
  +    Log log;
       
  -    public JspEngineContext1(Request req, Mangler m)
  +    public JspEngineContext1(Log log, Request req, Mangler m)
       {
  +     this.log=log;
        this.req=req;
        this.m=m;
       }
   
       public HttpServletRequest getRequest() {
  -     if( debug>0 ) log("JspEngineContext1: getRequest " + req );
  +     if( debug>0 ) log.log("getRequest " + req );
           return (HttpServletRequest)req.getFacade();
       }
       
  @@ -820,7 +600,7 @@
        * Get the http response we are using now...
        */
       public HttpServletResponse getResponse() {
  -     if( debug>0 ) log("JspEngineContext1: getResponse " );
  +     if( debug>0 ) log.log("getResponse " );
           return (HttpServletResponse)req.getResponse().getFacade();
       }
   
  @@ -828,16 +608,27 @@
        * The classpath that is passed off to the Java compiler. 
        */
       public String getClassPath() {
  -     if( debug>0 ) log("JspEngineContext1: getClassPath " +
  -         JspInterceptor.getClassPath(req.getContext()));
  -     return JspInterceptor.getClassPath(req.getContext());
  +     Context ctx=req.getContext();
  +     URL classP[]=ctx.getClassPath();
  +     String separator = System.getProperty("path.separator", ":");
  +        String cpath = "";
  +     
  +        for(int i=0; i< classP.length; i++ ) {
  +            URL cp = classP[i];
  +            File f = new File( cp.getFile());
  +            if (cpath.length()>0) cpath += separator;
  +            cpath += f;
  +        }
  +
  +     if( debug>0 ) log.log("getClassPath " + cpath);
  +     return cpath;
       }
       
       /**
        * Get the input reader for the JSP text. 
        */
       public JspReader getReader() {
  -     if( debug>0 ) log("JspEngineContext1: getReader " + reader );
  +     if( debug>0 ) log.log("getReader " + reader );
           return reader;
       }
       
  @@ -845,7 +636,7 @@
        * Where is the servlet being generated?
        */
       public ServletWriter getWriter() {
  -     if( debug>0 ) log("JspEngineContext1: getWriter " + writer );
  +     if( debug>0 ) log.log("getWriter " + writer );
           return writer;
       }
       
  @@ -853,7 +644,7 @@
        * Get the ServletContext for the JSP we're processing now. 
        */
       public ServletContext getServletContext() {
  -     if( debug>0 ) log("JspEngineContext1: getCtx " +
  +     if( debug>0 ) log.log("getCtx " +
                           req.getContext().getFacade());
           return (ServletContext)req.getContext().getFacade();
       }
  @@ -863,12 +654,12 @@
        * this JSP? I don't think this is used right now -- akv. 
        */
       public ClassLoader getClassLoader() {
  -     if( debug>0 ) log("JspEngineContext1: getLoader " + loader );
  +     if( debug>0 ) log.log("getLoader " + loader );
           return req.getContext().getClassLoader();
       }
   
       public void addJar( String jar ) throws IOException {
  -     if( debug>0 ) log("Add jar " + jar);
  +     if( debug>0 ) log.log("Add jar " + jar);
        //loader.addJar( jar );
       }
   
  @@ -877,7 +668,7 @@
        * errorpage? 
        */
       public boolean isErrorPage() {
  -     if( debug>0 ) log("JspEngineContext1: isErrorPage " + isErrPage );
  +     if( debug>0 ) log.log("isErrorPage " + isErrPage );
           return isErrPage;
       }
       
  @@ -887,7 +678,7 @@
        * other places it is called outputDir.
        */
       public String getOutputDir() {
  -     if( debug>0 ) log("JspEngineContext1: getOutputDir " +
  +     if( debug>0 ) log.log("getOutputDir " +
                           req.getContext().getWorkDir().getAbsolutePath());
           return req.getContext().getWorkDir().getAbsolutePath();
       }
  @@ -899,7 +690,7 @@
       public String getJspFile() {
        String sP=req.getServletPath();
        Context ctx=req.getContext();
  -     if( debug>0 ) log("JspEngineContext1: getJspFile " +
  +     if( debug>0 ) log.log("getJspFile " +
                           sP);//   ctx.getRealPath( sP ) );
        //        return ctx.getRealPath( sP );
        return sP;
  @@ -910,7 +701,7 @@
        * generated class. 
        */
       public String getServletClassName() {
  -     if( debug>0 ) log("JspEngineContext1: getServletClassName " +
  +     if( debug>0 ) log.log("getServletClassName " +
                           m.getClassName());
           return m.getClassName();
       }
  @@ -919,7 +710,7 @@
        * The package name into which the servlet class is generated. 
        */
       public String getServletPackageName() {
  -     if( debug>0 ) log("JspEngineContext1: getServletPackageName " +
  +     if( debug>0 ) log.log("getServletPackageName " +
                           servletPackageName );
           return servletPackageName;
       }
  @@ -929,7 +720,7 @@
        * class name. 
        */
       public final String getFullClassName() {
  -     if( debug>0 ) log("JspEngineContext1: getServletPackageName " +
  +     if( debug>0 ) log.log("getServletPackageName " +
                           servletPackageName + "." + servletClassName);
           if (servletPackageName == null)
               return servletClassName;
  @@ -941,7 +732,7 @@
        * generated. 
        */
       public String getServletJavaFileName() {
  -     if( debug>0 ) log("JspEngineContext1: getServletPackageName " +
  +     if( debug>0 ) log.log("getServletPackageName " +
                           servletPackageName + "." + servletClassName);
           return servletJavaFileName;
       }
  @@ -1001,19 +792,20 @@
       }
   
       public Compiler createCompiler() throws JasperException {
  -     if( debug>0 ) log("JspEngineContext1: createCompiler ");
  +     if( debug>0 ) log.log("createCompiler ");
        return null;
       }
       
       public String resolveRelativeUri(String uri)
       {
  -     if( debug>0 ) log("JspEngineContext1: resolveRelativeUri " + uri);
  +     if( debug>0 ) log.log("resolveRelativeUri " +
  +                              uri);
        return null;
       };    
   
       public java.io.InputStream getResourceAsStream(String res)
       {
  -     if( debug>0 ) log("JspEngineContext1: getRAS " + res);
  +     if( debug>0 ) log.log("getResourceAsStream " + res);
           ServletContext sctx=(ServletContext)req.getContext().getFacade();
        return sctx.getResourceAsStream(res);
       };
  @@ -1024,59 +816,175 @@
        */
       public String getRealPath(String path)
       {
  -     if( debug>0 ) log("GetRP " + path);
  +     if( debug>0 ) log.log("GetRP " + path);
        Context ctx=req.getContext();
        return FileUtil.safePath( ctx.getAbsolutePath(),
                                  path);
       };
  +}
   
  -    void log(String s, Exception e) {
  -     if (this.req != null && this.req.getContext() != null) {
  -         this.req.getContext().log(s, e);
  -     }
  -     else {
  -         System.err.println(s);
  -         e.printStackTrace();
  -     }
  +// -------------------- Jasper support - mangler --------------------
  +
  +final class JspMangler implements Mangler{
  +
  +    public JspMangler(String workDir, String docBase, String jspFile)
  +    {
  +     this.jspFile=jspFile;
  +     this.workDir=workDir;
  +     this.docBase=docBase;
  +     init();
       }
   
  -    void log(String s) {
  -     if (req != null && req.getContext() != null) {
  -         req.getContext().log(s);
  -     }
  -     else {
  -         System.err.println(s);
  -     }
  +    /** Versioned class name ( without package ).
  +     */
  +    public String getClassName() {
  +     return JavaGeneratorTool.getVersionedName( baseClassN, version );
  +    }
  +    
  +    /**
  +     *   Full path to the generated java file ( including version )
  +     */
  +    public String getJavaFileName() {
  +     return javaFileName;
       }
   
  -}
  +    /** The package name ( "." separated ) of the generated
  +     *  java file
  +     */
  +    public String getPackageName() {
  +     return pkgDir.replace('/', '.');
  +    }
   
  +    // -------------------- JspInterceptor fields --------------------
  +    
  +    /** Returns the jsp file, as declared by <jsp-file> in server.xml
  +     *  or the context-relative path that was extension mapped to jsp
  +     */
  +    public String getJspFile() {
  +     return jspFile;
  +    }
   
  -class JspMangler implements Mangler{
  -    JspInfo jspInfo;
  +    /** Returns the directory where the class is located, using
  +     *  the normal class loader rules.
  +     */
  +    public String getClassDir() {
  +     return classDir;
  +    }
  +    
  +    /** The class name ( package + class + versioning ) of the
  +     *  compilation result
  +     */
  +    public String getServletClassName() {
  +     if( pkgDir!=null ) {
  +         return getPackageName()  + "." + getClassName();
  +     } else {
  +         return getClassName();
  +     }
  +    }
   
  -    public JspMangler(JspInfo info)  {
  -     this.jspInfo=info;
  +    public int getVersion() {
  +     return version;
       }
   
  -    public final String getClassName() {
  -        return jspInfo.classN;
  +    /** Full path to the compiled class file ( including version )
  +     */
  +    public String getClassFileName() {
  +     return classFileName;
       }
  +    // In Jasper = not used - it's specific to the class scheme
  +    // used by JspServlet
  +    // Full path to the class file - without version.
  +    
   
  -    public final String getJavaFileName() {
  -     return jspInfo.javaFilePath;
  +    public String getBaseClassName() {
  +     return baseClassN;
       }
   
  -    public final String getPackageName() {
  -     return jspInfo.pkg;
  -     // It's not used, and shouldn't be used by compiler.
  -     // ( well, it's used to rename the file after compile
  -     // in JspServlet scheme - that must be out of compiler )
  +    public String getPackageDir() {
  +     return pkgDir;
  +    }
  +    
  +    public String getJspFilePath() {
  +     return FileUtil.safePath( docBase, jspFile);
       }
   
  -    // Full path to the class file - without version.
  -    public final String getClassFileName() {
  -     return null; // see getPackageName comment
  +    /** compute basic names - pkgDir and baseClassN
  +     */
  +    private void init() {
  +     int lastComp=jspFile.lastIndexOf(  "/" );
  +
  +     if( lastComp > 0 ) {
  +         // has package 
  +         // ignore the first "/" of jspFile
  +         pkgDir=jspFile.substring( 1, lastComp );
  +     }
  +     
  +     // remove "special" words, replace "."
  +     if( pkgDir!=null ) {
  +         pkgDir=JavaGeneratorTool.manglePackage(pkgDir);
  +         pkgDir=pkgDir.replace('.', '_');
  +         classDir=workDir + "/" + pkgDir;
  +     } else {
  +         classDir=workDir;
  +     }
  +     
  +     int extIdx=jspFile.lastIndexOf( "." );
  +
  +     if( extIdx<0 ) {
  +         // no "." 
  +         if( lastComp > 0 )
  +             baseClassN=jspFile.substring( lastComp+1 );
  +         else
  +             baseClassN=jspFile.substring( 1 );
  +     } else {
  +         if( lastComp > 0 )
  +             baseClassN=jspFile.substring( lastComp+1, extIdx );
  +         else
  +             baseClassN=jspFile.substring( 1, extIdx );
  +     }
  +
  +     System.out.println("XXXMangler: " + jspFile + " " + pkgDir + " " + baseClassN);
  +
  +     // extract version from the .class dir, using the base name
  +     version=JavaGeneratorTool.readVersion(classDir,
  +                                           baseClassN);
  +     if( version==-1 ) {
  +         version=0;
  +     }
  +     updateVersionPaths();
       }
  +
  +    private void updateVersionPaths() {
  +     // version dependent stuff
  +     String baseName=classDir + "/" + JavaGeneratorTool.
  +         getVersionedName( baseClassN, version);
  +     
  +     javaFileName= baseName + ".java";
  +
  +     classFileName=baseName +  ".class";
  +    }
  +    
  +    /** Move to a new class name, if a changes has been detected.
  +     */
  +    void nextVersion() {
  +     version++;
  +     JavaGeneratorTool.writeVersion( getClassDir(), baseClassN, version);
  +     updateVersionPaths();
  +    }
  +
  +    // context-relative jsp path 
  +    // extracted from the <jsp-file> or the result of a *.jsp mapping
  +    private String jspFile; 
  +    // version of the compiled java file
  +    private int version;
  +    private String workDir;
  +    private String docBase;
  +    // the "/" separted version
  +    private String pkgDir;
  +    // class name without package and version
  +    private String baseClassN;
  +    private String classDir;
  +    private String javaFileName;
  +    private String classFileName;
   }
   
  
  
  
  1.3       +2 -2      
jakarta-tomcat/src/facade22/org/apache/tomcat/modules/facade22/LoadOnStartupInterceptor.java
  
  Index: LoadOnStartupInterceptor.java
  ===================================================================
  RCS file: 
/home/cvs/jakarta-tomcat/src/facade22/org/apache/tomcat/modules/facade22/LoadOnStartupInterceptor.java,v
  retrieving revision 1.2
  retrieving revision 1.3
  diff -u -r1.2 -r1.3
  --- LoadOnStartupInterceptor.java     2000/12/12 22:32:57     1.2
  +++ LoadOnStartupInterceptor.java     2000/12/14 07:10:57     1.3
  @@ -132,7 +132,7 @@
                        // ServletHandler !
                        if( result instanceof ServletHandler &&
                            ((ServletHandler)result).getServletInfo().
  -                         getPath() != null ) {
  +                         getJspFile() != null ) {
                            loadJsp( ctx, result );
                        } else {
                            ((ServletHandler)result).init();
  @@ -156,7 +156,7 @@
        
        // Ugly code to trick JSPServlet into loading this.
        ContextManager cm=context.getContextManager();
  -     String path=((ServletHandler)result).getServletInfo().getPath();
  +     String path=((ServletHandler)result).getServletInfo().getJspFile();
        Request request = new Request();
        Response response = new Response();
        request.recycle();
  
  
  
  1.30      +1 -4      jakarta-tomcat/src/share/org/apache/tomcat/core/Handler.java
  
  Index: Handler.java
  ===================================================================
  RCS file: /home/cvs/jakarta-tomcat/src/share/org/apache/tomcat/core/Handler.java,v
  retrieving revision 1.29
  retrieving revision 1.30
  diff -u -r1.29 -r1.30
  --- Handler.java      2000/12/13 19:58:01     1.29
  +++ Handler.java      2000/12/14 07:10:58     1.30
  @@ -284,10 +284,7 @@
   
       protected final void log( String s ) {
        if ( logger==null ) 
  -         if( contextM!=null )
  -             contextM.log(s);
  -         else
  -             System.out.println("(cm==null) " + s );
  +         contextM.log(s);
        else 
            logger.log(s);
       }
  
  
  
  1.1                  
jakarta-tomcat/src/share/org/apache/tomcat/util/JavaGeneratorTool.java
  
  Index: JavaGeneratorTool.java
  ===================================================================
  /*
   * The Apache Software License, Version 1.1
   *
   * Copyright (c) 1999 The Apache Software Foundation.  All rights 
   * reserved.
   *
   * Redistribution and use in source and binary forms, with or without
   * modification, are permitted provided that the following conditions
   * are met:
   *
   * 1. Redistributions of source code must retain the above copyright
   *    notice, this list of conditions and the following disclaimer. 
   *
   * 2. Redistributions in binary form must reproduce the above copyright
   *    notice, this list of conditions and the following disclaimer in
   *    the documentation and/or other materials provided with the
   *    distribution.
   *
   * 3. The end-user documentation included with the redistribution, if
   *    any, must include the following acknowlegement:  
   *       "This product includes software developed by the 
   *        Apache Software Foundation (http://www.apache.org/)."
   *    Alternately, this acknowlegement may appear in the software itself,
   *    if and wherever such third-party acknowlegements normally appear.
   *
   * 4. The names "The Jakarta Project", "Tomcat", and "Apache Software
   *    Foundation" must not be used to endorse or promote products derived
   *    from this software without prior written permission. For written 
   *    permission, please contact [EMAIL PROTECTED]
   *
   * 5. Products derived from this software may not be called "Apache"
   *    nor may "Apache" appear in their names without prior written
   *    permission of the Apache Group.
   *
   * THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESSED OR IMPLIED
   * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
   * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
   * DISCLAIMED.  IN NO EVENT SHALL THE APACHE SOFTWARE FOUNDATION OR
   * ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
   * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
   * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF
   * USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
   * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
   * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT
   * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
   * SUCH DAMAGE.
   * ====================================================================
   *
   * This software consists of voluntary contributions made by many
   * individuals on behalf of the Apache Software Foundation.  For more
   * information on the Apache Software Foundation, please see
   * <http://www.apache.org/>.
   *
   */ 
  
  package org.apache.tomcat.util;
  
  import java.io.*;
  
  /** General-purpose utilities to help generation of syntetic java
   *  classes
   */
  public class JavaGeneratorTool {
  
      /** Mangle Package names to avoid reserver words
       **/
      public static final String manglePackage( String s ) {
            for (int i = 0; i < keywords.length; i++) {
              char fs = File.separatorChar;
              int index = s.indexOf(keywords[i]);
              if(index == -1 ) continue;
              while (index != -1) {
                  String tmpathName = s.substring (0,index) + "__";
                  s = tmpathName + s.substring (index);
                  index = s.indexOf(keywords[i],index+3);
              }
          }
          return(s);
      }
  
      /** 
       *        Generated java files may be versioned, to avoid full reloading
       *  when the source changes.
       *
       *  Before generating a file, we check if it is already generated,
       *  and for that we need the latest version of the file. One way
       *  to do it ( the original jasper ) is to modify the class file
       *  and use a class name without version number, then use a class
       *  loader trick to load the file and extract the version from the
       *  class name.
       * 
       *  This method implements a different strategy - the classes are generate
       *  with version number, and we use a map file to find the latest
       *  version of a class. ( we could list )
       *  That can be improved by using a single version file per directory,
       *  or by listing the directory.
       *
       *  The class file is generated to use _version extension.
       *
       *  @return int version number of the latest class file, or -1 if
       *          the mapFile or the coresponding class file is not found
       */
      public static int readVersion(String classDir, String baseClassName) {
        File mapFile=new File( classDir + "/" + baseClassName + ".ver");
        if( ! mapFile.exists() )
            return -1;
        
        int version=0;
        try {
            FileInputStream fis=new FileInputStream( mapFile );
            version=(int)fis.read();
            fis.close();
        } catch( Exception ex ) {
            System.out.println("readVersion() mapPath=" + mapFile + ex);
            return -1;
        }
  
        // check if the file exists
        String versionedFileName=classDir + "/" +
            getVersionedName( baseClassName, version ) + ".class";
  
        File vF=new File( versionedFileName );
        if( ! vF.exists() )
            return -1;
        
        return version;
      }
  
      /** After we compile a page, we save the version in a
        file with known name, so we can restore the state when we
        restart. Note that this should move to a general-purpose
        persist repository ( on my plans for next version of tomcat )
      */
      public static void writeVersion(String classDir, String baseClassName,
                                    int version)
      {
        File mapFile=new File(  classDir + "/" + baseClassName + ".ver");
  
        try {
            File dir=new File(mapFile.getParent());
            dir.mkdirs();
            FileOutputStream fis=new FileOutputStream( mapFile );
            fis.write(version);
            fis.close();
        } catch( Exception ex ) {
            System.out.println("writeVersion() " + mapFile + ex);
        }
      }
  
      public static String getVersionedName( String baseName, int version )
      {
        return baseName + "_" + version;
      }
  
      // -------------------- Constants --------------------
      
      private static final String [] keywords = {
          "abstract", "boolean", "break", "byte",
          "case", "catch", "char", "class",
          "const", "continue", "default", "do",
          "double", "else", "extends", "final",
          "finally", "float", "for", "goto",
          "if", "implements", "import",
          "instanceof", "int", "interface",
          "long", "native", "new", "package",
          "private", "protected", "public",
          "return", "short", "static", "super",
          "switch", "synchronized", "this",
          "throw", "throws", "transient",
          "try", "void", "volatile", "while"
      };
  
  }
  
  
  

Reply via email to