ttomcat-1778514358873.zip-extract/apache-tomcat-11.0.18-src/java/org/apache/el/lang/ExpressionBuilder.java

Path
ttomcat-1778514358873.zip-extract/apache-tomcat-11.0.18-src/java/org/apache/el/lang/ExpressionBuilder.java
Status
scanned
Type
file
Name
ExpressionBuilder.java
Extension
.java
Programming language
Java
Mime type
text/plain
File type
ASCII text, with CRLF line terminators
Tag

      
    
Rootfs path

      
    
Size
11139 (10.9 KB)
MD5
b818ca6d9e8443d95f1beb39ef0d4d86
SHA1
6aa0730c7b1bcc1218f0846e7e237150be363ef3
SHA256
b28d0314346058670ffea868f500e7547cd9f30e06bc946bbca24abe9d255c12
SHA512

      
    
SHA1_git
17a03a6834051a1a9e28d18870ec3fcf150d527b
Is binary

      
    
Is text
True
Is archive

      
    
Is media

      
    
Is legal

      
    
Is manifest

      
    
Is readme

      
    
Is top level

      
    
Is key file

      
    
ExpressionBuilder.java | 10.9 KB |

/* * Licensed to the Apache Software Foundation (ASF) under one or more * contributor license agreements. See the NOTICE file distributed with * this work for additional information regarding copyright ownership. * The ASF licenses this file to You under the Apache License, Version 2.0 * (the "License"); you may not use this file except in compliance with * the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package org.apache.el.lang; import java.io.StringReader; import java.lang.reflect.Method; import jakarta.el.ELContext; import jakarta.el.ELException; import jakarta.el.FunctionMapper; import jakarta.el.MethodExpression; import jakarta.el.ValueExpression; import jakarta.el.VariableMapper; import org.apache.el.MethodExpressionImpl; import org.apache.el.MethodExpressionLiteral; import org.apache.el.ValueExpressionImpl; import org.apache.el.parser.AstDeferredExpression; import org.apache.el.parser.AstDynamicExpression; import org.apache.el.parser.AstFunction; import org.apache.el.parser.AstIdentifier; import org.apache.el.parser.AstLiteralExpression; import org.apache.el.parser.AstValue; import org.apache.el.parser.ELParser; import org.apache.el.parser.Node; import org.apache.el.parser.NodeVisitor; import org.apache.el.util.ConcurrentCache; import org.apache.el.util.ExceptionUtils; import org.apache.el.util.MessageFactory; public final class ExpressionBuilder implements NodeVisitor { private static final SynchronizedStack<ELParser> parserCache = new SynchronizedStack<>(); private static final int CACHE_SIZE; private static final String CACHE_SIZE_PROP = "org.apache.el.ExpressionBuilder.CACHE_SIZE"; static { String cacheSizeStr = System.getProperty(CACHE_SIZE_PROP, "5000"); CACHE_SIZE = Integer.parseInt(cacheSizeStr); } private static final ConcurrentCache<String,Node> expressionCache = new ConcurrentCache<>(CACHE_SIZE); private FunctionMapper fnMapper; private VariableMapper varMapper; private final String expression; public ExpressionBuilder(String expression, ELContext ctx) throws ELException { this.expression = expression; FunctionMapper ctxFn = ctx.getFunctionMapper(); VariableMapper ctxVar = ctx.getVariableMapper(); if (ctxFn != null) { this.fnMapper = new FunctionMapperFactory(ctxFn); } if (ctxVar != null) { this.varMapper = new VariableMapperFactory(ctxVar); } } public static Node createNode(String expr) throws ELException { return createNodeInternal(expr); } private static Node createNodeInternal(String expr) throws ELException { if (expr == null) { throw new ELException(MessageFactory.get("error.null")); } Node n = expressionCache.get(expr); if (n == null) { ELParser parser = parserCache.pop(); try { if (parser == null) { parser = new ELParser(new StringReader(expr)); } else { parser.ReInit(new StringReader(expr)); } n = parser.CompositeExpression(); // validate composite expression int numChildren = n.jjtGetNumChildren(); if (numChildren == 1) { n = n.jjtGetChild(0); } else { Class<?> type = null; Node child; for (int i = 0; i < numChildren; i++) { child = n.jjtGetChild(i); if (child instanceof AstLiteralExpression) { continue; } if (type == null) { type = child.getClass(); } else { if (!type.equals(child.getClass())) { throw new ELException(MessageFactory.get("error.mixed", expr)); } } } } if (n instanceof AstDeferredExpression || n instanceof AstDynamicExpression) { n = n.jjtGetChild(0); } expressionCache.put(expr, n); } catch (Throwable t) { ExceptionUtils.handleThrowable(t); throw new ELException(MessageFactory.get("error.parseFail", expr), t); } finally { if (parser != null) { parserCache.push(parser); } } } return n; } private void prepare(Node node) throws ELException { try { node.accept(this); } catch (Exception e) { if (e instanceof ELException) { throw (ELException) e; } else { throw (new ELException(e)); } } if (this.fnMapper instanceof FunctionMapperFactory) { this.fnMapper = ((FunctionMapperFactory) this.fnMapper).create(); } if (this.varMapper instanceof VariableMapperFactory) { this.varMapper = ((VariableMapperFactory) this.varMapper).create(); } } private Node build() throws ELException { Node n = createNodeInternal(this.expression); this.prepare(n); if (n instanceof AstDeferredExpression || n instanceof AstDynamicExpression) { n = n.jjtGetChild(0); } return n; } @Override public void visit(Node node) throws ELException { if (node instanceof AstFunction funcNode) { Method m = null; if (this.fnMapper != null) { m = fnMapper.resolveFunction(funcNode.getPrefix(), funcNode.getLocalName()); } // References to variables that refer to lambda expressions will be // parsed as functions. This is handled at runtime but at this point // need to treat it as a variable rather than a function. if (m == null && this.varMapper != null && funcNode.getPrefix().isEmpty()) { this.varMapper.resolveVariable(funcNode.getLocalName()); return; } if (this.fnMapper == null) { throw new ELException(MessageFactory.get("error.fnMapper.null")); } if (m == null) { throw new ELException(MessageFactory.get("error.fnMapper.method", funcNode.getOutputName())); } int methodParameterCount = m.getParameterTypes().length; // AstFunction->MethodParameters->Parameters() int inputParameterCount = node.jjtGetChild(0).jjtGetNumChildren(); if (m.isVarArgs() && inputParameterCount < methodParameterCount - 1 || !m.isVarArgs() && inputParameterCount != methodParameterCount) { throw new ELException(MessageFactory.get("error.fnMapper.paramcount", funcNode.getOutputName(), "" + methodParameterCount, "" + node.jjtGetChild(0).jjtGetNumChildren())); } } else if (node instanceof AstIdentifier && this.varMapper != null) { String variable = node.getImage(); // simply capture it this.varMapper.resolveVariable(variable); } } public ValueExpression createValueExpression(Class<?> expectedType) throws ELException { Node n = this.build(); return new ValueExpressionImpl(this.expression, n, this.fnMapper, this.varMapper, expectedType); } public MethodExpression createMethodExpression(Class<?> expectedReturnType, Class<?>[] expectedParamTypes) throws ELException { Node n = this.build(); if (!n.isParametersProvided() && expectedParamTypes == null) { throw new NullPointerException(MessageFactory.get("error.method.nullParms")); } if (n instanceof AstValue || n instanceof AstIdentifier) { return new MethodExpressionImpl(expression, n, this.fnMapper, this.varMapper, expectedReturnType, expectedParamTypes); } else if (n instanceof AstLiteralExpression) { return new MethodExpressionLiteral(expression, expectedReturnType, expectedParamTypes); } else { throw new ELException(MessageFactory.get("error.invalidMethodExpression", expression)); } } /* * Copied from org.apache.tomcat.util.collections.SynchronizedStack since we don't want the EL implementation to * depend on the JAR where that class resides. */ private static class SynchronizedStack<T> { public static final int DEFAULT_SIZE = 128; private static final int DEFAULT_LIMIT = -1; private int size; private final int limit; /* * Points to the next available object in the stack */ private int index = -1; private Object[] stack; SynchronizedStack() { this(DEFAULT_SIZE, DEFAULT_LIMIT); } SynchronizedStack(int size, int limit) { this.size = size; this.limit = limit; stack = new Object[size]; } public synchronized boolean push(T obj) { index++; if (index == size) { if (limit == -1 || size < limit) { expand(); } else { index--; return false; } } stack[index] = obj; return true; } @SuppressWarnings("unchecked") public synchronized T pop() { if (index == -1) { return null; } T result = (T) stack[index]; stack[index--] = null; return result; } private void expand() { int newSize = size * 2; if (limit != -1 && newSize > limit) { newSize = limit; } Object[] newStack = new Object[newSize]; System.arraycopy(stack, 0, newStack, 0, size); // This is the only point where garbage is created by throwing away the // old array. Note it is only the array, not the contents, that becomes // garbage. stack = newStack; size = newSize; } } }
Detected license expression
apache-2.0
Detected license expression (SPDX)
Apache-2.0
Percentage of license text
11.88
Copyrights

      
    
Holders

      
    
Authors

      
    
License detections License expression License expression SPDX
apache_2_0-4bde3f57-78aa-4201-96bf-531cba09e7de apache-2.0 Apache-2.0
URL Start line End line
http://www.apache.org/licenses/LICENSE-2.0 9 9