📄 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
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -