Anforderungen  |   Konzepte  |   Entwurf  |   Entwicklung  |   Qualitätssicherung  |   Lebenszyklus  |   Steuerung
 
 
 
 


Quelle  Generator.java   Sprache: JAVA

 
/*
 * 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.compiler;

import java.beans.BeanInfo;
import java.beans.IntrospectionException;
import java.beans.Introspector;
import java.beans.PropertyDescriptor;
import java.lang.reflect.Constructor;
import java.lang.reflect.Method;
import java.lang.reflect.Modifier;
import java.text.DateFormat;
import java.text.SimpleDateFormat;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Collections;
import java.util.Date;
import java.util.HashMap;
import java.util.HashSet;
import java.util.List;
import java.util.Map;
import java.util.Map.Entry;
import java.util.Set;
import java.util.TimeZone;
import java.util.regex.Matcher;
import java.util.regex.Pattern;

import jakarta.el.MethodExpression;
import jakarta.el.ValueExpression;
import jakarta.servlet.jsp.tagext.TagAttributeInfo;
import jakarta.servlet.jsp.tagext.TagInfo;
import jakarta.servlet.jsp.tagext.TagVariableInfo;
import jakarta.servlet.jsp.tagext.VariableInfo;

import org.apache.jasper.JasperException;
import org.apache.jasper.JspCompilationContext;
import org.apache.jasper.TrimSpacesOption;
import org.apache.jasper.compiler.Node.ChildInfoBase;
import org.apache.jasper.compiler.Node.NamedAttribute;
import org.apache.jasper.runtime.JspRuntimeLibrary;
import org.apache.juli.logging.Log;
import org.apache.juli.logging.LogFactory;
import org.xml.sax.Attributes;

/**
 * Generate Java source from Nodes
 *
 * @author Anil K. Vijendran
 * @author Danno Ferrin
 * @author Mandar Raje
 * @author Rajiv Mordani
 * @author Pierre Delisle
 *
 * Tomcat 4.1.x and Tomcat 5:
 * @author Kin-man Chung
 * @author Jan Luehe
 * @author Shawn Bayern
 * @author Mark Roth
 * @author Denis Benoit
 *
 * Tomcat 6.x
 * @author Jacob Hookom
 * @author Remy Maucherat
 */


class Generator {

    private final Log log = LogFactory.getLog(Generator.class); // must not be static

    private static final Class<?>[] OBJECT_CLASS = { Object.class };

    private static final Pattern PRE_TAG_PATTERN = Pattern.compile("(?s).*(
|
).*"
);

    private static final Pattern BLANK_LINE_PATTERN = Pattern.compile("(\\s*(\\n|\\r)+\\s*)");

    private final ServletWriter out;

    private final ArrayList<GenBuffer> methodsBuffered;

    private final FragmentHelperClass fragmentHelperClass;

    private final ErrorDispatcher err;

    private final BeanRepository beanInfo;

    private final Set<String> varInfoNames;

    private final JspCompilationContext ctxt;

    private final boolean isPoolingEnabled;

    private final boolean breakAtLF;

    private String jspIdPrefix;

    private int jspId;

    private final PageInfo pageInfo;

    private final List<String> tagHandlerPoolNames;

    private GenBuffer charArrayBuffer;

    private final DateFormat timestampFormat;

    private final ELInterpreter elInterpreter;

    private final StringInterpreter stringInterpreter;

    /**
     * @param s
     *            the input string
     * @return quoted and escaped string, per Java rule
     */

    static String quote(String s) {

        if (s == null) {
            return "null";
        }

        return '"' + escape(s) + '"';
    }

    /**
     * @param s     the input string - must not be {@code null}
     *
     * @return escaped string, per Java rule
     */

    static String escape(String s) {

        StringBuilder b = new StringBuilder();
        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();
    }

    /**
     * Single quote and escape a character
     */

    static String quote(char c) {

        StringBuilder b = new StringBuilder();
        b.append('\'');
        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);
        }
        b.append('\'');
        return b.toString();
    }

    private String createJspId() {
        if (this.jspIdPrefix == null) {
            StringBuilder sb = new StringBuilder(32);
            String name = ctxt.getServletJavaFileName();
            sb.append("jsp_");
            // Cast to long to avoid issue with Integer.MIN_VALUE
            sb.append(Math.abs((long) name.hashCode()));
            sb.append('_');
            this.jspIdPrefix = sb.toString();
        }
        return this.jspIdPrefix + (this.jspId++);
    }

    /**
     * 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 {

            private boolean getServletInfoGenerated = false;

            /*
             * Generates getServletInfo() method that returns the value of the
             * page directive's 'info' attribute, if present.
             *
             * The Validator has already ensured that if the translation unit
             * contains more than one page directive with an 'info' attribute,
             * their values match.
             */

            @Override
            public void visit(Node.PageDirective n) throws JasperException {

                if (getServletInfoGenerated) {
                    return;
                }

                String info = n.getAttributeValue("info");
                if (info == null) {
                    return;
                }

                getServletInfoGenerated = true;
                out.printil("public java.lang.String getServletInfo() {");
                out.pushIndent();
                out.printin("return ");
                out.print(quote(info));
                out.println(";");
                out.popIndent();
                out.printil("}");
                out.println();
            }

            @Override
            public void visit(Node.Declaration n) throws JasperException {
                n.setBeginJavaLine(out.getJavaLine());
                out.printMultiLn(n.getText());
                out.println();
                n.setEndJavaLine(out.getJavaLine());
            }

            // Custom Tags may contain declarations from tag plugins.
            @Override
            public void visit(Node.CustomTag n) throws JasperException {
                if (n.useTagPlugin()) {
                    // If a custom tag is configured to use a plug-in
                    // getAtSTag() and  getAtETag() will always be non-null
                    n.getAtSTag().visit(this);
                    visitBody(n);
                    n.getAtETag().visit(this);
                } else {
                    visitBody(n);
                }
            }
        }

        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 final List<String> names;

            /*
             * Constructor
             *
             * @param v Vector of tag handler pool names to populate
             */

            TagHandlerPoolVisitor(List<String> 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.
             */

            @Override
            public void visit(Node.CustomTag n) throws JasperException {

                if (!n.implementsSimpleTag()) {
                    String name = createTagHandlerPoolName(n.getPrefix(), n
                            .getLocalName(), n.getAttributes(),
                            n.getNamedAttributeNodes(), n.hasEmptyBody());
                    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, Node.Nodes namedAttrs,
                    boolean hasEmptyBody) {
                StringBuilder poolName = new StringBuilder(64);
                poolName.append("_jspx_tagPool_").append(prefix).append('_')
                        .append(shortName);

                if (attrs != null) {
                    String[] attrNames =
                        new String[attrs.getLength() + namedAttrs.size()];
                    for (int i = 0; i < attrNames.length; i++) {
                        attrNames[i] = attrs.getQName(i);
                    }
                    for (int i = 0; i < namedAttrs.size(); i++) {
                        attrNames[attrs.getLength() + i] =
                            namedAttrs.getNode(i).getQName();
                    }
                    Arrays.sort(attrNames, Collections.reverseOrder());
                    if (attrNames.length > 0) {
                        poolName.append('&');
                    }
                    for (String attrName : attrNames) {
                        poolName.append('_');
                        poolName.append(attrName);
                    }
                }
                if (hasEmptyBody) {
                    poolName.append("_nobody");
                }
                return JspUtil.makeJavaIdentifier(poolName.toString());
            }
        }

        page.visit(new TagHandlerPoolVisitor(tagHandlerPoolNames));
    }

    private void declareTemporaryScriptingVars(Node.Nodes page)
            throws JasperException {

        class ScriptingVarVisitor extends Node.Visitor {

            private final List<String> vars;

            ScriptingVarVisitor() {
                vars = new ArrayList<>();
            }

            @Override
            public void visit(Node.CustomTag n) throws JasperException {
                // XXX - Actually there is no need to declare those
                // "_jspx_" + varName + "_" + nestingLevel variables when we are
                // inside a JspFragment.

                if (n.getCustomNestingLevel() > 0) {
                    TagVariableInfo[] tagVarInfos = n.getTagVariableInfos();
                    VariableInfo[] varInfos = n.getVariableInfos();

                    if (varInfos.length > 0) {
                        for (VariableInfo varInfo : varInfos) {
                            String varName = varInfo.getVarName();
                            String tmpVarName = "_jspx_" + varName + "_"
                                    + n.getCustomNestingLevel();
                            if (!vars.contains(tmpVarName)) {
                                vars.add(tmpVarName);
                                out.printin(varInfo.getClassName());
                                out.print(" ");
                                out.print(tmpVarName);
                                out.print(" = ");
                                out.print(null);
                                out.println(";");
                            }
                        }
                    } else {
                        for (TagVariableInfo tagVarInfo : tagVarInfos) {
                            String varName = tagVarInfo.getNameGiven();
                            if (varName == null) {
                                varName = n.getTagData().getAttributeString(
                                        tagVarInfo.getNameFromAttribute());
                            }
                            else if (tagVarInfo.getNameFromAttribute() != null) {
                                // alias
                                continue;
                            }
                            String tmpVarName = "_jspx_" + varName + "_"
                                    + n.getCustomNestingLevel();
                            if (!vars.contains(tmpVarName)) {
                                vars.add(tmpVarName);
                                out.printin(tagVarInfo.getClassName());
                                out.print(" ");
                                out.print(tmpVarName);
                                out.print(" = ");
                                out.print(null);
                                out.println(";");
                            }
                        }
                    }
                }

                visitBody(n);
            }
        }

        page.visit(new ScriptingVarVisitor());
    }

    /*
     * Generates getters for
     * - instance manager
     * - expression factory
     *
     * For JSPs these methods use lazy init. This is not an option for tag files
     * (at least it would be more complicated to generate) because the
     * ServletConfig is not readily available.
     */

    private void generateGetters() {
        out.printil("public jakarta.el.ExpressionFactory _jsp_getExpressionFactory() {");
        out.pushIndent();
        if (!ctxt.isTagFile()) {
            out.printin("if (");
            out.print(ctxt.getOptions().getVariableForExpressionFactory());
            out.println(" == null) {");
            out.pushIndent();
            out.printil("synchronized (this) {");
            out.pushIndent();
            out.printin("if (");
            out.print(ctxt.getOptions().getVariableForExpressionFactory());
            out.println(" == null) {");
            out.pushIndent();
            out.printin(ctxt.getOptions().getVariableForExpressionFactory());
            out.println(" = _jspxFactory.getJspApplicationContext(getServletConfig().getServletContext()).getExpressionFactory();");
            out.popIndent();
            out.printil("}");
            out.popIndent();
            out.printil("}");
            out.popIndent();
            out.printil("}");
        }
        out.printin("return ");
        out.print(ctxt.getOptions().getVariableForExpressionFactory());
        out.println(";");
        out.popIndent();
        out.printil("}");

        out.println();

        out.printil("public org.apache.tomcat.InstanceManager _jsp_getInstanceManager() {");
        out.pushIndent();
        if (!ctxt.isTagFile()) {
            out.printin("if (");
            out.print(ctxt.getOptions().getVariableForInstanceManager());
            out.println(" == null) {");
            out.pushIndent();
            out.printil("synchronized (this) {");
            out.pushIndent();
            out.printin("if (");
            out.print(ctxt.getOptions().getVariableForInstanceManager());
            out.println(" == null) {");
            out.pushIndent();
            out.printin(ctxt.getOptions().getVariableForInstanceManager());
            out.println(" = org.apache.jasper.runtime.InstanceManagerFactory.getInstanceManager(getServletConfig());");
            out.popIndent();
            out.printil("}");
            out.popIndent();
            out.printil("}");
            out.popIndent();
            out.printil("}");
        }
        out.printin("return ");
        out.print(ctxt.getOptions().getVariableForInstanceManager());
        out.println(";");
        out.popIndent();
        out.printil("}");

        out.println();
    }

    /**
     * Generates the _jspInit() method for instantiating the tag handler pools.
     * For tag file, _jspInit has to be invoked manually, and the ServletConfig
     * object explicitly passed.
     *
     * In JSP 2.1, we also instantiate an ExpressionFactory
     */

    private void generateInit() {

        if (ctxt.isTagFile()) {
            out.printil("private void _jspInit(jakarta.servlet.ServletConfig config) {");
        } else {
            out.printil("public void _jspInit() {");
        }

        out.pushIndent();
        if (isPoolingEnabled) {
            for (int i = 0; i < tagHandlerPoolNames.size(); i++) {
                out.printin(tagHandlerPoolNames.get(i));
                out.print(" = org.apache.jasper.runtime.TagHandlerPool.getTagHandlerPool(");
                if (ctxt.isTagFile()) {
                    out.print("config");
                } else {
                    out.print("getServletConfig()");
                }
                out.println(");");
            }
        }

        // Tag files can't (easily) use lazy init for these so initialise them
        // here.
        if (ctxt.isTagFile()) {
            out.printin(ctxt.getOptions().getVariableForExpressionFactory());
            out.println(" = _jspxFactory.getJspApplicationContext(config.getServletContext()).getExpressionFactory();");
            out.printin(ctxt.getOptions().getVariableForInstanceManager());
            out.println(" = org.apache.jasper.runtime.InstanceManagerFactory.getInstanceManager(config);");
        }

        out.popIndent();
        out.printil("}");
        out.println();
    }

    /**
     * Generates the _jspDestroy() method which is responsible for calling the
     * release() method on every tag handler in any of the tag handler pools.
     */

    private void generateDestroy() {

        out.printil("public void _jspDestroy() {");
        out.pushIndent();

        if (isPoolingEnabled) {
            for (int i = 0; i < tagHandlerPoolNames.size(); i++) {
                out.printin(tagHandlerPoolNames.get(i));
                out.println(".release();");
            }
        }

        out.popIndent();
        out.printil("}");
        out.println();
    }

    /**
     * Generate preamble package name (shared by servlet and tag handler
     * preamble generation). Package is always non-null as neither Servlets nor
     * tags can use a default package.
     */

    private void genPreamblePackage(String packageName) {
        out.printil("package " + packageName + ";");
        out.println();
    }

    /**
     * Generate preamble imports (shared by servlet and tag handler preamble
     * generation)
     */

    private void genPreambleImports() {
        for (String i : pageInfo.getImports()) {
            out.printin("import ");
            out.print(i);
            out.println(";");
        }

        out.println();
    }

    /**
     * Generation of static initializers in preamble. For example, dependent
     * list, el function map, prefix map. (shared by servlet and tag handler
     * preamble generation)
     */

    private void genPreambleStaticInitializers() {
        out.printil("private static final jakarta.servlet.jsp.JspFactory _jspxFactory =");
        out.printil(" jakarta.servlet.jsp.JspFactory.getDefaultFactory();");
        out.println();

        // Static data for getDependants()
        out.printil("private static java.util.Map _jspx_dependants;");
        out.println();
        Map<String,Long> dependants = pageInfo.getDependants();
        if (!dependants.isEmpty()) {
            out.printil("static {");
            out.pushIndent();
            out.printin("_jspx_dependants = new java.util.HashMap(");
            out.print("" + dependants.size());
            out.println(");");
            for (Entry<String, Long> entry : dependants.entrySet()) {
                out.printin("_jspx_dependants.put(\"");
                out.print(entry.getKey());
                out.print("\"Long.valueOf(");
                out.print(entry.getValue().toString());
                out.println("L));");
            }
            out.popIndent();
            out.printil("}");
            out.println();
        }

        // Static data for getImports()
        List<String> imports = pageInfo.getImports();
        Set<String> packages = new HashSet<>();
        Set<String> classes = new HashSet<>();
        for (String importName : imports) {
            String trimmed = importName.trim();
            if (trimmed.endsWith(".*")) {
                packages.add(trimmed.substring(0, trimmed.length() - 2));
            } else {
                classes.add(trimmed);
            }
        }
        out.printil("private static final java.util.Set _jspx_imports_packages;");
        out.println();
        out.printil("private static final java.util.Set _jspx_imports_classes;");
        out.println();
        out.printil("static {");
        out.pushIndent();
        // Packages is never empty because o.a.j.Constants.STANDARD_IMPORTS
        // contains 3 packages and is always added to the imports.
        out.printin("_jspx_imports_packages = new java.util.HashSet<>();");
        out.println();
        for (String packageName : packages) {
            out.printin("_jspx_imports_packages.add(\"");
            out.print(packageName);
            out.println("\");");
        }
        // classes however, may be empty depending on the import declarations
        if (classes.size() == 0) {
            out.printin("_jspx_imports_classes = null;");
            out.println();
        } else {
            out.printin("_jspx_imports_classes = new java.util.HashSet<>();");
            out.println();
            for (String className : classes) {
                out.printin("_jspx_imports_classes.add(\"");
                out.print(className);
                out.println("\");");
            }
        }
        out.popIndent();
        out.printil("}");
        out.println();
    }

    /**
     * Declare tag handler pools (tags of the same type and with the same
     * attribute set share the same tag handler pool) (shared by servlet and tag
     * handler preamble generation)
     *
     * In JSP 2.1, we also scope an instance of ExpressionFactory
     */

    private void genPreambleClassVariableDeclarations() {
        if (isPoolingEnabled && !tagHandlerPoolNames.isEmpty()) {
            for (int i = 0; i < tagHandlerPoolNames.size(); i++) {
                out.printil("private org.apache.jasper.runtime.TagHandlerPool " + tagHandlerPoolNames.get(i) + ";");
            }
            out.println();
        }
        out.printin("private volatile jakarta.el.ExpressionFactory ");
        out.print(ctxt.getOptions().getVariableForExpressionFactory());
        out.println(";");
        out.printin("private volatile org.apache.tomcat.InstanceManager ");
        out.print(ctxt.getOptions().getVariableForInstanceManager());
        out.println(";");
        out.println();
    }

    /**
     * Declare general-purpose methods (shared by servlet and tag handler
     * preamble generation)
     */

    private void genPreambleMethods() {
        // Implement JspSourceDependent
        out.printil("public java.util.Map getDependants() {");
        out.pushIndent();
        out.printil("return _jspx_dependants;");
        out.popIndent();
        out.printil("}");
        out.println();

        // Implement JspSourceImports
        out.printil("public java.util.Set getPackageImports() {");
        out.pushIndent();
        out.printil("return _jspx_imports_packages;");
        out.popIndent();
        out.printil("}");
        out.println();
        out.printil("public java.util.Set getClassImports() {");
        out.pushIndent();
        out.printil("return _jspx_imports_classes;");
        out.popIndent();
        out.printil("}");
        out.println();

        // Implement JspSourceDirectives
        out.printil("public boolean getErrorOnELNotFound() {");
        out.pushIndent();
        if (pageInfo.isErrorOnELNotFound()) {
            out.printil("return true;");
        } else {
            out.printil("return false;");
        }
        out.popIndent();
        out.printil("}");
        out.println();

        generateGetters();
        generateInit();
        generateDestroy();
    }

    /**
     * Generates the beginning of the static portion of the servlet.
     */

    private void generatePreamble(Node.Nodes page) throws JasperException {

        String servletPackageName = ctxt.getServletPackageName();
        String servletClassName = ctxt.getServletClassName();
        String serviceMethodName = ctxt.getOptions().getServiceMethodName();

        // First the package name:
        genPreamblePackage(servletPackageName);

        // Generate imports
        genPreambleImports();

        // Generate class declaration
        out.printin("public final class ");
        out.print(servletClassName);
        out.print(" extends ");
        out.println(pageInfo.getExtends());
        out.printin(" implements org.apache.jasper.runtime.JspSourceDependent,");
        out.println();
        out.printin(" org.apache.jasper.runtime.JspSourceImports");
        out.println(",");
        out.printin(" org.apache.jasper.runtime.JspSourceDirectives");
        out.println(" {");
        out.pushIndent();

        // Class body begins here
        generateDeclarations(page);

        // Static initializations here
        genPreambleStaticInitializers();

        // Class variable declarations
        genPreambleClassVariableDeclarations();

        // Methods here
        genPreambleMethods();

        // Now the service method
        if (pageInfo.isThreadSafe()) {
            out.printin("public void ");
        } else {
            // This is unlikely to perform well.
            out.printin("public synchronized void ");
            // As required by JSP 3.1, log a warning
            log.warn(Localizer.getMessage("jsp.warning.isThreadSafe", ctxt.getJspFile()));
        }
        out.print(serviceMethodName);
        out.println("(final jakarta.servlet.http.HttpServletRequest request, final jakarta.servlet.http.HttpServletResponse response)");
        out.pushIndent();
        out.pushIndent();
        out.printil("throws java.io.IOException, jakarta.servlet.ServletException {");
        out.popIndent();
        out.println();

        // Method check
        if (!pageInfo.isErrorPage()) {
            out.printil("if (!jakarta.servlet.DispatcherType.ERROR.equals(request.getDispatcherType())) {");
            out.pushIndent();
            out.printil("final java.lang.String _jspx_method = request.getMethod();");
            out.printil("if (\"OPTIONS\".equals(_jspx_method)) {");
            out.pushIndent();
            out.printil("response.setHeader(\"Allow\",\"GET, HEAD, POST, OPTIONS\");");
            out.printil("return;");
            out.popIndent();
            out.printil("}");
            out.printil("if (!\"GET\".equals(_jspx_method) && !\"POST\".equals(_jspx_method) && !\"HEAD\".equals(_jspx_method)) {");
            out.pushIndent();
            out.printil("response.setHeader(\"Allow\",\"GET, HEAD, POST, OPTIONS\");");
            out.printin("response.sendError(HttpServletResponse.SC_METHOD_NOT_ALLOWED, ");
            out.println("\"" + Localizer.getMessage("jsp.error.servlet.invalid.method") + "\");");
            out.printil("return;");
            out.popIndent();
            out.printil("}");
            out.popIndent();
            out.printil("}");
            out.println();
        }

        // Local variable declarations
        out.printil("final jakarta.servlet.jsp.PageContext pageContext;");

        if (pageInfo.isSession()) {
            out.printil("jakarta.servlet.http.HttpSession session = null;");
        }

        if (pageInfo.isErrorPage()) {
            out.printil("java.lang.Throwable exception = org.apache.jasper.runtime.JspRuntimeLibrary.getThrowable(request);");
            out.printil("if (exception != null) {");
            out.pushIndent();
            out.printil("response.setStatus(jakarta.servlet.http.HttpServletResponse.SC_INTERNAL_SERVER_ERROR);");
            out.popIndent();
            out.printil("}");
        }

        out.printil("final jakarta.servlet.ServletContext application;");
        out.printil("final jakarta.servlet.ServletConfig config;");
        out.printil("jakarta.servlet.jsp.JspWriter out = null;");
        out.printil("final java.lang.Object page = this;");

        out.printil("jakarta.servlet.jsp.JspWriter _jspx_out = null;");
        out.printil("jakarta.servlet.jsp.PageContext _jspx_page_context = null;");
        out.println();

        declareTemporaryScriptingVars(page);
        out.println();

        out.printil("try {");
        out.pushIndent();

        out.printin("response.setContentType(");
        out.print(quote(pageInfo.getContentType()));
        out.println(");");

        if (ctxt.getOptions().isXpoweredBy()) {
            out.printil("response.addHeader(\"X-Powered-By\", \"JSP/3.1\");");
        }

        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("_jspx_page_context = pageContext;");

        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 an XML Prolog, which includes an XML declaration and an XML
     * doctype declaration.
     */

    private void generateXmlProlog(Node.Nodes page) {

        /*
         * An XML declaration is generated under the following conditions: -
         * 'omit-xml-declaration' attribute of <jsp:output> action is set to
         * "no" or "false" - JSP document without a <jsp:root>
         */

        String omitXmlDecl = pageInfo.getOmitXmlDecl();
        if ((omitXmlDecl != null && !JspUtil.booleanValue(omitXmlDecl)) ||
                (omitXmlDecl == null && page.getRoot().isXmlSyntax() && !pageInfo.hasJspRoot() && !ctxt.isTagFile())) {
            String cType = pageInfo.getContentType();
            String charSet = cType.substring(cType.indexOf("charset=") + 8);
            out.printil("out.write(\"<?xml version=\\\"1.0\\\" encoding=\\\""
                    + charSet + "\\\"?>\\n\");");
        }

        /*
         * Output a DOCTYPE declaration if the doctype-root-element appears. If
         * doctype-public appears: <!DOCTYPE name PUBLIC "doctypePublic"
         * "doctypeSystem"> else <!DOCTYPE name SYSTEM "doctypeSystem" >
         */


        String doctypeName = pageInfo.getDoctypeName();
        if (doctypeName != null) {
            String doctypePublic = pageInfo.getDoctypePublic();
            String doctypeSystem = pageInfo.getDoctypeSystem();
            out.printin("out.write(\"<!DOCTYPE ");
            out.print(doctypeName);
            if (doctypePublic == null) {
                out.print(" SYSTEM \\\"");
            } else {
                out.print(" PUBLIC \\\"");
                out.print(doctypePublic);
                out.print("\\\" \\\"");
            }
            out.print(doctypeSystem);
            out.println("\\\">\\n\");");
        }
    }

    /**
     * A visitor that generates codes for the elements in the page.
     */

    private class GenerateVisitor extends Node.Visitor {

        /*
         * Map containing introspection information on tag handlers:
         * <key>: tag prefix <value>: Map containing introspection on tag
         * handlers: <key>: tag short name <value>: introspection info of tag
         * handler for <prefix:shortName> tag
         */

        private final Map<String,Map<String,TagHandlerInfo>> handlerInfos;

        private final Map<String,Integer> tagVarNumbers;

        private String parent;

        private boolean isSimpleTagParent; // Is parent a SimpleTag?

        private String pushBodyCountVar;

        private String simpleTagHandlerVar;

        private boolean isSimpleTagHandler;

        private boolean isFragment;

        private final boolean isTagFile;

        private ServletWriter out;

        private final ArrayList<GenBuffer> methodsBuffered;

        private final FragmentHelperClass fragmentHelperClass;

        private int methodNesting;

        private int charArrayCount;

        private HashMap<String,String> textMap;

        private final boolean useInstanceManagerForTags;

        GenerateVisitor(boolean isTagFile, ServletWriter out,
                ArrayList<GenBuffer> methodsBuffered,
                FragmentHelperClass fragmentHelperClass,
                boolean useInstanceManagerForTags) {

            this.isTagFile = isTagFile;
            this.out = out;
            this.methodsBuffered = methodsBuffered;
            this.fragmentHelperClass = fragmentHelperClass;
            this.useInstanceManagerForTags = useInstanceManagerForTags;
            methodNesting = 0;
            handlerInfos = new HashMap<>();
            tagVarNumbers = new HashMap<>();
            textMap = new HashMap<>();
        }

        /**
         * Returns an attribute value, optionally URL encoded. If the value is a
         * runtime expression, the result is the expression itself, as a string.
         * If the result is an EL expression, we insert a call to the
         * interpreter. If the result is a Named Attribute we insert the
         * generated variable name. Otherwise the result is a string literal,
         * quoted and escaped.
         *
         * @param attr
         *            An JspAttribute object
         * @param encode
         *            true if to be URL encoded
         * @param expectedType
         *            the expected type for an EL evaluation (ignored for
         *            attributes that aren't EL expressions)
         */

        private String attributeValue(Node.JspAttribute attr, boolean encode,
                Class<?> expectedType) {
            String v = attr.getValue();
            if (attr.isExpression()) {
                if (encode) {
                    return "org.apache.jasper.runtime.JspRuntimeLibrary.URLEncode(String.valueOf("
                            + v + "), request.getCharacterEncoding())";
                }
                return v;
            } else if (attr.isELInterpreterInput()) {
                v = elInterpreter.interpreterCall(ctxt, this.isTagFile, v,
                        expectedType, attr.getEL().getMapName());
                if (encode) {
                    return "org.apache.jasper.runtime.JspRuntimeLibrary.URLEncode("
                            + v + ", request.getCharacterEncoding())";
                }
                return v;
            } else if (attr.isNamedAttribute()) {
                return attr.getNamedAttributeNode().getTemporaryVariableName();
            } else {
                if (encode) {
                    return "org.apache.jasper.runtime.JspRuntimeLibrary.URLEncode("
                            + quote(v) + ", request.getCharacterEncoding())";
                }
                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, String pageParam, boolean literal)
                throws JasperException {

            class ParamVisitor extends Node.Visitor {
                private String separator;

                ParamVisitor(String separator) {
                    this.separator = separator;
                }

                @Override
                public void visit(Node.ParamAction n) throws JasperException {

                    out.print(" + ");
                    out.print(separator);
                    out.print(" + ");
                    out.print("org.apache.jasper.runtime.JspRuntimeLibrary."
                            + "URLEncode(" + quote(n.getTextAttribute("name"))
                            + ", request.getCharacterEncoding())");
                    out.print("+ \"=\" + ");
                    out.print(attributeValue(n.getValue(), true, String.class));

                    // The separator is '&' after the second use
                    separator = "\"&\"";
                }
            }

            String sep;
            if (literal) {
                sep = pageParam.indexOf('?') > 0 ? "\"&\"" : "\"?\"";
            } else {
                sep = "((" + pageParam + ").indexOf('?')>0? '&': '?')";
            }
            if (n.getBody() != null) {
                n.getBody().visit(new ParamVisitor(sep));
            }
        }

        @Override
        public void visit(Node.Expression n) throws JasperException {
            n.setBeginJavaLine(out.getJavaLine());
            out.printin("out.print(");
            out.printMultiLn(n.getText());
            out.println(");");
            n.setEndJavaLine(out.getJavaLine());
        }

        @Override
        public void visit(Node.Scriptlet n) throws JasperException {
            n.setBeginJavaLine(out.getJavaLine());
            out.printMultiLn(n.getText());
            out.println();
            n.setEndJavaLine(out.getJavaLine());
        }

        @Override
        public void visit(Node.ELExpression n) throws JasperException {
            n.setBeginJavaLine(out.getJavaLine());
            out.printil("out.write("
                    + elInterpreter.interpreterCall(ctxt, this.isTagFile,
                            n.getType() + "{" + n.getText() + "}",
                            String.class, n.getEL().getMapName()) +
                    ");");
            n.setEndJavaLine(out.getJavaLine());
        }

        @Override
        public void visit(Node.IncludeAction n) throws JasperException {

            String flush = n.getTextAttribute("flush");
            Node.JspAttribute page = n.getPage();

            boolean isFlush = "true".equals(flush);

            n.setBeginJavaLine(out.getJavaLine());

            String pageParam;
            if (page.isNamedAttribute()) {
                // If the page for jsp:include was specified via
                // jsp:attribute, first generate code to evaluate
                // that body.
                pageParam = generateNamedAttributeValue(page
                        .getNamedAttributeNode());
            } else {
                pageParam = attributeValue(page, false, String.class);
            }

            // If any of the params have their values specified by
            // jsp:attribute, prepare those values first.
            Node jspBody = findJspBody(n);
            if (jspBody != null) {
                prepareParams(jspBody);
            } else {
                prepareParams(n);
            }

            out.printin("org.apache.jasper.runtime.JspRuntimeLibrary.include(request, response, "
                    + pageParam);
            printParams(n, pageParam, page.isLiteral());
            out.println(", out, " + isFlush + ");");

            n.setEndJavaLine(out.getJavaLine());
        }

        /**
         * Scans through all child nodes of the given parent for <param>
         * subelements. For each <param> element, if its value is specified via
         * a Named Attribute (<jsp:attribute>), generate the code to evaluate
         * those bodies first.
         * <p>
         * {@code parent} is assumed to be non-null
         */

        private void prepareParams(Node parent) throws JasperException {
            Node.Nodes subelements = parent.getBody();
            if (subelements != null) {
                for (int i = 0; i < subelements.size(); i++) {
                    Node n = subelements.getNode(i);
                    // Validation during parsing ensures n is an instance of
                    // Node.ParamAction
                    Node.Nodes paramSubElements = n.getBody();
                    for (int j = 0; (paramSubElements != null)
                            && (j < paramSubElements.size()); j++) {
                        Node m = paramSubElements.getNode(j);
                        if (m instanceof Node.NamedAttribute) {
                            generateNamedAttributeValue((Node.NamedAttribute) m);
                        }
                    }
                }
            }
        }

        /**
         * Finds the <jsp:body> subelement of the given parent node. If not
         * found, null is returned.
         */

        private Node.JspBody findJspBody(Node parent) {
            Node.JspBody result = null;

            Node.Nodes subelements = parent.getBody();
            for (int i = 0; (subelements != null) && (i < subelements.size()); i++) {
                Node n = subelements.getNode(i);
                if (n instanceof Node.JspBody) {
                    result = (Node.JspBody) n;
                    break;
                }
            }

            return result;
        }

        @Override
        public void visit(Node.ForwardAction n) throws JasperException {
            Node.JspAttribute page = n.getPage();

            n.setBeginJavaLine(out.getJavaLine());

            out.printil("if (true) {"); // So that javac won't complain about
            out.pushIndent(); // codes after "return"

            String pageParam;
            if (page.isNamedAttribute()) {
                // If the page for jsp:forward was specified via
                // jsp:attribute, first generate code to evaluate
                // that body.
                pageParam = generateNamedAttributeValue(page.getNamedAttributeNode());
            } else {
                pageParam = attributeValue(page, false, String.class);
            }

            // If any of the params have their values specified by
            // jsp:attribute, prepare those values first.
            Node jspBody = findJspBody(n);
            if (jspBody != null) {
                prepareParams(jspBody);
            } else {
                prepareParams(n);
            }

            out.printin("_jspx_page_context.forward(");
            out.print(pageParam);
            printParams(n, pageParam, page.isLiteral());
            out.println(");");
            if (isTagFile || isFragment) {
                out.printil("throw new jakarta.servlet.jsp.SkipPageException();");
            } else {
                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.
        }

        @Override
        public void visit(Node.GetProperty n) throws JasperException {
            String name = n.getTextAttribute("name");
            String property = n.getTextAttribute("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.getCanonicalName();
                Method meth = JspRuntimeLibrary.getReadMethod(bean, property);
                String methodName = meth.getName();
                out.printil("out.write(org.apache.jasper.runtime.JspRuntimeLibrary.toString("
                        + "((("
                        + beanName
                        + ")_jspx_page_context.findAttribute("
                        + "\""
                        + name + "\"))." + methodName + "())));");
            } else if (!ctxt.getOptions().getStrictGetProperty() || varInfoNames.contains(name)) {
                // The object is a custom action with an associated
                // VariableInfo entry for this name.
                // Get the class name and then introspect at runtime.
                out.printil("out.write(org.apache.jasper.runtime.JspRuntimeLibrary.toString"
                        + "(org.apache.jasper.runtime.JspRuntimeLibrary.handleGetProperty"
                        + "(_jspx_page_context.findAttribute(\""
                        + name
                        + "\"), \""
                        + property
                        + "\")));");
            } else {
                throw new JasperException(Localizer.getMessage("jsp.error.invalid.name", n.getStart(), name));
            }

            n.setEndJavaLine(out.getJavaLine());
        }

        @Override
        public void visit(Node.SetProperty n) throws JasperException {
            String name = n.getTextAttribute("name");
            String property = n.getTextAttribute("property");
            String param = n.getTextAttribute("param");
            Node.JspAttribute value = n.getValue();

            n.setBeginJavaLine(out.getJavaLine());

            if ("*".equals(property)) {
                out.printil("org.apache.jasper.runtime.JspRuntimeLibrary.introspect("
                        + "_jspx_page_context.findAttribute("
                        + "\""
                        + name + "\"), request);");
            } else if (value == null) {
                if (param == null)
                 {
                    param = property; // default to same as property
                }
                out.printil("org.apache.jasper.runtime.JspRuntimeLibrary.introspecthelper("
                        + "_jspx_page_context.findAttribute(\""
                        + name
                        + "\"), \""
                        + property
                        + "\", request.getParameter(\""
                        + param
                        + "\"), "
                        + "request, \""
                        + param
                        + "\"false);");
            } else if (value.isExpression()) {
                out.printil("org.apache.jasper.runtime.JspRuntimeLibrary.handleSetProperty("
                        + "_jspx_page_context.findAttribute(\""
                        + name
                        + "\"), \"" + property + "\",");
                out.print(attributeValue(value, falsenull));
                out.println(");");
            } else if (value.isELInterpreterInput()) {
                // We've got to resolve the very call to the interpreter
                // at runtime since we don't know what type to expect
                // in the general case; we thus can't hard-wire the call
                // into the generated code. (XXX We could, however,
                // optimize the case where the bean is exposed with
                // <jsp:useBean>, much as the code here does for
                // getProperty.)

                // The following holds true for the arguments passed to
                // JspRuntimeLibrary.handleSetPropertyExpression():
                // - 'pageContext' is a VariableResolver.
                // - 'this' (either the generated Servlet or the generated tag
                // handler for Tag files) is a FunctionMapper.
                out.printil("org.apache.jasper.runtime.JspRuntimeLibrary.handleSetPropertyExpression("
                        + "_jspx_page_context.findAttribute(\""
                        + name
                        + "\"), \""
                        + property
                        + "\""
                        + quote(value.getValue())
                        + ", "
                        + "_jspx_page_context, "
                        + value.getEL().getMapName() + ");");
            } else if (value.isNamedAttribute()) {
                // If the value for setProperty was specified via
                // jsp:attribute, first generate code to evaluate
                // that body.
                String valueVarName = generateNamedAttributeValue(value
                        .getNamedAttributeNode());
                out.printil("org.apache.jasper.runtime.JspRuntimeLibrary.introspecthelper("
                        + "_jspx_page_context.findAttribute(\""
                        + name
                        + "\"), \""
                        + property
                        + "\""
                        + valueVarName
                        + ", null, null, false);");
            } else {
                out.printin("org.apache.jasper.runtime.JspRuntimeLibrary.introspecthelper("
                        + "_jspx_page_context.findAttribute(\""
                        + name
                        + "\"), \"" + property + "\"");
                out.print(attributeValue(value, falsenull));
                out.println(", null, null, false);");
            }

            n.setEndJavaLine(out.getJavaLine());
        }

        @Override
        public void visit(Node.UseBean n) throws JasperException {

            String name = n.getTextAttribute("id");
            String scope = n.getTextAttribute("scope");
            String klass = n.getTextAttribute("class");
            String type = n.getTextAttribute("type");
            Node.JspAttribute beanName = n.getBeanName();

            // If "class" is specified, try an instantiation at compile time
            boolean generateNew = false;
            String canonicalName = null// Canonical name for klass
            if (klass != null) {
                try {
                    Class<?> bean = ctxt.getClassLoader().loadClass(klass);
                    if (klass.indexOf('$') >= 0) {
                        // Obtain the canonical type name
                        canonicalName = bean.getCanonicalName();
                    } else {
                        canonicalName = klass;
                    }
                    // Check that there is a 0 arg constructor
                    Constructor<?> constructor = bean.getConstructor(new Class[] {});
                    // Check the bean is public, not an interface, not abstract
                    // and in an exported module
                    int modifiers = bean.getModifiers();
                    // No need to test for being an interface here as the
                    // getConstructor() call above will have already failed for
                    // any interfaces.
                    if (!Modifier.isPublic(modifiers) ||
                            Modifier.isAbstract(modifiers) ||
                            !constructor.canAccess(null) ) {
                        throw new JasperException(Localizer.getMessage("jsp.error.invalid.bean",
                                Integer.valueOf(modifiers)));
                    }
                    // At compile time, we have determined that the bean class
                    // exists, with a public zero constructor, new() can be
                    // used for bean instantiation.
                    generateNew = true;
                } catch (Exception e) {
                    // Cannot instantiate the specified class, either a
                    // compilation error or a runtime error will be raised,
                    // depending on a compiler flag.
                    if (ctxt.getOptions()
                            .getErrorOnUseBeanInvalidClassAttribute()) {
                        err.jspError(n, "jsp.error.invalid.bean", klass);
                    }
                    if (canonicalName == null) {
                        // Doing our best here to get a canonical name
                        // from the binary name, should work 99.99% of time.
                        canonicalName = klass.replace('$''.');
                    }
                }
                if (type == null) {
                    // if type is unspecified, use "class" as type of bean
                    type = canonicalName;
                }
            }

            // JSP.5.1, Semantics, para 1 - lock not required for request or
            // page scope
            String scopename = "jakarta.servlet.jsp.PageContext.PAGE_SCOPE"// Default to page
            String lock = null;

            if ("request".equals(scope)) {
                scopename = "jakarta.servlet.jsp.PageContext.REQUEST_SCOPE";
            } else if ("session".equals(scope)) {
                scopename = "jakarta.servlet.jsp.PageContext.SESSION_SCOPE";
                lock = "session";
            } else if ("application".equals(scope)) {
                scopename = "jakarta.servlet.jsp.PageContext.APPLICATION_SCOPE";
                lock = "application";
            }

            n.setBeginJavaLine(out.getJavaLine());

            // Declare bean
            out.printin(type);
            out.print(' ');
            out.print(name);
            out.println(" = null;");

            // Lock (if required) while getting or creating bean
            if (lock != null) {
                out.printin("synchronized (");
                out.print(lock);
                out.println(") {");
                out.pushIndent();
            }

            // Locate bean from context
            out.printin(name);
            out.print(" = (");
            out.print(type);
            out.print(") _jspx_page_context.getAttribute(");
            out.print(quote(name));
            out.print(", ");
            out.print(scopename);
            out.println(");");

            // Create bean
            /*
             * Check if bean is already 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 the bean if it is not in the specified scope.
                 */

                if (!generateNew) {
                    String binaryName;
                    if (beanName != null) {
                        if (beanName.isNamedAttribute()) {
                            // If the value for beanName was specified via
                            // jsp:attribute, first generate code to evaluate
                            // that body.
                            binaryName = generateNamedAttributeValue(beanName
                                    .getNamedAttributeNode());
                        } else {
                            binaryName = attributeValue(beanName, false, String.class);
                        }
                    } else {
                        // Implies klass is not null
                        binaryName = 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(binaryName);
                    out.println(");");
                    out.popIndent();
                    /*
                     * Note: Beans.instantiate throws ClassNotFoundException if
                     * the bean class is abstract.
                     */

                    out.printil("} catch (java.lang.ClassNotFoundException exc) {");
                    out.pushIndent();
                    out.printil("throw new InstantiationException(exc.getMessage());");
                    out.popIndent();
                    out.printil("} catch (java.lang.Exception exc) {");
                    out.pushIndent();
                    out.printin("throw new jakarta.servlet.ServletException(");
                    out.print("\"Cannot create bean of class \" + ");
                    out.print(binaryName);
                    out.println(", exc);");
                    out.popIndent();
                    out.printil("}"); // close of try
                } else {
                    // Implies klass is not null
                    // Generate codes to instantiate the bean class
                    out.printin(name);
                    out.print(" = new ");
                    out.print(canonicalName);
                    out.println("();");
                }
                /*
                 * Set attribute for bean in the specified scope
                 */

                out.printin("_jspx_page_context.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
            if (lock != null) {
                out.popIndent();
                out.printil("}");
            }

            n.setEndJavaLine(out.getJavaLine());
        }

        @Override
        public void visit(Node.PlugIn n) throws JasperException {

            // As of JSP 3.1, jsp:plugin must not generate any output
            n.setBeginJavaLine(out.getJavaLine());
            n.setEndJavaLine(out.getJavaLine());
        }

        @Override
        public void visit(Node.NamedAttribute n) throws JasperException {
            // Don't visit body of this tag - we already did earlier.
        }

        @Override
        public void visit(Node.CustomTag n) throws JasperException {

            // Use plugin to generate more efficient code if there is one.
            if (n.useTagPlugin()) {
                generateTagPlugin(n);
                return;
            }

            TagHandlerInfo handlerInfo = getTagHandlerInfo(n);

            // Create variable names
            String baseVar = createTagVarName(n.getQName(), n.getPrefix(), n
                    .getLocalName());
            String tagEvalVar = "_jspx_eval_" + baseVar;
            String tagHandlerVar = "_jspx_th_" + baseVar;
            String tagPushBodyCountVar = "_jspx_push_body_count_" + baseVar;

            // If the tag contains no scripting element, generate its codes
            // to a method.
            ServletWriter outSave = null;
            Node.ChildInfo ci = n.getChildInfo();
            if (ci.isScriptless() && !ci.hasScriptingVars()) {
                // The tag handler and its body code can reside in a separate
                // method if it is scriptless and does not have any scripting
                // variable defined.

                String tagMethod = "_jspx_meth_" + baseVar;

                // Generate a call to this method
                out.printin("if (");
                out.print(tagMethod);
                out.print("(");
                if (parent != null) {
                    out.print(parent);
                    out.print(", ");
                }
                out.print("_jspx_page_context");
                if (pushBodyCountVar != null) {
                    out.print(", ");
                    out.print(pushBodyCountVar);
                }
                out.println("))");
                out.pushIndent();
                out.printil((methodNesting > 0) ? "return true;" : "return;");
                out.popIndent();

                // Set up new buffer for the method
                outSave = out;
                /*
                 * For fragments, their bodies will be generated in fragment
                 * helper classes, and the Java line adjustments will be done
                 * there, hence they are set to null here to avoid double
                 * adjustments.
                 */

                GenBuffer genBuffer = new GenBuffer(n,
                        n.implementsSimpleTag() ? null : n.getBody());
                methodsBuffered.add(genBuffer);
                out = genBuffer.getOut();

                methodNesting++;
                // Generate code for method declaration
                out.println();
                out.pushIndent();
                out.printin("private boolean ");
                out.print(tagMethod);
                out.print("(");
                if (parent != null) {
                    out.print("jakarta.servlet.jsp.tagext.JspTag ");
                    out.print(parent);
                    out.print(", ");
                }
                out.print("jakarta.servlet.jsp.PageContext _jspx_page_context");
                if (pushBodyCountVar != null) {
                    out.print(", int[] ");
                    out.print(pushBodyCountVar);
                }
                out.println(")");
                out.printil(" throws java.lang.Throwable {");
                out.pushIndent();

                // Initialize local variables used in this method.
                if (!isTagFile) {
                    out.printil("jakarta.servlet.jsp.PageContext pageContext = _jspx_page_context;");
                }
                // Only need to define out if the tag has a non-empty body,
                // implements TryCatchFinally or uses
                // <jsp:attribute>...</jsp:attribute> nodes
                if (!n.hasEmptyBody() || n.implementsTryCatchFinally() || n.getNamedAttributeNodes().size() > 0) {
                    out.printil("jakarta.servlet.jsp.JspWriter out = _jspx_page_context.getOut();");
                }
                generateLocalVariables(out, n);
            }

            // Add the named objects to the list of 'introduced' names to enable
            // a later test as per JSP.5.3
            VariableInfo[] infos = n.getVariableInfos();
            // The Validator always calls setTagData() which ensures infos is
            // non-null
            if (infos.length > 0) {
                for (VariableInfo info : infos) {
                    // A null variable name will trigger multiple compilation
                    // failures so assume non-null here
                    pageInfo.getVarInfoNames().add(info.getVarName());
                }
            }
            TagVariableInfo[] tagInfos = n.getTagVariableInfos();
            // The way Tomcat constructs the TagInfo, getTagVariableInfos()
            // will never return null.
            if (tagInfos.length > 0) {
                for (TagVariableInfo tagInfo : tagInfos) {
                    // tagInfo is always non-null
                    String name = tagInfo.getNameGiven();
                    if (name == null) {
                        String nameFromAttribute =
                                tagInfo.getNameFromAttribute();
                        name = n.getAttributeValue(nameFromAttribute);
                    }
                    pageInfo.getVarInfoNames().add(name);
                }
            }


            if (n.implementsSimpleTag()) {
                generateCustomDoTag(n, handlerInfo, tagHandlerVar);
            } else {
                /*
                 * Classic tag handler: Generate code for start element, body,
                 * and end element
                 */

                generateCustomStart(n, handlerInfo, tagHandlerVar, tagEvalVar,
                        tagPushBodyCountVar);

                // visit body
                String tmpParent = parent;
                parent = tagHandlerVar;
                boolean isSimpleTagParentSave = isSimpleTagParent;
                isSimpleTagParent = false;
                String tmpPushBodyCountVar = null;
                if (n.implementsTryCatchFinally()) {
--> --------------------

--> maximum size reached

--> --------------------

90%


¤ Dauer der Verarbeitung: 0.33 Sekunden  (vorverarbeitet)  ¤

*© Formatika GbR, Deutschland






Wurzel

Suchen

Beweissystem der NASA

Beweissystem Isabelle

NIST Cobol Testsuite

Cephes Mathematical Library

Wiener Entwicklungsmethode

Haftungshinweis

Die Informationen auf dieser Webseite wurden nach bestem Wissen sorgfältig zusammengestellt. Es wird jedoch weder Vollständigkeit, noch Richtigkeit, noch Qualität der bereit gestellten Informationen zugesichert.

Bemerkung:

Die farbliche Syntaxdarstellung ist noch experimentell.






                                                                                                                                                                                                                                                                                                                                                                                                     


Neuigkeiten

     Aktuelles
     Motto des Tages

Software

     Produkte
     Quellcodebibliothek

Aktivitäten

     Artikel über Sicherheit
     Anleitung zur Aktivierung von SSL

Muße

     Gedichte
     Musik
     Bilder

Jenseits des Üblichen ....

Besucherstatistik

Besucherstatistik

Monitoring

Montastic status badge