kinman      2002/09/11 12:07:33

  Modified:    jasper2/src/share/org/apache/jasper
                        JspCompilationContext.java
               jasper2/src/share/org/apache/jasper/compiler Compiler.java
                        Generator.java TagFileProcessor.java
               jasper2/src/share/org/apache/jasper/resources
                        messages.properties
               jasper2/src/share/org/apache/jasper/servlet
                        JspServletWrapper.java
  Log:
  - Handle tag file compilations with circular dependencies.
  
    Approach taken:
    * Use a counter in JspServletWrapper for detection of circularities.
    * Generate a skeleton tag handler (which has no dependency) from TagInfo
      and use that to compile its clients.  It is eventually replaced by
      the real one.
  
    Todo:
    The compilation of tag files is now serialized.  Can be made more
    concurrent with more bookkeeping.
  
  Revision  Changes    Path
  1.21      +20 -3     
jakarta-tomcat-jasper/jasper2/src/share/org/apache/jasper/JspCompilationContext.java
  
  Index: JspCompilationContext.java
  ===================================================================
  RCS file: 
/home/cvs/jakarta-tomcat-jasper/jasper2/src/share/org/apache/jasper/JspCompilationContext.java,v
  retrieving revision 1.20
  retrieving revision 1.21
  diff -u -r1.20 -r1.21
  --- JspCompilationContext.java        6 Sep 2002 21:40:53 -0000       1.20
  +++ JspCompilationContext.java        11 Sep 2002 19:07:32 -0000      1.21
  @@ -122,6 +122,7 @@
       protected Class servletClass;
   
       protected boolean isTagFile;
  +    protected boolean protoTypeMode;
       protected TagInfo tagInfo;
       protected TagData tagData;
   
  @@ -235,6 +236,10 @@
           return jspCompiler;
       }
   
  +    public Compiler getCompiler() {
  +     return jspCompiler;
  +    }
  +
       /** ---------- Access resources in the webapp ---------- */
   
       /** 
  @@ -361,6 +366,18 @@
   
       public TagInfo getTagInfo() {
        return tagInfo;
  +    }
  +
  +    /**
  +     * True if we are compiling a tag file in prototype mode, i.e. we only
  +     * Generate codes with class for the tag handler with empty method bodies.
  +     */
  +    public boolean isPrototypeMode() {
  +     return protoTypeMode;
  +    }
  +
  +    public void setPrototypeMode(boolean pm) {
  +     protoTypeMode = pm;
       }
   
       public TagData getTagData() {
  
  
  
  1.32      +40 -3     
jakarta-tomcat-jasper/jasper2/src/share/org/apache/jasper/compiler/Compiler.java
  
  Index: Compiler.java
  ===================================================================
  RCS file: 
/home/cvs/jakarta-tomcat-jasper/jasper2/src/share/org/apache/jasper/compiler/Compiler.java,v
  retrieving revision 1.31
  retrieving revision 1.32
  diff -u -r1.31 -r1.32
  --- Compiler.java     28 Aug 2002 23:00:18 -0000      1.31
  +++ Compiler.java     11 Sep 2002 19:07:32 -0000      1.32
  @@ -119,6 +119,7 @@
       private ErrorDispatcher errDispatcher;
       private PageInfo pageInfo;
       private JspServletWrapper jsw;
  +    private TagFileProcessor tfp;
   
       protected Project project=null;
   
  @@ -256,6 +257,13 @@
        ParserController parserCtl = new ParserController(ctxt, this);
        pageNodes = parserCtl.parse(ctxt.getJspFile());
   
  +     if (ctxt.isPrototypeMode()) {
  +         // generate prototype .java file for the tag file
  +         Generator.generate(writer, this, pageNodes);
  +            writer.close();
  +         return;
  +     }
  +
        // Validate and process attributes
        Validator.validate(this, pageNodes);
   
  @@ -268,7 +276,8 @@
   
        // Compile (if necessary) and load the tag files referenced in
        // this compilation unit.
  -     TagFileProcessor.loadTagFiles(this, pageNodes);
  +     tfp = new TagFileProcessor();
  +     tfp.loadTagFiles(this, pageNodes);
   
           long t3=System.currentTimeMillis();
           
  @@ -287,6 +296,14 @@
           
           //JSR45 Support - note this needs to be checked by a JSR45 guru
        SmapUtil.generateSmap(ctxt, pageNodes, true);
  +
  +     // If any proto type .java and .class files was generated,
  +     // the prototype .java may have been replaced by the current
  +     // compilation (if the tag file is self referencing), but the
  +     // .class file need to be removed, to make sure that javac would
  +     // generate .class again from the new .java file just generated.
  +
  +     tfp.removeProtoTypeFiles(ctxt.getClassFileName());
       }
   
       /** 
  @@ -368,6 +385,11 @@
           if( t2-t1 > 500 ) {
               log.info( "Compiled " + javaFileName + " " + (t2-t1));
           }
  +
  +     if (ctxt.isPrototypeMode()) {
  +         return;
  +     }
  +
           //JSR45 Support - note this needs to be checked by a JSR45 guru
        SmapUtil.installSmap(ctxt);
       }
  @@ -380,6 +402,9 @@
       {
           generateJava();
           generateClass();
  +     if (tfp != null) {
  +         tfp.removeProtoTypeFiles(null);
  +     }
       }
   
       /**
  @@ -495,7 +520,7 @@
        */
       public void removeGeneratedFiles() {
           try {
  -            String classFileName = ctxt.getServletClassName();
  +            String classFileName = ctxt.getClassFileName();
               if (classFileName != null) {
                   File classFile = new File(classFileName);
                   if( log.isDebugEnabled() )
  @@ -518,5 +543,17 @@
           }
       }
   
  -
  +    public void removeGeneratedClassFiles() {
  +        try {
  +            String classFileName = ctxt.getClassFileName();
  +            if (classFileName != null) {
  +                File classFile = new File(classFileName);
  +                if( log.isDebugEnabled() )
  +                    log.debug( "Deleting " + classFile );
  +                classFile.delete();
  +            }
  +        } catch (Exception e) {
  +            // Remove as much as possible, ignore possible exceptions
  +        }
  +    }
   }
  
  
  
  1.99      +16 -3     
jakarta-tomcat-jasper/jasper2/src/share/org/apache/jasper/compiler/Generator.java
  
  Index: Generator.java
  ===================================================================
  RCS file: 
/home/cvs/jakarta-tomcat-jasper/jasper2/src/share/org/apache/jasper/compiler/Generator.java,v
  retrieving revision 1.98
  retrieving revision 1.99
  diff -u -r1.98 -r1.99
  --- Generator.java    11 Sep 2002 18:07:13 -0000      1.98
  +++ Generator.java    11 Sep 2002 19:07:32 -0000      1.99
  @@ -2873,6 +2873,11 @@
        if (gen.ctxt.isTagFile()) {
            TagInfo tagInfo = gen.ctxt.getTagInfo();
            gen.generateTagHandlerPreamble(tagInfo, page);
  +
  +         if (gen.ctxt.isPrototypeMode()) {
  +             return;
  +         }
  +
            gen.fragmentHelperClass.generatePreamble();
            page.visit(gen.new GenerateVisitor(gen.ctxt.isTagFile(), out,
                                               gen.methodsBuffer,
  @@ -2963,6 +2968,14 @@
           
           // Now the doTag() method
        out.printil("public void doTag() throws javax.servlet.jsp.JspException, 
java.io.IOException {");
  +
  +     if (ctxt.isPrototypeMode()) {
  +         out.printil("}");
  +         out.popIndent();
  +         out.printil("}");
  +         return;
  +     }
  +
        out.pushIndent();
        out.printil("PageContext pageContext = (PageContext)jspContext;");
           
  
  
  
  1.24      +65 -23    
jakarta-tomcat-jasper/jasper2/src/share/org/apache/jasper/compiler/TagFileProcessor.java
  
  Index: TagFileProcessor.java
  ===================================================================
  RCS file: 
/home/cvs/jakarta-tomcat-jasper/jasper2/src/share/org/apache/jasper/compiler/TagFileProcessor.java,v
  retrieving revision 1.23
  retrieving revision 1.24
  diff -u -r1.23 -r1.24
  --- TagFileProcessor.java     9 Sep 2002 20:36:07 -0000       1.23
  +++ TagFileProcessor.java     11 Sep 2002 19:07:32 -0000      1.24
  @@ -82,6 +82,8 @@
   
   public class TagFileProcessor {
   
  +    private Vector tempVector;
  +
       /**
        * A visitor the tag file
        */
  @@ -332,9 +334,9 @@
       /**
        * Compiles and loads a tagfile.
        */
  -    private static Class loadTagFile(Compiler compiler,
  -                                 String tagFilePath, TagInfo tagInfo,
  -                                 TagData tagData)
  +    private Class loadTagFile(Compiler compiler,
  +                           String tagFilePath, TagInfo tagInfo,
  +                           TagData tagData)
        throws JasperException {
   
        JspCompilationContext ctxt = compiler.getCompilationContext();
  @@ -342,29 +344,47 @@
           JspServletWrapper wrapper =
                (JspServletWrapper) rctxt.getWrapper(tagFilePath);
   
  -     // No need to synchronize wrapper creation since this can only
  -     // happen when a JSP file is compiled, which is synchronized.
  -     if (wrapper == null) {
  -         wrapper = new JspServletWrapper(ctxt.getServletContext(),
  +     synchronized(rctxt) {
  +         if (wrapper == null) {
  +             wrapper = new JspServletWrapper(ctxt.getServletContext(),
                                            ctxt.getOptions(),
                                            tagFilePath,
                                            tagInfo,
                                            tagData,
                                            ctxt.getRuntimeContext(),
                                            ctxt.getTagFileJars());
  -         rctxt.addWrapper(tagFilePath,wrapper);
  -     }
  +             rctxt.addWrapper(tagFilePath,wrapper);
  +         }
   
  -     // Check to see if we have been here before but not finished
  -     // compiling/loading.
  -     if (wrapper.incTripCount() > 0) {
  -         // Circular tag file dependencies
  -         compiler.getErrorDispatcher().jspError("jsp.error.circular.tagfile",
  -                     tagFilePath);
  +         Class tagClass;
  +         int tripCount = wrapper.incTripCount();
  +         try {
  +             if (tripCount > 0) {
  +                 // When tripCount is greater than zero, a circular
  +                 // dependency exists.  The circularily dependant tag
  +                 // file is compiled in prototype mode, to avoid infinite
  +                 // recursion.
  +
  +                 JspServletWrapper tempWrapper = new JspServletWrapper(
  +                                         ctxt.getServletContext(),
  +                                            ctxt.getOptions(),
  +                                            tagFilePath,
  +                                            tagInfo,
  +                                            tagData,
  +                                            ctxt.getRuntimeContext(),
  +                                            ctxt.getTagFileJars());
  +                 tagClass = tempWrapper.loadTagFilePrototype();
  +                 tempVector.add(
  +                     tempWrapper.getJspEngineContext().getCompiler());
  +             } else {
  +                 tagClass = wrapper.loadTagFile();
  +             }
  +         } finally {
  +             wrapper.decTripCount();
  +         }
  +
  +         return tagClass;
        }
  -     Class tagClass = wrapper.loadTagFile();
  -     wrapper.decTripCount();
  -     return tagClass;
       }
   
       /*
  @@ -372,12 +392,13 @@
        * files and compile (if necessary) and load them.
        */ 
   
  -    static class TagFileLoaderVisitor extends Node.Visitor {
  +    class TagFileLoaderVisitor extends Node.Visitor {
   
        private Compiler compiler;
        private PageInfo pageInfo;
   
        TagFileLoaderVisitor(Compiler compiler) {
  +         
            this.compiler = compiler;
            this.pageInfo = compiler.getPageInfo();
        }
  @@ -401,11 +422,32 @@
        * are assumed to have been proccessed and encapsulated as TagFileInfo
        * in the CustomTag nodes.
        */
  -    public static void loadTagFiles(Compiler compiler, Node.Nodes page)
  +    public void loadTagFiles(Compiler compiler, Node.Nodes page)
                throws JasperException {
   
  +     tempVector = new Vector();
        page.visit(new TagFileLoaderVisitor(compiler));
       }
  -     
  +
  +    /**
  +     * Removed the java and class files for the tag prototype 
  +     * generated from the current compilation.
  +     * @param classFileName If non-null, remove only the class file with
  +     *        with this name.
  +     */
  +    public void removeProtoTypeFiles(String classFileName) {
  +     Iterator iter = tempVector.iterator();
  +     while (iter.hasNext()) {
  +         Compiler c = (Compiler) iter.next();
  +         if (classFileName == null) {
  +             c.removeGeneratedClassFiles();
  +         } else if (classFileName.equals(
  +                     c.getCompilationContext().getClassFileName())) {
  +             c.removeGeneratedClassFiles();
  +             tempVector.remove(c);
  +             return;
  +         }
  +     }
  +    }
   }
   
  
  
  
  1.37      +1 -2      
jakarta-tomcat-jasper/jasper2/src/share/org/apache/jasper/resources/messages.properties
  
  Index: messages.properties
  ===================================================================
  RCS file: 
/home/cvs/jakarta-tomcat-jasper/jasper2/src/share/org/apache/jasper/resources/messages.properties,v
  retrieving revision 1.36
  retrieving revision 1.37
  diff -u -r1.36 -r1.37
  --- messages.properties       9 Sep 2002 20:36:07 -0000       1.36
  +++ messages.properties       11 Sep 2002 19:07:33 -0000      1.37
  @@ -300,4 +300,3 @@
   jsp.error.duplicate.name.jspattribute=The attribute {0} specified in the standard 
or custom action also appears as the value of the name attribute in the enclosed 
jsp:attribute
   jsp.error.not.in.template=Not allowed in a template text body.
   jsp.error.badaction=The action is not a recognizable standard action.
  -jsp.error.circular.tagfile=The tag file {0} contains a circular dependency on 
itself.  This is currently not implemented.
  
  
  
  1.18      +23 -8     
jakarta-tomcat-jasper/jasper2/src/share/org/apache/jasper/servlet/JspServletWrapper.java
  
  Index: JspServletWrapper.java
  ===================================================================
  RCS file: 
/home/cvs/jakarta-tomcat-jasper/jasper2/src/share/org/apache/jasper/servlet/JspServletWrapper.java,v
  retrieving revision 1.17
  retrieving revision 1.18
  diff -u -r1.17 -r1.18
  --- JspServletWrapper.java    9 Sep 2002 20:36:07 -0000       1.17
  +++ JspServletWrapper.java    11 Sep 2002 19:07:33 -0000      1.18
  @@ -199,6 +199,9 @@
           return config.getServletContext();
       }
   
  +    /**
  +     * Compile (if needed) and load a tag file
  +     */
       public Class loadTagFile() throws JasperException {
   
           try {
  @@ -211,17 +214,29 @@
                   }
               }
               if (ctxt.isReload()) {
  -                synchronized (this) {
  -                    if (ctxt.isReload()) {
  -                        tagHandlerClass = ctxt.load();
  -                    }
  -                }
  +                tagHandlerClass = ctxt.load();
               }
           } catch (FileNotFoundException ex) {
               throw new JasperException(ex);
        }
   
        return tagHandlerClass;
  +    }
  +
  +    /**
  +     * Compile and load a prototype for the Tag file.  This is needed
  +     * when compiling tag files with circular dependencies.  A prototpe
  +     * (skeleton) with no dependencies on other other tag files is
  +     * generated and compiled.
  +     */
  +    public Class loadTagFilePrototype() throws JasperException {
  +
  +     ctxt.setPrototypeMode(true);
  +     try {
  +         return loadTagFile();
  +     } finally {
  +         ctxt.setPrototypeMode(false);
  +     }
       }
   
       /**
  
  
  

--
To unsubscribe, e-mail:   <mailto:[EMAIL PROTECTED]>
For additional commands, e-mail: <mailto:[EMAIL PROTECTED]>

Reply via email to