kinman      2003/03/24 16:07:12

  Modified:    jasper2/src/share/org/apache/jasper/compiler
                        ELFunctionMapper.java ELNode.java Validator.java
               jasper2/src/share/org/apache/jasper/resources
                        messages.properties
  Log:
  - Implement a FunctionMapper to be used in parseExpression, for checking
    expression syntax.  Refactor some codes dealing with signature parsing,
    so that it can be used in both Validator and ELFunctionMapper.
  
  Revision  Changes    Path
  1.3       +10 -52    
jakarta-tomcat-jasper/jasper2/src/share/org/apache/jasper/compiler/ELFunctionMapper.java
  
  Index: ELFunctionMapper.java
  ===================================================================
  RCS file: 
/home/cvs/jakarta-tomcat-jasper/jasper2/src/share/org/apache/jasper/compiler/ELFunctionMapper.java,v
  retrieving revision 1.2
  retrieving revision 1.3
  diff -u -r1.2 -r1.3
  --- ELFunctionMapper.java     21 Mar 2003 00:43:57 -0000      1.2
  +++ ELFunctionMapper.java     25 Mar 2003 00:07:10 -0000      1.3
  @@ -185,64 +185,22 @@
                String key = f.getPrefix()+ ":" + f.getName();
                ds.append("  " + decName + ".mapFunction(\"" + key + "\", " +
                        funcInfo.getFunctionClass() + ".class, " +
  -                     '\"' + getMethod(f) + "\", " +
  -                     "new Class[] {" + getParameters(f) + "}" + 
  -                     ");\n");
  +                     '\"' + f.getMethodName() + "\", " +
  +                     "new Class[] {");
  +             String params[] = f.getParameters();
  +             for (int k = 0; k < params.length; k++) {
  +                 if (k != 0) {
  +                     ds.append(", ");
  +                 }
  +                 ds.append(params[k] + ".class");
  +             }
  +             ds.append("});\n");
            }
            el.setMapName(decName);
        }
   
        private String getMapName() {
            return "_jspx_fnmap_" + currFunc++;
  -     }
  -
  -     private String getMethod(ELNode.Function func)
  -             throws JasperException {
  -         FunctionInfo funcInfo = func.getFunctionInfo();
  -         String signature = funcInfo.getFunctionSignature();
  -         
  -         int start = signature.indexOf(' ');
  -         if (start < 0) {
  -             err.jspError("jsp.error.tld.fn.invalid.signature",
  -                     func.getPrefix(), func.getName());
  -         }
  -         int end = signature.indexOf('(');
  -         if (end < 0) {
  -             err.jspError("jsp.error.tld.fn.invalid.signature.parenexpected",
  -                     func.getPrefix(), func.getName());
  -         }
  -         return signature.substring(start+1, end).trim();
  -     }
  -
  -     private String getParameters(ELNode.Function func) 
  -             throws JasperException {
  -         FunctionInfo funcInfo = func.getFunctionInfo();
  -         StringBuffer buf = new StringBuffer();
  -         String signature = funcInfo.getFunctionSignature();
  -         // Signature is of the form
  -         // <return-type> S <method-name S? '('
  -         // < <arg-type> ( ',' <arg-type> )* )? ')'
  -         int start = signature.indexOf('(') + 1;
  -         boolean lastArg = false;
  -         while (true) {
  -             int p = signature.indexOf(',', start);
  -             if (p < 0) {
  -                 p = signature.indexOf(')', start);
  -                 if (p < 0) {
  -                     err.jspError("jsp.error.tld.fn.invalid.signature",
  -                             func.getPrefix(), func.getName());
  -                 }
  -                 lastArg = true;
  -             }
  -             String arg = signature.substring(start, p).trim();
  -             buf.append(arg + ".class");
  -             if (lastArg) {
  -                 break;
  -             }
  -             buf.append(',');
  -             start = p+1;
  -         }
  -         return buf.toString();
        }
       }
   }
  
  
  
  1.2       +21 -3     
jakarta-tomcat-jasper/jasper2/src/share/org/apache/jasper/compiler/ELNode.java
  
  Index: ELNode.java
  ===================================================================
  RCS file: 
/home/cvs/jakarta-tomcat-jasper/jasper2/src/share/org/apache/jasper/compiler/ELNode.java,v
  retrieving revision 1.1
  retrieving revision 1.2
  diff -u -r1.1 -r1.2
  --- ELNode.java       19 Mar 2003 20:51:34 -0000      1.1
  +++ ELNode.java       25 Mar 2003 00:07:10 -0000      1.2
  @@ -143,9 +143,11 @@
        */
       public static class Function extends ELNode {
   
  -     String prefix;
  -     String name;
  -     FunctionInfo functionInfo;
  +     private String prefix;
  +     private String name;
  +     private FunctionInfo functionInfo;
  +     private String methodName;
  +     private String[] parameters;
   
        Function(String prefix, String name) {
            this.prefix = prefix;
  @@ -170,6 +172,22 @@
   
        public FunctionInfo getFunctionInfo() {
            return functionInfo;
  +     }
  +
  +     public void setMethodName(String methodName) {
  +         this.methodName = methodName;
  +     }
  +
  +     public String getMethodName() {
  +         return methodName;
  +     }
  +
  +     public void setParameters(String[] parameters) {
  +         this.parameters = parameters;
  +     }
  +
  +     public String[] getParameters() {
  +         return parameters;
        }
       }
   
  
  
  
  1.96      +133 -8    
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.95
  retrieving revision 1.96
  diff -u -r1.95 -r1.96
  --- Validator.java    24 Mar 2003 23:50:40 -0000      1.95
  +++ Validator.java    25 Mar 2003 00:07:10 -0000      1.96
  @@ -62,6 +62,7 @@
   
   import java.lang.reflect.Method;
   
  +import java.util.ArrayList;
   import java.util.Hashtable;
   import java.util.HashMap;
   import java.util.Enumeration;
  @@ -666,16 +667,16 @@
            // a null FunctionMapper is passed.
               if ( !pageInfo.isELIgnored() ) {
                String expressions = "${" + new String(n.getText()) + "}";
  +             ELNode.Nodes el = ELParser.parse(expressions);
  +             validateFunctions(el, n);
                   JspUtil.validateExpressions(
                       n.getStart(),
                    expressions,
                       java.lang.String.class, // XXX - Should template text 
                                               // always evaluate to String?
  -                    null,
  +                    getFunctionMapper(el),
                       null,
                       err);
  -             ELNode.Nodes el = ELParser.parse(expressions);
  -             validateFunctions(el, n);
                n.setEL(el);
               }
           }
  @@ -1096,15 +1097,15 @@
                       // expression(s)
                       ELNode.Nodes el = ELParser.parse(value);
                       if (el.containsEL() && !pageInfo.isELIgnored()) {
  +                     validateFunctions(el, n);
                           JspUtil.validateExpressions(
                               n.getStart(),
                               value, 
                               expectedType, 
  -                            null,
  +                            getFunctionMapper(el),
                               defaultPrefix,
                               this.err);
   
  -                     validateFunctions(el, n);
                           
                           result = new Node.JspAttribute(qName, uri, localName,
                                                       value, false, el,
  @@ -1249,10 +1250,134 @@
                    }
                    // Skip TLD function uniqueness check.  Done by Schema ?
                    func.setFunctionInfo(funcInfo);
  +                 processSignature(func);
                }
            }
   
            el.visit(new FVVisitor(n));
  +     }
  +
  +     private void processSignature(ELNode.Function func)
  +             throws JasperException {
  +         func.setMethodName(getMethod(func));
  +         func.setParameters(getParameters(func));
  +     }
  +
  +     /**
  +      * Get the method name from the signature.
  +      */
  +     private String getMethod(ELNode.Function func)
  +             throws JasperException {
  +         FunctionInfo funcInfo = func.getFunctionInfo();
  +         String signature = funcInfo.getFunctionSignature();
  +         
  +         int start = signature.indexOf(' ');
  +         if (start < 0) {
  +             err.jspError("jsp.error.tld.fn.invalid.signature",
  +                     func.getPrefix(), func.getName());
  +         }
  +         int end = signature.indexOf('(');
  +         if (end < 0) {
  +             err.jspError("jsp.error.tld.fn.invalid.signature.parenexpected",
  +                     func.getPrefix(), func.getName());
  +         }
  +         return signature.substring(start+1, end).trim();
  +     }
  +
  +     /**
  +      * Get the parameters types from the function signature.
  +      * @return An array of parameter class names
  +      */
  +     private String[] getParameters(ELNode.Function func) 
  +             throws JasperException {
  +         FunctionInfo funcInfo = func.getFunctionInfo();
  +         String signature = funcInfo.getFunctionSignature();
  +         ArrayList params = new ArrayList();
  +         // Signature is of the form
  +         // <return-type> S <method-name S? '('
  +         // < <arg-type> ( ',' <arg-type> )* )? ')'
  +         int start = signature.indexOf('(') + 1;
  +         boolean lastArg = false;
  +         while (true) {
  +             int p = signature.indexOf(',', start);
  +             if (p < 0) {
  +                 p = signature.indexOf(')', start);
  +                 if (p < 0) {
  +                     err.jspError("jsp.error.tld.fn.invalid.signature",
  +                             func.getPrefix(), func.getName());
  +                 }
  +                 lastArg = true;
  +             }
  +             params.add(signature.substring(start, p).trim());
  +             if (lastArg) {
  +                 break;
  +             }
  +             start = p+1;
  +         }
  +         return (String[]) params.toArray(new String[params.size()]);
  +     }
  +
  +     private FunctionMapper getFunctionMapper(ELNode.Nodes el)
  +             throws JasperException {
  +
  +         class ValidateFunctionMapper implements FunctionMapper {
  +
  +             private HashMap fnmap = new java.util.HashMap();
  +             public void mapFunction(String fnQName, Method method) {
  +                 fnmap.put(fnQName, method);
  +             }
  +
  +             public Method resolveFunction(String prefix, String localName) {
  +                 return (Method) this.fnmap.get(prefix + ":" + localName);
  +             }
  +         }
  +
  +         class MapperELVisitor extends ELNode.Visitor {
  +             ValidateFunctionMapper fmapper;
  +
  +             MapperELVisitor(ValidateFunctionMapper fmapper) {
  +                 this.fmapper = fmapper;
  +             }
  +
  +             public void visit(ELNode.Function n) throws JasperException {
  +
  +                 Class c = null;
  +                 Method method = null;
  +                 try {
  +                     c = loader.loadClass(
  +                             n.getFunctionInfo().getFunctionClass());
  +                 } catch (ClassNotFoundException e) {
  +                     err.jspError("jsp.error.function.classnotfound",
  +                             n.getFunctionInfo().getFunctionClass(),
  +                             n.getPrefix() + ':' + n.getName(),
  +                             e.getMessage());
  +                 }
  +                 String paramTypes[] = n.getParameters();
  +                 int size = paramTypes.length;
  +                 Class params[] = new Class[size];
  +                 int i = 0;
  +                 try {
  +                     for (i = 0; i < size; i++) {
  +                         params[i] = JspUtil.toClass(paramTypes[i], loader);
  +                     }
  +                     method = c.getDeclaredMethod(n.getMethodName(), params);
  +                 } catch (ClassNotFoundException e) {
  +                     err.jspError("jsp.error.signature.classnotfound",
  +                             paramTypes[i],
  +                             n.getPrefix() + ':' + n.getName(),
  +                             e.getMessage());
  +                 } catch (NoSuchMethodException e ) {
  +                     err.jspError("jsp.error.noMethod", n.getName(),
  +                             n.getMethodName(), c.getName());
  +                 }
  +                 fmapper.mapFunction(n.getPrefix() + ':' + n.getName(),
  +                                     method);
  +             }
  +         }
  +
  +         ValidateFunctionMapper fmapper = new ValidateFunctionMapper();
  +         el.visit(new MapperELVisitor(fmapper));
  +         return fmapper;
        }
       } // End of ValidateVisitor
   
  
  
  
  1.108     +2 -1      
jakarta-tomcat-jasper/jasper2/src/share/org/apache/jasper/resources/messages.properties
  
  Index: messages.properties
  ===================================================================
  RCS file: 
/home/cvs/jakarta-tomcat-jasper/jasper2/src/share/org/apache/jasper/resources/messages.properties,v
  retrieving revision 1.107
  retrieving revision 1.108
  diff -u -r1.107 -r1.108
  --- messages.properties       24 Mar 2003 23:50:41 -0000      1.107
  +++ messages.properties       25 Mar 2003 00:07:12 -0000      1.108
  @@ -375,3 +375,4 @@
   jsp.error.jsproot.version.invalid=Invalid version number: \"{0}\", must be \"1.2\" 
or \"2.0\"
   jsp.error.noFunctionPrefix=The function {0} must be used with a prefix when a 
default namespace is not specified
   jsp.error.noFunction=The function {0} cannot be located with the specified prefix
  +jsp.error.noFunctionMethod=The method {0} for the function {1} is not defined in 
the class {2}
  
  
  

---------------------------------------------------------------------
To unsubscribe, e-mail: [EMAIL PROTECTED]
For additional commands, e-mail: [EMAIL PROTECTED]

Reply via email to