ASF Bugzilla – Attachment 29898 Details for
Bug 54499
Implementation of Extensible EL Interpreter
Home
|
New
|
Browse
|
Search
|
[?]
|
Reports
|
Help
|
New Account
|
Log In
Remember
[x]
|
Forgot Password
Login:
[x]
JasperELInterpreter implementation
JasperELInterpreter.java (text/plain), 8.37 KB, created by
Sheldon Shao
on 2013-01-29 08:26:38 UTC
(
hide
)
Description:
JasperELInterpreter implementation
Filename:
MIME Type:
Creator:
Sheldon Shao
Created:
2013-01-29 08:26:38 UTC
Size:
8.37 KB
patch
obsolete
>/* > * 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.jasper.interpreter; > >import java.io.StringReader; >import java.util.ArrayList; >import java.util.List; > >import org.apache.el.parser.AstDeferredExpression; >import org.apache.el.parser.AstDynamicExpression; >import org.apache.el.parser.AstLiteralExpression; >import org.apache.el.parser.ELParser; >import org.apache.el.parser.Node; >import org.apache.el.parser.ParseException; >import org.apache.jasper.JspCompilationContext; >import org.apache.jasper.compiler.ELInterpreter; >import org.apache.jasper.compiler.JspUtil; > >/** > * Simple ELInterpreter. It can transfer simple ELs to java code directly. > * EL is a big bottleneck of JSP. EL resolving takes much CPU expense. > * > * The performance is better when simple ELs were transfered to java code. > * > * However the code will by pass all ELResolvers. This interpreter is not a standard of JSP specification. > * When activate this ELInterpreter. User must know how it works. > * > * Here are the cases of Simple ELs, > * > * 1.Simple EL, only contains one part of expression, for example ${elemId}. This kind of EL will be generated as > * > * this.getJspContext().findAttribute("elemId") > * > * 2.EL with two parts of expression and type of first part is specified by attribute in Tag File. > * For example, ${model.location} . "model" is specified on the top of tag file, > * > * <%@ attribute name="model" required="true" type="org.apache.jasper.model.results.ItemModel" %>. > * > * It is generated as (getModel() != null ? getModel().getLocation() : null) > * > * 3.EL with logic or arithmetic and the value part can be generated. > * For example: ${(intlExpansion eq 'true' && not empty model.location) || sortType==7} > * > * It is generated as > * (org.apache.jasper.runtime.ELRuntimeUtil.equals(getIntlExpansion(), "true")&&(!org.apache.jasper.runtime.ELRuntimeUtil.isEmpty((getModel() != null ? getModel().getLocation() : null)))) > * > * How to apply this ELInterpreter? > * > * It is based on BUG 54239. > * > * @author Sheldon Shao <xshao@ebay.com> > */ >public class JasperELInterpreter implements ELInterpreter { > > public static enum ELFormat { > SINGLE, > > COUPLE, > > MULTIPLE, > > COMPLEX > }; > > public String interpreterCall(JspCompilationContext context, boolean isTagFile, String expression, > Class<?> expectedType, String fnmapvar, boolean xmlEscape) { > > if (fnmapvar == null) { > List<String> nodes = new ArrayList<String>(2); > ELFormat format = split(expression, nodes); > if (format == ELFormat.SINGLE) { > return ELCodegen.genSingleNode(context, isTagFile, nodes.get(0), expectedType, xmlEscape, true); > } else if (format == ELFormat.COUPLE && isTagFile) { > String firstNode = nodes.get(0); > String secondNode = nodes.get(1); > return ELCodegen.genCoupleNodes(context, isTagFile, firstNode, secondNode, expression, expectedType, xmlEscape, true); > } > > String extension = forExtend(format, context, isTagFile, expression, expectedType, fnmapvar, xmlEscape, nodes); > if (extension != null) { > return extension; > } > else { > Node node = parseAsNode(expression); > if (node != null) { > try { > return generate(context, isTagFile, expectedType, node, xmlEscape); > } > catch(IllegalStateException ise) { > } > } > } > } > > return JspUtil.interpreterCall(isTagFile, expression, expectedType, > fnmapvar, xmlEscape); > } > > protected String forExtend(ELFormat format, JspCompilationContext context, boolean isTagFile, String expression, > Class<?> expectedType, String fnmapvar, boolean xmlEscape, List<String> nodes) { > return null; > } > > private String generate(JspCompilationContext context, boolean isTagFile, Class<?> expectedType, Node node, boolean xmlEscape) { > String code = ELCodegen.generate(context, isTagFile, expectedType, node, true); > if (xmlEscape && String.class == expectedType) { > return "org.apache.jasper.runtime.ELRuntimeUtil.xmlEscape(" + code + ")"; > } > return code; > } > > private Node parseAsNode(String expression) { > ELParser parser = new ELParser(new StringReader(expression)); > Node n; > try { > n = parser.CompositeExpression(); > } catch (ParseException e) { > return null; > } > > // validate composite expression > int numChildren = n.jjtGetNumChildren(); > if (numChildren == 1) { > n = n.jjtGetChild(0); > } else { > Class<?> type = null; > Node child = null; > 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())) { > return null; > } > } > } > } > > if (n instanceof AstDeferredExpression > || n instanceof AstDynamicExpression) { > n = n.jjtGetChild(0); > } > > return n; > } > > > private static int[] trim(String text, int start, int end) { > char ch; > int i = start; > for (; i < end; i++) { > ch = text.charAt(i); > if (ch == ' ' || ch == '\t') { > continue; > } > else { > break; > } > } > start = i; > for (i = end -1; i > start; i--) { > ch = text.charAt(i); > if (ch == ' ' || ch == '\t') { > continue; > } > else { > break; > } > } > end = i + 1; > return new int[] { start, end }; > } > > private ELFormat split(String text, List<String> nodes) { > char ch = text.charAt(0); > int len = text.length(); > if (ch == '$' || ch == '#') { > int end = len - 1; > if (text.charAt(1) == '{' && text.charAt(end) == '}') { > int[] trimed = trim(text, 2, end); > ch = text.charAt(trimed[0]); > if ((ch >= 'A' && ch <= 'Z') || (ch >= 'a' && ch <= 'z')) { > int nodeCount = 1; > int pos = trimed[0]; > end = trimed[1]; > for (int i = pos+1; i < end; i++) { > ch = text.charAt(i); > if ((ch >= 'A' && ch <= 'Z') > || (ch >= 'a' && ch <= 'z') > || (ch >= '0' && ch <= '9') || ch == '_') { > continue; > } else if (ch == '.') { > String el = text.substring(pos, i); > nodes.add(el); > pos = i + 1; > nodeCount++; > } else { > return ELFormat.COMPLEX; > } > } > if (pos < end) { > String el = text.substring(pos, end); > nodes.add(el); > } > return nodeCount == 1 ? ELFormat.SINGLE :(nodeCount == 2 ? ELFormat.COUPLE : ELFormat.MULTIPLE); > } > } > } > return ELFormat.COMPLEX; > } >}
You cannot view the attachment while viewing its details because your browser does not support IFRAMEs.
View the attachment on a separate page
.
View Attachment As Raw
Actions:
View
Attachments on
bug 54499
: 29898 |
29899
|
29900
|
29901
|
29902
|
29907