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]>