📄 jspinterceptor.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 apache@apache.org.
*
* 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.request;
import javax.servlet.*;
import javax.servlet.http.*;
import javax.servlet.jsp.HttpJspPage;
import javax.servlet.jsp.JspFactory;
import java.util.*;
import java.io.*;
import org.apache.jasper.*;
import org.apache.jasper.Constants;
import org.apache.jasper.runtime.*;
import org.apache.jasper.compiler.*;
import org.apache.tomcat.logging.Logger;
import org.apache.jasper.compiler.Compiler;
import org.apache.tomcat.core.*;
/**
* Plug in the JSP engine (a.k.a Jasper)!
*
* @author Anil K. Vijendran
* @author Harish Prabandham
* @author Costin Manolache
*/
public class JspInterceptor extends BaseInterceptor {
int jspInfoNOTE;
public void engineInit(ContextManager cm )
throws TomcatException
{
super.engineInit(cm);
jspInfoNOTE=cm.getNoteId( ContextManager.HANDLER_NOTE,
"tomcat.jspInfoNote");
}
public void contextInit(Context ctx)
throws TomcatException
{
JspFactory.setDefaultFactory(new JspFactoryImpl());
ctx.getServletLoader().addRepository( ctx.getWorkDir(),
ctx.getProtectionDomain());
}
public void preServletInit( Context ctx, ServletWrapper sw )
throws TomcatException
{
Servlet theServlet = sw.getServlet();
if (theServlet instanceof HttpJspBase) {
if( debug > 0 )
log( "PreServletInit: HttpJspBase.setParentClassLoader" + sw );
HttpJspBase h = (HttpJspBase) theServlet;
h.setClassLoader(ctx.getServletLoader().getClassLoader());
}
}
public int requestMap( Request req ) {
ServletWrapper wrapper=req.getWrapper();
if( wrapper!=null && ! "jsp".equals( wrapper.getName())
&& wrapper.getPath() == null)
return 0;
// XXX jsp handler is still needed
if( wrapper==null )
return 0;
Context ctx= req.getContext();
// If this Wrapper was already used, we have all the info
JspInfo jspInfo=(JspInfo)wrapper.getNote( jspInfoNOTE );
if( jspInfo == null ) {
if( debug > 0 ) log("New jsp page - no jspInfo ");
jspInfo=new JspInfo(req);
mapJspPage( req, jspInfo, jspInfo.uri, jspInfo.fullClassN);
}
if( jspInfo.jspSource.lastModified()
> jspInfo.compileTime ) {
//XXX destroy();
// jump version number - the file needs to
// be recompiled, and we don't want a reload
jspInfo.nextVersion();
compile( req, jspInfo );
mapJspPage( req , jspInfo, jspInfo.uri, jspInfo.fullClassN);
}
return 0;
}
/** Add an exact map that will avoid *.jsp mapping and intermediate
* steps
*/
void mapJspPage( Request req, JspInfo jspInfo,
String servletName, String classN )
{
Context ctx=req.getContext();
ServletWrapper wrapper=null;
String servletPath=servletName;
// 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 {
wrapper=ctx.getServletByName( servletName );
// We may want to replace the class and reset it if changed
if( wrapper==null ) {
wrapper=ctx.addServlet( servletName, classN );
wrapper.setPath( servletName );
wrapper.setOrigin( ServletWrapper.ORIGIN_INVOKER );
ctx.addServletMapping( servletPath ,
servletPath );
log( "Added mapping " + servletPath +
" path=" + servletPath );
}
wrapper.setServletClass( classN );
wrapper.setNote( jspInfoNOTE, jspInfo );
} catch( TomcatException ex ) {
ex.printStackTrace();
return ;
}
req.setWrapper( wrapper );
if( debug>0) log("Wrapper " + wrapper);
}
/** Convert the .jsp file to a java file, then compile it to class
*/
void compile(Request req, JspInfo jspInfo ) {
log( "Compiling " + jspInfo.realClassPath);
try {
// make sure we have the directories
File dir=new File( jspInfo.outputDir + "/" + jspInfo.pkgDir);
dir.mkdirs();
JspMangler mangler= new JspMangler(jspInfo);
TomcatOptions options=new TomcatOptions();
JspEngineContext1 ctxt = new JspEngineContext1(req, mangler);
ctxt.setOptions( options );
Compiler compiler=new Compiler(ctxt);
compiler.setMangler( mangler );
// we will compile ourself
compiler.setJavaCompiler( null );
synchronized ( this ) {
compiler.compile();
}
javac( createJavaCompiler( options ), ctxt, mangler );
if(debug>0)log( "Compiled to " + jspInfo.realClassPath );
jspInfo.touch();
} catch( Exception ex ) {
ex.printStackTrace();
}
}
String javaEncoding = "UTF8"; // perhaps debatable?
static String sep = System.getProperty("path.separator");
/** 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,
Mangler mangler)
throws JasperException
{
javac.setEncoding(javaEncoding);
String cp=System.getProperty("java.class.path")+ sep +
ctxt.getClassPath() + sep + ctxt.getOutputDir();
javac.setClasspath( cp );
if( debug>0) log( "ClassPath " + cp);
ByteArrayOutputStream out = new ByteArrayOutputStream (256);
javac.setOutputDir(ctxt.getOutputDir());
javac.setMsgOutput(out);
String javaFileName = mangler.getJavaFileName();
/**
* Execute the compiler
*/
boolean status = javac.compile(javaFileName);
if (!ctxt.keepGenerated()) {
File javaFile = new File(javaFileName);
javaFile.delete();
}
if (status == false) {
String msg = out.toString ();
throw new JasperException("Unable to compile "
+ msg);
}
}
/** tool for customizing javac
*/
public JavaCompiler createJavaCompiler(Options options)
throws JasperException
{
String compilerPath = options.getJspCompilerPath();
Class jspCompilerPlugin = options.getJspCompilerPlugin();
JavaCompiler javac;
if (jspCompilerPlugin != null) {
try {
javac = (JavaCompiler) jspCompilerPlugin.newInstance();
} catch (Exception ex) {
Constants.message("jsp.warning.compiler.class.cantcreate",
new Object[] { jspCompilerPlugin, ex },
Logger.FATAL);
javac = new SunJavaCompiler();
}
} else {
javac = new SunJavaCompiler();
}
if (compilerPath != null)
javac.setCompilerPath(compilerPath);
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 {
String uri; // path
int version; // version
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 - avoid one extra access
JspInfo( Request req ) {
init( req );
}
public String toString() {
return 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() {
classN = baseClassN + "_" + version;
realClassPath = outputDir + "/" + pkgDir + "/" +
classN + ".class";
javaFilePath = outputDir + "/" + pkgDir + "/" +
classN + ".java";
fullClassN = pkg +"." + classN;
// System.out.println("ClassN=" + classN +
// " realClassPath=" + realClassPath +
// " javaFilePath=" + javaFilePath +
// " fullClassN =" + fullClassN);
writeVersion();
// save to mapFile
}
/** Compute various names used
*/
void init(Request req ) {
// String includeUri
// = (String) req.getAttribute(Constants.INC_SERVLET_PATH);
uri=req.getServletPath();
Context ctx=req.getContext();
outputDir = ctx.getWorkDir().getAbsolutePath();
String jspFilePath=ctx.getRealPath( uri );
jspSource = new File(jspFilePath);
// extension
int lastComp=uri.lastIndexOf( "/" );
String endUnproc=null;
if( lastComp > 0 ) {
// has package
pkgDir=uri.substring( 1, lastComp );
endUnproc=uri.substring( lastComp+1 );
} else {
endUnproc=uri.substring( 1 );
}
if( pkgDir!=null ) {
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
mapPath = outputDir + "/" + pkgDir + "/" + baseClassN + ".ver";
File mapFile=new File(mapPath);
if( mapFile.exists() ) {
// read version from file
readVersion();
updateVersionedPaths();
updateCompileTime();
} else {
version=0;
updateVersionedPaths();
}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -