You are viewing a plain text version of this content. The canonical link for it is here.
Posted to dev@tomcat.apache.org by ho...@apache.org on 2002/08/24 23:42:35 UTC

cvs commit: jakarta-tomcat-jasper/jasper2/src/share/org/apache/jasper/compiler Generator.java JspConfig.java JspDocumentParser.java JspReader.java Node.java Parser.java TagFileProcessor.java Validator.java

horwat      2002/08/24 14:42:35

  Modified:    jasper2/src/share/org/apache/jasper/compiler Generator.java
                        JspConfig.java JspDocumentParser.java
                        JspReader.java Node.java Parser.java
                        TagFileProcessor.java Validator.java
  Log:
  Summary of changes:
      - Updated taglib namespace support in XML parser to support xmlns:
        attributes on any node.  Redefinitions are still disallowed, and
        scoping is not implemented.  The spec needs some clarification
        in this space before we do more, but this will give users an
        opportunity to experiment and provide feedback.
      - Now fully supports multiple <url-pattern> elements
        per <jsp-property-group>.
      - Implemented the following attributes for the tag directive (they
        were parsed but effectively NOPs before):
          - language
          - isScriptingEnabled
          - isELEnabled
          - pageEncoding
          - import
      - Implemented support for XML elements in standard syntax, as per
        the PFD specification.  The following elements can now be used
        in standard syntax JSP pages:
          - jsp:scriptlet
          - jsp:expression
          - jsp:declaration
  	- jsp:text
          - jsp:directive.page
          - jsp:directive.include
  
        and in tag files...
          - jsp:scriptlet
          - jsp:expression
          - jsp:declaration
  	- jsp:text
          - jsp:directive.include
          - jsp:directive.tag
          - jsp:directive.variable
          - jsp:directive.attribute
      - Fixed NPE in tag file generation: When no value was passed for
        an attribute, a NPE was being thrown.  Now checks if attribute is
        null before assigning a page-scoped variable.
  
  Submitted by: Mark Roth
  
  Revision  Changes    Path
  1.79      +5 -4      jakarta-tomcat-jasper/jasper2/src/share/org/apache/jasper/compiler/Generator.java
  
  Index: Generator.java
  ===================================================================
  RCS file: /home/cvs/jakarta-tomcat-jasper/jasper2/src/share/org/apache/jasper/compiler/Generator.java,v
  retrieving revision 1.78
  retrieving revision 1.79
  diff -u -r1.78 -r1.79
  --- Generator.java	23 Aug 2002 23:56:53 -0000	1.78
  +++ Generator.java	24 Aug 2002 21:42:34 -0000	1.79
  @@ -3146,7 +3146,8 @@
   	if (attrInfos != null) {
   	    for (int i=0; i<attrInfos.length; i++) {
   		String attrName = attrInfos[i].getName();
  -		out.printin("pageContext.setAttribute(");
  +                out.println("if( " + toGetterMethod(attrName) + " != null ) " );
  +                out.print("pageContext.setAttribute(");
   		out.print(quote(attrName));
   		out.print(", ");
   		out.print(toGetterMethod(attrName));
  
  
  
  1.3       +138 -129  jakarta-tomcat-jasper/jasper2/src/share/org/apache/jasper/compiler/JspConfig.java
  
  Index: JspConfig.java
  ===================================================================
  RCS file: /home/cvs/jakarta-tomcat-jasper/jasper2/src/share/org/apache/jasper/compiler/JspConfig.java,v
  retrieving revision 1.2
  retrieving revision 1.3
  diff -u -r1.2 -r1.3
  --- JspConfig.java	22 Aug 2002 00:47:24 -0000	1.2
  +++ JspConfig.java	24 Aug 2002 21:42:34 -0000	1.3
  @@ -76,9 +76,9 @@
   
   /**
    * Handles the jsp-config element in WEB_INF/web.xml.  This is used
  - * for specifying the JSP configuration informantion on a JSP page
  + * for specifying the JSP configuration information on a JSP page
    *
  - * @authro Kin-man Chung
  + * @author Kin-man Chung
    */
   
   public class JspConfig {
  @@ -124,7 +124,7 @@
   	    TreeNode element = (TreeNode) jspPropertyList.next();
   	    Iterator list = element.findChildren();
   
  -	    String urlPattern = null;
  +            Vector urlPatterns = new Vector();
   	    String pageEncoding = null;
   	    String scriptingEnabled = null;
   	    String elEnabled = null;
  @@ -138,7 +138,7 @@
   		String tname = element.getName();
   
   		if ("url-pattern".equals(tname))
  -		    urlPattern = element.getBody();
  +                    urlPatterns.addElement( element.getBody() );
   		else if ("page-encoding".equals(tname))
   		    pageEncoding = element.getBody();
   		else if ("is-xml".equals(tname))
  @@ -152,51 +152,56 @@
   		else if ("include-coda".equals(tname))
   		    includeCoda.addElement(element.getBody());
   	    }
  -	    
  -	    String path = null;
  -	    String extension = null;
  -
  -	    if (urlPattern == null) {
  -		continue;
  -	    }
   
  -	    if (urlPattern.indexOf('*') < 0) {
  -		// Exact match
  -		path = urlPattern;
  -	    } else {
  -		int i = urlPattern.lastIndexOf('/');
  -		String file;
  -		if (i >= 0) {
  -		    path = urlPattern.substring(0,i+1);
  -		    file = urlPattern.substring(i+1);
  -		} else {
  -		    file = urlPattern;
  -		}
  -
  -		// pattern must be "*", or of the form "*.jsp"
  -		if (file.equals("*")) {
  -		    extension = "*";
  -		} else if (file.startsWith("*.")) {
  -		    extension = file.substring(file.indexOf('.')+1);
  -		} else {
  -		    Constants.message(
  -			"jsp.warning.bad.urlpattern.propertygroup",
  -			new Object[] {urlPattern},
  -			Logger.WARNING);
  -		    continue;
  -		}
  -	    }
  +             if (urlPatterns.size() == 0) {
  +                 continue;
  +             }
  + 
  +             // Add one JspPropertyGroup for each URL Pattern.  This makes
  +             // the matching logic easier.
  +             for( int p = 0; p < urlPatterns.size(); p++ ) {
  +                 String urlPattern = (String)urlPatterns.elementAt( p );
  +                 String path = null;
  +                 String extension = null;
  + 
  +                 if (urlPattern.indexOf('*') < 0) {
  +                     // Exact match
  +                     path = urlPattern;
  +                 } else {
  +                     int i = urlPattern.lastIndexOf('/');
  +                     String file;
  +                     if (i >= 0) {
  +                         path = urlPattern.substring(0,i+1);
  +                         file = urlPattern.substring(i+1);
  +                     } else {
  +                         file = urlPattern;
  +                     }
  + 
  +                     // pattern must be "*", or of the form "*.jsp"
  +                     if (file.equals("*")) {
  +                         extension = "*";
  +                     } else if (file.startsWith("*.")) {
  +                         extension = file.substring(file.indexOf('.')+1);
  +                     } else {
  +                         Constants.message(
  +                             "jsp.warning.bad.urlpattern.propertygroup",
  +                             new Object[] {urlPattern},
  +                             Logger.WARNING);
  +                         continue;
  +                     }
  +                 }
  + 
  +                 JspProperty property = new JspProperty(isXml,
  +                                                        elEnabled,
  +                                                        scriptingEnabled,
  +                                                        pageEncoding,
  +                                                        includePrelude,
  +                                                        includeCoda);
  +                 JspPropertyGroup propertyGroup =
  +                     new JspPropertyGroup(path, extension, property);
   
  -	    JspProperty property = new JspProperty(isXml,
  -						   elEnabled,
  -						   scriptingEnabled,
  -						   pageEncoding,
  -						   includePrelude,
  -						   includeCoda);
  -	    JspPropertyGroup propertyGroup =
  -		new JspPropertyGroup(path, extension, property);
  -
  -	    jspProperties.addElement(propertyGroup);
  +                 jspProperties.addElement(propertyGroup);
  +             }
   	}
       }
   
  @@ -243,85 +248,89 @@
   	    JspPropertyGroup jpg = (JspPropertyGroup) iter.next();
   	    JspProperty jp = jpg.getJspProperty();
   
  -	    if (jpg.getExtension() == null) {
  -
  -		// exact match pattern: /a/foo.jsp
  -		if (!uri.equals(jpg.getPath())) {
  -		    // not matched;
  -		    continue;
  -		}
  -
  -		// Add include-preludes and include-codas
  -		if (jp.getIncludePrelude() != null) {
  -		    includePreludes.addAll(jp.getIncludePrelude());
  -		}
  -		if (jp.getIncludeCoda() != null) {
  -		    includeCodas.addAll(jp.getIncludeCoda());
  -		}
  -
  -		// For other attributes, keep the best match.
  -		if (jp.isXml() != null) {
  -		    isXmlMatch = jpg;
  -		}
  -		if (jp.isELEnabled() != null) {
  -		    elEnabledMatch = jpg;
  -		}
  -		if (jp.isScriptingEnabled() != null) {
  -		    scriptingEnabledMatch = jpg;
  -		}
  -		if (jp.getPageEncoding() != null) {
  -		    pageEncodingMatch = jpg;
  -		}
  -	    } else {
  -
  -		// Possible patterns are *, *.ext, /p/*, and /p/*.ext
  -
  -		if (jpg.getPath() != null && !jpg.getPath().equals(uriPath)) {
  -		    // not matched
  -		    continue;
  -		}
  -		if (!jpg.getExtension().equals("*") &&
  -				!jpg.getExtension().equals(uriExtension)) {
  -		    // not matched
  -		    continue;
  -		}
  -
  -		// We have a match
  -		// Add include-preludes and include-codas
  -		if (jp.getIncludePrelude() != null) {
  -		    includePreludes.addAll(jp.getIncludePrelude());
  -		}
  -		if (jp.getIncludeCoda() != null) {
  -		    includeCodas.addAll(jp.getIncludeCoda());
  -		}
  -
  -		// If there is a previous match, and the current match is
  -		// more restrictive, use the current match.
  -		if (jp.isXml() != null &&
  -			(isXmlMatch == null ||
  -				(isXmlMatch.getExtension() != null &&
  -				 isXmlMatch.getExtension().equals("*")))) {
  -			isXmlMatch = jpg;
  -		}
  -		if (jp.isELEnabled() != null &&
  -			(elEnabledMatch == null ||
  -			    (elEnabledMatch.getExtension() != null &&
  -			     elEnabledMatch.getExtension().equals("*")))) {
  -		    elEnabledMatch = jpg;
  -		}
  -		if (jp.isScriptingEnabled() != null &&
  -			(scriptingEnabledMatch == null ||
  -			    (scriptingEnabledMatch.getExtension() != null &&
  -			     scriptingEnabledMatch.getExtension().equals("*")))) {
  -		    scriptingEnabledMatch = jpg;
  -		}
  -		if (jp.getPageEncoding() != null &&
  -			(pageEncodingMatch == null ||
  -			    (pageEncodingMatch.getExtension() != null &&
  -			     pageEncodingMatch.getExtension().equals("*")))) {
  -		    pageEncodingMatch = jpg;
  -		}
  -	    }
  +             // (arrays will be the same length)
  +             String extension = jpg.getExtension();
  +             String path = jpg.getPath();
  + 
  +             if (extension == null) {
  + 
  +                 // exact match pattern: /a/foo.jsp
  +                 if (!uri.equals(path)) {
  +                     // not matched;
  +                     continue;
  +                 }
  + 
  +                 // Add include-preludes and include-codas
  +                 if (jp.getIncludePrelude() != null) {
  +                     includePreludes.addAll(jp.getIncludePrelude());
  +                 }
  +                 if (jp.getIncludeCoda() != null) {
  +                     includeCodas.addAll(jp.getIncludeCoda());
  +                 }
  + 
  +                 // For other attributes, keep the best match.
  +                 if (jp.isXml() != null) {
  +                     isXmlMatch = jpg;
  +                 }
  +                 if (jp.isELEnabled() != null) {
  +                     elEnabledMatch = jpg;
  +                 }
  +                 if (jp.isScriptingEnabled() != null) {
  +                     scriptingEnabledMatch = jpg;
  +                 }
  +                 if (jp.getPageEncoding() != null) {
  +                     pageEncodingMatch = jpg;
  +                 }
  +             } else {
  + 
  +                 // Possible patterns are *, *.ext, /p/*, and /p/*.ext
  + 
  +                 if (path != null && !path.equals(uriPath)) {
  +                     // not matched
  +                     continue;
  +                 }
  +                 if (!extension.equals("*") &&
  +                                 !extension.equals(uriExtension)) {
  +                     // not matched
  +                     continue;
  +                 }
  + 
  +                 // We have a match
  +                 // Add include-preludes and include-codas
  +                 if (jp.getIncludePrelude() != null) {
  +                     includePreludes.addAll(jp.getIncludePrelude());
  +                 }
  +                 if (jp.getIncludeCoda() != null) {
  +                     includeCodas.addAll(jp.getIncludeCoda());
  +                 }
  + 
  +                 // If there is a previous match, and the current match is
  +                 // more restrictive, use the current match.
  +                 if (jp.isXml() != null &&
  +                         (isXmlMatch == null ||
  +                                 (isXmlMatch.getExtension() != null &&
  +                                  isXmlMatch.getExtension().equals("*")))) {
  +                         isXmlMatch = jpg;
  +                 }
  +                 if (jp.isELEnabled() != null &&
  +                         (elEnabledMatch == null ||
  +                             (elEnabledMatch.getExtension() != null &&
  +                              elEnabledMatch.getExtension().equals("*")))) {
  +                     elEnabledMatch = jpg;
  +                 }
  +                 if (jp.isScriptingEnabled() != null &&
  +                         (scriptingEnabledMatch == null ||
  +                             (scriptingEnabledMatch.getExtension() != null &&
  +                              scriptingEnabledMatch.getExtension().equals("*")))) {
  +                     scriptingEnabledMatch = jpg;
  +                 }
  +                 if (jp.getPageEncoding() != null &&
  +                         (pageEncodingMatch == null ||
  +                             (pageEncodingMatch.getExtension() != null &&
  +                              pageEncodingMatch.getExtension().equals("*")))) {
  +                     pageEncodingMatch = jpg;
  +                 }
  +             }
   	}
   
   
  
  
  
  1.16      +25 -18    jakarta-tomcat-jasper/jasper2/src/share/org/apache/jasper/compiler/JspDocumentParser.java
  
  Index: JspDocumentParser.java
  ===================================================================
  RCS file: /home/cvs/jakarta-tomcat-jasper/jasper2/src/share/org/apache/jasper/compiler/JspDocumentParser.java,v
  retrieving revision 1.15
  retrieving revision 1.16
  diff -u -r1.15 -r1.16
  --- JspDocumentParser.java	23 Aug 2002 16:35:07 -0000	1.15
  +++ JspDocumentParser.java	24 Aug 2002 21:42:34 -0000	1.16
  @@ -185,21 +185,20 @@
   	    rootAttrs.addAttribute("", "", "version", "CDATA", "2.0");
   	    node = new Node.JspRoot(rootAttrs, null, current, true);
   	    current = node;
  +            rootSeen = true;
   	}
   
  -	if (!rootSeen) {
  -	    rootSeen = true;
  -            // XXX - As of JSP 2.0, xmlns: can appear on the top node (either
  -            // <jsp:root> or another top node.  The spec needs clarification 
  -            // here.
  -            try {
  -                attrsCopy = addCustomTagLibraries(attrs);
  -            } catch (JasperException je) {
  -                throw new SAXException(je);
  -            }
  -        }
  -        else {
  -            attrsCopy = new AttributesImpl(attrs);
  +        // XXX - As of JSP 2.0, xmlns: can appear in any node (not just
  +        // <jsp:root>).  The spec still needs clarification here.
  +        // What we implement is that it can appear in any node and
  +        // is valid from that point forward.  Redefinitions cause an
  +        // error.  This isn't quite consistent with how xmlns: normally
  +        // works.
  +        try {
  +            attrsCopy = addCustomTagLibraries(attrs);
  +        } catch (JasperException je) {
  +            throw new SAXParseException( err.getString(
  +                "jsp.error.could.not.add.taglibraries" ), locator, je );
           }
   
   	if (qName.equals(JSP_ROOT)) {
  @@ -548,8 +547,16 @@
                       tl = new TagLibraryInfoImpl(ctxt, parserController, prefix,
   						uri, location, err);
                   }
  -		taglibs.put(prefix, tl);
  -                result.removeAttribute( i );
  +                if( taglibs.containsKey( prefix ) ) {
  +                    // Prefix already in taglib map.
  +                    throw new JasperException( err.getString(
  +                        "jsp.error.xmlns.redefinition.notimplemented",
  +                        prefix ) );
  +                }
  +                else {
  +                    taglibs.put(prefix, tl);
  +                    result.removeAttribute( i );
  +                }
   	    }
           }
           return result;
  
  
  
  1.8       +16 -0     jakarta-tomcat-jasper/jasper2/src/share/org/apache/jasper/compiler/JspReader.java
  
  Index: JspReader.java
  ===================================================================
  RCS file: /home/cvs/jakarta-tomcat-jasper/jasper2/src/share/org/apache/jasper/compiler/JspReader.java,v
  retrieving revision 1.7
  retrieving revision 1.8
  diff -u -r1.7 -r1.8
  --- JspReader.java	18 Jul 2002 20:18:10 -0000	1.7
  +++ JspReader.java	24 Aug 2002 21:42:34 -0000	1.8
  @@ -350,6 +350,22 @@
   	return false;
       }
   
  +    public boolean matchesETagWithoutLessThan(String tagName)
  +        throws JasperException
  +    {
  +       Mark mark = mark();
  +
  +       if (!matches("/" + tagName))
  +           return false;
  +       skipSpaces();
  +       if (nextChar() == '>')
  +           return true;
  +
  +       reset(mark);
  +       return false;
  +    }
  +
  +
       /**
        * Looks ahead to see if there are optional spaces followed by
        * the given String.  If so, true is returned and those spaces and
  
  
  
  1.31      +30 -3     jakarta-tomcat-jasper/jasper2/src/share/org/apache/jasper/compiler/Node.java
  
  Index: Node.java
  ===================================================================
  RCS file: /home/cvs/jakarta-tomcat-jasper/jasper2/src/share/org/apache/jasper/compiler/Node.java,v
  retrieving revision 1.30
  retrieving revision 1.31
  diff -u -r1.30 -r1.31
  --- Node.java	23 Aug 2002 23:56:53 -0000	1.30
  +++ Node.java	24 Aug 2002 21:42:34 -0000	1.31
  @@ -447,13 +447,40 @@
        * Represents a tag directive
        */
       public static class TagDirective extends Node {
  +        private Vector imports;
   
   	public TagDirective(Attributes attrs, Mark start, Node parent) {
   	    super(attrs, start, parent);
  +            imports = new Vector();
   	}
   
   	public void accept(Visitor v) throws JasperException {
   	    v.visit(this);
  +        }
  + 
  +        /**
  +         * Parses the comma-separated list of class or package names in the
  +         * given attribute value and adds each component to this
  +         * PageDirective's vector of imported classes and packages.
  +         * @param value A comma-separated string of imports.
  +         */
  +        public void addImport(String value) {
  +            int start = 0;
  +            int index;
  +            while ((index = value.indexOf(',', start)) != -1) {
  +                imports.add(value.substring(start, index).trim());
  +                start = index + 1;
  +            }
  +            if (start == 0) {
  +                // No comma found
  +                imports.add(value.trim());
  +            } else {
  +                imports.add(value.substring(start).trim());
  +            }
  +        }
  + 
  +        public List getImports() {
  +            return imports;
   	}
       }
   
  
  
  
  1.25      +307 -29   jakarta-tomcat-jasper/jasper2/src/share/org/apache/jasper/compiler/Parser.java
  
  Index: Parser.java
  ===================================================================
  RCS file: /home/cvs/jakarta-tomcat-jasper/jasper2/src/share/org/apache/jasper/compiler/Parser.java,v
  retrieving revision 1.24
  retrieving revision 1.25
  diff -u -r1.24 -r1.25
  --- Parser.java	23 Aug 2002 23:56:53 -0000	1.24
  +++ Parser.java	24 Aug 2002 21:42:34 -0000	1.25
  @@ -487,12 +487,94 @@
       }
   	
       /*
  +     * Parses a directive with the following syntax:
  +     *
  +     *   XMLJSPDirectiveBody ::= S? (   ( 'page' PageDirectiveAttrList
  +     *                                    S? ( '/>' | ( '>' S? ETag ) )
  +     *                               | ( 'include' IncludeDirectiveAttrList
  +     *                                    S? ( '/>' | ( '>' S? ETag ) )
  +     *                           | <TRANSLATION_ERROR>
  +     *
  +     *   XMLTagDefDirectiveBody ::= (   ( 'tag' TagDirectiveAttrList
  +     *                                    S? ( '/>' | ( '>' S? ETag ) )
  +     *                                | ( 'include' IncludeDirectiveAttrList
  +     *                                    S? ( '/>' | ( '>' S? ETag ) )
  +     *                                | ( 'attribute' AttributeDirectiveAttrList
  +     *                                    S? ( '/>' | ( '>' S? ETag ) )
  +     *                                | ( 'variable' VariableDirectiveAttrList
  +     *                                    S? ( '/>' | ( '>' S? ETag ) )
  +     *                              )
  +     *                            | <TRANSLATION_ERROR>
  +     */
  +    private void parseXMLDirective(Node parent) throws JasperException {
  +       reader.skipSpaces();
  +
  +        String eTag = null;
  +       if (reader.matches("page")) {
  +            eTag = "jsp:directive.page";
  +           if (isTagFile) {
  +               err.jspError(reader.mark(), "jsp.error.directive.istagfile",
  +                                           "&lt;" + eTag);
  +           }
  +           parsePageDirective(parent);
  +       } else if (reader.matches("include")) {
  +            eTag = "jsp:directive.include";
  +           parseIncludeDirective(parent);
  +       } else if (reader.matches("tag")) {
  +            eTag = "jsp:directive.tag";
  +           if (!isTagFile) {
  +               err.jspError(reader.mark(), "jsp.error.directive.isnottagfile",
  +                                           "&lt;" + eTag);
  +           }
  +           parseTagDirective(parent);
  +       } else if (reader.matches("attribute")) {
  +            eTag = "jsp:directive.attribute";
  +           if (!isTagFile) {
  +               err.jspError(reader.mark(), "jsp.error.directive.isnottagfile",
  +                                           "&lt;" + eTag);
  +           }
  +           parseAttributeDirective(parent);
  +       } else if (reader.matches("variable")) {
  +            eTag = "jsp:directive.variable";
  +           if (!isTagFile) {
  +               err.jspError(reader.mark(), "jsp.error.directive.isnottagfile",
  +                                           "&lt;" + eTag);
  +           }
  +           parseVariableDirective(parent);
  +       } else {
  +           err.jspError(reader.mark(), "jsp.error.invalid.directive");
  +       }
  +
  +       reader.skipSpaces();
  +        if( reader.matches( ">" ) ) {
  +            reader.skipSpaces();
  +            if( !reader.matchesETag( eTag ) ) {
  +                err.jspError(start, "jsp.error.unterminated", "&lt;" + eTag );
  +            }
  +        }
  +        else if( !reader.matches( "/>" ) ) {
  +            err.jspError(start, "jsp.error.unterminated", "&lt;" + eTag );
  +        }
  +    }
  +
  +    /*
        * Parses a tag directive with the following syntax:
        *   PageDirective ::= ( S Attribute)*
        */
       private void parseTagDirective(Node parent) throws JasperException {
   	Attributes attrs = parseAttributes();
   	Node.TagDirective n = new Node.TagDirective(attrs, start, parent);
  +
  +        /*
  +         * A page directive may contain multiple 'import' attributes, each of
  +         * which consists of a comma-separated list of package names.
  +         * Store each list with the node, where it is parsed.
  +         */
  +        for (int i = 0; i < attrs.getLength(); i++) {
  +            if ("import".equals(attrs.getQName(i))) {
  +                n.addImport(attrs.getValue(i));
  +            }
  +        }
       }
   
       /*
  @@ -543,6 +625,32 @@
       }
   
       /*
  +     * XMLDeclarationBody ::=   ( S? '/>' )
  +     *                        | ( S? '>' (Char* - (char* '<')) ETag )
  +     *                        | <TRANSLATION_ERROR>
  +     */
  +    private void parseXMLDeclaration(Node parent) throws JasperException {
  +        reader.skipSpaces();
  +        if( !reader.matches( "/>" ) ) {
  +            if( !reader.matches( ">" ) ) {
  +                err.jspError(start, "jsp.error.unterminated",
  +                        "&lt;jsp:declaration&gt;");
  +            }
  +            start = reader.mark();
  +            Mark stop = reader.skipUntil("<");
  +            if ((stop == null) || !reader.matchesETagWithoutLessThan(
  +                "jsp:declaration" ) )
  +            {
  +                err.jspError(start, "jsp.error.unterminated",
  +                        "&lt;jsp:declaration&gt;");
  +            }
  +
  +            new Node.Declaration(parseScriptText(reader.getText(start, stop)),
  +                               start, parent);
  +        }
  +    }
  +
  +    /*
        * ExpressionBody ::= (Char* - (char* '%>')) '%>'
        */
       private void parseExpression(Node parent) throws JasperException {
  @@ -557,6 +665,32 @@
       }
   
       /*
  +     * XMLExpressionBody ::=   ( S? '/>' )
  +     *                       | ( S? '>' (Char* - (char* '<')) ETag )
  +     *                       | <TRANSLATION_ERROR>
  +     */
  +    private void parseXMLExpression(Node parent) throws JasperException {
  +        reader.skipSpaces();
  +        if( !reader.matches( "/>" ) ) {
  +            if( !reader.matches( ">" ) ) {
  +                err.jspError(start, "jsp.error.unterminated",
  +                    "&lt;jsp:expression&gt;");
  +            }
  +            start = reader.mark();
  +            Mark stop = reader.skipUntil("<");
  +            if ((stop == null) || !reader.matchesETagWithoutLessThan(
  +                "jsp:expression" ))
  +            {
  +                err.jspError(start, "jsp.error.unterminated",
  +                    "&lt;jsp:expression&gt;");
  +            }
  +
  +            new Node.Expression(parseScriptText(reader.getText(start, stop)),
  +                                    start, parent);
  +        }
  +    }
  +
  +    /*
        * ELExpressionBody
        * (following "${" to first unquoted "}")
        * // XXX add formal production and confirm implementation against it,
  @@ -588,7 +722,7 @@
       }
   
       /*
  -     * Scriptlet ::= (Char* - (char* '%>')) '%>'
  +     * ScriptletBody ::= (Char* - (char* '%>')) '%>'
        */
       private void parseScriptlet(Node parent) throws JasperException {
   	start = reader.mark();
  @@ -600,6 +734,32 @@
   	new Node.Scriptlet(parseScriptText(reader.getText(start, stop)),
   				start, parent);
       }
  +
  +    /*
  +     * XMLScriptletBody ::=   ( S? '/>' )
  +     *                      | ( S? '>' (Char* - (char* '<')) ETag )
  +     *                      | <TRANSLATION_ERROR>
  +     */
  +    private void parseXMLScriptlet(Node parent) throws JasperException {
  +        reader.skipSpaces();
  +        if( !reader.matches( "/>" ) ) {
  +            if( !reader.matches( ">" ) ) {
  +                err.jspError(start, "jsp.error.unterminated",
  +                    "&lt;jsp:scriptlet&gt;");
  +            }
  +            start = reader.mark();
  +            Mark stop = reader.skipUntil("<");
  +            if ((stop == null) || !reader.matchesETagWithoutLessThan(
  +                "jsp:scriptlet" ))
  +            {
  +                err.jspError(start, "jsp.error.unterminated",
  +                    "&lt;jsp:scriptlet&gt;");
  +            }
  +
  +            new Node.Scriptlet(parseScriptText(reader.getText(start, stop)),
  +                                    start, parent );
  +        }
  +    }
   	
       /**
        * Param ::= '<jsp:param' S Attributes S? EmptyBody S?
  @@ -1119,14 +1279,91 @@
       }
       
       /*
  -     * AllBody ::=	  ( '<%--' JSPCommentBody )
  -     *			| ( '<%@' DirectiveBody )
  -     *			| ( '<%!' DeclarationBody )
  -     *			| ( '<%=' ExpressionBody )
  -     *                  | ( '${' ELExpressionBody )
  -     *			| ( '<%' ScriptletBody )
  -     *			| ( '<jsp:' StandardAction )
  -     *			| ( '<' CustomAction CustomActionBody )
  +     * XMLTemplateText ::=   ( S? '/>' )
  +     *                     | ( S? '>'
  +     *                         ( ( Char* - ( Char* ( '<' | '${' ) ) )
  +     *                           ( '${' ELExpressionBody )?
  +     *                         )* ETag
  +     *                       )
  +     *                     | <TRANSLATION_ERROR>
  +     */
  +    private void parseXMLTemplateText(Node parent) throws JasperException {
  +        reader.skipSpaces();
  +        if( !reader.matches( "/>" ) ) {
  +            if( !reader.matches( ">" ) ) {
  +                err.jspError(start, "jsp.error.unterminated",
  +                    "&lt;jsp:text&gt;" );
  +            }
  +            CharArrayWriter ttext = new CharArrayWriter();
  +            int lastCh = 0;
  +            do {
  +                int ch = reader.nextChar();
  +                if( ch == -1 ) {
  +                    err.jspError(start, "jsp.error.unterminated",
  +                        "&lt;jsp:text&gt;" );
  +                    break;
  +                }
  +                if( ch == '<' ) break;
  +                if( (lastCh == '$') && (ch == '{') ) {
  +                    // Create a template text node
  +                    new Node.TemplateText( ttext.toCharArray(), start, parent);
  +
  +                    // Mark and parse the EL expression and create its node:
  +                    start = reader.mark();
  +                    parseELExpression(parent);
  +
  +                    // Go back to parsing template text, unless next
  +                    // char is '<':
  +                    if( reader.peekChar() == '<' ) {
  +                        reader.nextChar();
  +                        ttext = null;
  +                        break;
  +                    }
  +                    start = reader.mark();
  +                    ttext = new CharArrayWriter();
  +                }
  +                else {
  +                    if( (lastCh == '$') && (ch != '{') ) {
  +                        ttext.write( '$' );
  +                    }
  +                    if( ch != '$' ) {
  +                        ttext.write( ch );
  +                    }
  +                }
  +                lastCh = ch;
  +            } while( true );
  +
  +            if( ttext != null ) {
  +                if( lastCh == '$' ) {
  +                    ttext.write( '$' );
  +                }
  +                // This could happen if we parsed an EL expression and then
  +                // there was no more template text (see above).
  +                new Node.TemplateText( ttext.toCharArray(), start, parent );
  +            }
  +
  +            if( !reader.matchesETagWithoutLessThan( "jsp:text" ) ) {
  +                err.jspError( start, "jsp.error.unterminated",
  +                    "&lt;jsp:text&gt;" );
  +            }
  +        }
  +    }
  +
  +    /*
  +     * AllBody ::=       ( '<%--'              JSPCommentBody     )
  +     *                 | ( '<%@'               DirectiveBody      )
  +     *                 | ( '<jsp:directive.'   XMLDirectiveBody   )
  +     *                 | ( '<%!'               DeclarationBody    )
  +     *                 | ( '<jsp:declaration'  XMLDeclarationBody )
  +     *                 | ( '<%='               ExpressionBody     )
  +     *                 | ( '<jsp:expression'   XMLExpressionBody  )
  +     *                  | ( '${'                ELExpressionBody   )
  +     *                 | ( '<%'                ScriptletBody      )
  +     *                 | ( '<jsp:scriptlet'    XMLScriptletBody   )
  +     *                  | ( '<jsp:text'         XMLTemplateText    )
  +     *                 | ( '<jsp:'             StandardAction     )
  +     *                 | ( '<'                 CustomAction
  +     *                                          CustomActionBody   )
        *			| TemplateText
        */
       private void parseElements(Node parent) 
  @@ -1145,12 +1382,22 @@
   	    parseComment(parent);
   	} else if (reader.matches("<%@")) {
   	    parseDirective(parent);
  +        } else if (reader.matches("<jsp:directive.")) {
  +            parseXMLDirective(parent);
   	} else if (reader.matches("<%!")) {
   	    parseDeclaration(parent);
  -	} else if (reader.matches("<%=")) {
  -	    parseExpression(parent);
  +        } else if (reader.matches("<jsp:declaration")) {
  +            parseXMLDeclaration(parent);
  +        } else if (reader.matches("<%=")) {
  +            parseExpression(parent);
  +        } else if (reader.matches("<jsp:expression")) {
  +            parseXMLExpression(parent);
   	} else if (reader.matches("<%")) {
   	    parseScriptlet(parent);
  +        } else if (reader.matches("<jsp:scriptlet")) {
  +            parseXMLScriptlet(parent);
  +        } else if (reader.matches("<jsp:text")) {
  +            parseXMLTemplateText(parent);
           } else if (reader.matches("${")) {
               parseELExpression(parent);
   	} else if (reader.matches("<jsp:")) {
  @@ -1161,14 +1408,20 @@
       }
   
       /*
  -     * ScriptlessBody ::=   ( '<%--' JSPCommentBody )
  -     *			  | ( '<%@' DirectiveBody )
  -     *			  | ( '<%!' <TRANSLATION_ERROR> )
  -     *			  | ( '<%=' <TRANSLATION_ERROR> )
  -     *			  | ( '<%' <TRANSLATION_ERROR> )
  -     *                    | ( '${' ELExpressionBody )
  -     *	  		  | ( '<jsp:' StandardAction )
  -     *			  | ( '<' CustomAction CustomActionBody )
  +     * ScriptlessBody ::=   ( '<%--'              JSPCommentBody      )
  +     *                   | ( '<%@'               DirectiveBody       )
  +     *                    | ( '<jsp:directive.'   XMLDirectiveBody    )
  +     *                   | ( '<%!'               <TRANSLATION_ERROR> )
  +     *                    | ( '<jsp:declaration'  <TRANSLATION_ERROR> )
  +     *                   | ( '<%='               <TRANSLATION_ERROR> )
  +     *                   | ( '<jsp:expression'   <TRANSLATION_ERROR> )
  +     *                   | ( '<%'                <TRANSLATION_ERROR> )
  +     *                   | ( '<jsp:scriptlet'    <TRANSLATION_ERROR> )
  +     *                    | ( '<jsp:text'         XMLTemplateText     )
  +     *                    | ( '${'                ELExpressionBody    )
  +     *                   | ( '<jsp:'             StandardAction      )
  +     *                   | ( '<'                 CustomAction
  +     *                                            CustomActionBody    )
        *			  | TemplateText
        */
       private void parseElementsScriptless(Node parent) 
  @@ -1183,12 +1436,22 @@
   	    parseComment(parent);
   	} else if (reader.matches("<%@")) {
   	    parseDirective(parent);
  +        } else if (reader.matches("<jsp:directive.")) {
  +            parseXMLDirective(parent);
   	} else if (reader.matches("<%!")) {
   	    err.jspError( reader.mark(), "jsp.error.no.scriptlets" );
  +        } else if (reader.matches("<jsp:declaration")) {
  +            err.jspError( reader.mark(), "jsp.error.no.scriptlets" );
   	} else if (reader.matches("<%=")) {
   	    err.jspError( reader.mark(), "jsp.error.no.scriptlets" );
  +        } else if (reader.matches("<jsp:expression")) {
  +            err.jspError( reader.mark(), "jsp.error.no.scriptlets" );
   	} else if (reader.matches("<%")) {
   	    err.jspError( reader.mark(), "jsp.error.no.scriptlets" );
  +        } else if (reader.matches("<jsp:scriptlet")) {
  +            err.jspError( reader.mark(), "jsp.error.no.scriptlets" );
  +        } else if (reader.matches("<jsp:text")) {
  +            parseXMLTemplateText(parent);
   	} else if (reader.matches("${")) {
   	    parseELExpression(parent);
   	} else if (reader.matches("<jsp:")) {
  @@ -1201,13 +1464,18 @@
       }
       
       /*
  -     * TemplateTextBody ::=   ( '<%--' JSPCommentBody )
  -     *                      | ( '<%@' DirectiveBody )
  -     *                      | ( '<%!' <TRANSLATION_ERROR> )
  -     *                      | ( '<%=' <TRANSLATION_ERROR> )
  -     *                      | ( '<%' <TRANSLATION_ERROR> )
  -     *                      | ( '${' <TRANSLATION_ERROR> )
  -     *                      | ( '<jsp:' <TRANSLATION_ERROR> )
  +     * TemplateTextBody ::=   ( '<%--'              JSPCommentBody      )
  +     *                      | ( '<%@'               DirectiveBody       )
  +     *                      | ( '<jsp:directive.'   XMLDirectiveBody    )
  +     *                      | ( '<%!'               <TRANSLATION_ERROR> )
  +     *                      | ( '<jsp:declaration'  <TRANSLATION_ERROR> )
  +     *                      | ( '<%='               <TRANSLATION_ERROR> )
  +     *                      | ( '<jsp:expression'   <TRANSLATION_ERROR> )
  +     *                      | ( '<%'                <TRANSLATION_ERROR> )
  +     *                      | ( '<jsp:scriptlet'    <TRANSLATION_ERROR> )
  +     *                      | ( '<jsp:text'         <TRANSLATION_ERROR> )
  +     *                      | ( '${'                <TRANSLATION_ERROR> )
  +     *                      | ( '<jsp:'             <TRANSLATION_ERROR> )
        *                      | TemplateText
        */
       private void parseElementsTemplateText(Node parent)
  @@ -1218,12 +1486,22 @@
               parseComment(parent);
           } else if (reader.matches("<%@")) {
               parseDirective(parent);
  +        } else if (reader.matches("<jsp:directive.")) {
  +            parseXMLDirective(parent);
           } else if (reader.matches("<%!")) {
               err.jspError( reader.mark(), "jsp.error.not.in.template" );
  +        } else if (reader.matches("<jsp:declaration")) {
  +            err.jspError( reader.mark(), "jsp.error.not.in.template" );
           } else if (reader.matches("<%=")) {
               err.jspError( reader.mark(), "jsp.error.not.in.template" );
  +        } else if (reader.matches("<jsp:expression")) {
  +            err.jspError( reader.mark(), "jsp.error.not.in.template" );
           } else if (reader.matches("<%")) {
               err.jspError( reader.mark(), "jsp.error.not.in.template" );
  +            err.jspError( reader.mark(), "jsp.error.not.in.template" );
  +        } else if (reader.matches("<jsp:scriptlet")) {
  +            err.jspError( reader.mark(), "jsp.error.not.in.template" );
  +        } else if (reader.matches("<jsp:text")) {
           } else if (reader.matches("${")) {
               err.jspError( reader.mark(), "jsp.error.not.in.template" );
           } else if (reader.matches("<jsp:")) {
  
  
  
  1.17      +2 -3      jakarta-tomcat-jasper/jasper2/src/share/org/apache/jasper/compiler/TagFileProcessor.java
  
  Index: TagFileProcessor.java
  ===================================================================
  RCS file: /home/cvs/jakarta-tomcat-jasper/jasper2/src/share/org/apache/jasper/compiler/TagFileProcessor.java,v
  retrieving revision 1.16
  retrieving revision 1.17
  diff -u -r1.16 -r1.17
  --- TagFileProcessor.java	21 Aug 2002 17:05:52 -0000	1.16
  +++ TagFileProcessor.java	24 Aug 2002 21:42:34 -0000	1.17
  @@ -142,7 +142,6 @@
   
           private Vector attributeVector = new Vector();
           private Vector variableVector = new Vector();
  -        private Vector fragmentAttributeVector = new Vector();
           private Map fragmentAttributesMap = new Hashtable();
   
           public TagFileVisitor(Compiler compiler, TagLibraryInfo tagLibInfo,
  
  
  
  1.30      +8 -6      jakarta-tomcat-jasper/jasper2/src/share/org/apache/jasper/compiler/Validator.java
  
  Index: Validator.java
  ===================================================================
  RCS file: /home/cvs/jakarta-tomcat-jasper/jasper2/src/share/org/apache/jasper/compiler/Validator.java,v
  retrieving revision 1.29
  retrieving revision 1.30
  diff -u -r1.29 -r1.30
  --- Validator.java	23 Aug 2002 23:56:53 -0000	1.29
  +++ Validator.java	24 Aug 2002 21:42:34 -0000	1.30
  @@ -270,9 +270,11 @@
   	}
   
   	public void visit(Node.TagDirective n) throws JasperException {
  -	    // Do nothing, since this tag directive has already been validated
  -	    // by TagFileProcessor when it created a TagInfo object from the
  -	    // tag file in which the directive appeared
  +            // Note: Most of the validation is done in TagFileProcessor
  +            // when it created a TagInfo object from the
  +            // tag file in which the directive appeared.
  +        
  +            // This method does additional processing to collect page info
   	}
   
   	public void visit(Node.AttributeDirective n) throws JasperException {
  
  
  

--
To unsubscribe, e-mail:   <ma...@jakarta.apache.org>
For additional commands, e-mail: <ma...@jakarta.apache.org>