com.caucho.jsp.java.JspNode Maven / Gradle / Ivy
Go to download
Show more of this group Show more artifacts with this name
Show all versions of resin Show documentation
Show all versions of resin Show documentation
Resin Java Application Server
/*
* Copyright (c) 1998-2018 Caucho Technology -- all rights reserved
*
* This file is part of Resin(R) Open Source
*
* Each copy or derived work must preserve the copyright notice and this
* notice unmodified.
*
* Resin Open Source is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2 of the License, or
* (at your option) any later version.
*
* Resin Open Source is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE, or any warranty
* of NON-INFRINGEMENT. See the GNU General Public License for more
* details.
*
* You should have received a copy of the GNU General Public License
* along with Resin Open Source; if not, write to the
*
* Free Software Foundation, Inc.
* 59 Temple Place, Suite 330
* Boston, MA 02111-1307 USA
*
* @author Scott Ferguson
*/
package com.caucho.jsp.java;
import com.caucho.el.Expr;
import com.caucho.jsp.JspLineParseException;
import com.caucho.jsp.JspParseException;
import com.caucho.jsp.JspParser;
import com.caucho.jsp.Namespace;
import com.caucho.jsp.ParseState;
import com.caucho.jsp.TagInstance;
import com.caucho.util.CharBuffer;
import com.caucho.util.CompileException;
import com.caucho.util.L10N;
import com.caucho.util.LineCompileException;
import com.caucho.vfs.Path;
import com.caucho.vfs.WriteStream;
import com.caucho.xml.QName;
import com.caucho.xml.XmlChar;
import com.caucho.xpath.NamespaceContext;
import com.caucho.xpath.XPath;
import javax.el.MethodExpression;
import javax.el.ValueExpression;
import javax.servlet.jsp.tagext.JspFragment;
import javax.servlet.jsp.tagext.TagAttributeInfo;
import java.beans.PropertyEditor;
import java.beans.PropertyEditorManager;
import java.io.IOException;
import java.lang.reflect.Method;
import java.math.BigDecimal;
import java.math.BigInteger;
import java.util.ArrayList;
import java.util.logging.Level;
import java.util.logging.Logger;
public abstract class JspNode {
static final L10N L = new L10N(JspNode.class);
private static final Logger log
= Logger.getLogger(JspNode.class.getName());
static final String JSP_NS = JspParser.JSP_NS;
protected Path _sourcePath;
protected String _filename;
protected int _startLine;
protected int _endAttributeLine;
protected int _endLine;
protected Namespace _ns;
protected JavaJspGenerator _gen;
protected ParseState _parseState;
protected QName _name;
protected JspNode _parent;
protected JspNode()
{
}
/**
* Sets the Java generator.
*/
public void setGenerator(JavaJspGenerator gen)
{
_gen = gen;
}
public JavaJspGenerator getGenerator()
{
return _gen;
}
/**
* Sets the parse state
*/
public void setParseState(ParseState parseState)
{
_parseState = parseState;
}
/**
* Returns the qname of the node.
*/
public QName getQName()
{
return _name;
}
/**
* Sets the node's qname
*/
public void setQName(QName name)
{
_name = name;
}
/**
* Returns the qname of the node.
*/
public String getTagName()
{
if (_name != null)
return _name.getName();
else
return "jsp:unknown";
}
/**
* Returns the parent node.
*/
public JspNode getParent()
{
return _parent;
}
/**
* Sets the parent node
*/
public void setParent(JspNode parent)
{
_parent = parent;
}
/**
* Sets the start location of the node.
*/
public void setStartLocation(Path sourcePath, String filename, int line)
{
_sourcePath = sourcePath;
_filename = filename;
_startLine = line;
_endAttributeLine = line;
}
/**
* Sets the end location of the node.
*/
public void setEndAttributeLocation(String filename, int line)
{
if (_filename != null && _filename.equals(filename))
_endAttributeLine = line;
}
/**
* Sets the end location of the node.
*/
public void setEndLocation(String filename, int line)
{
if (_filename != null && _filename.equals(filename))
_endLine = line;
}
/**
* Gets the filename of the node
*/
public String getFilename()
{
return _filename;
}
/**
* Gets the starting line number
*/
public int getStartLine()
{
return _startLine;
}
/**
* Gets the attribute ending line number
*/
public int getEndAttributeLine()
{
return _endAttributeLine;
}
/**
* Gets the ending line number
*/
public int getEndLine()
{
return _endLine;
}
/**
* True if the node only has static text.
*/
public boolean isStatic()
{
return false;
}
/**
* True if this is a jstl node.
*/
public boolean isJstl()
{
return false;
}
/**
* True for 2.1 or later taglib
*/
public boolean isJsp21()
{
return true;
}
/**
* Returns the static text.
*/
public String getStaticText()
{
CharBuffer cb = CharBuffer.allocate();
getStaticText(cb);
return cb.close();
}
/**
* Returns the static text.
*/
public void getStaticText(CharBuffer cb)
{
}
/**
* True if the node has scripting (counting rtexpr)
*/
public boolean hasScripting()
{
return false;
}
/**
* True if the node has scripting element (i.e. not counting rtexpr values)
*/
public boolean hasScriptingElement()
{
return false;
}
/**
* Finds the first scripting node
*/
public JspNode findScriptingNode()
{
if (hasScripting())
return this;
else
return null;
}
/**
* Returns the body content.
*/
public String getBodyContent()
{
return "jsp";
}
/**
* True if the node contains a child tag.
*/
public boolean hasCustomTag()
{
return false;
}
/**
* True if the node contains a child tag.
*/
public boolean hasTag()
{
return hasCustomTag();
}
/**
* Returns the tag name for the current tag.
*/
public String getCustomTagName()
{
return null;
}
/**
* Returns true for a simple tag.
*/
public boolean isSimpleTag()
{
return false;
}
/**
* Returns parent tag node
*/
public JspNode getParentTagNode()
{
if (getCustomTagName() != null)
return this;
else {
JspNode parent = getParent();
if (parent != null)
return parent.getParentTagNode();
else
return null;
}
}
/**
* Returns parent tag node
*/
public String getParentTagName()
{
if (getCustomTagName() != null)
return getCustomTagName();
else {
JspNode parent = getParent();
if (parent != null)
return parent.getParentTagName();
else
return null;
}
}
/**
* Returns true if the namespace decl has been printed.
*/
public boolean hasNamespace(String prefix, String uri)
{
if (_parent == null)
return false;
else
return _parent.hasNamespace(prefix, uri);
}
/**
* Adds a namespace, e.g. from a prefix declaration.
*/
public final void addNamespace(String prefix, String value)
{
addNamespaceRec(prefix, value);
}
/**
* Adds a namespace, e.g. from a prefix declaration.
*/
public final void setNamespace(Namespace ns)
{
_ns = ns;
}
/**
* Returns the XPath namespace context.
*/
public final NamespaceContext getNamespaceContext()
{
NamespaceContext ns = null;
for (Namespace ptr = _ns; ptr != null; ptr = ptr.getNext()) {
// jsp/1g58
if (! "".equals(ptr.getPrefix()))
ns = new NamespaceContext(ns, ptr.getPrefix(), ptr.getURI());
}
return ns;
}
/**
* Adds a namespace, e.g. from a prefix declaration.
*/
public void addNamespaceRec(String prefix, String value)
{
if (_parent != null)
_parent.addNamespaceRec(prefix, value);
}
/**
* Adds a namespace, e.g. from a prefix declaration.
*/
public String getNamespacePrefix(String uri)
{
if (_parent != null)
return _parent.getNamespacePrefix(uri);
else
return null;
}
/**
* Returns true if the namespace decl has been printed.
*/
public boolean hasNamespace(QName name)
{
return hasNamespace(name.getPrefix(), name.getNamespaceURI());
}
/**
* Adds an attribute.
*/
public void addAttribute(QName name, String value)
throws JspParseException
{
throw error(L.l("attribute '{0}' is not allowed in <{1}>.",
name.getName(), getTagName()));
}
/**
* Adds a JspAttribute attribute.
*
* @param name the name of the attribute.
* @param value the value of the attribute.
*/
public void addAttribute(QName name, JspAttribute value)
throws JspParseException
{
if (value.isStatic()) {
addAttribute(name, value.getStaticText().trim());
}
else
throw error(L.l("attribute '{0}' is not allowed in <{1}>.",
name.getName(), getTagName()));
}
/**
* Called after all the attributes from the tag.
*/
public void endAttributes()
throws JspParseException
{
}
/**
* Adds text.
*/
public JspNode addText(String text)
throws JspParseException
{
for (int i = 0; i < text.length(); i++) {
char ch = text.charAt(i);
if (! XmlChar.isWhitespace(ch))
throw error(L.l("Text is not allowed in <{0}> at '{1}'.",
_name.getName(), text));
}
return null;
}
/**
* Adds a child node.
*/
public void addChild(JspNode node)
throws JspParseException
{
node.setParent(this);
if (node instanceof JspAttribute) {
}
else if (node instanceof StaticText
&& ((StaticText) node).isWhitespace()) {
}
else
throw node.error(L.l("<{0}> does not allow any child elements at {1}",
getTagName(), node.getTagName()));
}
/**
* Adds a child node after its completely initialized..
*/
public void addChildEnd(JspNode node)
throws JspParseException
{
if (node instanceof JspAttribute) {
JspAttribute attr = (JspAttribute) node;
QName name = attr.getName();
addAttribute(name, attr);
}
}
/**
* Called when the tag closes.
*/
public void endElement()
throws Exception
{
}
/**
* Returns the children.
*/
public ArrayList getChildren()
{
return null;
}
/**
* Returns the TagInstance of the enclosing parent.
*/
public TagInstance getTag()
{
JspNode parent = getParent();
if (parent != null)
return parent.getTag();
else {
return _gen.getRootTag();
}
}
/**
* Return true for pre-21 taglib.
*/
public boolean isPre21Taglib()
{
return false;
}
/**
* Generates the XML text representation for the tag validation.
*
* @param os write stream to the generated XML.
*/
abstract public void printXml(WriteStream os)
throws IOException;
protected String printXmlOpen(WriteStream os,
String ns,
String localName)
throws IOException
{
String prefix = getNamespacePrefix(ns);
if (prefix == null) {
prefix = "c";
os.print("")) {
os.print("%=");
os.print(xmlAttrText(text.substring(3, text.length() - 2)));
os.print("%");
}
else
os.print(xmlAttrText(text));
os.print("\"");
}
/**
* Generates the XML text.
*/
public String xmlText(String text)
{
if (text == null)
return "";
CharBuffer cb = new CharBuffer();
for (int i = 0; i < text.length(); i++) {
char ch = text.charAt(i);
switch (ch) {
case '<':
cb.append("<");
break;
case '>':
cb.append(">");
break;
case '&':
cb.append("&");
break;
case '"':
cb.append(""");
break;
default:
cb.append(ch);
break;
}
}
return cb.toString();
}
/**
* Generates the XML text.
*/
public String xmlAttrText(String text)
{
if (text == null)
return "";
CharBuffer cb = new CharBuffer();
for (int i = 0; i < text.length(); i++) {
char ch = text.charAt(i);
switch (ch) {
case '&':
cb.append("&");
break;
case '<':
cb.append("<");
break;
case '>':
cb.append(">");
break;
case '"':
cb.append(""");
break;
case '\'':
cb.append("'");
break;
default:
cb.append(ch);
break;
}
}
return cb.toString();
}
/**
* Generates the start location.
*/
public void generateStartLocation(JspJavaWriter out)
throws IOException
{
out.setLocation(_filename, _startLine);
}
/**
* Generates the start location.
*/
public void generateEndLocation(JspJavaWriter out)
throws IOException
{
out.setLocation(_filename, _endLine);
}
/**
* generates prologue data.
*/
public void generatePrologue(JspJavaWriter out)
throws Exception
{
generatePrologueChildren(out);
}
/**
* generates prologue data.
*/
public void generatePrologueDeclare(JspJavaWriter out)
throws Exception
{
}
/**
* generates data for prologue children.
*/
public void generatePrologueChildren(JspJavaWriter out)
throws Exception
{
}
/**
* generates declaration data.
*/
public void generateDeclaration(JspJavaWriter out)
throws IOException
{
generateDeclarationChildren(out);
}
/**
* generates data for declaration children.
*/
public void generateDeclarationChildren(JspJavaWriter out)
throws IOException
{
}
/**
* generates tag state
*/
public void generateTagState(JspJavaWriter out)
throws Exception
{
generateTagStateChildren(out);
}
/**
* generates tag state
*/
public void generateTagStateChildren(JspJavaWriter out)
throws Exception
{
}
/**
* generates tag state release
*/
public void generateTagRelease(JspJavaWriter out)
throws Exception
{
generateTagReleaseChildren(out);
}
/**
* generates tag state
*/
public void generateTagReleaseChildren(JspJavaWriter out)
throws Exception
{
}
/**
* Generates the code for the tag
*
* @param out the output writer for the generated java.
*/
abstract public void generate(JspJavaWriter out)
throws Exception;
/**
* Generates the code for the children.
*
* @param out the output writer for the generated java.
*/
public void generateChildren(JspJavaWriter out)
throws Exception
{
}
/**
* Generates the code for the tag
*
* @param out the output writer for the generated java.
*/
public void generateClassEpilogue(JspJavaWriter out)
throws IOException
{
generateClassEpilogueChildren(out);
}
/**
* Generates the code for the tag
*
* @param out the output writer for the generated java.
*/
public void generateClassEpilogueChildren(JspJavaWriter out)
throws IOException
{
}
/**
* Generates the code for the tag
*
* @param out the output writer for the generated java.
*/
public void generateStatic(JspJavaWriter out)
throws Exception
{
}
/**
* Generates the code for the tag
*
* @param out the output writer for the generated java.
*/
public void generateEmpty()
throws Exception
{
generateChildrenEmpty();
}
/**
* Generates the code for the children.
*
* @param out the output writer for the generated java.
*/
public void generateChildrenEmpty()
throws Exception
{
}
/**
* Converts the string to a boolean.
*/
protected boolean attributeToBoolean(String attr, String value)
throws JspParseException
{
if (value.equals("yes") || value.equals("true"))
return true;
else if (value.equals("no") || value.equals("false"))
return false;
else
throw error(L.l("'{0}' is an unknown value for {1}. 'true' or 'false' are the expected values.",
value, attr));
}
/**
* Returns true if in a fragment
*/
public boolean isInFragment()
{
for (JspNode node = getParent(); node != null; node = node.getParent()) {
if (node instanceof JspAttribute || node instanceof CustomSimpleTag)
return true;
}
return false;
}
void generateSetParameter(JspJavaWriter out,
String obj, Object objValue, Method method,
boolean allowRtexpr,
String contextVar, boolean isParentSimpleTag,
boolean isFragment, TagAttributeInfo attrInfo)
throws Exception
{
Class> type = method.getParameterTypes()[0];
if (isFragment || JspFragment.class.equals(type)) {
generateFragmentParameter(out, obj, objValue, method,
allowRtexpr, contextVar,
isParentSimpleTag);
return;
}
if (objValue instanceof JspAttribute) {
JspAttribute attr = (JspAttribute) objValue;
if (attr.isStatic())
objValue = attr.getStaticText();
else {
String str = "_jsp_str_" + _gen.uniqueId();
out.printClass(type);
out.println(" " + str + " = " + attr.generateValue(type) + ";");
out.println(obj + "." + method.getName() + "(" + str + ");");
return;
}
}
else if (objValue instanceof JspNode)
throw error(L.l("jsp:attribute may not set this attribute."));
String strValue = (String) objValue;
String convValue = generateParameterValue(type,
strValue,
allowRtexpr,
attrInfo,
_parseState.isELIgnored());
PropertyEditor editor;
if (convValue != null)
out.println(obj + "." + method.getName() + "(" + convValue + ");");
else if ((editor = PropertyEditorManager.findEditor(type)) != null) {
generateSetParameter(out, obj, strValue, method, editor.getClass());
}
else
throw error(L.l("expected '<%= ... %>' at '{0}' for tag attribute setter '{1}'. Tag attributes which can't be converted from strings must use a runtime attribute expression.",
strValue, method.getName() + "(" + type.getName() + ")"));
}
void generateSetParameter(JspJavaWriter out,
String obj, String value, Method method,
Class> editorClass)
throws Exception
{
Class> type = method.getParameterTypes()[0];
String name = "_jsp_editor" + _gen.uniqueId();
out.print("java.beans.PropertyEditor " + name + " = new " + editorClass.getName() + "();");
out.println(name + ".setAsText(\"" + escapeJavaString(value) + "\");");
out.println(obj + "." + method.getName() + "((" +
type.getName() + ") " + name + ".getValue());");
}
void generateFragmentParameter(JspJavaWriter out,
Object obj, Object objValue, Method method,
boolean allowRtexpr, String contextVar,
boolean isParentSimpleTag)
throws Exception
{
out.print(obj + "." + method.getName() + "(");
if (objValue instanceof JspFragmentNode)
generateFragment(out, (JspFragmentNode) objValue, contextVar,
isParentSimpleTag);
else if (objValue instanceof String) {
String string = (String) objValue;
int index = _gen.addExpr(string);
out.print("new com.caucho.jsp.ELExprFragment(pageContext, _caucho_expr_" + index + ")");
}
else {
throw error(L.l("can't handle fragment '{0}' of type {1}",
objValue, objValue.getClass()));
}
out.println(");");
}
String generateFragmentParameter(String string, boolean allowRtexpr)
throws Exception
{
int index = _gen.addExpr(string);
return ("new com.caucho.jsp.ELExprFragment(pageContext, _caucho_expr_" + index + ")");
}
/**
* Returns the containing segment.
*/
public JspSegmentNode getSegment()
{
JspNode parent = getParent();
if (parent != null)
return parent.getSegment();
else
return null;
}
void generateFragment(JspJavaWriter out,
JspFragmentNode frag,
String contextVar,
boolean isParentSimpleTag)
throws Exception
{
out.print(generateFragment(frag, contextVar));
}
void generateParentTag(JspJavaWriter out, TagInstance parent)
throws IOException
{
String parentId = parent.getId();
if (parentId == null || parentId.startsWith("top_")) {
out.print("null");
}
else if (parent.isSimpleTag()) {
out.print("(" + parentId + "_adapter != null ? ");
out.print(parentId + "_adapter : ");
out.print("(" + parentId + "_adapter = new javax.servlet.jsp.tagext.TagAdapter(" + parentId + ")))");
}
else
out.print(parentId);
}
String generateRTValue(Class> type, Object value)
throws Exception
{
if (value instanceof String)
return generateParameterValue(type, (String) value,
true, null, _parseState.isELIgnored());
else {
JspAttribute attr = (JspAttribute) value;
return stringToValue(type, attr.generateValue());
}
}
/**
* Generates the code invoking a fragment to a string.
*/
protected String invokeFragment(JspFragmentNode frag)
throws Exception
{
return frag.generateValue();
}
/**
* Generates the code for a fragment.
*/
protected String generateFragment(JspFragmentNode frag,
String contextVar)
throws Exception
{
StringBuffer cb = new StringBuffer();
if (frag.isStatic()) {
String fragmentVar = frag.getFragmentName();
cb.append(fragmentVar + " = com.caucho.jsp.StaticJspFragmentSupport.create(" + fragmentVar + ", " + contextVar + ", \"");
cb.append(escapeJavaString(frag.getStaticText()));
cb.append("\")");
return cb.toString();
}
int index = frag.getFragmentCode();
getGenerator().addFragment(frag);
String fragmentVar = frag.getFragmentName();
JspNode parentTag = getParentTagNode();
// jsp/0800
boolean isParentSimpleTag = (parentTag instanceof CustomSimpleTag);
if (! isParentSimpleTag) {
cb.append(fragmentVar + " = createFragment_" + index
+ "(" + fragmentVar
+ ", _jsp_parentContext"
+ ", " + contextVar
+ ", ");
}
else {
cb.append(fragmentVar + " = createFragment_" + index
+ "(null"
+ ", _jsp_parentContext"
+ ", " + contextVar
+ ", ");
}
if (parentTag == null)
cb.append("null");
else if (frag.hasCustomTag() && parentTag instanceof CustomSimpleTag)
cb.append(parentTag.getCustomTagName() + "_adapter");
else
cb.append(parentTag.getCustomTagName());
if (_gen instanceof JavaTagGenerator) {
JavaTagGenerator tagGen = (JavaTagGenerator) _gen;
if (tagGen.isStaticDoTag()) // jsp/1025
cb.append(", _jspBody");
else
cb.append(", getJspBody()");
}
else
cb.append(", null");
cb.append(", _jsp_state");
cb.append(", _jsp_pageManager");
cb.append(")");
return cb.toString();
}
/**
* Generates the code for the value of a parent tag.
*/
protected String generateParentTag(TagInstance parent)
throws IOException
{
String parentId = parent.getId();
if (parent.isTop()) {
return "null";
}
else if (parent.isSimpleTag()) {
CharBuffer cb = CharBuffer.allocate();
cb.append("(" + parentId + "_adapter != null ? ");
cb.append(parentId + "_adapter : ");
cb.append("(" + parentId + "_adapter = new javax.servlet.jsp.tagext.TagAdapter(" + parentId + ")))");
return cb.close();
}
else
return parentId;
}
//
// JSF functions
//
/**
* Returns the variable containing the jsf component
*/
public String getJsfVar()
{
if (_parent != null)
return _parent.getJsfVar();
else
return null;
}
/**
* Returns the variable containing the jsf body
*/
public String getJsfBodyVar()
{
if (_parent != null)
return _parent.getJsfBodyVar();
else
return null;
}
/**
* True if the jsf-parent setting is required.
*/
public boolean isJsfParentRequired()
{
return false;
}
//
// value generation
//
/**
* Generate include params.
*/
void generateIncludeParams(JspJavaWriter out,
ArrayList params)
throws Exception
{
boolean hasQuery = false;
for (int i = 0; i < params.size(); i++) {
JspParam param = (JspParam) params.get(i);
String value = param.getValue();
if (hasQuery)
out.print("+ \"&\" + ");
hasQuery = true;
out.print("\"" + param.getName() + "=\"");
String outValue = generateParameterValue(String.class, value);
if (outValue.equals("null")) {
}
else if (outValue.startsWith("\""))
out.print(" + (" + outValue + ")");
else
out.print(" + com.caucho.el.Expr.toString(" + outValue + ", null)");
}
}
protected void generateIncludeUrl(JspJavaWriter out, String page,
ArrayList params)
throws Exception
{
if (params != null) {
for (int i = 0; i < params.size(); i++) {
out.print("pageContext.encode(");
}
out.print("pageContext.encode(");
}
if (hasRuntimeAttribute(page)) {
out.print(getRuntimeAttribute(page));
}
else {
out.print(generateParameterValue(String.class, page));
}
if (params != null) {
out.print(")");
for (int i = 0; i < params.size(); i++) {
if (i > 0)
out.print(".append('&')");
out.print(", ");
generateIncludeParam(out, params.get(i));
out.print(")");
}
out.print(".toString()");
}
}
/**
* Generate include params.
*/
void generateIncludeParam(JspJavaWriter out,
JspParam param)
throws Exception
{
String value = param.getValue();
out.print("\"" + param.getName() + "=\"");
String outValue = generateParameterValue(String.class, value);
if (outValue.equals("null")) {
}
else if (outValue.startsWith("\"")) {
out.print(" + (" + outValue + ")");
}
else
out.print(" + com.caucho.el.Expr.toString(" + outValue + ", null)");
}
String generateJstlValue(Class> type, String value)
throws Exception
{
return generateParameterValue(type, value, true, null, false);
}
String generateValue(Class> type, String value)
throws Exception
{
return generateParameterValue(type, value, true, null,
_parseState.isELIgnored());
}
String generateParameterValue(Class> type, String value)
throws Exception
{
return generateParameterValue(type, value, true, null,
_parseState.isELIgnored());
}
String generateParameterValue(Class> type,
String value,
boolean rtexpr,
TagAttributeInfo attrInfo,
boolean isELIgnored)
throws Exception
{
// jsp/1c2m
if (isJstl())
isELIgnored = false;
boolean isEmpty = value == null || value.equals("");
if (isEmpty)
value = "0";
try {
String typeName = attrInfo != null ? attrInfo.getExpectedTypeName() : "";
boolean isValueDeferred
= (attrInfo != null && attrInfo.isDeferredValue()
|| typeName != null && ! "".equals(typeName));
boolean isMethodDeferred
= (attrInfo != null && attrInfo.isDeferredMethod());
if (JspFragment.class.equals(type))
return generateFragmentParameter(value, rtexpr);
else if (type.equals(ValueExpression.class)) {
int exprIndex;
if (isEmpty)
exprIndex = _gen.addValueExpr("", typeName);
else
exprIndex = _gen.addValueExpr(value, typeName);
if (isValueDeferred
&& value.indexOf("#{") < 0
&& value.indexOf("${") >= 0) {
throw error(L.l("ValueExpression '{0}' must use deferred syntax '#{...}'",
value));
}
else if (! isValueDeferred
&& value.indexOf("#{") >= 0
&& value.indexOf("${") < 0) {
throw error(L.l("Deferred syntax '#{...}' is not allowed for '{0}'",
value));
}
if (value.indexOf("#{") < 0 && value.indexOf("${") < 0) {
return ("_caucho_value_expr_" + exprIndex);
}
else {
StringBuilder sb = new StringBuilder();
sb.append("pageContext.createExpr(_caucho_value_expr_");
sb.append(exprIndex);
sb.append(", \"");
sb.append(escapeJavaString(value));
sb.append("\", ");
if (null == typeName || "".equals(typeName)) {
sb.append("java.lang.Object.class)");
} else {
sb.append(escapeJavaString(typeName));
sb.append(".class)");
}
return sb.toString();
}
}
else if (type.equals(MethodExpression.class)) {
int exprIndex;
String sig = attrInfo != null ? attrInfo.getMethodSignature() : "java.lang.String misc()";
if (isEmpty)
exprIndex = _gen.addMethodExpr("", sig);
else
exprIndex = _gen.addMethodExpr(value, sig);
if (value.indexOf("${") >= 0)
throw error(L.l("MethodExpression '{0}' must use deferred syntax '$#{...}'",
value));
return ("_caucho_method_expr_" + exprIndex);
}
else if (! isValueDeferred
&& ! _gen.getParseState().isDeferredSyntaxAllowedAsLiteral()
&& value.indexOf("#{") >= 0
&& value.indexOf("${") < 0
&& rtexpr
&& isJsp21()) {
// jsp/10h2, jsp/1cn0, jsp/10h3
throw error(L.l("deferred expression '{0}' is not allowed here",
value));
}
else if (com.caucho.el.Expr.class.equals(type)) {
int exprIndex;
if (isEmpty)
exprIndex = _gen.addExpr("");
else
exprIndex = _gen.addExpr(value);
return ("_caucho_expr_" + exprIndex);
}
else if (com.caucho.xpath.Expr.class.equals(type)) {
com.caucho.xpath.Expr expr;
if (isEmpty)
expr = XPath.parseExpr("");
else
expr = XPath.parseExpr(value, getNamespaceContext());
return _gen.addXPathExpr(expr);
}
else if (rtexpr && hasRuntimeAttribute(value)) {
return getRuntimeAttribute(value);
}
else if (rtexpr && hasELAttribute(value, isELIgnored)) {
// jsp/0138, jsp/18s0, jsp/1ce5, jsp/1e0a
return generateELValue(type, value);
}
else if (! rtexpr && hasELAttribute(value, isELIgnored)) {
// JSP.2.3.6 says this is an error
// jsp/184v vs jsp/18cr vs jsp/18f5 vs jsp/18f7 (tck)
// #2112
if (String.class.equals(type) && _gen.isELIgnore())
return '"' + escapeJavaString(value) + '"';
else
throw error(L.l("EL expression '{0}' is only allowed for attributes with rtexprvalue='true'.",
value));
}
else if (rtexpr && hasDeferredAttribute(value, false)) {
// jsp/1c2m, jsp/1ce8
if (type.equals(String.class))
return '"' + value + '"';
else
return generateELValue(type, value);
}
else if (! rtexpr
&& hasDeferredAttribute(value, isELIgnored)
&& ! _gen.getParseState().isDeferredSyntaxAllowedAsLiteral()) {
throw error(L.l("Deferred syntax '{0}' is not allowed as a literal.",
value));
}
else if (type.equals(boolean.class))
return String.valueOf(Boolean.valueOf(isEmpty ? "false" : value));
else if (type.equals(Boolean.class)) {
if (isEmpty)
return "java.lang.Boolean.FALSE";
else
return "new java.lang.Boolean(" + Boolean.valueOf(value) + ")";
}
else if (type.equals(byte.class))
return "(byte) " + Byte.valueOf(value);
else if (type.equals(Byte.class))
return "new java.lang.Byte((byte) " + Byte.valueOf(value) + ")";
else if (type.equals(char.class)) {
if (isEmpty)
return "'\\0'";
else
return "'" + value.charAt(0) + "'";
}
else if (type.equals(Character.class)) {
if (isEmpty)
return "new java.lang.Character('\\0')";
else
return ("new Character('" + value.charAt(0) + "')");
}
else if (type.equals(short.class))
return ("(short) " + Short.valueOf(value));
else if (type.equals(Short.class))
return ("new java.lang.Short((short) " + Short.valueOf(value) + ")");
else if (type.equals(int.class))
return String.valueOf(Integer.valueOf(value));
else if (type.equals(Integer.class))
return ("new java.lang.Integer(" + Integer.valueOf(value) + ")");
else if (type.equals(long.class))
return String.valueOf(Long.valueOf(value));
else if (type.equals(Long.class))
return ("new java.lang.Long(" + Long.valueOf(value) + ")");
else if (type.equals(float.class))
return ("(float) " + Float.valueOf(value));
else if (type.equals(Float.class))
return ("new java.lang.Float((float) " + Float.valueOf(value) + ")");
else if (type.equals(double.class))
return String.valueOf(Double.valueOf(value));
else if (type.equals(Double.class)) {
double v = Double.valueOf(value);
if (Double.isNaN(v))
return ("new java.lang.Double(Double.NaN)");
else
return ("new java.lang.Double(" + v + ")");
}
else if (! type.equals(String.class)
&& ! type.equals(Object.class)) {
return null;
}
else if (! isEmpty) {
return '"' + escapeJavaString(value) + '"';
}
else
return "\"\"";
} catch (NumberFormatException e) {
throw error(L.l("parameter format error: {0}", e.getMessage()), e);
}
}
protected String generateELValue(Class> type, String value)
throws Exception
{
if (type.equals(com.caucho.el.Expr.class)) {
int exprIndex;
exprIndex = _gen.addExpr(value);
return ("_caucho_expr_" + exprIndex);
}
else if (type.equals(ValueExpression.class)) {
int exprIndex;
exprIndex = _gen.addValueExpr(value, "");
return ("_caucho_value_expr_" + exprIndex);
}
else if (type.equals(Object.class)
&& value.contains("#{")
&& CustomTag.class.equals(getClass())) {
int exprIndex;
exprIndex = _gen.addValueExpr(value, "");
return ("_caucho_value_expr_" + exprIndex);
}
else if (type.equals(com.caucho.xpath.Expr.class)) {
com.caucho.xpath.Expr expr;
expr = XPath.parseExpr(value, getNamespaceContext());
return _gen.addXPathExpr(expr);
}
Expr expr = _gen.genExpr(value);
if (expr.isConstant()) {
try {
if (expr.evalObject(null) != null) {
}
else if (Character.class.isAssignableFrom(type)) {
// jsp/18s0
return "new Character((char) 0)";
}
else if (Boolean.class.isAssignableFrom(type)) {
// jsp/18s1
return "Boolean.FALSE";
}
else if (String.class.isAssignableFrom(type)) {
// jsp/18s2
return "\"\"";
}
else if (BigInteger.class.isAssignableFrom(type)) {
return "java.math.BigInteger.ZERO";
}
else if (BigDecimal.class.isAssignableFrom(type)) {
return "java.math.BigDecimal.ZERO";
}
else if (Number.class.isAssignableFrom(type)) {
// jsp/18s6
return "new " + type.getName() + "((byte) 0)";
}
else if (Object.class.isAssignableFrom(type))
return "null";
if (boolean.class.equals(type))
return expr.evalBoolean(null) ? "true" : "false";
else if (Boolean.class.equals(type))
return expr.evalBoolean(null) ? "java.lang.Boolean.TRUE" : "java.lang.Boolean.FALSE";
else if (byte.class.equals(type))
return "(byte) " + expr.evalLong(null);
else if (Byte.class.equals(type))
return "new java.lang.Byte((byte) " + expr.evalLong(null) + "L)";
else if (short.class.equals(type))
return "(short) " + expr.evalLong(null);
else if (Short.class.equals(type))
return "new java.lang.Short((short) " + expr.evalLong(null) + "L)";
else if (int.class.equals(type))
return "(int) " + expr.evalLong(null);
else if (Integer.class.equals(type))
return "new java.lang.Integer((int) " + expr.evalLong(null) + "L)";
else if (long.class.equals(type))
return "" + expr.evalLong(null) + "L";
else if (Long.class.equals(type))
return "new java.lang.Long(" + expr.evalLong(null) + "L)";
else if (float.class.equals(type))
return "(float) " + expr.evalDouble(null);
else if (Float.class.equals(type))
return "new java.lang.Float((float) " + expr.evalDouble(null) + ")";
else if (double.class.equals(type)) {
double v = expr.evalDouble(null);
if (Double.isNaN(v))
return "Double.NaN";
else
return "" + v;
}
else if (Double.class.equals(type)) {
double v = expr.evalDouble(null);
if (Double.isNaN(v))
return "new Double(Double.NaN)";
else
return "new java.lang.Double(" + v + ")";
}
else if (char.class.equals(type))
return "((char) " + (int) expr.evalCharacter(null) + ")";
else if (Character.class.equals(type)) {
// jsp/18s0
return "new Character((char) " + (int) expr.evalCharacter(null) + ")";
}
else if (String.class.equals(type))
return "\"" + escapeJavaString(expr.evalString(null)) + "\"";
else if (BigInteger.class.equals(type)) {
String v = expr.evalBigInteger(null).toString();
// 18s3
if (v.equals("") || v.equals("0"))
return "java.math.BigInteger.ZERO";
else
return "new java.math.BigInteger(\"" + v + "\")";
}
else if (BigDecimal.class.equals(type)) {
String v = expr.evalBigDecimal(null).toString();
// 18s4
if (v.equals("") || v.equals("0.0"))
return "java.math.BigDecimal.ZERO";
else
return "new java.math.BigDecimal(\"" + v + "\")";
}
else if (Object.class.equals(type)) {
Object cValue = expr.evalObject(null);
String result = generateObject(cValue);
if (result != null)
return result;
}
else {
Object cValue = expr.evalObject(null);
// jsp/184t
if ("".equals(cValue))
return "null";
}
} catch (Throwable e) {
// jsp/18co
// exceptions are caught at runtime
log.log(Level.FINER, e.toString(), e);
log.fine(e.getMessage());
}
}
int exprIndex = _gen.addExpr(value);
String var = "_caucho_expr_" + exprIndex;
if (boolean.class.equals(type))
return var + ".evalBoolean(_jsp_env)";
else if (Boolean.class.equals(type))
return var + ".evalBoolean(_jsp_env) ? java.lang.Boolean.TRUE : java.lang.Boolean.FALSE";
else if (byte.class.equals(type))
return "(byte) " + var + ".evalLong(_jsp_env)";
else if (Byte.class.equals(type))
return "new java.lang.Byte((byte) " + var + ".evalLong(_jsp_env))";
else if (short.class.equals(type))
return "(short) " + var + ".evalLong(_jsp_env)";
else if (Short.class.equals(type))
return "new java.lang.Short((short) " + var + ".evalLong(_jsp_env))";
else if (int.class.equals(type))
return "(int) " + var + ".evalLong(_jsp_env)";
else if (Integer.class.equals(type))
return "new java.lang.Integer((int) " + var + ".evalLong(_jsp_env))";
else if (long.class.equals(type))
return var + ".evalLong(_jsp_env)";
else if (Long.class.equals(type))
return "new java.lang.Long(" + var + ".evalLong(_jsp_env))";
else if (float.class.equals(type))
return "(float) " + var + ".evalDouble(_jsp_env)";
else if (Float.class.equals(type))
return "new java.lang.Float((float) " + var + ".evalDouble(_jsp_env))";
else if (double.class.equals(type))
return var + ".evalDouble(_jsp_env)";
else if (Double.class.equals(type))
return "new java.lang.Double(" + var + ".evalDouble(_jsp_env))";
else if (java.math.BigDecimal.class.equals(type))
return "" + var + ".evalBigDecimal(_jsp_env)";
else if (java.math.BigInteger.class.equals(type))
return "" + var + ".evalBigInteger(_jsp_env)";
else if (char.class.equals(type))
return var + ".evalCharacter(_jsp_env)";
else if (Character.class.equals(type))
return "new Character(" + var + ".evalCharacter(_jsp_env))";
else if (String.class.equals(type))
return var + ".evalString(_jsp_env)";
else if (BigInteger.class.equals(type))
return var + ".evalBigInteger(_jsp_env)";
else if (BigDecimal.class.equals(type))
return var + ".evalBigDecimal(_jsp_env)";
else if (Object.class.equals(type))
return var + ".evalObject(_jsp_env)";
else {
return "(" + classToString(type) + ") " + var + ".evalObject(_jsp_env)";
}
}
public void convertParameterValue(JspJavaWriter out, String type, String value)
throws IOException
{
if (type.equals("boolean"))
out.print("java.lang.Boolean.TRUE.equals(" + value + ")");
else if (type.equals("byte"))
out.print("java.lang.Byte.valueOf(" + value + ")");
else if (type.equals("char"))
out.print("java.lang.Character.valueOf(" + value + ")");
else if (type.equals("short"))
out.print("java.lang.Short.valueOf(" + value + ")");
else if (type.equals("int"))
out.print("((java.lang.Integer) " + value + ").intValue()");
else if (type.equals("long"))
out.print("((java.lang.Long) " + value + ").longValue()");
else if (type.equals("float"))
out.print("((java.lang.Float) " + value + ").floatValue()");
else if (type.equals("double"))
out.print("((java.lang.Double) " + value + ").doubleValue()");
else
out.print("(" + type + ")" + value);
}
protected String classToString(Class> cl)
{
if (cl.isArray())
return classToString(cl.getComponentType()) + "[]";
else
return cl.getName();
}
/**
* Returns true if the value is a runtime attribute.
*/
public boolean hasRuntimeAttribute(String value)
throws JspParseException
{
if (_parseState.isScriptingInvalid()) {
// && value.indexOf("<%=") >= 0) {
return false;
/*
throw error(L.l("Runtime expressions are forbidden here. Scripting has been disabled either:\n1) disabled by the web.xml scripting-invalid\n2) disabled in a tag's descriptor\n3) forbidden in or tags."));
*/
}
if (value.startsWith("<%=") && value.endsWith("%>"))
return true;
else if (value.startsWith("%=") && value.endsWith("%"))
return true;
else if (value.indexOf("<%=") >= 0 &&
value.indexOf("<%=") < value.indexOf("%>"))
throw error(L.l("interpolated runtime values are forbidden by the JSP spec at '{0}'",
value));
else
return false;
}
/**
* Returns true if the string has scripting.
*/
public boolean hasScripting(String value)
{
try {
return value != null && hasRuntimeAttribute(value);
} catch (Exception e) {
throw new RuntimeException(e);
}
}
/**
* Returns true if the string has scripting.
*/
public boolean hasScripting(JspAttribute value)
{
return value != null && value.hasScripting();
}
/**
* Returns true if the value is a runtime attribute.
*/
public boolean hasELAttribute(String value)
{
return ! _parseState.isELIgnored() && value.indexOf("${") >= 0;
}
/**
* Returns true if the value is a runtime attribute.
*/
public boolean hasDeferredAttribute(String value)
{
if (value.indexOf("#{") < 0)
return false;
else if (isPre21Taglib())
return false;
else
return ! _parseState.isELIgnored();
}
/**
* Returns true if the value is a runtime attribute.
*/
public boolean hasELAttribute(String value, boolean isELIgnored)
{
return ! isELIgnored && value.indexOf("${") >= 0;
}
/**
* Returns true if the value is a runtime attribute.
*/
public boolean hasDeferredAttribute(String value, boolean isELIgnored)
{
if (isELIgnored)
return false;
else if (value.indexOf("#{") < 0)
return false;
else if (isPre21Taglib())
return false;
else
return true;
}
/**
* Returns the runtime attribute of the value.
*/
public String getRuntimeAttribute(String value)
throws Exception
{
if (value.startsWith("<%=") && value.endsWith("%>"))
return value.substring(3, value.length() - 2);
else if (value.startsWith("%=") && value.endsWith("%"))
return value.substring(2, value.length() - 1);
else
return value;
}
/**
* Converts a string-valued expression to the given type.
*/
String stringToValue(Class> type, String obj)
{
if (boolean.class.equals(type))
return "com.caucho.jsp.PageContextImpl.toBoolean(" + obj + ")";
else if (Boolean.class.equals(type))
return "java.lang.Boolean.valueOf(" + obj + ")";
else if (byte.class.equals(type))
return "java.lang.Byte.parseByte(" + obj + ")";
else if (Byte.class.equals(type))
return "java.lang.Byte.valueOf(" + obj + ")";
else if (char.class.equals(type))
return obj + ".charAt(0)";
else if (Character.class.equals(type))
return "new java.lang.Character(" + obj + ".charAt(0))";
else if (short.class.equals(type))
return "java.lang.Short.parseShort(" + obj + ")";
else if (Short.class.equals(type))
return "java.lang.Short.valueOf(" + obj + ")";
else if (int.class.equals(type))
return "java.lang.Integer.parseInt(" + obj + ")";
else if (Integer.class.equals(type))
return "java.lang.Integer.valueOf(" + obj + ")";
else if (long.class.equals(type))
return "java.lang.Long.parseLong(" + obj + ")";
else if (Long.class.equals(type))
return "java.lang.Long.valueOf(" + obj + ")";
else if (float.class.equals(type))
return "java.lang.Float.parseFloat(" + obj + ")";
else if (Float.class.equals(type))
return "java.lang.Float.valueOf(" + obj + ")";
else if (double.class.equals(type))
return "java.lang.Double.parseDouble(" + obj + ")";
else if (Double.class.equals(type))
return "java.lang.Double.valueOf(" + obj + ")";
else if (type.isAssignableFrom(String.class))
return obj;
else
return null;
}
/**
* Converts a string-valued expression to the given type.
*/
Object staticStringToValue(Class> type, String obj)
{
if (boolean.class.equals(type) || Boolean.class.equals(type))
return Boolean.valueOf(obj);
else if (byte.class.equals(type) || Byte.class.equals(type))
return Byte.parseByte(obj);
else if (char.class.equals(type) || Character.class.equals(type))
return obj.charAt(0);
else if (short.class.equals(type) || Short.class.equals(type))
return Short.parseShort(obj);
else if (int.class.equals(type) || Integer.class.equals(type))
return Integer.parseInt(obj);
else if (long.class.equals(type) || Long.class.equals(type))
return Long.parseLong(obj);
else if (float.class.equals(type) || Float.class.equals(type))
return Float.parseFloat(obj);
else if (double.class.equals(type) || Double.class.equals(type))
return Double.parseDouble(obj);
else if (type.isAssignableFrom(String.class))
return obj;
else
return obj; // XXX:
}
protected String generateObject(Object obj)
{
if (obj instanceof String)
return "\"" + escapeJavaString((String) obj) + "\"";
else if (obj instanceof Long)
return "new java.lang.Long(" + obj + "L)";
else if (obj instanceof Integer)
return "new java.lang.Integer((int) " + obj + "L)";
else if (obj instanceof Double) {
double v = (Double) obj;
if (Double.isNaN(v))
return "new java.lang.Double(Double.NaN)";
else
return "new java.lang.Double(" + v + ")";
}
else if (obj instanceof Boolean)
return ((Boolean) obj).booleanValue() ? "java.lang.Boolean.TRUE" : "java.lang.Boolean.FALSE";
else
return null;
}
public static String toELObject(String expr, Class> type)
{
if (boolean.class.equals(type))
return "((" + expr + ") ? Boolean.TRUE : Boolean.FALSE)";
else if (byte.class.equals(type))
return "new Long(" + expr + ")";
else if (short.class.equals(type))
return "new Long(" + expr + ")";
else if (int.class.equals(type))
return "new Long(" + expr + ")";
else if (long.class.equals(type))
return "new Long(" + expr + ")";
else if (float.class.equals(type))
return "new Double(" + expr + ")";
else if (double.class.equals(type))
return "new Double(" + expr + ")";
else if (char.class.equals(type))
return "String.valueOf(" + expr + ")";
else
return expr;
}
/**
* Escapes a java string.
*/
public static String escapeJavaString(String s)
{
if (s == null)
return "";
CharBuffer cb = CharBuffer.allocate();
for (int i = 0; i < s.length(); i++) {
if (s.charAt(i) == '\\')
cb.append("\\\\");
else if (s.charAt(i) == '"')
cb.append("\\\"");
else if (s.charAt(i) == '\n')
cb.append("\\n");
else if (s.charAt(i) == '\r')
cb.append("\\r");
else
cb.append(s.charAt(i));
}
return cb.close();
}
protected Class loadClass(String type)
throws JspParseException
{
if (type == null)
return null;
else {
try {
return _gen.getBeanClass(type);
} catch (Exception e) {
throw new JspParseException(e);
}
}
}
/**
* Creates a parse exception with the proper line information.
*/
protected JspParseException error(String msg)
{
return error(msg, null);
}
/**
* Creates a parse exception with the proper line information.
*/
protected JspParseException error(String msg, Throwable e)
{
if (_filename != null) {
String lines = _gen.getSourceLines(_sourcePath, _startLine);
return new JspLineParseException(_filename + ":" + _startLine + ": " + msg + lines, e);
}
else
return new JspParseException(msg, e);
}
/**
* Creates a parse exception with the proper line information.
*/
protected JspParseException error(Throwable e)
{
if (e instanceof JspLineParseException)
return (JspParseException) e;
else if (_filename == null || e instanceof LineCompileException)
return new JspLineParseException(e);
String msg;
if (e instanceof CompileException)
msg = e.getMessage();
else
msg = String.valueOf(e);
String lines = _gen.getSourceLines(_sourcePath, _startLine);
return new JspLineParseException(_filename + ":" + _startLine + ": " + msg + lines, e);
}
/**
* Returns a printable version of the node.
*/
public String toString()
{
if (_name == null)
return "<" + getClass().getName() + ">";
else
return "<" + _name.getName() + ">";
}
}