📄 tagbegingenerator.java
字号:
/* * * The Apache Software License, Version 1.1 * * Copyright (c) 1999 The Apache Software Foundation. All rights * reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * * 1. Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * * 2. Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in * the documentation and/or other materials provided with the * distribution. * * 3. The end-user documentation included with the redistribution, if * any, must include the following acknowlegement: * "This product includes software developed by the * Apache Software Foundation (http://www.apache.org/)." * Alternately, this acknowlegement may appear in the software itself, * if and wherever such third-party acknowlegements normally appear. * * 4. The names "The Jakarta Project", "Tomcat", and "Apache Software * Foundation" must not be used to endorse or promote products derived * from this software without prior written permission. For written * permission, please contact apache@apache.org. * * 5. Products derived from this software may not be called "Apache" * nor may "Apache" appear in their names without prior written * permission of the Apache Group. * * THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESSED OR IMPLIED * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE * DISCLAIMED. IN NO EVENT SHALL THE APACHE SOFTWARE FOUNDATION OR * ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF * USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF * SUCH DAMAGE. * ==================================================================== * * This software consists of voluntary contributions made by many * individuals on behalf of the Apache Software Foundation. For more * information on the Apache Software Foundation, please see * <http://www.apache.org/>. * */package org.apache.jasper.compiler;import java.util.Hashtable;import java.util.Stack;import java.util.Enumeration;import java.lang.reflect.Method;import javax.servlet.jsp.tagext.TagLibraryInfo;import javax.servlet.jsp.tagext.TagInfo;import javax.servlet.jsp.tagext.TagAttributeInfo;import javax.servlet.jsp.tagext.VariableInfo;import javax.servlet.jsp.tagext.TagData;import javax.servlet.jsp.tagext.Tag;import javax.servlet.jsp.tagext.BodyTag;import org.apache.jasper.JasperException;import org.apache.jasper.JspCompilationContext;import org.apache.jasper.Constants;import org.apache.jasper.compiler.ServletWriter;/** * Custom tag support. * * @author Anil K. Vijendran */public class TagBeginGenerator extends TagGeneratorBase implements ServiceMethodPhase{ String prefix; String shortTagName; Hashtable attrs; TagLibraryInfo tli; TagInfo ti; TagAttributeInfo[] attributes; String baseVarName, thVarName; TagCache tc; TagData tagData; Mark start; TagLibraries libraries; public TagBeginGenerator(Mark start, String prefix, String shortTagName, Hashtable attrs, TagLibraryInfo tli, TagInfo ti, TagLibraries libraries, Stack tagHandlerStack, Hashtable tagVarNumbers) throws JasperException { setTagHandlerStack(tagHandlerStack); setTagVarNumbers(tagVarNumbers); this.prefix = prefix; this.shortTagName = shortTagName; this.attrs = attrs; this.tli = tli; this.ti = ti; this.attributes = ti.getAttributes(); this.baseVarName = getTagVarName(prefix, shortTagName); this.thVarName = "_jspx_th_"+baseVarName; this.start = start; this.libraries = libraries; } public void init(JspCompilationContext ctxt) throws JasperException { validate(); tc = libraries.getTagCache(prefix, shortTagName); if (tc == null) { tc = new TagCache(shortTagName); ClassLoader cl = ctxt.getClassLoader(); Class clz = null; try { clz = cl.loadClass(ti.getTagClassName()); } catch (Exception ex) { throw new CompileException(start, Constants.getString("jsp.error.unable.loadclass", new Object[] { ti.getTagClassName(), ex.getMessage() } )); } tc.setTagHandlerClass(clz); libraries.putTagCache(prefix, shortTagName, tc); } } void validate() throws JasperException { // Sigh! I wish I didn't have to clone here. Hashtable attribs = (Hashtable) attrs.clone(); // First make sure all required attributes are indeed present. for(int i = 0; i < attributes.length; i++) if (attributes[i].isRequired() && attribs.get(attributes[i].getName()) == null) throw new CompileException(start, Constants.getString("jsp.error.missing_attribute", new Object[] { attributes[i].getName(), shortTagName } )); // Now make sure there are no invalid attributes... Enumeration e = attribs.keys(); while (e.hasMoreElements()) { String attr = (String) e.nextElement(); boolean found = false; for(int i = 0; i < attributes.length; i++) if (attr.equals(attributes[i].getName())) { found = true; if (attributes[i].canBeRequestTime() && JspUtil.isExpression((String)attribs.get(attr))) attribs.put(attr, TagData.REQUEST_TIME_VALUE); } if (!found) throw new CompileException(start, Constants.getString("jsp.error.bad_attribute", new Object[] { attr } )); } tagData = new TagData(attribs); if (!ti.isValid(tagData)) throw new CompileException(start, Constants.getString("jsp.error.invalid_attributes")); } private final void generateSetters(ServletWriter writer, String parent) throws JasperException { writer.println(thVarName+".setPageContext(pageContext);"); writer.println(thVarName+".setParent("+parent+");"); if (attributes.length != 0) for(int i = 0; i < attributes.length; i++) { String attrValue = (String) attrs.get(attributes[i].getName()); if (attrValue != null) { String attrName = attributes[i].getName(); Method m = tc.getSetterMethod(attrName); Class c[] = m.getParameterTypes(); // assert(c.length > 0) if (attributes[i].canBeRequestTime()) { if (JspUtil.isExpression(attrValue)) attrValue = JspUtil.getExpr(attrValue); else attrValue = convertString(c[0], attrValue, writer, attrName); } else attrValue = convertString(c[0], attrValue, writer, attrName); if (m == null) throw new CompileException (start, Constants.getString ("jsp.error.unable.to_find_method", new Object[] { attrName })); writer.println(thVarName+"."+m.getName()+"("+attrValue+");"); } } } public String convertString(Class c, String s, ServletWriter writer, String attrName) throws JasperException { if (c == String.class) { return writer.quoteString(s); } else if (c == boolean.class) { return Boolean.valueOf(s).toString(); } else if (c == Boolean.class) { return "new Boolean(" + Boolean.valueOf(s).toString() + ")"; } else if (c == byte.class) { return "((byte)" + Byte.valueOf(s).toString() + ")"; } else if (c == Byte.class) { return "new Byte((byte)" + Byte.valueOf(s).toString() + ")"; } else if (c == char.class) { // non-normative, because a normative method would fail to compile if (s.length() > 1) { char ch = s.charAt(0); // this trick avoids escaping issues return "((char) " + (int) ch + ")"; } else { throw new NumberFormatException(Constants.getString( "jsp.error.bad_string_char", new Object[0])); } } else if (c == Character.class) { // non-normative, because a normative method would fail to compile if (s.length() > 1) { char ch = s.charAt(0); // this trick avoids escaping issues return "new Character((char) " + (int) ch + ")"; } else { throw new NumberFormatException(Constants.getString( "jsp.error.bad_string_Character", new Object[0])); } } else if (c == double.class) { return Double.valueOf(s).toString(); } else if (c == Double.class) { return "new Double(" + Double.valueOf(s).toString() + ")"; } else if (c == float.class) { return Float.valueOf(s).toString() + "f"; } else if (c == Float.class) { return "new Float(" + Float.valueOf(s).toString() + "f)"; } else if (c == int.class) { return Integer.valueOf(s).toString(); } else if (c == Integer.class) { return "new Integer(" + Integer.valueOf(s).toString() + ")"; } else if (c == long.class) { return Long.valueOf(s).toString() + "l"; } else if (c == Long.class) { return "new Long(" + Long.valueOf(s).toString() + "l)"; } else { throw new CompileException (start, Constants.getString ("jsp.error.unable.to_convert_string", new Object[] { c.getName(), attrName })); } } public void generateServiceMethodStatements(ServletWriter writer) throws JasperException { TagVariableData top = topTag(); String parent = top == null ? null : top.tagHandlerInstanceName; String evalVar = "_jspx_eval_"+baseVarName; tagBegin(new TagVariableData(thVarName, evalVar)); writer.println("/* ---- "+prefix+":"+shortTagName+" ---- */"); writer.println(ti.getTagClassName()+" "+thVarName+" = new "+ti.getTagClassName()+"();"); generateSetters(writer, parent); VariableInfo[] vi = ti.getVariableInfo(tagData); // Just declare AT_BEGIN here... declareVariables(writer, vi, true, false, VariableInfo.AT_BEGIN); writer.println("try {"); writer.pushIndent(); writer.println("int "+evalVar+" = " +thVarName+".doStartTag();"); boolean implementsBodyTag = BodyTag.class.isAssignableFrom(tc.getTagHandlerClass()); // Need to update AT_BEGIN variables here declareVariables(writer, vi, false, true, VariableInfo.AT_BEGIN); // FIXME: I'm not too sure if this is the right approach. I don't like // throwing English language strings into the generated servlet. // Perhaps, I'll just define an inner classes as necessary for these // types of exceptions? -akv if (implementsBodyTag) { writer.println("if ("+evalVar+" == Tag.EVAL_BODY_INCLUDE)"); writer.pushIndent(); writer.println("throw new JspTagException(\"Since tag handler "+tc.getTagHandlerClass()+ " implements BodyTag, it can't return Tag.EVAL_BODY_INCLUDE\");"); writer.popIndent(); } else { writer.println("if ("+evalVar+" == BodyTag.EVAL_BODY_TAG)"); writer.pushIndent(); writer.println("throw new JspTagException(\"Since tag handler "+tc.getTagHandlerClass()+ " does not implement BodyTag, it can't return BodyTag.EVAL_BODY_TAG\");"); writer.popIndent(); } writer.println("if ("+evalVar+" != Tag.SKIP_BODY) {"); writer.pushIndent(); if (implementsBodyTag) { writer.println("try {"); writer.pushIndent(); writer.println("if ("+evalVar+" != Tag.EVAL_BODY_INCLUDE) {"); writer.pushIndent(); writer.println("out = pageContext.pushBody();"); writer.println(thVarName+".setBodyContent((BodyContent) out);"); writer.popIndent(); writer.println("}"); writer.println(thVarName+".doInitBody();"); } writer.println("do {"); writer.pushIndent(); // Need to declare and update NESTED variables here declareVariables(writer, vi, true, true, VariableInfo.NESTED); // Need to update AT_BEGIN variables here declareVariables(writer, vi, false, true, VariableInfo.AT_BEGIN); } public void generate(ServletWriter writer, Class phase) throws JasperException { generateServiceMethodStatements(writer); }}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -