1 17 18 package org.apache.el.lang; 19 20 import java.io.StringReader ; 21 import java.lang.ref.SoftReference ; 22 import java.lang.reflect.Method ; 23 import java.util.Map ; 24 import java.util.WeakHashMap ; 25 import java.util.concurrent.ConcurrentHashMap ; 26 import java.util.concurrent.ConcurrentMap ; 27 28 import javax.el.ELContext; 29 import javax.el.ELException; 30 import javax.el.FunctionMapper; 31 import javax.el.MethodExpression; 32 import javax.el.ValueExpression; 33 import javax.el.VariableMapper; 34 35 import org.apache.el.MethodExpressionImpl; 36 import org.apache.el.MethodExpressionLiteral; 37 import org.apache.el.ValueExpressionImpl; 38 import org.apache.el.parser.AstCompositeExpression; 39 import org.apache.el.parser.AstDeferredExpression; 40 import org.apache.el.parser.AstDynamicExpression; 41 import org.apache.el.parser.AstFunction; 42 import org.apache.el.parser.AstIdentifier; 43 import org.apache.el.parser.AstLiteralExpression; 44 import org.apache.el.parser.AstValue; 45 import org.apache.el.parser.ELParser; 46 import org.apache.el.parser.Node; 47 import org.apache.el.parser.NodeVisitor; 48 import org.apache.el.parser.ParseException; 49 import org.apache.el.util.ConcurrentCache; 50 import org.apache.el.util.MessageFactory; 51 52 56 public final class ExpressionBuilder implements NodeVisitor { 57 58 private static final ConcurrentCache cache = new ConcurrentCache(5000); 59 60 private FunctionMapper fnMapper; 61 62 private VariableMapper varMapper; 63 64 private String expression; 65 66 69 public ExpressionBuilder(String expression, ELContext ctx) 70 throws ELException { 71 this.expression = expression; 72 73 FunctionMapper ctxFn = ctx.getFunctionMapper(); 74 VariableMapper ctxVar = ctx.getVariableMapper(); 75 76 if (ctxFn != null) { 77 this.fnMapper = new FunctionMapperFactory(ctxFn); 78 } 79 if (ctxVar != null) { 80 this.varMapper = new VariableMapperFactory(ctxVar); 81 } 82 } 83 84 public final static Node createNode(String expr) throws ELException { 85 Node n = createNodeInternal(expr); 86 return n; 87 } 88 89 private final static Node createNodeInternal(String expr) 90 throws ELException { 91 if (expr == null) { 92 throw new ELException(MessageFactory.get("error.null")); 93 } 94 95 Node n = (Node) cache.get(expr); 96 if (n == null) { 97 try { 98 n = (new ELParser(new StringReader (expr))) 99 .CompositeExpression(); 100 101 if (n instanceof AstCompositeExpression) { 103 int numChildren = n.jjtGetNumChildren(); 104 if (numChildren == 1) { 105 n = n.jjtGetChild(0); 106 } else { 107 Class type = null; 108 Node child = null; 109 for (int i = 0; i < numChildren; i++) { 110 child = n.jjtGetChild(i); 111 if (child instanceof AstLiteralExpression) 112 continue; 113 if (type == null) 114 type = child.getClass(); 115 else { 116 if (!type.equals(child.getClass())) { 117 throw new ELException(MessageFactory.get( 118 "error.mixed", expr)); 119 } 120 } 121 } 122 } 123 } 124 if (n instanceof AstDeferredExpression 125 || n instanceof AstDynamicExpression) { 126 n = n.jjtGetChild(0); 127 } 128 cache.put(expr, n); 129 } catch (ParseException pe) { 130 throw new ELException("Error Parsing: " + expr, pe); 131 } 132 } 133 return n; 134 } 135 136 private void prepare(Node node) throws ELException { 137 try { 138 node.accept(this); 139 } catch (Exception e) { 140 throw (ELException) e; 141 } 142 if (this.fnMapper instanceof FunctionMapperFactory) { 143 this.fnMapper = ((FunctionMapperFactory) this.fnMapper).create(); 144 } 145 if (this.varMapper instanceof VariableMapperFactory) { 146 this.varMapper = ((VariableMapperFactory) this.varMapper).create(); 147 } 148 } 149 150 private Node build() throws ELException { 151 Node n = createNodeInternal(this.expression); 152 this.prepare(n); 153 if (n instanceof AstDeferredExpression 154 || n instanceof AstDynamicExpression) { 155 n = n.jjtGetChild(0); 156 } 157 return n; 158 } 159 160 165 public void visit(Node node) throws ELException { 166 if (node instanceof AstFunction) { 167 168 AstFunction funcNode = (AstFunction) node; 169 170 if (this.fnMapper == null) { 171 throw new ELException(MessageFactory.get("error.fnMapper.null")); 172 } 173 Method m = fnMapper.resolveFunction(funcNode.getPrefix(), funcNode 174 .getLocalName()); 175 if (m == null) { 176 throw new ELException(MessageFactory.get( 177 "error.fnMapper.method", funcNode.getOutputName())); 178 } 179 int pcnt = m.getParameterTypes().length; 180 if (node.jjtGetNumChildren() != pcnt) { 181 throw new ELException(MessageFactory.get( 182 "error.fnMapper.paramcount", funcNode.getOutputName(), 183 "" + pcnt, "" + node.jjtGetNumChildren())); 184 } 185 } else if (node instanceof AstIdentifier && this.varMapper != null) { 186 String variable = ((AstIdentifier) node).getImage(); 187 188 this.varMapper.resolveVariable(variable); 190 } 191 } 192 193 public ValueExpression createValueExpression(Class expectedType) 194 throws ELException { 195 Node n = this.build(); 196 return new ValueExpressionImpl(this.expression, n, this.fnMapper, 197 this.varMapper, expectedType); 198 } 199 200 public MethodExpression createMethodExpression(Class expectedReturnType, 201 Class [] expectedParamTypes) throws ELException { 202 Node n = this.build(); 203 if (n instanceof AstValue || n instanceof AstIdentifier) { 204 return new MethodExpressionImpl(expression, n, this.fnMapper, 205 this.varMapper, expectedReturnType, expectedParamTypes); 206 } else if (n instanceof AstLiteralExpression) { 207 return new MethodExpressionLiteral(expression, expectedReturnType, 208 expectedParamTypes); 209 } else { 210 throw new ELException("Not a Valid Method Expression: " 211 + expression); 212 } 213 } 214 } 215 | Popular Tags |