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"
};
}