You are viewing a plain text version of this content. The canonical link for it is here.
Posted to dev@tapestry.apache.org by hl...@apache.org on 2009/02/07 20:11:40 UTC

svn commit: r741938 - in /tapestry/tapestry5/trunk: src/site/apt/ tapestry-core/ tapestry-core/src/main/java/org/apache/tapestry5/ tapestry-core/src/main/java/org/apache/tapestry5/internal/bindings/ tapestry-core/src/main/java/org/apache/tapestry5/inte...

Author: hlship
Date: Sat Feb  7 19:11:39 2009
New Revision: 741938

URL: http://svn.apache.org/viewvc?rev=741938&view=rev
Log:
Convert Tapestry to use the Woodstox StAX2 parser when parsing Tapestry Markup Templates

Added:
    tapestry/tapestry5/trunk/tapestry-core/src/main/java/org/apache/tapestry5/internal/services/StaxTemplateParser.java
    tapestry/tapestry5/trunk/tapestry-core/src/main/java/org/apache/tapestry5/internal/services/TemplateParserImpl.java
    tapestry/tapestry5/trunk/tapestry-core/src/main/java/org/apache/tapestry5/internal/services/TemplateParserState.java
Removed:
    tapestry/tapestry5/trunk/tapestry-core/src/test/resources/org/apache/tapestry5/internal/services/illegal_nesting_within_body_element.tml
Modified:
    tapestry/tapestry5/trunk/src/site/apt/upgrade.apt
    tapestry/tapestry5/trunk/tapestry-core/pom.xml
    tapestry/tapestry5/trunk/tapestry-core/src/main/java/org/apache/tapestry5/Asset.java
    tapestry/tapestry5/trunk/tapestry-core/src/main/java/org/apache/tapestry5/internal/bindings/AssetBinding.java
    tapestry/tapestry5/trunk/tapestry-core/src/main/java/org/apache/tapestry5/internal/parser/StartElementToken.java
    tapestry/tapestry5/trunk/tapestry-core/src/main/java/org/apache/tapestry5/internal/services/AbstractAsset.java
    tapestry/tapestry5/trunk/tapestry-core/src/main/java/org/apache/tapestry5/internal/services/ClasspathAssetFactory.java
    tapestry/tapestry5/trunk/tapestry-core/src/main/java/org/apache/tapestry5/internal/services/ContextAssetFactory.java
    tapestry/tapestry5/trunk/tapestry-core/src/main/java/org/apache/tapestry5/internal/services/IdentityAssetPathConverter.java
    tapestry/tapestry5/trunk/tapestry-core/src/main/java/org/apache/tapestry5/services/AssetPathConverter.java
    tapestry/tapestry5/trunk/tapestry-core/src/test/java/org/apache/tapestry5/internal/services/ClasspathAssetFactoryTest.java
    tapestry/tapestry5/trunk/tapestry-core/src/test/java/org/apache/tapestry5/internal/services/ContextAssetFactoryTest.java
    tapestry/tapestry5/trunk/tapestry-core/src/test/java/org/apache/tapestry5/internal/services/TemplateParserImplTest.java
    tapestry/tapestry5/trunk/tapestry-core/src/test/resources/org/apache/tapestry5/internal/services/system_doctype.xml

Modified: tapestry/tapestry5/trunk/src/site/apt/upgrade.apt
URL: http://svn.apache.org/viewvc/tapestry/tapestry5/trunk/src/site/apt/upgrade.apt?rev=741938&r1=741937&r2=741938&view=diff
==============================================================================
--- tapestry/tapestry5/trunk/src/site/apt/upgrade.apt (original)
+++ tapestry/tapestry5/trunk/src/site/apt/upgrade.apt Sat Feb  7 19:11:39 2009
@@ -38,12 +38,17 @@
 
 * Module Classes
 
-  Many questionable practices in Tapestry module classes that used to produce warnings (which were
-  ignored, leading to more difficult questions) have been changed to fail early with exceptions. This includes
-  extra public methods on a module class that are not used by Tapestry IoC, and several other similar
-  scenarios.
+  Many questionable practices in Tapestry module classes that used to produce warnings
+  have been changed to fail early with exceptions. The rationale is that the warnings would be ignored,
+  resulting in more difficult to diagnose runtime errors. 
 
   Extra public methods on module classes (methods that do not define services, contribute to services,
   or decorate or advise services) are now errors.
 
+* Asset interface
+
+  The {{{apidocs/org/apache/tapestry5/Asset.html}Asset}} interface has been changed incompatibly:
+  A new method, isInvariant(), has been added. This will only affect applications that have provided
+  their own implementations of Asset.
+
 

Modified: tapestry/tapestry5/trunk/tapestry-core/pom.xml
URL: http://svn.apache.org/viewvc/tapestry/tapestry5/trunk/tapestry-core/pom.xml?rev=741938&r1=741937&r2=741938&view=diff
==============================================================================
--- tapestry/tapestry5/trunk/tapestry-core/pom.xml (original)
+++ tapestry/tapestry5/trunk/tapestry-core/pom.xml Sat Feb  7 19:11:39 2009
@@ -53,6 +53,13 @@
                 </exclusion>
             </exclusions>
         </dependency>
+
+        <dependency>
+            <groupId>org.codehaus.woodstox</groupId>
+            <artifactId>woodstox-core-asl</artifactId>
+            <version>4.0.1</version>
+        </dependency>
+
     </dependencies>
 
     <build>

Modified: tapestry/tapestry5/trunk/tapestry-core/src/main/java/org/apache/tapestry5/Asset.java
URL: http://svn.apache.org/viewvc/tapestry/tapestry5/trunk/tapestry-core/src/main/java/org/apache/tapestry5/Asset.java?rev=741938&r1=741937&r2=741938&view=diff
==============================================================================
--- tapestry/tapestry5/trunk/tapestry-core/src/main/java/org/apache/tapestry5/Asset.java (original)
+++ tapestry/tapestry5/trunk/tapestry-core/src/main/java/org/apache/tapestry5/Asset.java Sat Feb  7 19:11:39 2009
@@ -43,4 +43,16 @@
      * Returns the underlying Resource for the Asset.
      */
     Resource getResource();
+
+    /**
+     * Returns true if the Asset is invariant (meaning that it returns the same value from {@link #toClientURL()} at all
+     * times}. Assets that are used as binding values will be cached more aggresively by Tapestry is they are
+     * invariant.
+     *
+     * @return true if invariant
+     * @see org.apache.tapestry5.services.AssetPathConverter#isInvariant()
+     * @see Binding#isInvariant()
+     * @since 5.1.0.0
+     */
+    boolean isInvariant();
 }

Modified: tapestry/tapestry5/trunk/tapestry-core/src/main/java/org/apache/tapestry5/internal/bindings/AssetBinding.java
URL: http://svn.apache.org/viewvc/tapestry/tapestry5/trunk/tapestry-core/src/main/java/org/apache/tapestry5/internal/bindings/AssetBinding.java?rev=741938&r1=741937&r2=741938&view=diff
==============================================================================
--- tapestry/tapestry5/trunk/tapestry-core/src/main/java/org/apache/tapestry5/internal/bindings/AssetBinding.java (original)
+++ tapestry/tapestry5/trunk/tapestry-core/src/main/java/org/apache/tapestry5/internal/bindings/AssetBinding.java Sat Feb  7 19:11:39 2009
@@ -17,17 +17,26 @@
 import org.apache.tapestry5.Asset;
 import org.apache.tapestry5.ioc.Location;
 
-public class AssetBinding extends InvariantBinding
+public class AssetBinding extends AbstractBinding
 {
+    private final String description;
+
     private final Asset asset;
 
     AssetBinding(Location location, String description, Asset asset)
     {
-        super(location, Asset.class, description);
+        super(location);
 
+        this.description = description;
         this.asset = asset;
     }
 
+    @Override
+    public Class getBindingType()
+    {
+        return Asset.class;
+    }
+
     public Object get()
     {
         return asset;

Modified: tapestry/tapestry5/trunk/tapestry-core/src/main/java/org/apache/tapestry5/internal/parser/StartElementToken.java
URL: http://svn.apache.org/viewvc/tapestry/tapestry5/trunk/tapestry-core/src/main/java/org/apache/tapestry5/internal/parser/StartElementToken.java?rev=741938&r1=741937&r2=741938&view=diff
==============================================================================
--- tapestry/tapestry5/trunk/tapestry-core/src/main/java/org/apache/tapestry5/internal/parser/StartElementToken.java (original)
+++ tapestry/tapestry5/trunk/tapestry-core/src/main/java/org/apache/tapestry5/internal/parser/StartElementToken.java Sat Feb  7 19:11:39 2009
@@ -1,4 +1,4 @@
-// Copyright 2006 The Apache Software Foundation
+// Copyright 2006, 2009 The Apache Software Foundation
 //
 // Licensed under the Apache License, Version 2.0 (the "License");
 // you may not use this file except in compliance with the License.
@@ -58,7 +58,7 @@
     {
         StringBuilder builder = new StringBuilder("Start[");
 
-        if (namespaceURI.length() > 0) builder.append(namespaceURI).append(" ");
+        if (namespaceURI != null && namespaceURI.length() > 0) builder.append(namespaceURI).append(" ");
 
         builder.append(name).append("]");
 

Modified: tapestry/tapestry5/trunk/tapestry-core/src/main/java/org/apache/tapestry5/internal/services/AbstractAsset.java
URL: http://svn.apache.org/viewvc/tapestry/tapestry5/trunk/tapestry-core/src/main/java/org/apache/tapestry5/internal/services/AbstractAsset.java?rev=741938&r1=741937&r2=741938&view=diff
==============================================================================
--- tapestry/tapestry5/trunk/tapestry-core/src/main/java/org/apache/tapestry5/internal/services/AbstractAsset.java (original)
+++ tapestry/tapestry5/trunk/tapestry-core/src/main/java/org/apache/tapestry5/internal/services/AbstractAsset.java Sat Feb  7 19:11:39 2009
@@ -17,12 +17,23 @@
 import org.apache.tapestry5.Asset;
 
 /**
- * Base class for an <em>invariant</em> asset.
+ * Base class for assets.
  *
  * @since 5.1.0.0
  */
 public abstract class AbstractAsset implements Asset
 {
+    private final boolean invariant;
+
+    public AbstractAsset(boolean invariant)
+    {
+        this.invariant = invariant;
+    }
+
+    public boolean isInvariant()
+    {
+        return invariant;
+    }
 
     @Override
     public String toString()

Modified: tapestry/tapestry5/trunk/tapestry-core/src/main/java/org/apache/tapestry5/internal/services/ClasspathAssetFactory.java
URL: http://svn.apache.org/viewvc/tapestry/tapestry5/trunk/tapestry-core/src/main/java/org/apache/tapestry5/internal/services/ClasspathAssetFactory.java?rev=741938&r1=741937&r2=741938&view=diff
==============================================================================
--- tapestry/tapestry5/trunk/tapestry-core/src/main/java/org/apache/tapestry5/internal/services/ClasspathAssetFactory.java (original)
+++ tapestry/tapestry5/trunk/tapestry-core/src/main/java/org/apache/tapestry5/internal/services/ClasspathAssetFactory.java Sat Feb  7 19:11:39 2009
@@ -43,7 +43,9 @@
 
     private final AssetPathConverter converter;
 
-    public ClasspathAssetFactory(final ResourceCache cache, final ClasspathAssetAliasManager aliasManager,
+    private final boolean invariant;
+
+    public ClasspathAssetFactory(ResourceCache cache, ClasspathAssetAliasManager aliasManager,
                                  AssetPathConverter converter)
     {
         this.cache = cache;
@@ -51,6 +53,8 @@
         this.converter = converter;
 
         rootResource = new ClasspathResource("");
+
+        invariant = converter.isInvariant();
     }
 
     public void objectWasInvalidated()
@@ -92,7 +96,7 @@
 
     public Asset createAsset(final Resource resource)
     {
-        return new AbstractAsset()
+        return new AbstractAsset(invariant)
         {
             public Resource getResource()
             {

Modified: tapestry/tapestry5/trunk/tapestry-core/src/main/java/org/apache/tapestry5/internal/services/ContextAssetFactory.java
URL: http://svn.apache.org/viewvc/tapestry/tapestry5/trunk/tapestry-core/src/main/java/org/apache/tapestry5/internal/services/ContextAssetFactory.java?rev=741938&r1=741937&r2=741938&view=diff
==============================================================================
--- tapestry/tapestry5/trunk/tapestry-core/src/main/java/org/apache/tapestry5/internal/services/ContextAssetFactory.java (original)
+++ tapestry/tapestry5/trunk/tapestry-core/src/main/java/org/apache/tapestry5/internal/services/ContextAssetFactory.java Sat Feb  7 19:11:39 2009
@@ -34,28 +34,31 @@
 
     private final Resource rootResource;
 
-    private final AssetPathConverter assetPathConverter;
+    private final AssetPathConverter converter;
+
+    private final boolean invariant;
 
     public ContextAssetFactory(Request request, Context context,
 
                                String applicationVersion,
 
-                               AssetPathConverter assetPathConverter)
+                               AssetPathConverter converter)
     {
         this.request = request;
-        this.assetPathConverter = assetPathConverter;
+        this.converter = converter;
 
         pathPrefix = RequestConstants.ASSET_PATH_PREFIX + RequestConstants.CONTEXT_FOLDER
                 + applicationVersion + "/";
 
         rootResource = new ContextResource(context, "/");
+        invariant = this.converter.isInvariant();
     }
 
     public Asset createAsset(final Resource resource)
     {
         final String defaultPath = request.getContextPath() + pathPrefix + resource.getPath();
 
-        return new AbstractAsset()
+        return new AbstractAsset(invariant)
         {
             public Resource getResource()
             {
@@ -64,7 +67,7 @@
 
             public String toClientURL()
             {
-                return assetPathConverter.convertAssetPath(defaultPath);
+                return converter.convertAssetPath(defaultPath);
             }
         };
     }

Modified: tapestry/tapestry5/trunk/tapestry-core/src/main/java/org/apache/tapestry5/internal/services/IdentityAssetPathConverter.java
URL: http://svn.apache.org/viewvc/tapestry/tapestry5/trunk/tapestry-core/src/main/java/org/apache/tapestry5/internal/services/IdentityAssetPathConverter.java?rev=741938&r1=741937&r2=741938&view=diff
==============================================================================
--- tapestry/tapestry5/trunk/tapestry-core/src/main/java/org/apache/tapestry5/internal/services/IdentityAssetPathConverter.java (original)
+++ tapestry/tapestry5/trunk/tapestry-core/src/main/java/org/apache/tapestry5/internal/services/IdentityAssetPathConverter.java Sat Feb  7 19:11:39 2009
@@ -17,13 +17,21 @@
 import org.apache.tapestry5.services.AssetPathConverter;
 
 /**
- * Returns the default asset path unchanged.
+ * Returns the default asset path unchanged. This is an invariant converter.
  *
  * @since 5.1.0.0
  */
 public class IdentityAssetPathConverter implements AssetPathConverter
 {
     /**
+     * @return true
+     */
+    public boolean isInvariant()
+    {
+        return true;
+    }
+
+    /**
      * @param assetPath default asset path
      * @return assetPath unchanged
      */

Added: tapestry/tapestry5/trunk/tapestry-core/src/main/java/org/apache/tapestry5/internal/services/StaxTemplateParser.java
URL: http://svn.apache.org/viewvc/tapestry/tapestry5/trunk/tapestry-core/src/main/java/org/apache/tapestry5/internal/services/StaxTemplateParser.java?rev=741938&view=auto
==============================================================================
--- tapestry/tapestry5/trunk/tapestry-core/src/main/java/org/apache/tapestry5/internal/services/StaxTemplateParser.java (added)
+++ tapestry/tapestry5/trunk/tapestry-core/src/main/java/org/apache/tapestry5/internal/services/StaxTemplateParser.java Sat Feb  7 19:11:39 2009
@@ -0,0 +1,788 @@
+// Copyright 2009 The Apache Software Foundation
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+//     http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+
+package org.apache.tapestry5.internal.services;
+
+import org.apache.tapestry5.internal.parser.*;
+import org.apache.tapestry5.ioc.Location;
+import org.apache.tapestry5.ioc.Resource;
+import org.apache.tapestry5.ioc.internal.util.CollectionFactory;
+import org.apache.tapestry5.ioc.internal.util.InternalUtils;
+import org.apache.tapestry5.ioc.internal.util.LocationImpl;
+import org.apache.tapestry5.ioc.internal.util.TapestryException;
+import org.codehaus.plexus.util.xml.pull.MXParser;
+import org.codehaus.stax2.DTDInfo;
+import org.codehaus.stax2.XMLInputFactory2;
+import org.codehaus.stax2.XMLStreamReader2;
+
+import javax.xml.namespace.QName;
+import static javax.xml.stream.XMLStreamConstants.*;
+import javax.xml.stream.XMLStreamException;
+import java.io.IOException;
+import java.util.List;
+import java.util.Map;
+import java.util.regex.Matcher;
+import java.util.regex.Pattern;
+
+/**
+ * Implementation of {@link org.apache.tapestry5.internal.services.TemplateParser} based on the <a
+ * href="http://en.wikipedia.org/wiki/StAX">Streaming API for XML</a>.   It uses a few features of Stax2 and is
+ * therefore dependent on the Woodstock STAX parser.
+ */
+@SuppressWarnings({ "JavaDoc" })
+public class StaxTemplateParser
+{
+    private static final String MIXINS_ATTRIBUTE_NAME = "mixins";
+
+    private static final String TYPE_ATTRIBUTE_NAME = "type";
+
+    private static final String ID_ATTRIBUTE_NAME = "id";
+
+    public static final String XML_NAMESPACE_URI = "http://www.w3.org/XML/1998/namespace";
+
+    /**
+     * Used as the namespace URI for Tapestry templates.
+     */
+    public static final String TAPESTRY_SCHEMA_5_0_0 = "http://tapestry.apache.org/schema/tapestry_5_0_0.xsd";
+
+    /**
+     * Special namespace used to denote Block parameters to components, as a (preferred) alternative to the t:parameter
+     * element.  The simple element name is the name of the parameter.
+     */
+    private static final String TAPESTRY_PARAMETERS_URI = "tapestry:parameter";
+
+    /**
+     * URI prefix used to identify a Tapestry library, the remainder of the URI becomes a prefix on the element name.
+     */
+    private static final String LIB_NAMESPACE_URI_PREFIX = "tapestry-library:";
+
+    /**
+     * Pattern used to parse the path portion of the library namespace URI.  A series of simple identifiers with slashes
+     * allowed as seperators.
+     */
+
+    private static final Pattern LIBRARY_PATH_PATTERN = Pattern.compile("^[a-z]\\w*(/[a-z]\\w*)*$",
+                                                                        Pattern.CASE_INSENSITIVE);
+
+    private static final Pattern ID_PATTERN = Pattern.compile("^[a-z]\\w*$", Pattern.CASE_INSENSITIVE);
+
+    /**
+     * Any amount of mixed simple whitespace (space, tab, form feed) mixed with at least one carriage return or line
+     * feed, followed by any amount of whitespace.  Will be reduced to a single linefeed.
+     */
+    private static final Pattern REDUCE_LINEBREAKS_PATTERN = Pattern.compile("[ \\t\\f]*[\\r\\n]\\s*",
+                                                                             Pattern.MULTILINE);
+
+    /**
+     * Used when compressing whitespace, matches any sequence of simple whitespace (space, tab, formfeed). Applied after
+     * REDUCE_LINEBREAKS_PATTERN.
+     */
+    private static final Pattern REDUCE_WHITESPACE_PATTERN = Pattern.compile("[ \\t\\f]+", Pattern.MULTILINE);
+
+    // Note the use of the non-greedy modifier; this prevents the pattern from merging multiple
+    // expansions on the same text line into a single large
+    // but invalid expansion.
+
+    private static final Pattern EXPANSION_PATTERN = Pattern.compile("\\$\\{\\s*(.*?)\\s*}");
+
+    private static final String[] EVENT_NAMES = { "",
+            "START_ELEMENT", "END_ELEMENT", "PROCESSING_INSTRUCTION",
+            "CHARACTERS", "COMMENT", "SPACE", "START_DOCUMENT",
+            "END_DOCUMENT", "ENTITY_REFERENCE", "ATTRIBUTE", "DTD", "CDATA",
+            "NAMESPACE", "NOTATION_DECLARATION", "ENTITY_DECLARATION" };
+
+    private final Resource resource;
+
+    private final XMLStreamReader2 reader;
+
+    private final StringBuilder textBuffer = new StringBuilder();
+
+    private final List<TemplateToken> tokens = CollectionFactory.newList();
+
+    /**
+     * Primarily used as a set of componentIds (to check for duplicates and conflicts).
+     */
+    private final Map<String, Location> componentIds = CollectionFactory.newCaseInsensitiveMap();
+
+    private Location textStartLocation;
+
+    private boolean active = true;
+
+    private Location cachedLocation;
+
+    public StaxTemplateParser(Resource resource, XMLInputFactory2 inputFactory) throws XMLStreamException, IOException
+    {
+        this.resource = resource;
+        this.reader = (XMLStreamReader2) inputFactory.createXMLStreamReader(resource.openStream());
+    }
+
+    public ComponentTemplate parse(boolean compressWhitespace)
+    {
+        try
+        {
+            root(new TemplateParserState(compressWhitespace));
+
+            reader.close();
+        }
+        catch (Exception ex)
+        {
+            try
+            {
+                reader.closeCompletely();
+            }
+            catch (XMLStreamException e)
+            {
+                // Ignore it.
+            }
+
+            throw new TapestryException(ServicesMessages.templateParseError(resource, ex), getLocation(),
+                                        ex);
+        }
+
+        return new ComponentTemplateImpl(resource, tokens, componentIds);
+    }
+
+    void root(TemplateParserState state) throws XMLStreamException
+    {
+        while (active && reader.hasNext())
+        {
+            switch (reader.next())
+            {
+                case DTD:
+
+                    dtd();
+
+                    break;
+
+                case START_ELEMENT:
+
+                    element(state);
+
+                    break;
+
+                case END_DOCUMENT:
+                    // Ignore it.
+                    break;
+
+                default:
+                    textContent(state);
+            }
+        }
+    }
+
+    private void unexpectedEventType()
+    {
+        int eventType = reader.getEventType();
+
+        throw new IllegalStateException(
+                String.format("Unexpected XML parse event %s.", MXParser.TYPES[eventType - 1]));
+    }
+
+    private void dtd() throws XMLStreamException
+    {
+        DTDInfo dtdInfo = reader.getDTDInfo();
+
+        tokens.add(new DTDToken(dtdInfo.getDTDRootName(), dtdInfo.getDTDPublicId(), dtdInfo.getDTDSystemId(),
+                                getLocation()));
+    }
+
+    private Location getLocation()
+    {
+        int lineNumber = reader.getLocation().getLineNumber();
+
+        if (cachedLocation != null && cachedLocation.getLine() != lineNumber)
+            cachedLocation = null;
+
+        if (cachedLocation == null)
+            cachedLocation = new LocationImpl(resource, lineNumber);
+
+        return cachedLocation;
+    }
+
+    /**
+     * Processes an element through to its matching end tag.
+     */
+    void element(TemplateParserState initialState) throws XMLStreamException
+    {
+
+        processTextBuffer(initialState);
+
+        TemplateParserState state = checkForXMLSpaceAttribute(initialState);
+
+
+        if (!processStartElement(state)) return;
+
+        // Now start working through the body of the element, recursively.
+
+        while (active)
+        {
+            switch (reader.next())
+            {
+                case START_ELEMENT:
+
+                    // The recursive part: when we see a new element start.
+
+                    element(state);
+                    break;
+
+                case END_ELEMENT:
+
+                    // At the end of an element, we're done and can return.
+                    // This is the matching end element for the start element
+                    // that invoked this method.
+
+                    endElement(state);
+
+                    return;
+
+                default:
+                    textContent(state);
+            }
+        }
+    }
+
+    /**
+     * An element can be:
+     * <p/>
+     * a Tapestry component via &lt;t:type&gt;
+     * <p/>
+     * a Tapestry component via t:type="type"  and/or t:id="id"
+     * <p/>
+     * a Tapestry component via a library namespace
+     * <p/>
+     * A parameter element via &lt;t:parameter&gt;
+     * <p/>
+     * A parameter element via &lt;p:name&gt;
+     * <p/>
+     * A &lt;t:block&gt; element
+     * <p/>
+     * The body &lt;t:body&gt;
+     * <p/>
+     * An ordinary element
+     *
+     * @return true if processing of the elements body should continue normally, or false if the elements body (and end
+     *         tag) have already been consumed
+     */
+    private boolean processStartElement(TemplateParserState state) throws XMLStreamException
+    {
+        String uri = reader.getNamespaceURI();
+        String name = reader.getLocalName();
+
+        if (TAPESTRY_SCHEMA_5_0_0.equals(uri))
+        {
+
+            if (name.equalsIgnoreCase("body"))
+            {
+                body();
+                return false;
+            }
+
+            if (name.equals("container"))
+            {
+                container(state);
+                return false;
+            }
+
+            if (name.equals("block"))
+            {
+                block(state);
+                return false;
+            }
+
+            if (name.equals("parameter"))
+            {
+                classicParameter();
+
+                // Default handling for the body of the parameter is acceptible.
+                return true;
+            }
+
+            possibleTapestryComponent(null, reader.getLocalName().replace('.', '/'));
+
+            return true;
+        }
+
+        if (uri != null && uri.startsWith(LIB_NAMESPACE_URI_PREFIX))
+        {
+            libraryNamespaceComponent();
+
+            return true;
+        }
+
+        if (TAPESTRY_PARAMETERS_URI.equals(uri))
+        {
+            parameterElement();
+
+            return true;
+        }
+
+        // Just an ordinary element ... unless it has t:id or t:type
+
+        possibleTapestryComponent(reader.getLocalName(), null);
+
+        // Let element() take it from here (body plus end element token).
+
+        return true;
+    }
+
+    private String nullForBlank(String input)
+    {
+        return InternalUtils.isBlank(input) ? null : input;
+    }
+
+
+    /**
+     * Added in release 5.1.
+     */
+    private void libraryNamespaceComponent()
+    {
+        String uri = reader.getNamespaceURI();
+
+        // The library path is encoded into the namespace URI.
+
+        String path = uri.substring(LIB_NAMESPACE_URI_PREFIX.length());
+
+        if (!LIBRARY_PATH_PATTERN.matcher(path).matches())
+            throw new RuntimeException(ServicesMessages.invalidPathForLibraryNamespace(uri));
+
+        possibleTapestryComponent(null, path + "/" + reader.getLocalName());
+    }
+
+    /**
+     * @param elementName
+     * @param identifiedType the type of the element, usually null, but may be the component type derived from element
+     */
+    private void possibleTapestryComponent(String elementName, String identifiedType)
+    {
+        String id = null;
+        String type = identifiedType;
+        String mixins = null;
+
+        int count = reader.getAttributeCount();
+
+        Location location = getLocation();
+
+        List<TemplateToken> attributeTokens = CollectionFactory.newList();
+
+        for (int i = 0; i < count; i++)
+        {
+            QName qname = reader.getAttributeName(i);
+
+            if (isXMLSpaceAttribute(qname)) continue;
+
+            // The name will be blank for an xmlns: attribute
+
+            String localName = qname.getLocalPart();
+
+            if (InternalUtils.isBlank(localName)) continue;
+
+            String uri = qname.getNamespaceURI();
+
+            String value = reader.getAttributeValue(i);
+
+            if (TAPESTRY_SCHEMA_5_0_0.equals(uri))
+            {
+                if (localName.equalsIgnoreCase(ID_ATTRIBUTE_NAME))
+                {
+                    id = nullForBlank(value);
+
+                    validateId(id, "invalid-component-id");
+
+                    continue;
+                }
+
+                if (type == null && localName.equalsIgnoreCase(TYPE_ATTRIBUTE_NAME))
+                {
+                    type = nullForBlank(value);
+                    continue;
+                }
+
+                if (localName.equalsIgnoreCase(MIXINS_ATTRIBUTE_NAME))
+                {
+                    mixins = nullForBlank(value);
+                    continue;
+                }
+
+                // Anything else is the name of a Tapestry component parameter that is simply
+                // not part of the template's doctype for the element being instrumented.
+            }
+
+
+            attributeTokens.add(new AttributeToken(uri, localName, value, location));
+        }
+
+        boolean isComponent = (id != null || type != null);
+
+        // If provided t:mixins but not t:id or t:type, then its not quite a component
+
+        if (mixins != null && !isComponent)
+            throw new TapestryException(ServicesMessages.mixinsInvalidWithoutIdOrType(elementName), location, null);
+
+        if (isComponent)
+        {
+            tokens.add(new StartComponentToken(elementName, id, type, mixins, location));
+        }
+        else
+        {
+            tokens.add(new StartElementToken(reader.getNamespaceURI(), elementName, location));
+        }
+
+        addDefineNamespaceTokens();
+
+        tokens.addAll(attributeTokens);
+
+        if (id != null)
+            componentIds.put(id, location);
+    }
+
+    private void addDefineNamespaceTokens()
+    {
+        for (int i = 0; i < reader.getNamespaceCount(); i++)
+        {
+            String uri = reader.getNamespaceURI(i);
+
+            // These URIs are strictly part of the server-side Tapestry template and are not ever sent to the client.
+
+            if (uri.equals(TAPESTRY_SCHEMA_5_0_0)) continue;
+
+            if (uri.equals(TAPESTRY_PARAMETERS_URI)) continue;
+
+            if (uri.startsWith(LIB_NAMESPACE_URI_PREFIX)) continue;
+
+            tokens.add(new DefineNamespacePrefixToken(uri, reader.getNamespacePrefix(i),
+                                                      getLocation()));
+        }
+    }
+
+
+    private TemplateParserState checkForXMLSpaceAttribute(TemplateParserState state)
+    {
+        for (int i = 0; i < reader.getAttributeCount(); i++)
+        {
+            QName qName = reader.getAttributeName(i);
+
+            if (isXMLSpaceAttribute(qName))
+            {
+                boolean compress = !"preserve".equals(reader.getAttributeValue(i));
+
+                return state.compressWhitespace(compress);
+            }
+        }
+
+        return state;
+    }
+
+    /**
+     * Processes the text buffer and then adds an end element token.
+     */
+    private void endElement(TemplateParserState state)
+    {
+        processTextBuffer(state);
+
+        tokens.add(new EndElementToken(getLocation()));
+    }
+
+    /**
+     * Handler for Tapestry 5.0's "classic" &lt;t:parameter&gt; element. This turns into a {@link
+     * org.apache.tapestry5.internal.parser.ParameterToken} and the body and end element are provided normally.
+     */
+    private void classicParameter()
+    {
+        String parameterName = getSingleParameter("name");
+
+        if (InternalUtils.isBlank(parameterName))
+            throw new TapestryException(ServicesMessages.parameterElementNameRequired(), getLocation(), null);
+
+        tokens.add(new ParameterToken(parameterName, getLocation()));
+    }
+
+    /**
+     * Tapestry 5.1 uses a special namespace (usually mapped to "p:") and the name becomes the parameter element.
+     */
+    private void parameterElement()
+    {
+        if (reader.getAttributeCount() > 0)
+            throw new TapestryException(ServicesMessages.parameterElementDoesNotAllowAttributes(), getLocation(),
+                                        null);
+
+        tokens.add(new ParameterToken(reader.getLocalName(), getLocation()));
+    }
+
+
+    /**
+     * Checks that a body element is empty. Returns after the body's close element. Adds a single body token (but not an
+     * end token).
+     */
+    private void body() throws XMLStreamException
+    {
+        tokens.add(new BodyToken(getLocation()));
+
+        while (active)
+        {
+            switch (reader.next())
+            {
+                case END_ELEMENT:
+                    return;
+
+                default:
+                    throw new IllegalStateException(ServicesMessages.contentInsideBodyNotAllowed(getLocation()));
+            }
+        }
+    }
+
+    /**
+     * Driven by the &lt;t:container&gt; element, this state adds elements for its body but not its start or end tags.
+     *
+     * @param state
+     * @throws XMLStreamException
+     */
+    private void container(TemplateParserState state) throws XMLStreamException
+    {
+        while (active)
+        {
+            switch (reader.next())
+            {
+                case START_ELEMENT:
+                    element(state);
+                    break;
+
+                // The matching end-element for the container. Don't add a token.
+
+                case END_ELEMENT:
+
+                    processTextBuffer(state);
+
+                    return;
+
+                default:
+                    textContent(state);
+            }
+        }
+    }
+
+    /**
+     * A block adds a token for its start tag and end tag and allows any content within.
+     */
+    private void block(TemplateParserState state) throws XMLStreamException
+    {
+        String blockId = getSingleParameter("id");
+
+        validateId(blockId, "invalid-block-id");
+
+        tokens.add(new BlockToken(blockId, getLocation()));
+
+        while (active)
+        {
+            switch (reader.next())
+            {
+                case START_ELEMENT:
+                    element(state);
+                    break;
+
+                case END_ELEMENT:
+                    endElement(state);
+                    return;
+
+                default:
+                    textContent(state);
+            }
+        }
+
+    }
+
+    private String getSingleParameter(String attributeName)
+    {
+        String result = null;
+
+        for (int i = 0; i < reader.getAttributeCount(); i++)
+        {
+            QName qName = reader.getAttributeName(i);
+
+            if (isXMLSpaceAttribute(qName)) continue;
+
+            if (qName.getLocalPart().equals(attributeName))
+            {
+                result = reader.getAttributeValue(i);
+                continue;
+            }
+
+            // Only the named attribute is allowed.
+
+            throw new TapestryException(ServicesMessages.undefinedTapestryAttribute(reader.getLocalName(),
+                                                                                    qName.toString(), attributeName),
+                                        getLocation(), null);
+        }
+
+        return result;
+    }
+
+    private void validateId(String id, String messageKey)
+    {
+        if (id == null) return;
+
+        if (ID_PATTERN.matcher(id).matches()) return;
+
+        // Not a match.
+
+        throw new TapestryException(ServicesMessages.invalidId(messageKey, id), getLocation(), null);
+    }
+
+    private boolean isXMLSpaceAttribute(QName qName)
+    {
+        return XML_NAMESPACE_URI.equals(qName.getNamespaceURI()) &&
+                "space".equals(qName.getLocalPart());
+    }
+
+
+    /**
+     * Processes text content if in the correct state, or throws an exception. This is used as a default for matching
+     * case statements.
+     *
+     * @param state
+     */
+    private void textContent(TemplateParserState state)
+    {
+        switch (reader.getEventType())
+        {
+            case COMMENT:
+                comment(state);
+                break;
+
+            case CDATA:
+                cdata(state);
+                break;
+
+            case CHARACTERS:
+            case SPACE:
+                characters();
+                break;
+
+            default:
+                unexpectedEventType();
+        }
+    }
+
+    private void characters()
+    {
+        if (textStartLocation == null)
+            textStartLocation = getLocation();
+
+        textBuffer.append(reader.getText());
+    }
+
+    private void cdata(TemplateParserState state)
+    {
+        processTextBuffer(state);
+
+        tokens.add(new CDATAToken(reader.getText(), getLocation()));
+    }
+
+    private void comment(TemplateParserState state)
+    {
+        processTextBuffer(state);
+
+        // Trim the excess whitespace; the Comment DOM node will add a leading/trailing space.
+
+        String comment = reader.getText().trim();
+
+        tokens.add(new CommentToken(comment, getLocation()));
+    }
+
+    /**
+     * Processes the accumulated text in the text buffer as a text token.
+     */
+    private void processTextBuffer(TemplateParserState state)
+    {
+        if (textBuffer.length() != 0)
+            convertTextBufferToTokens(state);
+
+        textStartLocation = null;
+    }
+
+    private void convertTextBufferToTokens(TemplateParserState state)
+    {
+        String text = textBuffer.toString();
+
+        textBuffer.setLength(0);
+
+        if (state.isCompressWhitespace())
+        {
+            text = compressWhitespaceInText(text);
+
+            if (InternalUtils.isBlank(text)) return;
+        }
+
+        addTokensForText(text);
+    }
+
+    /**
+     * Reduces vertical whitespace to a single newline, then reduces horizontal whitespace to a single space.
+     *
+     * @param text
+     * @return compressed version of text
+     */
+    private String compressWhitespaceInText(String text)
+    {
+        String linebreaksReduced = REDUCE_LINEBREAKS_PATTERN.matcher(text).replaceAll("\n");
+
+        return REDUCE_WHITESPACE_PATTERN.matcher(linebreaksReduced).replaceAll(" ");
+    }
+
+    /**
+     * Scans the text, using a regular expression pattern, for expansion patterns, and adds appropriate tokens for what
+     * it finds.
+     *
+     * @param text to add as {@link org.apache.tapestry5.internal.parser.TextToken}s and {@link
+     *             org.apache.tapestry5.internal.parser.ExpansionToken}s
+     */
+    private void addTokensForText(String text)
+    {
+        Matcher matcher = EXPANSION_PATTERN.matcher(text);
+
+        int startx = 0;
+
+        // The big problem with all this code is that everything gets assigned to the
+        // start of the text block, even if there are line breaks leading up to it.
+        // That's going to take a lot more work and there are bigger fish to fry.  In addition,
+        // TAPESTRY-2028 means that the whitespace has likely been stripped out of the text
+        // already anyway.
+
+        while (matcher.find())
+        {
+            int matchStart = matcher.start();
+
+            if (matchStart != startx)
+            {
+                String prefix = text.substring(startx, matchStart);
+
+                tokens.add(new TextToken(prefix, textStartLocation));
+            }
+
+            // Group 1 includes the real text of the expansion, with whitespace around the
+            // expression (but inside the curly braces) excluded.
+
+            String expression = matcher.group(1);
+
+            tokens.add(new ExpansionToken(expression, textStartLocation));
+
+            startx = matcher.end();
+        }
+
+        // Catch anything after the final regexp match.
+
+        if (startx < text.length())
+            tokens.add(new TextToken(text.substring(startx, text.length()), textStartLocation));
+    }
+
+}

Added: tapestry/tapestry5/trunk/tapestry-core/src/main/java/org/apache/tapestry5/internal/services/TemplateParserImpl.java
URL: http://svn.apache.org/viewvc/tapestry/tapestry5/trunk/tapestry-core/src/main/java/org/apache/tapestry5/internal/services/TemplateParserImpl.java?rev=741938&view=auto
==============================================================================
--- tapestry/tapestry5/trunk/tapestry-core/src/main/java/org/apache/tapestry5/internal/services/TemplateParserImpl.java (added)
+++ tapestry/tapestry5/trunk/tapestry-core/src/main/java/org/apache/tapestry5/internal/services/TemplateParserImpl.java Sat Feb  7 19:11:39 2009
@@ -0,0 +1,111 @@
+// Copyright 2006, 2007, 2008, 2009 The Apache Software Foundation
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+//     http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+
+package org.apache.tapestry5.internal.services;
+
+import org.apache.tapestry5.SymbolConstants;
+import org.apache.tapestry5.internal.parser.ComponentTemplate;
+import org.apache.tapestry5.ioc.Resource;
+import org.apache.tapestry5.ioc.annotations.Symbol;
+import org.apache.tapestry5.ioc.internal.util.InternalUtils;
+import org.codehaus.stax2.XMLInputFactory2;
+
+import javax.xml.stream.XMLInputFactory;
+import javax.xml.stream.XMLResolver;
+import javax.xml.stream.XMLStreamException;
+import java.io.IOException;
+import java.net.URL;
+import java.util.Map;
+
+/**
+ * Responsible for acquiring a StAX reader and configuring an instance of {@link org.apache.tapestry5.internal.services.StaxTemplateParser},
+ * which does all the real work. This is dependent on a few features of StAX2, and therefore, on the Woodstock StAX
+ * parser.
+ *
+ * @since 5.1.0.0
+ */
+public class TemplateParserImpl implements TemplateParser, XMLResolver
+{
+    private final Map<String, URL> configuration;
+
+    private final boolean defaultCompressWhitespace;
+
+    private final XMLInputFactory2 inputFactory = (XMLInputFactory2) XMLInputFactory2.newInstance();
+
+    public TemplateParserImpl(Map<String, URL> configuration,
+
+                              @Symbol(SymbolConstants.COMPRESS_WHITESPACE)
+                              boolean defaultCompressWhitespace)
+    {
+
+        this.configuration = configuration;
+        this.defaultCompressWhitespace = defaultCompressWhitespace;
+
+        inputFactory.configureForSpeed();
+
+        inputFactory.setXMLResolver(this);
+
+        // Coalescing must be off, or CDATA sections can "coealesce" into CHARACTER events
+        inputFactory.setProperty(XMLInputFactory.IS_COALESCING, false);
+
+        inputFactory.setProperty(XMLInputFactory.IS_SUPPORTING_EXTERNAL_ENTITIES, true);
+
+        inputFactory.setProperty(XMLInputFactory.SUPPORT_DTD, true);
+    }
+
+    public ComponentTemplate parseTemplate(Resource templateResource)
+    {
+        if (!templateResource.exists())
+            throw new RuntimeException(ServicesMessages.missingTemplateResource(templateResource));
+
+
+        StaxTemplateParser parser;
+
+        try
+        {
+            parser = new StaxTemplateParser(templateResource, inputFactory);
+        }
+        catch (Exception ex)
+        {
+            throw new RuntimeException(ServicesMessages.newParserError(templateResource, ex), ex);
+        }
+
+        return parser.parse(defaultCompressWhitespace);
+    }
+
+    // XMLResolver methods
+
+    public Object resolveEntity(String publicID,
+                                String systemID,
+                                String baseURI,
+                                String namespace) throws XMLStreamException
+    {
+        URL url = configuration.get(publicID);
+
+        try
+        {
+            if (url != null)
+                return url.openStream();
+        }
+        catch (IOException ex)
+        {
+            throw new XMLStreamException(
+                    String.format("Unable to open stream for resource %s: %s",
+                                  url,
+                                  InternalUtils.toMessage(ex)), ex);
+        }
+
+        return null;
+    }
+}

Added: tapestry/tapestry5/trunk/tapestry-core/src/main/java/org/apache/tapestry5/internal/services/TemplateParserState.java
URL: http://svn.apache.org/viewvc/tapestry/tapestry5/trunk/tapestry-core/src/main/java/org/apache/tapestry5/internal/services/TemplateParserState.java?rev=741938&view=auto
==============================================================================
--- tapestry/tapestry5/trunk/tapestry-core/src/main/java/org/apache/tapestry5/internal/services/TemplateParserState.java (added)
+++ tapestry/tapestry5/trunk/tapestry-core/src/main/java/org/apache/tapestry5/internal/services/TemplateParserState.java Sat Feb  7 19:11:39 2009
@@ -0,0 +1,47 @@
+// Copyright 2009 The Apache Software Foundation
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+//     http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+
+package org.apache.tapestry5.internal.services;
+
+/**
+ * Used to track behaviors inside {@link org.apache.tapestry5.internal.services.StaxTemplateParser}. Internal state is
+ * immutable, the set-like methods return a new immutable instance.
+ *
+ * @since 5.1.0.0
+ */
+class TemplateParserState
+{
+    private final boolean compressWhitespace;
+
+    TemplateParserState(boolean compressWhitespace)
+    {
+        this.compressWhitespace = compressWhitespace;
+    }
+
+    TemplateParserState compressWhitespace(boolean flag)
+    {
+        return new TemplateParserState(flag);
+    }
+
+    boolean isCompressWhitespace()
+    {
+        return compressWhitespace;
+    }
+
+    @Override
+    public String toString()
+    {
+        return String.format("TemplateParserState[compressWhitespace=%s]", compressWhitespace);
+    }
+}

Modified: tapestry/tapestry5/trunk/tapestry-core/src/main/java/org/apache/tapestry5/services/AssetPathConverter.java
URL: http://svn.apache.org/viewvc/tapestry/tapestry5/trunk/tapestry-core/src/main/java/org/apache/tapestry5/services/AssetPathConverter.java?rev=741938&r1=741937&r2=741938&view=diff
==============================================================================
--- tapestry/tapestry5/trunk/tapestry-core/src/main/java/org/apache/tapestry5/services/AssetPathConverter.java (original)
+++ tapestry/tapestry5/trunk/tapestry-core/src/main/java/org/apache/tapestry5/services/AssetPathConverter.java Sat Feb  7 19:11:39 2009
@@ -27,6 +27,16 @@
 public interface AssetPathConverter
 {
     /**
+     * Returns true if the converter returns that same converted path for any specific asset path (in which case, the
+     * converted asset path may be cached more aggresively).  This value should be false if the the converted path can
+     * vary for the same input path ... that is, if external factors (such as the identity of the user, or information
+     * obtained from the request) is involved in generating the final client URI.
+     *
+     * @return true if invariant (and therefore cachable)
+     */
+    boolean isInvariant();
+
+    /**
      * Converts the default asset client URI to its final form, ready to be sent to the client. The default asset path
      * is an absolute path (it starts with a leading slash) and incorporates the context path if any.
      *

Modified: tapestry/tapestry5/trunk/tapestry-core/src/test/java/org/apache/tapestry5/internal/services/ClasspathAssetFactoryTest.java
URL: http://svn.apache.org/viewvc/tapestry/tapestry5/trunk/tapestry-core/src/test/java/org/apache/tapestry5/internal/services/ClasspathAssetFactoryTest.java?rev=741938&r1=741937&r2=741938&view=diff
==============================================================================
--- tapestry/tapestry5/trunk/tapestry-core/src/test/java/org/apache/tapestry5/internal/services/ClasspathAssetFactoryTest.java (original)
+++ tapestry/tapestry5/trunk/tapestry-core/src/test/java/org/apache/tapestry5/internal/services/ClasspathAssetFactoryTest.java Sat Feb  7 19:11:39 2009
@@ -24,6 +24,8 @@
 
 public class ClasspathAssetFactoryTest extends InternalBaseTestCase
 {
+    private final IdentityAssetPathConverter converter = new IdentityAssetPathConverter();
+
     @Test
     public void asset_client_URL_is_cached()
     {
@@ -42,7 +44,7 @@
         replay();
 
         ClasspathAssetFactory factory = new ClasspathAssetFactory(cache, aliasManager,
-                                                                  new IdentityAssetPathConverter());
+                                                                  converter);
 
         Asset asset = factory.createAsset(r);
 

Modified: tapestry/tapestry5/trunk/tapestry-core/src/test/java/org/apache/tapestry5/internal/services/ContextAssetFactoryTest.java
URL: http://svn.apache.org/viewvc/tapestry/tapestry5/trunk/tapestry-core/src/test/java/org/apache/tapestry5/internal/services/ContextAssetFactoryTest.java?rev=741938&r1=741937&r2=741938&view=diff
==============================================================================
--- tapestry/tapestry5/trunk/tapestry-core/src/test/java/org/apache/tapestry5/internal/services/ContextAssetFactoryTest.java (original)
+++ tapestry/tapestry5/trunk/tapestry-core/src/test/java/org/apache/tapestry5/internal/services/ContextAssetFactoryTest.java Sat Feb  7 19:11:39 2009
@@ -24,6 +24,7 @@
 
 public class ContextAssetFactoryTest extends InternalBaseTestCase
 {
+    private final IdentityAssetPathConverter converter = new IdentityAssetPathConverter();
 
     @Test
     public void root_resource()
@@ -33,7 +34,7 @@
 
         replay();
 
-        AssetFactory factory = new ContextAssetFactory(request, context, "1.2.3", new IdentityAssetPathConverter());
+        AssetFactory factory = new ContextAssetFactory(request, context, "1.2.3", converter);
 
         assertEquals(factory.getRootResource().toString(), "context:/");
 

Modified: tapestry/tapestry5/trunk/tapestry-core/src/test/java/org/apache/tapestry5/internal/services/TemplateParserImplTest.java
URL: http://svn.apache.org/viewvc/tapestry/tapestry5/trunk/tapestry-core/src/test/java/org/apache/tapestry5/internal/services/TemplateParserImplTest.java?rev=741938&r1=741937&r2=741938&view=diff
==============================================================================
--- tapestry/tapestry5/trunk/tapestry-core/src/test/java/org/apache/tapestry5/internal/services/TemplateParserImplTest.java (original)
+++ tapestry/tapestry5/trunk/tapestry-core/src/test/java/org/apache/tapestry5/internal/services/TemplateParserImplTest.java Sat Feb  7 19:11:39 2009
@@ -391,21 +391,6 @@
     }
 
     @Test
-    public void content_within_body_element()
-    {
-        List<TemplateToken> tokens = parse("content_within_body_element.tml").getTokens();
-
-        assertEquals(tokens.size(), 5);
-
-        // javac bug is requires use of isInstance() instead of instanceof
-        // https://bugs.eclipse.org/bugs/show_bug.cgi?id=113218
-
-        assertTrue(BodyToken.class.isInstance(get(tokens, 2)));
-        assertTrue(TextToken.class.isInstance(get(tokens, 3)));
-        assertTrue(EndElementToken.class.isInstance(get(tokens, 4)));
-    }
-
-    @Test
     public void component_with_parameters()
     {
         List<TemplateToken> tokens = tokens("componentWithParameters.tml");
@@ -645,32 +630,31 @@
     {
         return new Object[][] {
 
-                {"mixin_requires_id_or_type.tml",
+                { "mixin_requires_id_or_type.tml",
                         "You may not specify mixins for element <span> because it does not represent a component (which requires either an id attribute or a type attribute).",
-                        2},
+                        2 },
 
-                {"illegal_nesting_within_body_element.tml", "Element 'xyz' is nested within a Tapestry body element",
-                        2},
-
-                {"unexpected_attribute_in_parameter_element.tml",
+                { "unexpected_attribute_in_parameter_element.tml",
                         "Element <parameter> does not support an attribute named 'grok'. The only allowed attribute name is 'name'.",
-                        4},
+                        4 },
 
-                {"name_attribute_of_parameter_element_omitted.tml",
-                        "The name attribute of the <parameter> element must be specified.", 4},
+                { "name_attribute_of_parameter_element_omitted.tml",
+                        "The name attribute of the <parameter> element must be specified.", 4 },
 
-                {"name_attribute_of_parameter_element_blank.tml",
-                        "The name attribute of the <parameter> element must be specified.", 4},
+                { "name_attribute_of_parameter_element_blank.tml",
+                        "The name attribute of the <parameter> element must be specified.", 4 },
 
-                {"unexpected_attribute_in_block_element.tml",
+                { "unexpected_attribute_in_block_element.tml",
                         "Element <block> does not support an attribute named 'name'. The only allowed attribute name is 'id'.",
-                        3},
+                        3 },
+
+                { "parameter_namespace_with_attributes.tml",
+                        ServicesMessages.parameterElementDoesNotAllowAttributes(), 4 },
 
-                {"parameter_namespace_with_attributes.tml",
-                        ServicesMessages.parameterElementDoesNotAllowAttributes(), 4},
+                { "invalid_library_namespace_path.tml",
+                        "The path portion of library namespace URI 'tapestry-library:subfolder/' is not valid", 2 },
 
-                {"invalid_library_namespace_path.tml",
-                        "The path portion of library namespace URI 'tapestry-library:subfolder/' is not valid", 2}
+                { "content_within_body_element.tml", "", 2 }
         };
     }
 
@@ -697,8 +681,8 @@
     @DataProvider(name = "doctype_parsed_correctly_data")
     public Object[][] doctype_parsed_correctly_data()
     {
-        return new Object[][] {{"xhtml1_strict_doctype.tml"}, {"xhtml1_transitional_doctype.tml"},
-                {"xhtml1_frameset_doctype.tml"}};
+        return new Object[][] { { "xhtml1_strict_doctype.tml" }, { "xhtml1_transitional_doctype.tml" },
+                { "xhtml1_frameset_doctype.tml" } };
     }
 
     @Test(dataProvider = "doctype_parsed_correctly_data")
@@ -715,26 +699,26 @@
     {
         return new Object[][] {
 
-                {"xhtml1_strict_doctype.tml", "html", "-//W3C//DTD XHTML 1.0 Strict//EN",
-                        "http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd"},
+                { "xhtml1_strict_doctype.tml", "html", "-//W3C//DTD XHTML 1.0 Strict//EN",
+                        "http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd" },
 
-                {"xhtml1_transitional_doctype.tml", "html", "-//W3C//DTD XHTML 1.0 Transitional//EN",
-                        "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd"},
+                { "xhtml1_transitional_doctype.tml", "html", "-//W3C//DTD XHTML 1.0 Transitional//EN",
+                        "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd" },
 
-                {"xhtml1_frameset_doctype.tml", "html", "-//W3C//DTD XHTML 1.0 Frameset//EN",
-                        "http://www.w3.org/TR/xhtml1/DTD/xhtml1-frameset.dtd"},
+                { "xhtml1_frameset_doctype.tml", "html", "-//W3C//DTD XHTML 1.0 Frameset//EN",
+                        "http://www.w3.org/TR/xhtml1/DTD/xhtml1-frameset.dtd" },
 
-                {"html4_strict_doctype.tml", "HTML", "-//W3C//DTD HTML 4.01//EN",
-                        "http://www.w3.org/TR/html4/strict.dtd"},
+                { "html4_strict_doctype.tml", "HTML", "-//W3C//DTD HTML 4.01//EN",
+                        "http://www.w3.org/TR/html4/strict.dtd" },
 
-                {"html4_transitional_doctype.tml", "HTML", "-//W3C//DTD HTML 4.01 Transitional//EN",
-                        "http://www.w3.org/TR/html4/loose.dtd"},
+                { "html4_transitional_doctype.tml", "HTML", "-//W3C//DTD HTML 4.01 Transitional//EN",
+                        "http://www.w3.org/TR/html4/loose.dtd" },
 
-                {"html4_frameset_doctype.tml", "HTML", "-//W3C//DTD HTML 4.01 Frameset//EN",
-                        "http://www.w3.org/TR/html4/frameset.dtd"},
+                { "html4_frameset_doctype.tml", "HTML", "-//W3C//DTD HTML 4.01 Frameset//EN",
+                        "http://www.w3.org/TR/html4/frameset.dtd" },
 
-                {"system_doctype.xml", "foo", null,
-                        "src/test/resources/org/apache/tapestry5/internal/services/simple.dtd"}};
+                { "system_doctype.xml", "foo", null,
+                        "src/test/resources/org/apache/tapestry5/internal/services/simple.dtd" } };
     }
 
     @Test(dataProvider = "doctype_token_added_correctly_data")
@@ -743,10 +727,10 @@
         System.setProperty("user.dir", TapestryTestConstants.MODULE_BASE_DIR_PATH);
 
         List<TemplateToken> tokens = tokens(fileName);
-        DTDToken t2 = get(tokens, 0);
-        assertEquals(t2.getName(), name);
-        assertEquals(t2.getPublicId(), publicId);
-        assertEquals(t2.getSystemId(), systemId);
+        DTDToken t0 = get(tokens, 0);
+        assertEquals(t0.getName(), name);
+        assertEquals(t0.getPublicId(), publicId);
+        assertEquals(t0.getSystemId(), systemId);
     }
 
     @Test

Modified: tapestry/tapestry5/trunk/tapestry-core/src/test/resources/org/apache/tapestry5/internal/services/system_doctype.xml
URL: http://svn.apache.org/viewvc/tapestry/tapestry5/trunk/tapestry-core/src/test/resources/org/apache/tapestry5/internal/services/system_doctype.xml?rev=741938&r1=741937&r2=741938&view=diff
==============================================================================
--- tapestry/tapestry5/trunk/tapestry-core/src/test/resources/org/apache/tapestry5/internal/services/system_doctype.xml (original)
+++ tapestry/tapestry5/trunk/tapestry-core/src/test/resources/org/apache/tapestry5/internal/services/system_doctype.xml Sat Feb  7 19:11:39 2009
@@ -1,17 +1,2 @@
-<!--
-   Copyright 2007, 2008 The Apache Software Foundation
-
-   Licensed under the Apache License, Version 2.0 (the "License");
-   you may not use this file except in compliance with the License.
-   You may obtain a copy of the License at
-
-       http://www.apache.org/licenses/LICENSE-2.0
-
-   Unless required by applicable law or agreed to in writing, software
-   distributed under the License is distributed on an "AS IS" BASIS,
-   WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-   See the License for the specific language governing permissions and
-   limitations under the License.
--->
 <!DOCTYPE foo SYSTEM "src/test/resources/org/apache/tapestry5/internal/services/simple.dtd" >
 <foo>bar</foo>