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