Start line:  
End line:  

Snippet Preview

Snippet HTML Code

Stack Overflow Questions
   /*
    * 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 static org.jboss.web.JasperMessages.MESSAGES;
  
  import java.util.List;
  
  
Class implementing a parser for a JSP document, that is, a JSP page in XML syntax.

Author(s):
Jan Luehe
Kin-man Chung
  
  
      extends DefaultHandler
      implements LexicalHandlerTagConstants {
  
      private static final String JSP_VERSION = "version";
      private static final String LEXICAL_HANDLER_PROPERTY =
          "http://xml.org/sax/properties/lexical-handler";
      private static final String JSP_URI = "http://java.sun.com/JSP/Page";
  
      private ParserController parserController;
      private JspCompilationContext ctxt;
      private PageInfo pageInfo;
      private String path;
      private StringBuilder charBuffer;
  
      // Node representing the XML element currently being parsed
      private Node current;
  
      /*
       * Outermost (in the nesting hierarchy) node whose body is declared to be
       * scriptless. If a node's body is declared to be scriptless, all its
       * nested nodes must be scriptless, too.
       */ 
      private Node scriptlessBodyNode;
  
      private Locator locator;
  
      //Mark representing the start of the current element.  Note
      //that locator.getLineNumber() and locator.getColumnNumber()
      //return the line and column numbers for the character
      //immediately _following_ the current element.  The underlying
      //XMl parser eats white space that is not part of character
      //data, so for Nodes that are not created from character data,
      //this is the best we can do.  But when we parse character data,
      //we get an accurate starting location by starting with startMark
      //as set by the previous element, and updating it as we advance
      //through the characters.
      private Mark startMark;
  
      // Flag indicating whether we are inside DTD declarations
      private boolean inDTD;
 
     private boolean isValidating;
 
     private ErrorDispatcher err;
     private boolean isTagFile;
     private boolean directivesOnly;
     private boolean isTop;
 
     // Nesting level of Tag dependent bodies
     private int tagDependentNesting = 0;
     // Flag set to delay incrmenting tagDependentNesting until jsp:body
     // is first encountered
     private boolean tagDependentPending = false;
 
     /*
      * Constructor
      */
     public JspDocumentParser(
         ParserController pc,
         String path,
         boolean isTagFile,
         boolean directivesOnly) {
         this. = pc;
         this. = pc.getJspCompilationContext();
         this. = pc.getCompiler().getPageInfo();
         this. = pc.getCompiler().getErrorDispatcher();
         this. = path;
         this. = isTagFile;
         this. = directivesOnly;
         this. = true;
     }
 
     /*
      * Parses a JSP document by responding to SAX events.
      *
      * @throws JasperException
      */
     public static Node.Nodes parse(
         ParserController pc,
         String path,
         JarFile jarFile,
         Node parent,
         boolean isTagFile,
         boolean directivesOnly,
         String pageEnc,
         String jspConfigPageEnc,
         boolean isEncodingSpecifiedInProlog,
         boolean isBomPresent)
         throws JasperException {
 
         JspDocumentParser jspDocParser =
             new JspDocumentParser(pcpathisTagFiledirectivesOnly);
         Node.Nodes pageNodes = null;
 
         try {
 
             // Create dummy root and initialize it with given page encodings
             Node.Root dummyRoot = new Node.Root(nullparenttrue);
             dummyRoot.setPageEncoding(pageEnc);
             dummyRoot.setJspConfigPageEncoding(jspConfigPageEnc);
             dummyRoot.setIsEncodingSpecifiedInProlog(
                 isEncodingSpecifiedInProlog);
             dummyRoot.setIsBomPresent(isBomPresent);
             jspDocParser.current = dummyRoot;
             if (parent == null) {
                 jspDocParser.addInclude(
                     dummyRoot,
                     jspDocParser.pageInfo.getIncludePrelude());
             } else {
                 jspDocParser.isTop = false;
             }
 
             // Parse the input
             SAXParser saxParser = getSAXParser(falsejspDocParser);
             InputStream inStream = null;
             try {
                 inStream = JspUtil.getInputStream(pathjarFile,
                                                   jspDocParser.ctxt,
                                                   jspDocParser.err);
                 saxParser.parse(new InputSource(inStream), jspDocParser);
             } catch (EnableDTDValidationException e) {
                 saxParser = getSAXParser(truejspDocParser);
                 jspDocParser.isValidating = true;
                 if (inStream != null) {
                     try {
                         inStream.close();
                     } catch (Exception any) {
                     }
                 }
                 inStream = JspUtil.getInputStream(pathjarFile,
                                                   jspDocParser.ctxt,
                                                   jspDocParser.err);
                 saxParser.parse(new InputSource(inStream), jspDocParser);
             } finally {
                 if (inStream != null) {
                     try {
                         inStream.close();
                     } catch (Exception any) {
                     }
                 }
             }
 
             if (parent == null) {
                 jspDocParser.addInclude(
                     dummyRoot,
                     jspDocParser.pageInfo.getIncludeCoda());
             }
 
             // Create Node.Nodes from dummy root
             pageNodes = new Node.Nodes(dummyRoot);
 
         } catch (IOException ioe) {
             jspDocParser.err.jspError(.errorReadingFile(path), ioe);
         } catch (SAXParseException e) {
             jspDocParser.err.jspError
                 (new Mark(jspDocParser.ctxtpathe.getLineNumber(),
                           e.getColumnNumber()),
                           .errorParsingFile(path), e);
         } catch (Exception e) {
             jspDocParser.err.jspError(.errorParsingFile(path), e);
         }
 
         return pageNodes;
     }
 
     /*
      * Processes the given list of included files.
      *
      * This is used to implement the include-prelude and include-coda
      * subelements of the jsp-config element in web.xml
      */
     private void addInclude(Node parentList filesthrows SAXException {
         if (files != null) {
             Iterator iter = files.iterator();
             while (iter.hasNext()) {
                 String file = (String)iter.next();
                 AttributesImpl attrs = new AttributesImpl();
                 attrs.addAttribute("""file""file""CDATA"file);
 
                 // Create a dummy Include directive node
                     Node includeDir =
                         new Node.IncludeDirective(attrsnull// XXX
     parent);
                 processIncludeDirective(fileincludeDir);
             }
         }
     }
 
     /*
      * Receives notification of the start of an element.
      *
      * This method assigns the given tag attributes to one of 3 buckets:
      * 
      * - "xmlns" attributes that represent (standard or custom) tag libraries.
      * - "xmlns" attributes that do not represent tag libraries.
      * - all remaining attributes.
      *
      * For each "xmlns" attribute that represents a custom tag library, the
      * corresponding TagLibraryInfo object is added to the set of custom
      * tag libraries.
      */
     public void startElement(
         String uri,
         String localName,
         String qName,
         Attributes attrs)
         throws SAXException {
 
         AttributesImpl taglibAttrs = null;
         AttributesImpl nonTaglibAttrs = null;
         AttributesImpl nonTaglibXmlnsAttrs = null;
 
         processChars();
 
         checkPrefixes(uriqNameattrs);
 
         if ( &&
             !(.equals(uri) && localName.startsWith())) {
             return;
         }
 
         String currentPrefix = getPrefix(.getQName());
 
         // jsp:text must not have any subelements
         if (.equals(uri) && .equals(.getLocalName())
                                 && "jsp".equals(currentPrefix)) {
             throw new SAXParseException(
                 .invalidJspTextSubelements(),
                 );
         }
 
          = new Mark(.getLineNumber(),
                              .getColumnNumber());
 
         if (attrs != null) {
             /*
              * Notice that due to a bug in the underlying SAX parser, the
              * attributes must be enumerated in descending order. 
              */
             boolean isTaglib = false;
             for (int i = attrs.getLength() - 1; i >= 0; i--) {
                 isTaglib = false;
                 String attrQName = attrs.getQName(i);
                 if (!attrQName.startsWith("xmlns")) {
                     if (nonTaglibAttrs == null) {
                         nonTaglibAttrs = new AttributesImpl();
                     }
                     nonTaglibAttrs.addAttribute(
                         attrs.getURI(i),
                         attrs.getLocalName(i),
                         attrs.getQName(i),
                         attrs.getType(i),
                         attrs.getValue(i));
                 } else {
                     if (attrQName.startsWith("xmlns:jsp")) {
                         isTaglib = true;
                     } else {
                         String attrUri = attrs.getValue(i);
                         // TaglibInfo for this uri already established in
                         // startPrefixMapping
                         isTaglib = .hasTaglib(attrUri);
                     }
                     if (isTaglib) {
                         if (taglibAttrs == null) {
                             taglibAttrs = new AttributesImpl();
                         }
                         taglibAttrs.addAttribute(
                             attrs.getURI(i),
                             attrs.getLocalName(i),
                             attrs.getQName(i),
                             attrs.getType(i),
                             attrs.getValue(i));
                     } else {
                         if (nonTaglibXmlnsAttrs == null) {
                             nonTaglibXmlnsAttrs = new AttributesImpl();
                         }
                         nonTaglibXmlnsAttrs.addAttribute(
                             attrs.getURI(i),
                             attrs.getLocalName(i),
                             attrs.getQName(i),
                             attrs.getType(i),
                             attrs.getValue(i));
                     }
                 }
             }
         }
 
         Node node = null;
 
         if ( && .equals(uri) &&
                      localName.equals()) {
              = false;
             ++;
              =
                 parseStandardAction(
                     qName,
                     localName,
                     nonTaglibAttrs,
                     nonTaglibXmlnsAttrs,
                     taglibAttrs,
                     ,
                     );
             return;
         }
 
         if ( && .equals(uri) &&
                      localName.equals()) {
              =
                 parseStandardAction(
                     qName,
                     localName,
                     nonTaglibAttrs,
                     nonTaglibXmlnsAttrs,
                     taglibAttrs,
                     ,
                     );
             return;
         }
 
         if () {
              = false;
             ++;
         }
 
         if ( > 0) {
             node =
                 new Node.UninterpretedTag(
                     qName,
                     localName,
                     nonTaglibAttrs,
                     nonTaglibXmlnsAttrs,
                     taglibAttrs,
                     ,
                     );
         } else if (.equals(uri)) {
             node =
                 parseStandardAction(
                     qName,
                     localName,
                     nonTaglibAttrs,
                     nonTaglibXmlnsAttrs,
                     taglibAttrs,
                     ,
                     );
         } else {
             node =
                 parseCustomAction(
                     qName,
                     localName,
                     uri,
                     nonTaglibAttrs,
                     nonTaglibXmlnsAttrs,
                     taglibAttrs,
                     ,
                     );
             if (node == null) {
                 node =
                     new Node.UninterpretedTag(
                         qName,
                         localName,
                         nonTaglibAttrs,
                         nonTaglibXmlnsAttrs,
                         taglibAttrs,
                         ,
                         );
             } else {
                 // custom action
                 String bodyType = getBodyType((Node.CustomTagnode);
 
                 if ( == null
                         && bodyType.equalsIgnoreCase(.)) {
                      = node;
                 }
                 else if (..equalsIgnoreCase(bodyType)) {
                      = true;
                 }
             }
         }
 
          = node;
     }
 
     /*
      * Receives notification of character data inside an element.
      *
      * The SAX does not call this method with all of the template text, but may
      * invoke this method with chunks of it.  This is a problem when we try
      * to determine if the text contains only whitespaces, or when we are
      * looking for an EL expression string.  Therefore it is necessary to
      * buffer and concatenate the chunks and process the concatenated text 
      * later (at beginTag and endTag)
      *
      * @param buf The characters
      * @param offset The start position in the character array
      * @param len The number of characters to use from the character array
      *
      * @throws SAXException
      */
     public void characters(char[] bufint offsetint len) {
         if ( == null) {
              = new StringBuilder();
         }
         .append(bufoffsetlen);
     }
 
     private void processChars() throws SAXException {
 
         if ( == null || ) {
             return;
         }
 
         /*
          * JSP.6.1.1: All textual nodes that have only white space are to be
          * dropped from the document, except for nodes in a jsp:text element,
          * and any leading and trailing white-space-only textual nodes in a
          * jsp:attribute whose 'trim' attribute is set to FALSE, which are to
          * be kept verbatim.
          * JSP.6.2.3 defines white space characters.
          */
         boolean isAllSpace = true;
         if (!( instanceof Node.JspText)
             && !( instanceof Node.NamedAttribute)) {
             for (int i = 0; i < .length(); i++) {
                 if (!(.charAt(i) == ' '
                     || .charAt(i) == '\n'
                     || .charAt(i) == '\r'
                     || .charAt(i) == '\t')) {
                     isAllSpace = false;
                     break;
                 }
             }
         }
 
         if (!isAllSpace && ) {
              = false;
             ++;
         }
 
         if ( > 0) {
             if (.length() > 0) {
                 new Node.TemplateText(.toString(), );
             }
              = new Mark(.getLineNumber(),
                                  .getColumnNumber());
              = null;
             return;
         }
 
         if (( instanceof Node.JspText)
             || ( instanceof Node.NamedAttribute)
             || !isAllSpace) {
 
             int line = .getLineNumber();
             int column = .getColumnNumber();
 
             CharArrayWriter ttext = new CharArrayWriter();
             int lastCh = 0, elType = 0;
             for (int i = 0; i < .length(); i++) {
 
                 int ch = .charAt(i);
                 if (ch == '\n') {
                     column = 1;
                     line++;
                 } else {
                     column++;
                 }
                 if ((lastCh == '$' || lastCh == '#') && ch == '{') {
                     elType = lastCh;
                     if (ttext.size() > 0) {
                         new Node.TemplateText(
                             ttext.toString(),
                             ,
                             );
                         ttext = new CharArrayWriter();
                         //We subtract two from the column number to
                         //account for the '[$,#]{' that we've already parsed
                          = new Mark(linecolumn - 2);
                     }
                     // following "${" || "#{" to first unquoted "}"
                     i++;
                     boolean singleQ = false;
                     boolean doubleQ = false;
                     lastCh = 0;
                     for (;; i++) {
                         if (i >= .length()) {
                             throw new SAXParseException(.unterminatedTag((charelType + "{"),
                                 );
 
                         }
                         ch = .charAt(i);
                         if (ch == '\n') {
                             column = 1;
                             line++;
                         } else {
                             column++;
                         }
                         if (lastCh == '\\' && (singleQ || doubleQ)) {
                             ttext.write(ch);
                             lastCh = 0;
                             continue;
                         }
                         if (ch == '}') {
                             new Node.ELExpression((charelType,
                                 ttext.toString(),
                                 ,
                                 );
                             ttext = new CharArrayWriter();
                              = new Mark(linecolumn);
                             break;
                         }
                         if (ch == '"')
                             doubleQ = !doubleQ;
                         else if (ch == '\'')
                             singleQ = !singleQ;
 
                         ttext.write(ch);
                         lastCh = ch;
                     }
                 } else if (lastCh == '\\' && (ch == '$' || ch == '#')) {
                     if (.isELIgnored()) {
                         ttext.write('\\');
                     }
                     ttext.write(ch);
                     ch = 0;  // Not start of EL anymore
                 } else {
                     if (lastCh == '$' || lastCh == '#' || lastCh == '\\') {
                         ttext.write(lastCh);
                     }
                     if (ch != '$' && ch != '#' && ch != '\\') {
                         ttext.write(ch);
                     }
                 }
                 lastCh = ch;
             }
             if (lastCh == '$' || lastCh == '#' || lastCh == '\\') {
                 ttext.write(lastCh);
             }
             if (ttext.size() > 0) {
                 new Node.TemplateText(ttext.toString(), );
             }
         }
          = new Mark(.getLineNumber(),
                              .getColumnNumber());
 
          = null;
     }
 
     /*
      * Receives notification of the end of an element.
      */
     public void endElement(String uriString localNameString qName)
         throws SAXException {
 
         processChars();
 
         if ( &&
             !(.equals(uri) && localName.startsWith())) {
             return;
         }
 
         if ( instanceof Node.NamedAttribute) {
             boolean isTrim = ((Node.NamedAttribute)).isTrim();
             Node.Nodes subElems = ((Node.NamedAttribute)).getBody();
             for (int i = 0; subElems != null && i < subElems.size(); i++) {
                 Node subElem = subElems.getNode(i);
                 if (!(subElem instanceof Node.TemplateText)) {
                     continue;
                 }
                 // Ignore any whitespace (including spaces, carriage returns,
                 // line feeds, and tabs, that appear at the beginning and at
                 // the end of the body of the <jsp:attribute> action, if the
                 // action's 'trim' attribute is set to TRUE (default).
                 // In addition, any textual nodes in the <jsp:attribute> that
                 // have only white space are dropped from the document, with
                 // the exception of leading and trailing white-space-only
                 // textual nodes in a <jsp:attribute> whose 'trim' attribute
                 // is set to FALSE, which must be kept verbatim.
                 if (i == 0) {
                     if (isTrim) {
                         ((Node.TemplateText)subElem).ltrim();
                     }
                 } else if (i == subElems.size() - 1) {
                     if (isTrim) {
                         ((Node.TemplateText)subElem).rtrim();
                     }
                 } else {
                     if (((Node.TemplateText)subElem).isAllSpace()) {
                         subElems.remove(subElem);
                     }
                 }
             }
         } else if ( instanceof Node.ScriptingElement) {
             checkScriptingBody((Node.ScriptingElement));
         }
 
         if ( isTagDependent()) {
             --;
         }
 
         if ( != null
                 && .equals()) {
              = null;
         }
 
         if ( instanceof Node.CustomTag) {
             String bodyType = getBodyType((Node.CustomTag);
             if (..equalsIgnoreCase(bodyType)) {
                 // Children - if any - must be JSP attributes
                 Node.Nodes children = .getBody();
                 if (children != null && children.size() > 0) {
                     for (int i = 0; i < children.size(); i++) {
                         Node child = children.getNode(i);
                         if (!(child instanceof Node.NamedAttribute)) {
                             throw new SAXParseException(.invalidEmptyTagSubelements(.), ); 
                         }
                     }
                 }
             }
         }
         if (.getParent() != null) {
              = .getParent();
         }
     }
 
     /*
      * Receives the document locator.
      *
      * @param locator the document locator
      */
     public void setDocumentLocator(Locator locator) {
         this. = locator;
     }
 
     /*
      * See org.xml.sax.ext.LexicalHandler.
      */
     public void comment(char[] bufint offsetint lenthrows SAXException {
 
         processChars();  // Flush char buffer and remove white spaces
 
         // ignore comments in the DTD
         if (!) {
              =
                 new Mark(
                     ,
                     ,
                     .getLineNumber(),
                     .getColumnNumber());
             new Node.Comment(new String(bufoffsetlen), );
         }
     }
 
     /*
      * See org.xml.sax.ext.LexicalHandler.
      */
     public void startCDATA() throws SAXException {
 
         processChars();  // Flush char buffer and remove white spaces
          = new Mark(.getLineNumber(),
                              .getColumnNumber());
     }
 
     /*
      * See org.xml.sax.ext.LexicalHandler.
      */
     public void endCDATA() throws SAXException {
         processChars();  // Flush char buffer and remove white spaces
     }
 
     /*
      * See org.xml.sax.ext.LexicalHandler.
      */
     public void startEntity(String namethrows SAXException {
         // do nothing
     }
 
     /*
      * See org.xml.sax.ext.LexicalHandler.
      */
     public void endEntity(String namethrows SAXException {
         // do nothing
     }
 
     /*
      * See org.xml.sax.ext.LexicalHandler.
      */
     public void startDTD(String nameString publicIdString systemId)
         throws SAXException {
         if (!) {
             fatalError(new EnableDTDValidationException("jsp.error.enable_dtd_validation"null));
         }
 
          = true;
     }
 
     /*
      * See org.xml.sax.ext.LexicalHandler.
      */
     public void endDTD() throws SAXException {
          = false;
     }
 
     /*
      * Receives notification of a non-recoverable error.
      */
     public void fatalError(SAXParseException ethrows SAXException {
         throw e;
     }
 
     /*
      * Receives notification of a recoverable error.
      */
     public void error(SAXParseException ethrows SAXException {
         throw e;
     }
 
     /*
      * Receives notification of the start of a Namespace mapping. 
      */
     public void startPrefixMapping(String prefixString uri)
         throws SAXException {
         TagLibraryInfo taglibInfo;
 
         if ( && !(.equals(uri))) {
             return;
         }
         
         try {
             taglibInfo = getTaglibInfo(prefixuri);
         } catch (JasperException je) {
             throw new SAXParseException(.errorAddingTagLibraries(je.getMessage()),
                 ,
                 je);
         }
 
         if (taglibInfo != null) {
             if (.getTaglib(uri) == null) {
                 .addTaglib(uritaglibInfo);
             }
             .pushPrefixMapping(prefixuri);
         } else {
             .pushPrefixMapping(prefixnull);
         }
     }
 
     /*
      * Receives notification of the end of a Namespace mapping. 
      */
     public void endPrefixMapping(String prefixthrows SAXException {
 
         if () {
             String uri = .getURI(prefix);
             if (!.equals(uri)) {
                 return;
             }
         }
 
         .popPrefixMapping(prefix);
     }
 
     //*********************************************************************
     // Private utility methods
 
     private Node parseStandardAction(
         String qName,
         String localName,
         Attributes nonTaglibAttrs,
         Attributes nonTaglibXmlnsAttrs,
         Attributes taglibAttrs,
         Mark start,
         Node parent)
         throws SAXException {
 
         Node node = null;
 
         if (localName.equals()) {
             if (!( instanceof Node.Root)) {
                 throw new SAXParseException(.nestedJspRoot(),
                     );
             }
             node =
                 new Node.JspRoot(
                     qName,
                     nonTaglibAttrs,
                     nonTaglibXmlnsAttrs,
                     taglibAttrs,
                     start,
                     );
             if () {
                 .setHasJspRoot(true);
             }
         } else if (localName.equals()) {
             if () {
                 throw new SAXParseException(.invalidDirectiveInTagFile(localName),
                     );
             }
             node =
                 new Node.PageDirective(
                     qName,
                     nonTaglibAttrs,
                     nonTaglibXmlnsAttrs,
                     taglibAttrs,
                     start,
                     );
             String imports = nonTaglibAttrs.getValue("import");
             // There can only be one 'import' attribute per page directive
             if (imports != null) {
                 ((Node.PageDirective)node).addImport(imports);
             }
         } else if (localName.equals()) {
             node =
                 new Node.IncludeDirective(
                     qName,
                     nonTaglibAttrs,
                     nonTaglibXmlnsAttrs,
                     taglibAttrs,
                     start,
                     );
             processIncludeDirective(nonTaglibAttrs.getValue("file"), node);
         } else if (localName.equals()) {
             if ( != null) {
                 // We're nested inside a node whose body is
                 // declared to be scriptless
                 throw new SAXParseException(.invalidScriptingElement(),
                     );
             }
             node =
                 new Node.Declaration(
                     qName,
                     nonTaglibXmlnsAttrs,
                     taglibAttrs,
                     start,
                     );
         } else if (localName.equals()) {
             if ( != null) {
                 // We're nested inside a node whose body is
                 // declared to be scriptless
                 throw new SAXParseException(.invalidScriptingElement(),
                     );
             }
             node =
                 new Node.Scriptlet(
                     qName,
                     nonTaglibXmlnsAttrs,
                     taglibAttrs,
                     start,
                     );
         } else if (localName.equals()) {
             if ( != null) {
                 // We're nested inside a node whose body is
                 // declared to be scriptless
                 throw new SAXParseException(.invalidScriptingElement(),
                     );
             }
             node =
                 new Node.Expression(
                     qName,
                     nonTaglibXmlnsAttrs,
                     taglibAttrs,
                     start,
                     );
         } else if (localName.equals()) {
             node =
                 new Node.UseBean(
                     qName,
                     nonTaglibAttrs,
                     nonTaglibXmlnsAttrs,
                     taglibAttrs,
                     start,
                     );
         } else if (localName.equals()) {
             node =
                 new Node.SetProperty(
                     qName,
                     nonTaglibAttrs,
                     nonTaglibXmlnsAttrs,
                     taglibAttrs,
                     start,
                     );
         } else if (localName.equals()) {
             node =
                 new Node.GetProperty(
                     qName,
                     nonTaglibAttrs,
                     nonTaglibXmlnsAttrs,
                     taglibAttrs,
                     start,
                     );
         } else if (localName.equals()) {
             node =
                 new Node.IncludeAction(
                     qName,
                     nonTaglibAttrs,
                     nonTaglibXmlnsAttrs,
                     taglibAttrs,
                     start,
                     );
         } else if (localName.equals()) {
             node =
                 new Node.ForwardAction(
                     qName,
                     nonTaglibAttrs,
                     nonTaglibXmlnsAttrs,
                     taglibAttrs,
                     start,
                     );
         } else if (localName.equals()) {
             node =
                 new Node.ParamAction(
                     qName,
                     nonTaglibAttrs,
                     nonTaglibXmlnsAttrs,
                     taglibAttrs,
                     start,
                     );
         } else if (localName.equals()) {
             node =
                 new Node.ParamsAction(
                     qName,
                     nonTaglibXmlnsAttrs,
                     taglibAttrs,
                     start,
                     );
         } else if (localName.equals()) {
             node =
                 new Node.PlugIn(
                     qName,
                     nonTaglibAttrs,
                     nonTaglibXmlnsAttrs,
                     taglibAttrs,
                     start,
                     );
         } else if (localName.equals()) {
             node =
                 new Node.JspText(
                     qName,
                     nonTaglibXmlnsAttrs,
                     taglibAttrs,
                     start,
                     );
        } else if (localName.equals()) {
            node =
                new Node.JspBody(
                    qName,
                    nonTaglibXmlnsAttrs,
                    taglibAttrs,
                    start,
                    );
        } else if (localName.equals()) {
            node =
                new Node.NamedAttribute(
                    qName,
                    nonTaglibAttrs,
                    nonTaglibXmlnsAttrs,
                    taglibAttrs,
                    start,
                    );
        } else if (localName.equals()) {
            node =
                new Node.JspOutput(
                    qName,
                    nonTaglibAttrs,
                    nonTaglibXmlnsAttrs,
                    taglibAttrs,
                    start,
                    );
        } else if (localName.equals()) {
            if (!) {
                throw new SAXParseException(.invalidDirectiveInTagFile(localName),
                    );
            }
            node =
                new Node.TagDirective(
                    qName,
                    nonTaglibAttrs,
                    nonTaglibXmlnsAttrs,
                    taglibAttrs,
                    start,
                    );
            String imports = nonTaglibAttrs.getValue("import");
            // There can only be one 'import' attribute per tag directive
            if (imports != null) {
                ((Node.TagDirective)node).addImport(imports);
            }
        } else if (localName.equals()) {
            if (!) {
                throw new SAXParseException(.invalidDirectiveInTagFile(localName),
                    );
            }
            node =
                new Node.AttributeDirective(
                    qName,
                    nonTaglibAttrs,
                    nonTaglibXmlnsAttrs,
                    taglibAttrs,
                    start,