
org.apache.jasper.compiler.Generator Maven / Gradle / Ivy
/*
* Copyright 1999,2004 The Apache Software Foundation.
*
* Licensed 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.compiler;
import java.util.*;
import java.beans.*;
import java.net.URLEncoder;
import java.lang.reflect.Method;
import javax.servlet.jsp.tagext.*;
import org.xml.sax.Attributes;
import org.apache.jasper.JasperException;
import org.apache.jasper.JspCompilationContext;
import org.apache.jasper.runtime.JspRuntimeLibrary;
import org.apache.jasper.Constants;
/**
* Generate Java source from Nodes
*
* @author Anil K. Vijendran
* @author Danno Ferrin
* @author Mandar Raje
* @author Rajiv Mordani
* @author Pierre Delisle
* @author Kin-man Chung
* @author Jan Luehe
* @author Denis Benoit
*/
public class Generator {
private ServletWriter out;
private MethodsBuffer methodsBuffer;
private ErrorDispatcher err;
private BeanRepository beanInfo;
private JspCompilationContext ctxt;
private boolean breakAtLF;
private PageInfo pageInfo;
private int maxTagNesting;
private Vector tagHandlerPoolNames;
/**
* @param s the input string
* @return quoted and escaped string, per Java rule
*/
private static String quote(String s) {
if (s == null)
return "null";
return '"' + escape( s ) + '"';
}
/**
* @param s the input string
* @return escaped string, per Java rule
*/
private static String escape(String s) {
if (s == null)
return "";
StringBuffer b = new StringBuffer();
for (int i = 0; i < s.length(); i++) {
char c = s.charAt(i);
if (c == '"')
b.append('\\').append('"');
else if (c == '\\')
b.append('\\').append('\\');
else if (c == '\n')
b.append('\\').append('n');
else if (c == '\r')
b.append('\\').append('r');
else
b.append(c);
}
return b.toString();
}
/**
* Generates declarations. This includes "info" of the page directive,
* and scriptlet declarations.
*/
private void generateDeclarations(Node.Nodes page) throws JasperException {
class DeclarationVisitor extends Node.Visitor {
public void visit(Node.PageDirective n) throws JasperException {
String info = n.getAttributeValue("info");
if (info == null)
return;
out.printil("public String getServletInfo() {");
out.pushIndent();
out.printin("return ");
out.print (quote(info));
out.println(";");
out.popIndent();
out.print ('}');
out.println();
}
public void visit(Node.Declaration n) throws JasperException {
out.printMultiLn(new String(n.getText()));
out.println();
}
}
out.println();
page.visit(new DeclarationVisitor());
}
/**
* Compiles list of tag handler pool names.
*/
private void compileTagHandlerPoolList(Node.Nodes page)
throws JasperException {
class TagHandlerPoolVisitor extends Node.Visitor {
private Vector names;
/*
* Constructor
*
* @param v Vector of tag handler pool names to populate
*/
TagHandlerPoolVisitor(Vector v) {
names = v;
}
/*
* Gets the name of the tag handler pool for the given custom tag
* and adds it to the list of tag handler pool names unless it is
* already contained in it.
*/
public void visit(Node.CustomTag n) throws JasperException {
String name = createTagHandlerPoolName(n.getPrefix(),
n.getShortName(),
n.getAttributes(),
n.getBody() == null);
n.setTagHandlerPoolName(name);
if (!names.contains(name)) {
names.add(name);
}
visitBody(n);
}
/*
* Creates the name of the tag handler pool whose tag handlers may
* be (re)used to service this action.
*
* @return The name of the tag handler pool
*/
private String createTagHandlerPoolName(String prefix,
String shortName,
Attributes attrs,
boolean hasEmptyBody) {
String poolName = null;
if (prefix.indexOf('-') >= 0)
prefix = JspUtil.replace(prefix, '-', "$1");
if (prefix.indexOf('.') >= 0)
prefix = JspUtil.replace(prefix, '.', "$2");
if (shortName.indexOf('-') >= 0)
shortName = JspUtil.replace(shortName, '-', "$1");
if (shortName.indexOf('.') >= 0)
shortName = JspUtil.replace(shortName, '.', "$2");
if (shortName.indexOf(':') >= 0)
shortName = JspUtil.replace(shortName, ':', "$3");
poolName = "_jspx_tagPool_" + prefix + "_" + shortName;
if (attrs != null) {
String[] attrNames = new String[attrs.getLength()];
for (int i=0; i 0) {
TagVariableInfo[] tagVarInfos = n.getTagVariableInfos();
VariableInfo[] varInfos = n.getVariableInfos();
if (varInfos != null) {
for (int i=0; i 0) {
out.printil("JspxState _jspxState = new JspxState();");
}
*/
out.printil("JspWriter _jspx_out = null;");
out.println();
declareTemporaryScriptingVars(page);
out.println();
out.printil("try {");
out.pushIndent();
out.printil("_jspxFactory = JspFactory.getDefaultFactory();");
out.printin("response.setContentType(");
out.print (quote(pageInfo.getContentType()));
out.println(");");
out.printil("pageContext = _jspxFactory.getPageContext(this, request, response,");
out.printin("\t\t\t");
out.print (quote(pageInfo.getErrorPage()));
out.print (", " + pageInfo.isSession());
out.print (", " + pageInfo.getBuffer());
out.print (", " + pageInfo.isAutoFlush());
out.println(");");
out.printil("application = pageContext.getServletContext();");
out.printil("config = pageContext.getServletConfig();");
if (pageInfo.isSession())
out.printil("session = pageContext.getSession();");
out.printil("out = pageContext.getOut();");
out.printil("_jspx_out = out;");
out.println();
}
/*
* Generates the servlet constructor.
*/
private void generateServletConstructor(String servletClassName) {
out.printil("public " + servletClassName + "() {");
out.pushIndent();
for (int i=0; i: tag prefix
* : hashtable containing introspection on tag handlers:
* : tag short name
* : introspection info of tag handler for
* tag
*/
private Hashtable handlerInfos;
private Hashtable tagVarNumbers;
private String parent;
private String pushBodyCountVar;
private ServletWriter out;
private MethodsBuffer methodsBuffer;
private int methodNesting;
/**
* Constructor.
*/
public GenerateVisitor(ServletWriter out,
MethodsBuffer methodsBuffer) {
this.out = out;
this.methodsBuffer = methodsBuffer;
methodNesting = 0;
handlerInfos = new Hashtable();
tagVarNumbers = new Hashtable();
}
/**
* Returns an attribute value, optionally URL encoded. If
* the value is a runtime expression, the result is the string for
* the expression, otherwise the result is the string literal,
* quoted and escaped.
* @param attr An JspAttribute object
* @param encode true if to be URL encoded
*/
private String attributeValue(Node.JspAttribute attr, boolean encode) {
String v = attr.getValue();
if (v == null)
return "";
if (attr.isExpression()) {
if (encode) {
return "java.net.URLEncoder.encode(\"\" + " + v + ")";
}
return v;
} else {
if (encode) {
v = URLEncoder.encode(v);
}
return quote(v);
}
}
/**
* Prints the attribute value specified in the param action, in the
* form of name=value string.
*
* @param n the parent node for the param action nodes.
*/
private void printParams(Node n, Node.JspAttribute page)
throws JasperException {
class ParamVisitor extends Node.Visitor {
String separator;
ParamVisitor(String separator){
this.separator = separator;
}
public void visit(Node.ParamAction n) throws JasperException {
out.print(" + ");
out.print(separator);
out.print(" + \"");
out.print(n.getAttributeValue("name"));
out.print("=\" + ");
out.print(attributeValue(n.getValue(), true));
// The separator is '&' after the second use
separator = "\"&\"";
}
}
String pValue = page.getValue();
String sep;
if (page.isExpression()) {
sep = "((" + pValue + ").indexOf('?')>0? '&': '?')";
} else {
sep = pValue.indexOf('?')>0? "\"&\"": "\"?\"";
}
if (n.getBody() != null) {
n.getBody().visit(new ParamVisitor(sep));
}
}
public void visit(Node.Expression n) throws JasperException {
n.setBeginJavaLine(out.getJavaLine());
out.printil("out.print(" + new String(n.getText()) + ");");
n.setEndJavaLine(out.getJavaLine());
}
public void visit(Node.Scriptlet n) throws JasperException {
n.setBeginJavaLine(out.getJavaLine());
out.printMultiLn(new String(n.getText()));
out.println();
n.setEndJavaLine(out.getJavaLine());
}
public void visit(Node.IncludeAction n) throws JasperException {
String flush = n.getAttributeValue("flush");
boolean isFlush = false; // default to false;
if ("true".equals(flush))
isFlush = true;
n.setBeginJavaLine(out.getJavaLine());
out.printin("JspRuntimeLibrary.include(request, response, ");
out.print(attributeValue(n.getPage(), false));
printParams(n, n.getPage());
out.println(", out, " + isFlush + ");");
n.setEndJavaLine(out.getJavaLine());
}
public void visit(Node.ForwardAction n) throws JasperException {
String page = n.getAttributeValue("page");
n.setBeginJavaLine(out.getJavaLine());
out.printil("if (true) {"); // So that javac won't complain about
out.pushIndent(); // codes after "return"
out.printin("pageContext.forward(");
out.print(attributeValue(n.getPage(), false));
printParams(n, n.getPage());
out.println(");");
out.printil((methodNesting > 0)? "return true;": "return;");
out.popIndent();
out.printil("}");
n.setEndJavaLine(out.getJavaLine());
// XXX Not sure if we can eliminate dead codes after this.
}
public void visit(Node.GetProperty n) throws JasperException {
String name = n.getAttributeValue("name");
String property = n.getAttributeValue("property");
n.setBeginJavaLine(out.getJavaLine());
if (beanInfo.checkVariable(name)) {
// Bean is defined using useBean, introspect at compile time
Class bean = beanInfo.getBeanType(name);
String beanName = bean.getName();
java.lang.reflect.Method meth =
JspRuntimeLibrary.getReadMethod(bean, property);
String methodName = meth.getName();
out.printil("out.print(JspRuntimeLibrary.toString(" +
"(((" + beanName + ")pageContext.findAttribute(" +
"\"" + name + "\"))." + methodName + "())));");
} else {
// The object could be a custom action with an associated
// VariableInfo entry for this name.
// Get the class name and then introspect at runtime.
out.printil("out.print(JspRuntimeLibrary.toString" +
"(JspRuntimeLibrary.handleGetProperty" +
"(pageContext.findAttribute(\"" +
name + "\"), \"" + property + "\")));");
}
n.setEndJavaLine(out.getJavaLine());
}
public void visit(Node.SetProperty n) throws JasperException {
String name = n.getAttributeValue("name");
String property = n.getAttributeValue("property");
String param = n.getAttributeValue("param");
Node.JspAttribute value = n.getValue();
n.setBeginJavaLine(out.getJavaLine());
if ("*".equals(property)){
out.printil("JspRuntimeLibrary.introspect(" +
"pageContext.findAttribute(" +
"\"" + name + "\"), request);");
} else if (value == null) {
if (param == null)
param = property; // default to same as property
out.printil("JspRuntimeLibrary.introspecthelper(" +
"pageContext.findAttribute(\"" + name + "\"), \"" +
property + "\", request.getParameter(\"" + param +
"\"), " + "request, \"" + param + "\", false);");
} else if (value.isExpression()) {
out.printil("JspRuntimeLibrary.handleSetProperty(" +
"pageContext.findAttribute(\"" + name + "\"), \""
+ property + "\",");
out.print(attributeValue(value, false));
out.println(");");
} else {
out.printil("JspRuntimeLibrary.introspecthelper(" +
"pageContext.findAttribute(\"" + name + "\"), \"" +
property + "\",");
out.print(attributeValue(value, false));
out.println(",null, null, false);");
}
n.setEndJavaLine(out.getJavaLine());
}
public void visit(Node.UseBean n) throws JasperException {
String name = n.getAttributeValue ("id");
String scope = n.getAttributeValue ("scope");
String klass = n.getAttributeValue ("class");
String type = n.getAttributeValue ("type");
Node.JspAttribute beanName = n.getBeanName();
if (type == null) // if unspecified, use class as type of bean
type = klass;
String scopename = "PageContext.PAGE_SCOPE"; // Default to page
String lock = "pageContext";
if ("request".equals(scope)) {
scopename = "PageContext.REQUEST_SCOPE";
lock = "request";
} else if ("session".equals(scope)) {
scopename = "PageContext.SESSION_SCOPE";
lock = "session";
} else if ("application".equals(scope)) {
scopename = "PageContext.APPLICATION_SCOPE";
lock = "application";
}
n.setBeginJavaLine(out.getJavaLine());
// Declare bean
out.printin(type);
out.print (' ');
out.print (name);
out.println(" = null;");
// Lock while getting or creating bean
out.printin("synchronized (");
out.print (lock);
out.println(") {");
out.pushIndent();
// Locate bean from context
out.printin(name);
out.print (" = (");
out.print (type);
out.print (") pageContext.getAttribute(");
out.print (quote(name));
out.print (", ");
out.print (scopename);
out.println(");");
// Create bean
/*
* Check if bean is alredy there
*/
out.printin("if (");
out.print (name);
out.println(" == null){");
out.pushIndent();
if (klass == null && beanName == null) {
/*
* If both class name and beanName is not specified, the bean
* must be found locally, otherwise it's an error
*/
out.printin("throw new java.lang.InstantiationException(\"bean ");
out.print (name);
out.println(" not found within scope\");");
} else {
/*
* Instantiate bean if not there
*/
String className;
if (beanName != null) {
className = attributeValue(beanName, false);
}
else {
// Implies klass is not null
className = quote(klass);
}
out.printil("try {");
out.pushIndent();
out.printin(name);
out.print (" = (");
out.print (type);
out.print (") java.beans.Beans.instantiate(");
out.print ("this.getClass().getClassLoader(), ");
out.print (className);
out.println(");");
out.popIndent();
/*
* Note: Beans.instantiate throws ClassNotFoundException
* if the bean class is abstract.
*/
out.printil("} catch (ClassNotFoundException exc) {");
out.pushIndent();
out.printil("throw new InstantiationException(exc.getMessage());");
out.popIndent();
out.printil("} catch (Exception exc) {");
out.pushIndent();
out.printin("throw new ServletException(");
out.print ("\"Cannot create bean of class \" + ");
out.print (className);
out.println(", exc);");
out.popIndent();
out.printil("}"); // close of try
/*
* Set attribute for bean in the specified scope
*/
out.printin("pageContext.setAttribute(");
out.print (quote(name));
out.print (", ");
out.print (name);
out.print (", ");
out.print (scopename);
out.println(");");
// Only visit the body when bean is instantiated
visitBody(n);
}
out.popIndent();
out.printil("}");
// End of lock block
out.popIndent();
out.printil("}");
n.setEndJavaLine(out.getJavaLine());
}
/**
* @return a string for the form 'attr = "value"'
*/
private String makeAttr(String attr, String value) {
if (value == null)
return "";
return " " + attr + "=\"" + value + '\"';
}
public void visit(Node.PlugIn n) throws JasperException {
/**
* A visitor to handle in a plugin
*/
class ParamVisitor extends Node.Visitor {
private boolean ie;
ParamVisitor(boolean ie) {
this.ie = ie;
}
public void visit(Node.ParamAction n) throws JasperException {
String name = n.getAttributeValue("name");
if (name.equalsIgnoreCase("object"))
name = "java_object";
else if (name.equalsIgnoreCase ("type"))
name = "java_type";
n.setBeginJavaLine(out.getJavaLine());
if( ie ) {
// We want something of the form
// out.println( "" );
out.printil( "out.write( \"\" );" );
out.printil("out.write(\"\\n\");");
}
else {
// We want something of the form
// out.print( " blah=\"" + ... + "\"" );
out.printil( "out.write( \" " + escape( name ) +
"=\\\"\" + " +
attributeValue( n.getValue(), false) +
" + \"\\\"\" );" );
}
n.setEndJavaLine(out.getJavaLine());
}
}
String type = n.getAttributeValue("type");
String code = n.getAttributeValue("code");
String name = n.getAttributeValue("name");
Node.JspAttribute height = n.getHeight();
Node.JspAttribute width = n.getWidth();
String hspace = n.getAttributeValue("hspace");
String vspace = n.getAttributeValue("vspace");
String align = n.getAttributeValue("align");
String iepluginurl = n.getAttributeValue("iepluginurl");
String nspluginurl = n.getAttributeValue("nspluginurl");
String codebase = n.getAttributeValue("codebase");
String archive = n.getAttributeValue("archive");
String jreversion = n.getAttributeValue("jreversion");
if (iepluginurl == null)
iepluginurl = Constants.IE_PLUGIN_URL;
if (nspluginurl == null)
nspluginurl = Constants.NS_PLUGIN_URL;
n.setBeginJavaLine(out.getJavaLine());
// IE style plugin
//
© 2015 - 2025 Weber Informatics LLC | Privacy Policy