luehe 2003/02/25 16:11:39 Modified: jasper2/src/share/org/apache/jasper/compiler Compiler.java Generator.java JspUtil.java PageInfo.java Validator.java jasper2/src/share/org/apache/jasper/runtime ProtectedFunctionMapper.java Added: jasper2/src/share/org/apache/jasper/compiler FunctionMapperImpl.java Log: Consolidated all code that is concerned with populating EL function map into new FunctionMapperImpl class, an instance of which is stored with a compilation unit's PageInfo. This class is also leveraged by the Validator and Generator classes. Revision Changes Path 1.55 +4 -0 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.54 retrieving revision 1.55 diff -u -r1.54 -r1.55 --- Compiler.java 24 Feb 2003 19:39:39 -0000 1.54 +++ Compiler.java 26 Feb 2003 00:11:37 -0000 1.55 @@ -249,6 +249,10 @@ return; } + // Generate FunctionMapper (used for validation of EL expressions and + // code generation) + pageInfo.setFunctionMapper(new FunctionMapperImpl(this)); + // Validate and process attributes Validator.validate(this, pageNodes); 1.166 +32 -56 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.165 retrieving revision 1.166 diff -u -r1.165 -r1.166 --- Generator.java 24 Feb 2003 18:09:36 -0000 1.165 +++ Generator.java 26 Feb 2003 00:11:38 -0000 1.166 @@ -613,66 +613,42 @@ private void generateELFunctionMap() throws JasperException { - Hashtable taglibs = pageInfo.getTagLibraries(); - Iterator iter = taglibs.keySet().iterator(); - boolean fnPresent = false; - - // Check to see if at least one function is present. - while( iter.hasNext() ) { - String key = (String)iter.next(); - TagLibraryInfo tli = (TagLibraryInfo)taglibs.get( key ); - if( tli.getFunctions() != null && tli.getFunctions().length > 0 ) { - fnPresent = true; - break; - } - } - + FunctionMapperImpl fnMap = pageInfo.getFunctionMapper(); + out.printil("private static org.apache.jasper.runtime.ProtectedFunctionMapper _jspx_fnmap;"); - if( fnPresent ) { - iter = taglibs.keySet().iterator(); + if (!fnMap.isEmpty()) { + Iterator iter = fnMap.keySet().iterator(); out.println(); out.printil("static {"); out.pushIndent(); out.printil("_jspx_fnmap = org.apache.jasper.runtime.ProtectedFunctionMapper.getInstance();"); - while( iter.hasNext() ) { - String key = (String)iter.next(); - TagLibraryInfo tli = (TagLibraryInfo)taglibs.get( key ); - FunctionInfo[] fnInfo = tli.getFunctions(); - String fnPrefix = tli.getPrefixString(); - out.printil( "// Functions for " + tli.getShortName() ); - for( int i = 0; i < fnInfo.length; i++ ) { - out.printin("_jspx_fnmap.mapFunction("); - out.print(quote(fnPrefix)); - out.print(", "); - out.print(quote(fnInfo[i].getName())); - out.print(", "); - out.print(fnInfo[i].getFunctionClass() + ".class, "); - String fnSignature = fnInfo[i].getFunctionSignature(); - JspUtil.FunctionSignature functionSignature = - new JspUtil.FunctionSignature( fnSignature, - tli.getShortName(), err, ctxt.getClassLoader() ); - out.print( quote( functionSignature.getMethodName() ) ); - out.print(", "); - Class[] args = functionSignature.getParameterTypes(); - if (args != null) { - out.print("new Class[] {" ); - for( int j = 0; j < args.length; j++ ) { - out.print( args[j].getName() + ".class" ); - if( j < (args.length - 1) ) { - out.print( ", " ); - } + while (iter.hasNext()) { + String key = (String) iter.next(); + out.printin("_jspx_fnmap.mapFunction("); + out.print(quote(key)); + out.print(", "); + out.print(fnMap.getFunctionClass(key) + ".class, "); + out.print(quote(fnMap.getMethodName(key))); + out.print(", "); + Class[] args = fnMap.getParameterTypes(key); + if (args != null) { + out.print("new Class[] {" ); + for( int j = 0; j < args.length; j++ ) { + out.print( args[j].getName() + ".class" ); + if( j < (args.length - 1) ) { + out.print( ", " ); } - out.print("} "); - } else { - out.print("null"); } - out.println(");"); - } - } - out.popIndent(); - out.printil("}"); - out.println(); - } + out.print("} "); + } else { + out.print("null"); + } + out.println(");"); + } + } + out.popIndent(); + out.printil("}"); + out.println(); } /** 1.33 +3 -117 jakarta-tomcat-jasper/jasper2/src/share/org/apache/jasper/compiler/JspUtil.java Index: JspUtil.java =================================================================== RCS file: /home/cvs/jakarta-tomcat-jasper/jasper2/src/share/org/apache/jasper/compiler/JspUtil.java,v retrieving revision 1.32 retrieving revision 1.33 diff -u -r1.32 -r1.33 --- JspUtil.java 20 Feb 2003 15:50:36 -0000 1.32 +++ JspUtil.java 26 Feb 2003 00:11:38 -0000 1.33 @@ -63,12 +63,9 @@ import java.net.URL; import java.io.*; -import java.util.ArrayList; import java.util.Enumeration; import java.util.Hashtable; -import java.util.NoSuchElementException; import java.util.Vector; -import java.util.StringTokenizer; import java.util.jar.JarFile; import java.util.zip.ZipEntry; @@ -629,117 +626,6 @@ */ public static String nextTemporaryVariableName() { return Constants.TEMP_VARIABLE_NAME_PREFIX + (tempSequenceNumber++); - } - - /** - * Parses and encapsulates a function signature, as would appear in - * a TLD. - */ - public static class FunctionSignature { - private String returnType; - private String methodName; - private Class[] parameterTypes; - - /** - * Parses a function signature, as would appear in the TLD - * - * @param signature The signature to parse - * @param tagName Name of tag, for error messages. - * @throws JasperException If an error occurred while parsing the - * signature. - */ - public FunctionSignature( String signature, String tagName, - ErrorDispatcher err, ClassLoader loader ) - throws JasperException - { - try { - // Parse function signature, assuming syntax: - // <return-type> S <method-name> S? '(' - // ( <arg-type> ( ',' <arg-type> )* )? ')' - String ws = " \t\n\r"; - StringTokenizer sigTokenizer = new StringTokenizer( - signature, ws + "(),", true); - - // Return type: - this.returnType = sigTokenizer.nextToken(); - - // Skip whitespace and read <method-name>: - do { - this.methodName = sigTokenizer.nextToken(); - } while( ws.indexOf( this.methodName ) != -1 ); - - // Skip whitespace and read '(': - String paren; - do { - paren = sigTokenizer.nextToken(); - } while( ws.indexOf( paren ) != -1 ); - - if( !paren.equals( "(" ) ) { - err.jspError("jsp.error.tld.fn.invalid.signature.parenexpected", - tagName, this.methodName); - } - - // ( <arg-type> S? ( ',' S? <arg-type> S? )* )? ')' - - // Skip whitespace and read <arg-type>: - String argType; - do { - argType = sigTokenizer.nextToken(); - } while( ws.indexOf( argType ) != -1 ); - - if( !argType.equals( ")" ) ) { - ArrayList parameterTypes = new ArrayList(); - do { - if( ",(".indexOf( argType ) != -1 ) { - err.jspError("jsp.error.tld.fn.invalid.signature", - tagName, this.methodName); - } - - parameterTypes.add(toClass(argType, loader)); - - String comma; - do { - comma = sigTokenizer.nextToken(); - } while( ws.indexOf( comma ) != -1 ); - - if( comma.equals( ")" ) ) { - break; - } - if( !comma.equals( "," ) ) { - err.jspError("jsp.error.tld.fn.invalid.signature.commaexpected", - tagName, this.methodName); - } - - // <arg-type> - do { - argType = sigTokenizer.nextToken(); - } while( ws.indexOf( argType ) != -1 ); - } while( true ); - this.parameterTypes = (Class[])parameterTypes.toArray( - new Class[parameterTypes.size()] ); - } - } - catch( NoSuchElementException e ) { - err.jspError("jsp.error.tld.fn.invalid.signature", - tagName, this.methodName); - } - catch( ClassNotFoundException e ) { - err.jspError("jsp.error.tld.fn.invalid.signature.classnotfound", - e.getMessage(), tagName, this.methodName); - } - } - - public String getReturnType() { - return this.returnType; - } - - public String getMethodName() { - return this.methodName; - } - - public Class[] getParameterTypes() { - return this.parameterTypes; - } } public static String coerceToPrimitiveBoolean(String s, 1.22 +12 -3 jakarta-tomcat-jasper/jasper2/src/share/org/apache/jasper/compiler/PageInfo.java Index: PageInfo.java =================================================================== RCS file: /home/cvs/jakarta-tomcat-jasper/jasper2/src/share/org/apache/jasper/compiler/PageInfo.java,v retrieving revision 1.21 retrieving revision 1.22 diff -u -r1.21 -r1.22 --- PageInfo.java 19 Feb 2003 19:00:59 -0000 1.21 +++ PageInfo.java 26 Feb 2003 00:11:38 -0000 1.22 @@ -77,6 +77,7 @@ private BeanRepository beanRepository; private Hashtable tagLibraries; + private FunctionMapperImpl funcMap; private String language = "java"; private String xtends = Constants.JSP_SERVLET_BASE; @@ -373,5 +374,13 @@ public void setOmitXmlDecl(String omit) { omitXmlDecl = omit; + } + + public void setFunctionMapper(FunctionMapperImpl map) { + this.funcMap = map; + } + + public FunctionMapperImpl getFunctionMapper() { + return this.funcMap; } } 1.80 +4 -95 jakarta-tomcat-jasper/jasper2/src/share/org/apache/jasper/compiler/Validator.java Index: Validator.java =================================================================== RCS file: /home/cvs/jakarta-tomcat-jasper/jasper2/src/share/org/apache/jasper/compiler/Validator.java,v retrieving revision 1.79 retrieving revision 1.80 diff -u -r1.79 -r1.80 --- Validator.java 24 Feb 2003 18:09:37 -0000 1.79 +++ Validator.java 26 Feb 2003 00:11:38 -0000 1.80 @@ -448,8 +448,7 @@ this.err = compiler.getErrorDispatcher(); this.tagInfo = compiler.getCompilationContext().getTagInfo(); this.loader = compiler.getCompilationContext().getClassLoader(); - this.functionMapper = new ValidatorFunctionMapper( this.pageInfo, - this.err, this.loader ); + this.functionMapper = pageInfo.getFunctionMapper(); } public void visit(Node.JspRoot n) throws JasperException { @@ -1268,96 +1267,6 @@ if (errMsg != null) { errDisp.jspError(errMsg.toString()); } - } - - /** - * A Function Mapper to be used by the validator to help in parsing - * EL Expressions. - */ - private static class ValidatorFunctionMapper - implements FunctionMapper - { - private PageInfo pageInfo; - private ErrorDispatcher err; - private ClassLoader loader; - - /** - * HashMap of cached functions that we already looked up. - * Key = prefix, value = HashMap, where key = localName, - * value = Method. - */ - private HashMap cachedFunctions = new HashMap(); - - public ValidatorFunctionMapper( PageInfo pageInfo, - ErrorDispatcher err, ClassLoader loader ) - { - this.pageInfo = pageInfo; - this.err = err; - this.loader = loader; - } - - public Method resolveFunction( String prefix, String localName ) { - boolean cached = false; - Method result = null; - - // Look up entry in cache: - HashMap cachedMethods = (HashMap)this.cachedFunctions.get( prefix ); - if( cachedMethods != null ) { - if( cachedMethods.containsKey( localName ) ) { - result = (Method)cachedMethods.get( localName ); - cached = true; - } - } - - // If not cached, look it up: - if( !cached ) { - Hashtable taglibraries = pageInfo.getTagLibraries(); - TagLibraryInfo info = - (TagLibraryInfo)taglibraries.get( prefix ); - if( info != null ) { - FunctionInfo fnInfo = - (FunctionInfo)info.getFunction( localName ); - if( fnInfo != null ) { - String clazz = fnInfo.getFunctionClass(); - try { - JspUtil.FunctionSignature functionSignature = - new JspUtil.FunctionSignature( - fnInfo.getFunctionSignature(), - info.getShortName(), this.err, this.loader ); - Class c = Class.forName( clazz ); - result = c.getDeclaredMethod( - functionSignature.getMethodName(), - functionSignature.getParameterTypes() ); - } - catch( JasperException e ) { - // return null. - // XXX - If the EL API evolves to allow for - // an exception to be thrown, we should provide - // details here. - } - catch( ClassNotFoundException e ) { - // return null. - // XXX - See above comment regarding detailed - // error reporting. - } - catch( NoSuchMethodException e ) { - // return null. - // XXX - See above comment regarding detailed - // error reporting. - } - } - } - - // Store result in cache: - if( cachedMethods == null ) { - cachedMethods = new HashMap(); - this.cachedFunctions.put( prefix, cachedMethods ); - } - cachedMethods.put( localName, result ); - } - - return result; - } } } 1.1 jakarta-tomcat-jasper/jasper2/src/share/org/apache/jasper/compiler/FunctionMapperImpl.java Index: FunctionMapperImpl.java =================================================================== /* * $Header: /home/cvs/jakarta-tomcat-jasper/jasper2/src/share/org/apache/jasper/compiler/FunctionMapperImpl.java,v 1.1 2003/02/26 00:11:38 luehe Exp $ * $Revision: 1.1 $ * $Date: 2003/02/26 00:11:38 $ * * ==================================================================== * * 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.jasper.compiler; import java.lang.reflect.Method; import java.util.HashMap; import java.util.Hashtable; import java.util.ArrayList; import java.util.Iterator; import java.util.StringTokenizer; import java.util.NoSuchElementException; import java.util.Set; import javax.servlet.jsp.tagext.TagLibraryInfo; import javax.servlet.jsp.tagext.FunctionInfo; import javax.servlet.jsp.el.FunctionMapper; import org.apache.jasper.JasperException; class FunctionMapperImpl implements FunctionMapper { // Maps "prefix:name" to java.lang.Method objects private HashMap fnMap; // Maps "prefix:name" to FunctionSignature private HashMap fnSigMap; // Maps "prefix:name" to FunctionInfo private HashMap fnInfoMap; /* * Constructor */ FunctionMapperImpl(Compiler compiler) throws JasperException { this.fnMap = new java.util.HashMap(); this.fnSigMap = new java.util.HashMap(); this.fnInfoMap = new java.util.HashMap(); ErrorDispatcher err = compiler.getErrorDispatcher(); Hashtable taglibs = compiler.getPageInfo().getTagLibraries(); Iterator iter = taglibs.keySet().iterator(); ClassLoader loader = compiler.getCompilationContext().getClassLoader(); while (iter.hasNext()) { String prefix = (String) iter.next(); TagLibraryInfo tli = (TagLibraryInfo) taglibs.get(prefix); FunctionInfo[] fnInfos = tli.getFunctions(); for (int i = 0; fnInfos != null && i < fnInfos.length; i++) { FunctionSignature fnSig = new FunctionSignature(fnInfos[i].getFunctionSignature(), tli.getShortName(), err, loader); Method method = null; try { Class c = loader.loadClass(fnInfos[i].getFunctionClass()); method = c.getDeclaredMethod(fnSig.getMethodName(), fnSig.getParameterTypes()); } catch (Exception e) { err.jspError(e); } String key = prefix + ":" + fnInfos[i].getName(); this.fnMap.put(key, method); this.fnSigMap.put(key, fnSig); this.fnInfoMap.put(key, fnInfos[i]); } } } /** * Resolves the specified local name and prefix into a Java.lang.Method. * Returns null if the prefix and local name are not found. * * @param prefix the prefix of the function * @param localName the short name of the function * @return the result of the method mapping. Null means no entry found. */ public Method resolveFunction(String prefix, String localName) { return (Method) fnMap.get(prefix + ":" + localName); } /* */ String getMethodName(String fnQName) { String result = null; FunctionSignature fnSig = (FunctionSignature) fnSigMap.get(fnQName); if (fnSig != null) { result = fnSig.getMethodName(); } return result; } /* */ Class[] getParameterTypes(String fnQName) { Class[] result = null; FunctionSignature fnSig = (FunctionSignature) fnSigMap.get(fnQName); if (fnSig != null) { result = fnSig.getParameterTypes(); } return result; } /* */ String getFunctionClass(String fnQName) { String result = null; FunctionInfo fnInfo = (FunctionInfo) this.fnInfoMap.get(fnQName); if (fnInfo != null) { result = fnInfo.getFunctionClass(); } return result; } Set keySet() { return fnMap.keySet(); } boolean isEmpty() { return fnMap.isEmpty(); } /** * Parses and encapsulates a function signature, as would appear in * a TLD. */ private static class FunctionSignature { private String returnType; private String methodName; private Class[] parameterTypes; /** * Parses a function signature, as would appear in the TLD * * @param signature The signature to parse * @param tagName Name of tag, for error messages. * @throws JasperException If an error occurred while parsing the * signature. */ public FunctionSignature(String signature, String tagName, ErrorDispatcher err, ClassLoader loader) throws JasperException { try { // Parse function signature, assuming syntax: // <return-type> S <method-name> S? '(' // ( <arg-type> ( ',' <arg-type> )* )? ')' String ws = " \t\n\r"; StringTokenizer sigTokenizer = new StringTokenizer( signature, ws + "(),", true); // Return type: this.returnType = sigTokenizer.nextToken(); // Skip whitespace and read <method-name>: do { this.methodName = sigTokenizer.nextToken(); } while( ws.indexOf( this.methodName ) != -1 ); // Skip whitespace and read '(': String paren; do { paren = sigTokenizer.nextToken(); } while( ws.indexOf( paren ) != -1 ); if( !paren.equals( "(" ) ) { err.jspError("jsp.error.tld.fn.invalid.signature.parenexpected", tagName, this.methodName); } // ( <arg-type> S? ( ',' S? <arg-type> S? )* )? ')' // Skip whitespace and read <arg-type>: String argType; do { argType = sigTokenizer.nextToken(); } while( ws.indexOf( argType ) != -1 ); if( !argType.equals( ")" ) ) { ArrayList parameterTypes = new ArrayList(); do { if( ",(".indexOf( argType ) != -1 ) { err.jspError("jsp.error.tld.fn.invalid.signature", tagName, this.methodName); } parameterTypes.add(JspUtil.toClass(argType, loader)); String comma; do { comma = sigTokenizer.nextToken(); } while( ws.indexOf( comma ) != -1 ); if( comma.equals( ")" ) ) { break; } if( !comma.equals( "," ) ) { err.jspError("jsp.error.tld.fn.invalid.signature.commaexpected", tagName, this.methodName); } // <arg-type> do { argType = sigTokenizer.nextToken(); } while( ws.indexOf( argType ) != -1 ); } while( true ); this.parameterTypes = (Class[])parameterTypes.toArray( new Class[parameterTypes.size()] ); } } catch( NoSuchElementException e ) { err.jspError("jsp.error.tld.fn.invalid.signature", tagName, this.methodName); } catch( ClassNotFoundException e ) { err.jspError("jsp.error.tld.fn.invalid.signature.classnotfound", e.getMessage(), tagName, this.methodName); } } public String getReturnType() { return this.returnType; } public String getMethodName() { return this.methodName; } public Class[] getParameterTypes() { return this.parameterTypes; } } } 1.5 +11 -10 jakarta-tomcat-jasper/jasper2/src/share/org/apache/jasper/runtime/ProtectedFunctionMapper.java Index: ProtectedFunctionMapper.java =================================================================== RCS file: /home/cvs/jakarta-tomcat-jasper/jasper2/src/share/org/apache/jasper/runtime/ProtectedFunctionMapper.java,v retrieving revision 1.4 retrieving revision 1.5 diff -u -r1.4 -r1.5 --- ProtectedFunctionMapper.java 4 Feb 2003 23:38:46 -0000 1.4 +++ ProtectedFunctionMapper.java 26 Feb 2003 00:11:39 -0000 1.5 @@ -115,16 +115,15 @@ * Stores a mapping from the given EL function prefix and name to * the given Java method. * - * @param prefix The EL function prefix - * @param fnName The EL function name + * @param fnQName The EL function qualified name (including prefix) * @param c The class containing the Java method * @param methodName The name of the Java method * @param args The arguments of the Java method * @throws RuntimeException if no method with the given signature * could be found. */ - public void mapFunction( String prefix, String fnName, - final Class c, final String methodName, final Class[] args ) + public void mapFunction(String fnQName, final Class c, + final String methodName, final Class[] args ) { java.lang.reflect.Method method; if (System.getSecurityManager() != null){ @@ -137,18 +136,20 @@ }); } catch (PrivilegedActionException ex){ throw new RuntimeException( - "Invalid function mapping - no such method: " + ex.getException().getMessage()); + "Invalid function mapping - no such method: " + + ex.getException().getMessage()); } } else { try { method = c.getDeclaredMethod(methodName, args); } catch( NoSuchMethodException e ) { throw new RuntimeException( - "Invalid function mapping - no such method: " + e.getMessage()); + "Invalid function mapping - no such method: " + + e.getMessage()); } } - this.fnmap.put( prefix + ":" + fnName, method ); + this.fnmap.put(fnQName, method ); } /**
--------------------------------------------------------------------- To unsubscribe, e-mail: [EMAIL PROTECTED] For additional commands, e-mail: [EMAIL PROTECTED]