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/12/10 23:38:40 UTC
svn commit: r889446 [1/2] - in /tapestry/tapestry5/trunk: ./ quickstart/
src/site/apt/ tapestry-core/
tapestry-core/src/main/java/org/apache/tapestry5/internal/services/
tapestry-core/src/main/resources/org/apache/tapestry5/internal/services/
tapestry-...
Author: hlship
Date: Thu Dec 10 22:38:39 2009
New Revision: 889446
URL: http://svn.apache.org/viewvc?rev=889446&view=rev
Log:
TAP5-713: Change template parser to not use StAX, as it is not (yet) compatible with Google App Engine
Added:
tapestry/tapestry5/trunk/tapestry-core/src/main/java/org/apache/tapestry5/internal/services/AttributeInfo.java (with props)
tapestry/tapestry5/trunk/tapestry-core/src/main/java/org/apache/tapestry5/internal/services/DTDData.java (with props)
tapestry/tapestry5/trunk/tapestry-core/src/main/java/org/apache/tapestry5/internal/services/NamespaceMapping.java (with props)
tapestry/tapestry5/trunk/tapestry-core/src/main/java/org/apache/tapestry5/internal/services/SaxTemplateParser.java
- copied, changed from r888990, 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/XMLToken.java (with props)
tapestry/tapestry5/trunk/tapestry-core/src/main/java/org/apache/tapestry5/internal/services/XMLTokenStream.java (with props)
tapestry/tapestry5/trunk/tapestry-core/src/main/java/org/apache/tapestry5/internal/services/XMLTokenType.java (with props)
Removed:
tapestry/tapestry5/trunk/tapestry-core/src/main/java/org/apache/tapestry5/internal/services/StaxTemplateParser.java
Modified:
tapestry/tapestry5/trunk/ (props changed)
tapestry/tapestry5/trunk/quickstart/ (props changed)
tapestry/tapestry5/trunk/src/site/apt/index.apt
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/internal/services/ServicesMessages.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
tapestry/tapestry5/trunk/tapestry-core/src/main/resources/org/apache/tapestry5/internal/services/ServicesStrings.properties
tapestry/tapestry5/trunk/tapestry-core/src/test/java/org/apache/tapestry5/integration/IntegrationTests.java
Propchange: tapestry/tapestry5/trunk/
------------------------------------------------------------------------------
--- svn:ignore (original)
+++ svn:ignore Thu Dec 10 22:38:39 2009
@@ -2,4 +2,10 @@
target
bin-test
temp-testng-customsuite.xml
-*.iml
*.ipr
*.iws
.classpath
.project
.settings
+*.iml
+*.ipr
+*.iws
+.classpath
+.project
+.settings
+.externalToolBuilders
Propchange: tapestry/tapestry5/trunk/quickstart/
------------------------------------------------------------------------------
--- svn:ignore (original)
+++ svn:ignore Thu Dec 10 22:38:39 2009
@@ -1,3 +1,4 @@
target
.settings
.project
+.classpath
Modified: tapestry/tapestry5/trunk/src/site/apt/index.apt
URL: http://svn.apache.org/viewvc/tapestry/tapestry5/trunk/src/site/apt/index.apt?rev=889446&r1=889445&r2=889446&view=diff
==============================================================================
--- tapestry/tapestry5/trunk/src/site/apt/index.apt (original)
+++ tapestry/tapestry5/trunk/src/site/apt/index.apt Thu Dec 10 22:38:39 2009
@@ -34,39 +34,6 @@
New And Of Note
- * Tapestry now uses the {{{http://www.gscottolson.com/blackbirdjs/}Blackbird}} JavaScript console.
-
- * Tapestry now automatically combines multiple JavaScript libraries into a single request.
-
- * An Ajax event request may now return a
- {{{apidocs/org/apache/tapestry5/ajax/MultiZoneUpdate.html}MultiZoneUpdate}} instance
- to update multiple zones in the client web browser.
-
- * Client-side numeric validation is now locale-sensitive.
-
- * Some significant performance improvements over Tapestry 5.0.18: the time to initially load a page,
- and the time to render a page have decreased.
-
- * Tapestry IoC services can now be easily <{{{tapestry-ioc/advice.html}advised}}> as well as
- <{{{tapestry-ioc/decorator.html}decorated}}> (both of these refer to Aspect Oriented Techniques applied to
- Tapestry IoC services).
-
- * Tapestry Services can now be injected into Spring Beans, when using the Tapestry/Spring integration library.
-
- * Tapestry now {{{guide/compress.html}compresses}} responses for clients that support GZIP compression.
- Context and classpath assets
- are now handled uniformly: versioned URLs, far-future expiration headers, and GZIP compression where applicable.
-
- * Ordered and mapped configurations can now have overrides.
-
- * Property expressions have been improved: You can now invoke methods with parameters, or create a list (very useful for link contexts).
-
- * IoC Service contributions may now be made in terms of classes (that are automatically instantiated) as well as
- instances.
-
- * A simpler method of {{{apidocs/org/apache/tapestry5/ioc/services/ServiceOverride}overriding built-in services}}
- has been added.
-
[]
Roadmap
Modified: tapestry/tapestry5/trunk/src/site/apt/upgrade.apt
URL: http://svn.apache.org/viewvc/tapestry/tapestry5/trunk/src/site/apt/upgrade.apt?rev=889446&r1=889445&r2=889446&view=diff
==============================================================================
--- tapestry/tapestry5/trunk/src/site/apt/upgrade.apt (original)
+++ tapestry/tapestry5/trunk/src/site/apt/upgrade.apt Thu Dec 10 22:38:39 2009
@@ -4,15 +4,20 @@
Upgrade Notes
- This is a quick guide to changes <since> Tapestry 5.0.18. This is meant to provide information
- on any additions or changes that developers will face after upgrading from Tapestry 5.0 to Tapestry 5.1, or from one
- 5.1 snapshot release to another.
-
+ This is a quick guide to changes <since> Tapestry 5.1.0.5. This is meant to provide information
+ on any additions or changes that developers will face after upgrading to Tapestry 5.2.
+
It is always advised to perform a full and complete build after upgrading.
You should also check the {{{release-notes.html}project-wide release notes}} for information
about bugs fixes and other improvements.
+Release 5.2.0
+
+ Tapestry no longer uses a StAX parser (it uses a normal SAX parser) to parse template. This change
+ reduces the number of dependencies for Tapestry, and is a stepping stone to compatibility with
+ Google App Engine.
+
Release 5.1.0.4
Tapestry's alpha URL rewriting support (available from 5.1.0.1) has undergone some API changes:
Modified: tapestry/tapestry5/trunk/tapestry-core/pom.xml
URL: http://svn.apache.org/viewvc/tapestry/tapestry5/trunk/tapestry-core/pom.xml?rev=889446&r1=889445&r2=889446&view=diff
==============================================================================
--- tapestry/tapestry5/trunk/tapestry-core/pom.xml (original)
+++ tapestry/tapestry5/trunk/tapestry-core/pom.xml Thu Dec 10 22:38:39 2009
@@ -53,12 +53,6 @@
</exclusions>
</dependency>
- <dependency>
- <groupId>org.codehaus.woodstox</groupId>
- <artifactId>woodstox-core-asl</artifactId>
- <version>4.0.3</version>
- </dependency>
-
</dependencies>
<build>
Added: tapestry/tapestry5/trunk/tapestry-core/src/main/java/org/apache/tapestry5/internal/services/AttributeInfo.java
URL: http://svn.apache.org/viewvc/tapestry/tapestry5/trunk/tapestry-core/src/main/java/org/apache/tapestry5/internal/services/AttributeInfo.java?rev=889446&view=auto
==============================================================================
--- tapestry/tapestry5/trunk/tapestry-core/src/main/java/org/apache/tapestry5/internal/services/AttributeInfo.java (added)
+++ tapestry/tapestry5/trunk/tapestry-core/src/main/java/org/apache/tapestry5/internal/services/AttributeInfo.java Thu Dec 10 22:38:39 2009
@@ -0,0 +1,36 @@
+// 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 javax.xml.namespace.QName;
+
+/**
+ * Tracks the qualified name and value of an attribute within a start element
+ * XMLToken.
+ *
+ * @since 5.2.0
+ */
+public class AttributeInfo
+{
+ final QName attributeName;
+
+ final String value;
+
+ public AttributeInfo(QName attributeName, String value)
+ {
+ this.attributeName = attributeName;
+ this.value = value;
+ }
+}
Propchange: tapestry/tapestry5/trunk/tapestry-core/src/main/java/org/apache/tapestry5/internal/services/AttributeInfo.java
------------------------------------------------------------------------------
svn:eol-style = native
Added: tapestry/tapestry5/trunk/tapestry-core/src/main/java/org/apache/tapestry5/internal/services/DTDData.java
URL: http://svn.apache.org/viewvc/tapestry/tapestry5/trunk/tapestry-core/src/main/java/org/apache/tapestry5/internal/services/DTDData.java?rev=889446&view=auto
==============================================================================
--- tapestry/tapestry5/trunk/tapestry-core/src/main/java/org/apache/tapestry5/internal/services/DTDData.java (added)
+++ tapestry/tapestry5/trunk/tapestry-core/src/main/java/org/apache/tapestry5/internal/services/DTDData.java Thu Dec 10 22:38:39 2009
@@ -0,0 +1,32 @@
+// 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.xml.sax.ext.LexicalHandler;
+
+/**
+ * A capturing of the data from
+ * {@link LexicalHandler#startDTD(String, String, String)}.
+ *
+ * @since 5.2.0
+ */
+public interface DTDData
+{
+ String getRootName();
+
+ String getPublicId();
+
+ String getSystemId();
+}
Propchange: tapestry/tapestry5/trunk/tapestry-core/src/main/java/org/apache/tapestry5/internal/services/DTDData.java
------------------------------------------------------------------------------
svn:eol-style = native
Added: tapestry/tapestry5/trunk/tapestry-core/src/main/java/org/apache/tapestry5/internal/services/NamespaceMapping.java
URL: http://svn.apache.org/viewvc/tapestry/tapestry5/trunk/tapestry-core/src/main/java/org/apache/tapestry5/internal/services/NamespaceMapping.java?rev=889446&view=auto
==============================================================================
--- tapestry/tapestry5/trunk/tapestry-core/src/main/java/org/apache/tapestry5/internal/services/NamespaceMapping.java (added)
+++ tapestry/tapestry5/trunk/tapestry-core/src/main/java/org/apache/tapestry5/internal/services/NamespaceMapping.java Thu Dec 10 22:38:39 2009
@@ -0,0 +1,33 @@
+// 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 within a {@link XMLToken} to identify namespaces defined with a start
+ * element token.
+ *
+ * @since 5.2.0
+ */
+class NamespaceMapping
+{
+ final String prefix, uri;
+
+ public NamespaceMapping(String prefix, String uri)
+ {
+ this.prefix = prefix;
+ this.uri = uri;
+ }
+
+}
Propchange: tapestry/tapestry5/trunk/tapestry-core/src/main/java/org/apache/tapestry5/internal/services/NamespaceMapping.java
------------------------------------------------------------------------------
svn:eol-style = native
Copied: tapestry/tapestry5/trunk/tapestry-core/src/main/java/org/apache/tapestry5/internal/services/SaxTemplateParser.java (from r888990, 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/SaxTemplateParser.java?p2=tapestry/tapestry5/trunk/tapestry-core/src/main/java/org/apache/tapestry5/internal/services/SaxTemplateParser.java&p1=tapestry/tapestry5/trunk/tapestry-core/src/main/java/org/apache/tapestry5/internal/services/StaxTemplateParser.java&r1=888990&r2=889446&rev=889446&view=diff
==============================================================================
--- tapestry/tapestry5/trunk/tapestry-core/src/main/java/org/apache/tapestry5/internal/services/StaxTemplateParser.java (original)
+++ tapestry/tapestry5/trunk/tapestry-core/src/main/java/org/apache/tapestry5/internal/services/SaxTemplateParser.java Thu Dec 10 22:38:39 2009
@@ -14,34 +14,53 @@
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.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.net.URL;
import java.util.List;
import java.util.Map;
import java.util.Set;
import java.util.regex.Matcher;
import java.util.regex.Pattern;
+import javax.xml.namespace.QName;
+
+import org.apache.tapestry5.internal.parser.AttributeToken;
+import org.apache.tapestry5.internal.parser.BlockToken;
+import org.apache.tapestry5.internal.parser.BodyToken;
+import org.apache.tapestry5.internal.parser.CDATAToken;
+import org.apache.tapestry5.internal.parser.CommentToken;
+import org.apache.tapestry5.internal.parser.ComponentTemplate;
+import org.apache.tapestry5.internal.parser.ComponentTemplateImpl;
+import org.apache.tapestry5.internal.parser.DTDToken;
+import org.apache.tapestry5.internal.parser.DefineNamespacePrefixToken;
+import org.apache.tapestry5.internal.parser.EndElementToken;
+import org.apache.tapestry5.internal.parser.ExpansionToken;
+import org.apache.tapestry5.internal.parser.ExtensionPointToken;
+import org.apache.tapestry5.internal.parser.ParameterToken;
+import org.apache.tapestry5.internal.parser.StartComponentToken;
+import org.apache.tapestry5.internal.parser.StartElementToken;
+import org.apache.tapestry5.internal.parser.TemplateToken;
+import org.apache.tapestry5.internal.parser.TextToken;
+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.TapestryException;
+
/**
- * 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.
+ * SAX-based template parser logic, taking a {@link Resource} to a Tapestry
+ * template file and returning
+ * a {@link ComponentTemplate}.
+ * <p>
+ * Earlier versions of this code used the StAX (streaming XML parser), but that
+ * was really, really bad for Google App Engine. This version uses SAX under the
+ * covers, but kind of replicates the important bits of the StAX API as
+ * {@link XMLTokenStream}.
+ *
+ * @since 5.2.0
*/
-@SuppressWarnings({ "JavaDoc" })
-public class StaxTemplateParser
+@SuppressWarnings(
+{ "JavaDoc" })
+public class SaxTemplateParser
{
private static final String MIXINS_ATTRIBUTE_NAME = "mixins";
@@ -61,76 +80,83 @@
*/
public static final String TAPESTRY_SCHEMA_5_1_0 = "http://tapestry.apache.org/schema/tapestry_5_1_0.xsd";
- // Might want to change this from a Set to a map from URI to version number (if we hit a 3rd version of the namespace URI).
- private static final Set<String> TAPESTRY_SCHEMA_URIS = CollectionFactory.newSet(TAPESTRY_SCHEMA_5_0_0,
- TAPESTRY_SCHEMA_5_1_0);
+ // Might want to change this from a Set to a map from URI to version number
+ // (if we hit a 3rd version of the namespace URI).
+ private static final Set<String> TAPESTRY_SCHEMA_URIS = CollectionFactory.newSet(
+ TAPESTRY_SCHEMA_5_0_0, TAPESTRY_SCHEMA_5_1_0);
/**
- * 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.
+ * 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.
+ * 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
+ * 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);
+ Pattern.CASE_INSENSITIVE);
- private static final Pattern ID_PATTERN = Pattern.compile("^[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.
+ * 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);
+ 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
+ * 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);
+ 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
+ // 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 static final Set<String> MUST_BE_ROOT = CollectionFactory.newSet("extend", "container");
private final Resource resource;
- private final XMLStreamReader2 reader;
+ private final XMLTokenStream tokenStream;
private final StringBuilder textBuffer = new StringBuilder();
private final List<TemplateToken> tokens = CollectionFactory.newList();
- // This starts pointing at tokens but occasionally shifts to a list inside the overrides Map.
+ // This starts pointing at tokens but occasionally shifts to a list inside
+ // the overrides Map.
private List<TemplateToken> tokenAccumulator = tokens;
/**
- * Primarily used as a set of componentIds (to check for duplicates and conflicts).
+ * Primarily used as a set of componentIds (to check for duplicates and
+ * conflicts).
*/
private final Map<String, Location> componentIds = CollectionFactory.newCaseInsensitiveMap();
/**
- * Map from override id to a list of tokens; this actually works both for overrides defined by this template and
+ * Map from override id to a list of tokens; this actually works both for
+ * overrides defined by this template and
* overrides provided by this template.
*/
private Map<String, List<TemplateToken>> overrides;
@@ -141,47 +167,38 @@
private boolean active = true;
- private Location cachedLocation;
-
- public StaxTemplateParser(Resource resource, XMLInputFactory2 inputFactory) throws XMLStreamException, IOException
+ public SaxTemplateParser(Resource resource, Map<String, URL> publicIdToURL)
{
this.resource = resource;
- this.reader = (XMLStreamReader2) inputFactory.createXMLStreamReader(resource.openStream());
+ this.tokenStream = new XMLTokenStream(resource, publicIdToURL);
}
public ComponentTemplate parse(boolean compressWhitespace)
{
- TemplateParserState initialParserState = new TemplateParserState().compressWhitespace(compressWhitespace);
-
try
{
+ tokenStream.parse();
+
+ TemplateParserState initialParserState = new TemplateParserState()
+ .compressWhitespace(compressWhitespace);
+
root(initialParserState);
- reader.close();
+ return new ComponentTemplateImpl(resource, tokens, componentIds, extension, overrides);
}
catch (Exception ex)
{
- try
- {
- reader.closeCompletely();
- }
- catch (XMLStreamException e)
- {
- // Ignore it.
- }
-
- throw new TapestryException(ServicesMessages.templateParseError(resource, ex), getLocation(),
- ex);
+ throw new TapestryException(String.format("Failure parsing template %s: %s", resource,
+ InternalUtils.toMessage(ex)), tokenStream.getLocation(), ex);
}
- return new ComponentTemplateImpl(resource, tokens, componentIds, extension, overrides);
}
- void root(TemplateParserState state) throws XMLStreamException
+ void root(TemplateParserState state)
{
- while (active && reader.hasNext())
+ while (active && tokenStream.hasNext())
{
- switch (reader.next())
+ switch (tokenStream.next())
{
case DTD:
@@ -205,12 +222,12 @@
}
}
- private void rootElement(TemplateParserState initialState) throws XMLStreamException
+ private void rootElement(TemplateParserState initialState)
{
TemplateParserState state = setupForElement(initialState);
- String uri = reader.getNamespaceURI();
- String name = reader.getLocalName();
+ String uri = tokenStream.getNamespaceURI();
+ String name = tokenStream.getLocalName();
if (TAPESTRY_SCHEMA_5_1_0.equals(uri))
{
@@ -230,23 +247,21 @@
}
}
-
element(state);
}
- private void extend(TemplateParserState state) throws XMLStreamException
+ private void extend(TemplateParserState state)
{
extension = true;
while (active)
{
- switch (reader.next())
+ switch (tokenStream.next())
{
case START_ELEMENT:
- if (reader.getNamespaceURI().equals(
- TAPESTRY_SCHEMA_5_1_0) && reader.getLocalName().equalsIgnoreCase(
- "replace"))
+ if (tokenStream.getNamespaceURI().equals(TAPESTRY_SCHEMA_5_1_0)
+ && tokenStream.getLocalName().equalsIgnoreCase("replace"))
{
replace(state);
break;
@@ -258,7 +273,7 @@
return;
- // Ignore spaces and characters inside <extend>.
+ // Ignore spaces and characters inside <extend>.
case COMMENT:
case SPACE:
@@ -267,7 +282,7 @@
// Other content (characters, etc.) are forbidden.
case CHARACTERS:
- if (InternalUtils.isBlank(reader.getText()))
+ if (InternalUtils.isBlank(tokenStream.getText()))
break;
default:
@@ -276,7 +291,7 @@
}
}
- private void replace(TemplateParserState state) throws XMLStreamException
+ private void replace(TemplateParserState state)
{
String id = getRequiredIdAttribute();
@@ -285,28 +300,23 @@
private void unexpectedEventType()
{
- int eventType = reader.getEventType();
+ XMLTokenType eventType = tokenStream.getEventType();
- throw new IllegalStateException(
- String.format("Unexpected XML parse event %s.", EVENT_NAMES[eventType]));
+ throw new IllegalStateException(String.format("Unexpected XML parse event %s.", eventType
+ .name()));
}
- private void dtd() throws XMLStreamException
+ private void dtd()
{
- DTDInfo dtdInfo = reader.getDTDInfo();
+ DTDData dtdInfo = tokenStream.getDTDInfo();
- tokenAccumulator.add(new DTDToken(dtdInfo.getDTDRootName(), dtdInfo.getDTDPublicId(), dtdInfo.getDTDSystemId(),
- getLocation()));
+ tokenAccumulator.add(new DTDToken(dtdInfo.getRootName(), dtdInfo.getPublicId(), dtdInfo
+ .getSystemId(), getLocation()));
}
private Location getLocation()
{
- int lineNumber = reader.getLocation().getLineNumber();
-
- if (cachedLocation == null || cachedLocation.getLine() != lineNumber)
- cachedLocation = new LocationImpl(resource, lineNumber);
-
- return cachedLocation;
+ return tokenStream.getLocation();
}
/**
@@ -316,7 +326,7 @@
* <p/>
* a Tapestry component via <t:type>
* <p/>
- * a Tapestry component via t:type="type" and/or t:id="id"
+ * a Tapestry component via t:type="type" and/or t:id="id"
* <p/>
* a Tapestry component via a library namespace
* <p/>
@@ -334,12 +344,12 @@
* <p/>
* An ordinary element
*/
- void element(TemplateParserState initialState) throws XMLStreamException
+ void element(TemplateParserState initialState)
{
TemplateParserState state = setupForElement(initialState);
- String uri = reader.getNamespaceURI();
- String name = reader.getLocalName();
+ String uri = tokenStream.getNamespaceURI();
+ String name = tokenStream.getLocalName();
if (TAPESTRY_SCHEMA_5_1_0.equals(uri))
{
@@ -365,10 +375,8 @@
return;
}
- if (name.equalsIgnoreCase("replace"))
- {
- throw new RuntimeException("The <replace> element may only appear directly within an extend element.");
- }
+ if (name.equalsIgnoreCase("replace")) { throw new RuntimeException(
+ "The <replace> element may only appear directly within an extend element."); }
if (MUST_BE_ROOT.contains(name))
mustBeRoot(name);
@@ -401,7 +409,7 @@
return;
}
- possibleTapestryComponent(state, null, reader.getLocalName().replace('.', '/'));
+ possibleTapestryComponent(state, null, tokenStream.getLocalName().replace('.', '/'));
return;
}
@@ -422,22 +430,22 @@
// Just an ordinary element ... unless it has t:id or t:type
- possibleTapestryComponent(state, reader.getLocalName(), null);
+ possibleTapestryComponent(state, tokenStream.getLocalName(), null);
}
/**
- * Processes a body of an element including text and (recursively) nested elements. Adds an {@link
- * org.apache.tapestry5.internal.parser.TokenType#END_ELEMENT} token before returning.
- *
+ * Processes a body of an element including text and (recursively) nested
+ * elements. Adds an
+ * {@link org.apache.tapestry5.internal.parser.TokenType#END_ELEMENT} token
+ * before returning.
+ *
* @param state
- * @throws XMLStreamException
*/
private void processBody(TemplateParserState state)
- throws XMLStreamException
{
while (active)
{
- switch (reader.next())
+ switch (tokenStream.next())
{
case START_ELEMENT:
@@ -470,15 +478,17 @@
}
/**
- * Handles an extension point, putting a RenderExtension token in position in the template.
- *
+ * Handles an extension point, putting a RenderExtension token in position
+ * in the template.
+ *
* @param state
- * @throws XMLStreamException
*/
- private void extensionPoint(TemplateParserState state) throws XMLStreamException
+ private void extensionPoint(TemplateParserState state)
{
- // An extension point adds a token that represents where the override (either the default
- // provided in the parent template, or the true override from a child template) is positioned.
+ // An extension point adds a token that represents where the override
+ // (either the default
+ // provided in the parent template, or the true override from a child
+ // template) is positioned.
String id = getRequiredIdAttribute();
@@ -493,19 +503,20 @@
if (InternalUtils.isBlank(id))
throw new RuntimeException(String.format("The <%s> element must have an id attribute.",
- reader.getLocalName()));
+ tokenStream.getLocalName()));
return id;
}
private void addContentToOverride(TemplateParserState state, String id)
- throws XMLStreamException
+
{
List<TemplateToken> savedTokenAccumulator = tokenAccumulator;
tokenAccumulator = CollectionFactory.newList();
- // TODO: id should probably be unique; i.e., you either define an override or you
+ // TODO: id should probably be unique; i.e., you either define an
+ // override or you
// provide an override, but you don't do both in the same template.
if (overrides == null)
@@ -515,7 +526,7 @@
while (active)
{
- switch (reader.next())
+ switch (tokenStream.next())
{
case START_ELEMENT:
element(state);
@@ -525,7 +536,8 @@
processTextBuffer(state);
- // Restore everthing to how it was before the extention-point was reached.
+ // Restore everthing to how it was before the
+ // extention-point was reached.
tokenAccumulator = savedTokenAccumulator;
return;
@@ -538,40 +550,43 @@
private void mustBeRoot(String name)
{
- throw new RuntimeException(
- String.format("Element <%s> is only valid as the root element of a template.", name));
+ throw new RuntimeException(String.format(
+ "Element <%s> is only valid as the root element of a template.", name));
}
/**
- * Triggered by <t:content> element; limits template content to just what's inside.
+ * Triggered by <t:content> element; limits template content to just
+ * what's inside.
*/
- private void limitContent(TemplateParserState state) throws XMLStreamException
+ private void limitContent(TemplateParserState state)
{
if (state.isCollectingContent())
throw new IllegalStateException(
"The <content> element may not be nested within another <content> element.");
-
TemplateParserState newState = state.collectingContent().insideComponent(false);
// Clear out any tokens that precede the <t:content> element
tokens.clear();
- // I'm not happy about this; you really shouldn't define overrides just to clear them out,
- // but it is consistent. Perhaps this should be an error if overrides is non-empty.
+ // I'm not happy about this; you really shouldn't define overrides just
+ // to clear them out,
+ // but it is consistent. Perhaps this should be an error if overrides is
+ // non-empty.
overrides = null;
- // Make sure that if the <t:content> appears inside a <t:replace> or <t:extension-point>, that
+ // Make sure that if the <t:content> appears inside a <t:replace> or
+ // <t:extension-point>, that
// it is still handled correctly.
tokenAccumulator = tokens;
while (active)
{
- switch (reader.next())
+ switch (tokenStream.next())
{
case START_ELEMENT:
element(newState);
@@ -579,7 +594,8 @@
case END_ELEMENT:
- // The active flag is global, once we hit it, the entire parse is aborted, leaving
+ // The active flag is global, once we hit it, the entire
+ // parse is aborted, leaving
// tokens with just tokens defined inside <t:content>.
active = false;
@@ -593,13 +609,13 @@
}
- private void removeContent() throws XMLStreamException
+ private void removeContent()
{
int depth = 1;
while (active)
{
- switch (reader.next())
+ switch (tokenStream.next())
{
case START_ELEMENT:
depth++;
@@ -610,7 +626,8 @@
case END_ELEMENT:
depth--;
- if (depth == 0) return;
+ if (depth == 0)
+ return;
break;
@@ -625,13 +642,12 @@
return InternalUtils.isBlank(input) ? null : input;
}
-
/**
* Added in release 5.1.
*/
- private void libraryNamespaceComponent(TemplateParserState state) throws XMLStreamException
+ private void libraryNamespaceComponent(TemplateParserState state)
{
- String uri = reader.getNamespaceURI();
+ String uri = tokenStream.getNamespaceURI();
// The library path is encoded into the namespace URI.
@@ -640,21 +656,23 @@
if (!LIBRARY_PATH_PATTERN.matcher(path).matches())
throw new RuntimeException(ServicesMessages.invalidPathForLibraryNamespace(uri));
- possibleTapestryComponent(state, null, path + "/" + reader.getLocalName());
+ possibleTapestryComponent(state, null, path + "/" + tokenStream.getLocalName());
}
/**
* @param elementName
- * @param identifiedType the type of the element, usually null, but may be the component type derived from element
+ * @param identifiedType
+ * the type of the element, usually null, but may be the
+ * component type derived from element
*/
- private void possibleTapestryComponent(TemplateParserState state, String elementName, String identifiedType)
- throws XMLStreamException
+ private void possibleTapestryComponent(TemplateParserState state, String elementName,
+ String identifiedType)
{
String id = null;
String type = identifiedType;
String mixins = null;
- int count = reader.getAttributeCount();
+ int count = tokenStream.getAttributeCount();
Location location = getLocation();
@@ -662,19 +680,21 @@
for (int i = 0; i < count; i++)
{
- QName qname = reader.getAttributeName(i);
+ QName qname = tokenStream.getAttributeName(i);
- if (isXMLSpaceAttribute(qname)) continue;
+ if (isXMLSpaceAttribute(qname))
+ continue;
// The name will be blank for an xmlns: attribute
String localName = qname.getLocalPart();
- if (InternalUtils.isBlank(localName)) continue;
+ if (InternalUtils.isBlank(localName))
+ continue;
String uri = qname.getNamespaceURI();
- String value = reader.getAttributeValue(i);
+ String value = tokenStream.getAttributeValue(i);
if (TAPESTRY_SCHEMA_URIS.contains(uri))
{
@@ -699,20 +719,23 @@
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.
+ // 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 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);
+ throw new TapestryException(ServicesMessages.mixinsInvalidWithoutIdOrType(elementName),
+ location, null);
if (isComponent)
{
@@ -720,7 +743,8 @@
}
else
{
- tokenAccumulator.add(new StartElementToken(reader.getNamespaceURI(), elementName, location));
+ tokenAccumulator.add(new StartElementToken(tokenStream.getNamespaceURI(), elementName,
+ location));
}
addDefineNamespaceTokens();
@@ -735,33 +759,36 @@
private void addDefineNamespaceTokens()
{
- for (int i = 0; i < reader.getNamespaceCount(); i++)
+ for (int i = 0; i < tokenStream.getNamespaceCount(); i++)
{
- String uri = reader.getNamespaceURI(i);
+ String uri = tokenStream.getNamespaceURI(i);
- // These URIs are strictly part of the server-side Tapestry template and are not ever sent to the client.
+ // These URIs are strictly part of the server-side Tapestry template
+ // and are not ever sent to the client.
- if (TAPESTRY_SCHEMA_URIS.contains(uri)) continue;
+ if (TAPESTRY_SCHEMA_URIS.contains(uri))
+ continue;
- if (uri.equals(TAPESTRY_PARAMETERS_URI)) continue;
+ if (uri.equals(TAPESTRY_PARAMETERS_URI))
+ continue;
- if (uri.startsWith(LIB_NAMESPACE_URI_PREFIX)) continue;
+ if (uri.startsWith(LIB_NAMESPACE_URI_PREFIX))
+ continue;
- tokenAccumulator.add(new DefineNamespacePrefixToken(uri, reader.getNamespacePrefix(i),
- getLocation()));
+ tokenAccumulator.add(new DefineNamespacePrefixToken(uri, tokenStream
+ .getNamespacePrefix(i), getLocation()));
}
}
-
private TemplateParserState checkForXMLSpaceAttribute(TemplateParserState state)
{
- for (int i = 0; i < reader.getAttributeCount(); i++)
+ for (int i = 0; i < tokenStream.getAttributeCount(); i++)
{
- QName qName = reader.getAttributeName(i);
+ QName qName = tokenStream.getAttributeName(i);
if (isXMLSpaceAttribute(qName))
{
- boolean compress = !"preserve".equals(reader.getAttributeValue(i));
+ boolean compress = !"preserve".equals(tokenStream.getAttributeValue(i));
return state.compressWhitespace(compress);
}
@@ -781,15 +808,17 @@
}
/**
- * Handler for Tapestry 5.0's "classic" <t:parameter> element. This turns into a {@link
- * org.apache.tapestry5.internal.parser.ParameterToken} and the body and end element are provided normally.
+ * Handler for Tapestry 5.0's "classic" <t:parameter> element. This
+ * turns into a {@link org.apache.tapestry5.internal.parser.ParameterToken}
+ * and the body and end element are provided normally.
*/
- private void classicParameter(TemplateParserState state) throws XMLStreamException
+ private void classicParameter(TemplateParserState state)
{
String parameterName = getSingleParameter("name");
if (InternalUtils.isBlank(parameterName))
- throw new TapestryException(ServicesMessages.parameterElementNameRequired(), getLocation(), null);
+ throw new TapestryException(ServicesMessages.parameterElementNameRequired(),
+ getLocation(), null);
ensureParameterWithinComponent(state);
@@ -801,64 +830,68 @@
private void ensureParameterWithinComponent(TemplateParserState state)
{
if (!state.isInsideComponent())
- throw new RuntimeException("Block parameters are only allowed directly within component elements.");
+ throw new RuntimeException(
+ "Block parameters are only allowed directly within component elements.");
}
/**
- * Tapestry 5.1 uses a special namespace (usually mapped to "p:") and the name becomes the parameter element.
+ * Tapestry 5.1 uses a special namespace (usually mapped to "p:") and the
+ * name becomes the parameter element.
*/
- private void parameterElement(TemplateParserState state) throws XMLStreamException
+ private void parameterElement(TemplateParserState state)
{
ensureParameterWithinComponent(state);
- if (reader.getAttributeCount() > 0)
- throw new TapestryException(ServicesMessages.parameterElementDoesNotAllowAttributes(), getLocation(),
- null);
+ if (tokenStream.getAttributeCount() > 0)
+ throw new TapestryException(ServicesMessages.parameterElementDoesNotAllowAttributes(),
+ getLocation(), null);
- tokenAccumulator.add(new ParameterToken(reader.getLocalName(), getLocation()));
+ tokenAccumulator.add(new ParameterToken(tokenStream.getLocalName(), getLocation()));
processBody(state.insideComponent(false));
}
-
/**
- * Checks that a body element is empty. Returns after the body's close element. Adds a single body token (but not an
+ * 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
+ private void body()
{
tokenAccumulator.add(new BodyToken(getLocation()));
while (active)
{
- switch (reader.next())
+ switch (tokenStream.next())
{
case END_ELEMENT:
return;
default:
- throw new IllegalStateException(ServicesMessages.contentInsideBodyNotAllowed(getLocation()));
+ throw new IllegalStateException(ServicesMessages
+ .contentInsideBodyNotAllowed(getLocation()));
}
}
}
/**
- * Driven by the <t:container> element, this state adds elements for its body but not its start or end tags.
- *
+ * Driven by the <t:container> 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
+ private void container(TemplateParserState state)
{
while (active)
{
- switch (reader.next())
+ switch (tokenStream.next())
{
case START_ELEMENT:
element(state);
break;
- // The matching end-element for the container. Don't add a token.
+ // The matching end-element for the container. Don't add a
+ // token.
case END_ELEMENT:
@@ -873,9 +906,10 @@
}
/**
- * A block adds a token for its start tag and end tag and allows any content within.
+ * A block adds a token for its start tag and end tag and allows any content
+ * within.
*/
- private void block(TemplateParserState state) throws XMLStreamException
+ private void block(TemplateParserState state)
{
String blockId = getSingleParameter("id");
@@ -890,23 +924,23 @@
{
String result = null;
- for (int i = 0; i < reader.getAttributeCount(); i++)
+ for (int i = 0; i < tokenStream.getAttributeCount(); i++)
{
- QName qName = reader.getAttributeName(i);
+ QName qName = tokenStream.getAttributeName(i);
- if (isXMLSpaceAttribute(qName)) continue;
+ if (isXMLSpaceAttribute(qName))
+ continue;
if (qName.getLocalPart().equalsIgnoreCase(attributeName))
{
- result = reader.getAttributeValue(i);
+ result = tokenStream.getAttributeValue(i);
continue;
}
// Only the named attribute is allowed.
- throw new TapestryException(ServicesMessages.undefinedTapestryAttribute(reader.getLocalName(),
- qName.toString(), attributeName),
- getLocation(), null);
+ throw new TapestryException(ServicesMessages.undefinedTapestryAttribute(tokenStream
+ .getLocalName(), qName.toString(), attributeName), getLocation(), null);
}
return result;
@@ -914,9 +948,11 @@
private void validateId(String id, String messageKey)
{
- if (id == null) return;
+ if (id == null)
+ return;
- if (ID_PATTERN.matcher(id).matches()) return;
+ if (ID_PATTERN.matcher(id).matches())
+ return;
// Not a match.
@@ -925,20 +961,20 @@
private boolean isXMLSpaceAttribute(QName qName)
{
- return XML_NAMESPACE_URI.equals(qName.getNamespaceURI()) &&
- "space".equals(qName.getLocalPart());
+ 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
+ * 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())
+ switch (tokenStream.getEventType())
{
case COMMENT:
comment(state);
@@ -963,23 +999,24 @@
if (textStartLocation == null)
textStartLocation = getLocation();
- textBuffer.append(reader.getText());
+ textBuffer.append(tokenStream.getText());
}
private void cdata(TemplateParserState state)
{
processTextBuffer(state);
- tokenAccumulator.add(new CDATAToken(reader.getText(), getLocation()));
+ tokenAccumulator.add(new CDATAToken(tokenStream.getText(), getLocation()));
}
private void comment(TemplateParserState state)
{
processTextBuffer(state);
- // Trim the excess whitespace; the Comment DOM node will add a leading/trailing space.
+ // Trim the excess whitespace; the Comment DOM node will add a
+ // leading/trailing space.
- String comment = reader.getText().trim();
+ String comment = tokenStream.getText().trim();
tokenAccumulator.add(new CommentToken(comment, getLocation()));
}
@@ -1005,15 +1042,17 @@
{
text = compressWhitespaceInText(text);
- if (InternalUtils.isBlank(text)) return;
+ if (InternalUtils.isBlank(text))
+ return;
}
addTokensForText(text);
}
/**
- * Reduces vertical whitespace to a single newline, then reduces horizontal whitespace to a single space.
- *
+ * Reduces vertical whitespace to a single newline, then reduces horizontal
+ * whitespace to a single space.
+ *
* @param text
* @return compressed version of text
*/
@@ -1025,11 +1064,14 @@
}
/**
- * Scans the text, using a regular expression pattern, for expansion patterns, and adds appropriate tokens for what
+ * 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
+ *
+ * @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)
{
@@ -1037,10 +1079,14 @@
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
+ // 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())
@@ -1054,7 +1100,8 @@
tokenAccumulator.add(new TextToken(prefix, textStartLocation));
}
- // Group 1 includes the real text of the expansion, with whitespace around the
+ // 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);
@@ -1067,7 +1114,8 @@
// Catch anything after the final regexp match.
if (startx < text.length())
- tokenAccumulator.add(new TextToken(text.substring(startx, text.length()), textStartLocation));
+ tokenAccumulator.add(new TextToken(text.substring(startx, text.length()),
+ textStartLocation));
}
}
Modified: tapestry/tapestry5/trunk/tapestry-core/src/main/java/org/apache/tapestry5/internal/services/ServicesMessages.java
URL: http://svn.apache.org/viewvc/tapestry/tapestry5/trunk/tapestry-core/src/main/java/org/apache/tapestry5/internal/services/ServicesMessages.java?rev=889446&r1=889445&r2=889446&view=diff
==============================================================================
--- tapestry/tapestry5/trunk/tapestry-core/src/main/java/org/apache/tapestry5/internal/services/ServicesMessages.java (original)
+++ tapestry/tapestry5/trunk/tapestry-core/src/main/java/org/apache/tapestry5/internal/services/ServicesMessages.java Thu Dec 10 22:38:39 2009
@@ -71,21 +71,11 @@
return MESSAGES.format("class-not-transformed", className);
}
- static String newParserError(Resource resource, Throwable cause)
- {
- return MESSAGES.format("new-parser-error", resource, cause);
- }
-
static String missingTemplateResource(Resource resource)
{
return MESSAGES.format("missing-template-resource", resource);
}
- static String templateParseError(Resource resource, Throwable cause)
- {
- return MESSAGES.format("template-parse-error", resource, cause);
- }
-
static String contentInsideBodyNotAllowed(Location location)
{
return MESSAGES.format("content-inside-body-not-allowed", location);
Modified: 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=889446&r1=889445&r2=889446&view=diff
==============================================================================
--- tapestry/tapestry5/trunk/tapestry-core/src/main/java/org/apache/tapestry5/internal/services/TemplateParserImpl.java (original)
+++ tapestry/tapestry5/trunk/tapestry-core/src/main/java/org/apache/tapestry5/internal/services/TemplateParserImpl.java Thu Dec 10 22:38:39 2009
@@ -14,54 +14,35 @@
package org.apache.tapestry5.internal.services;
+import java.net.URL;
+import java.util.Map;
+
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.
- *
+ * Parses Tapestry XML template files into {@link ComponentTemplate} instances.
+ * A new instance of {@link SaxTemplateParser} is created for each document
+ * parsed.
+ *
* @since 5.1.0.0
*/
-public class TemplateParserImpl implements TemplateParser, XMLResolver
+public class TemplateParserImpl implements TemplateParser
{
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)
+ @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)
@@ -69,43 +50,8 @@
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);
+ return new SaxTemplateParser(templateResource, configuration)
+ .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;
- }
}
Modified: 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=889446&r1=889445&r2=889446&view=diff
==============================================================================
--- tapestry/tapestry5/trunk/tapestry-core/src/main/java/org/apache/tapestry5/internal/services/TemplateParserState.java (original)
+++ tapestry/tapestry5/trunk/tapestry-core/src/main/java/org/apache/tapestry5/internal/services/TemplateParserState.java Thu Dec 10 22:38:39 2009
@@ -15,7 +15,7 @@
package org.apache.tapestry5.internal.services;
/**
- * Used to track behaviors inside {@link org.apache.tapestry5.internal.services.StaxTemplateParser}. Internal state is
+ * Used to track behaviors inside {@link org.apache.tapestry5.internal.services.SaxTemplateParser}. Internal state is
* immutable, the set-like methods return a new immutable instance.
*
* @since 5.1.0.0
Added: tapestry/tapestry5/trunk/tapestry-core/src/main/java/org/apache/tapestry5/internal/services/XMLToken.java
URL: http://svn.apache.org/viewvc/tapestry/tapestry5/trunk/tapestry-core/src/main/java/org/apache/tapestry5/internal/services/XMLToken.java?rev=889446&view=auto
==============================================================================
--- tapestry/tapestry5/trunk/tapestry-core/src/main/java/org/apache/tapestry5/internal/services/XMLToken.java (added)
+++ tapestry/tapestry5/trunk/tapestry-core/src/main/java/org/apache/tapestry5/internal/services/XMLToken.java Thu Dec 10 22:38:39 2009
@@ -0,0 +1,49 @@
+// 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 java.util.List;
+
+import org.apache.tapestry5.ioc.BaseLocatable;
+import org.apache.tapestry5.ioc.Location;
+
+/**
+ * A token parsed from an XML file, used when parsing templates.
+ *
+ * @since 5.2.0
+ */
+class XMLToken extends BaseLocatable
+{
+ final XMLTokenType type;
+
+ DTDData dtdData;
+
+ String uri, localName, qName;
+
+ List<AttributeInfo> attributes;
+
+ List<NamespaceMapping> namespaceMappings;
+
+ // COMMENT, CDATA, CHARACTERS, WHITESPACE
+ String text;
+
+ XMLToken(XMLTokenType type, Location location)
+ {
+ super(location);
+
+ this.type = type;
+ }
+
+}
Propchange: tapestry/tapestry5/trunk/tapestry-core/src/main/java/org/apache/tapestry5/internal/services/XMLToken.java
------------------------------------------------------------------------------
svn:eol-style = native
Added: tapestry/tapestry5/trunk/tapestry-core/src/main/java/org/apache/tapestry5/internal/services/XMLTokenStream.java
URL: http://svn.apache.org/viewvc/tapestry/tapestry5/trunk/tapestry-core/src/main/java/org/apache/tapestry5/internal/services/XMLTokenStream.java?rev=889446&view=auto
==============================================================================
--- tapestry/tapestry5/trunk/tapestry-core/src/main/java/org/apache/tapestry5/internal/services/XMLTokenStream.java (added)
+++ tapestry/tapestry5/trunk/tapestry-core/src/main/java/org/apache/tapestry5/internal/services/XMLTokenStream.java Thu Dec 10 22:38:39 2009
@@ -0,0 +1,412 @@
+// 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 java.io.IOException;
+import java.io.InputStream;
+import java.net.URL;
+import java.util.Collections;
+import java.util.List;
+import java.util.Map;
+
+import javax.xml.namespace.QName;
+
+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.xml.sax.Attributes;
+import org.xml.sax.ContentHandler;
+import org.xml.sax.EntityResolver;
+import org.xml.sax.InputSource;
+import org.xml.sax.Locator;
+import org.xml.sax.SAXException;
+import org.xml.sax.XMLReader;
+import org.xml.sax.ext.LexicalHandler;
+import org.xml.sax.helpers.XMLReaderFactory;
+
+/** Parses a document as a stream of XML tokens */
+public class XMLTokenStream
+{
+ private final class SaxHandler implements LexicalHandler, EntityResolver, ContentHandler
+ {
+ private Locator locator;
+
+ private int currentLine = -1;
+
+ private Location cachedLocation;
+
+ private Location textLocation;
+
+ private final StringBuilder builder = new StringBuilder();
+
+ private boolean inCDATA, insideDTD;
+
+ private List<NamespaceMapping> namespaceMappings = CollectionFactory.newList();
+
+ private Location getLocation()
+ {
+ int line = locator.getLineNumber();
+
+ if (currentLine != line)
+ cachedLocation = null;
+
+ if (cachedLocation == null)
+ {
+ cachedLocation = new LocationImpl(resource, line);
+ }
+
+ return cachedLocation;
+ }
+
+ private XMLToken add(XMLTokenType type)
+ {
+ XMLToken token = new XMLToken(type, getLocation());
+
+ tokens.add(token);
+
+ return token;
+ }
+
+ public InputSource resolveEntity(String publicId, String systemId) throws SAXException,
+ IOException
+ {
+ URL url = publicIdToURL.get(publicId);
+
+ try
+ {
+ if (url != null)
+ return new InputSource(url.openStream());
+ }
+ catch (IOException ex)
+ {
+ throw new SAXException(String.format("Unable to open stream for resource %s: %s",
+ url, InternalUtils.toMessage(ex)), ex);
+ }
+
+ return null;
+ }
+
+ public void comment(char[] ch, int start, int length) throws SAXException
+ {
+ if (insideDTD)
+ return;
+
+ // TODO: Coalesce?
+ add(XMLTokenType.COMMENT).text = new String(ch, start, length);
+ }
+
+ public void startCDATA() throws SAXException
+ {
+ // TODO: Flush characters?
+
+ inCDATA = true;
+ }
+
+ public void endCDATA() throws SAXException
+ {
+ if (builder.length() != 0)
+ {
+ add(XMLTokenType.CDATA).text = builder.toString();
+ }
+
+ builder.setLength(0);
+ inCDATA = false;
+ }
+
+ public void characters(char[] ch, int start, int length) throws SAXException
+ {
+ if (inCDATA)
+ {
+ builder.append(ch, start, length);
+ return;
+ }
+
+ XMLToken token = new XMLToken(XMLTokenType.CHARACTERS, textLocation);
+ token.text = new String(ch, start, length);
+
+ tokens.add(token);
+ }
+
+ public void ignorableWhitespace(char[] ch, int start, int length) throws SAXException
+ {
+ }
+
+ public void startDTD(final String name, final String publicId, final String systemId)
+ throws SAXException
+ {
+ insideDTD = true;
+
+ DTDData data = new DTDData()
+ {
+
+ public String getSystemId()
+ {
+ return systemId;
+
+ }
+
+ public String getRootName()
+ {
+ return name;
+ }
+
+ public String getPublicId()
+ {
+ return publicId;
+ }
+ };
+
+ add(XMLTokenType.DTD).dtdData = data;
+ }
+
+ public void endDocument() throws SAXException
+ {
+ add(XMLTokenType.END_DOCUMENT);
+ }
+
+ public void endElement(String uri, String localName, String qName) throws SAXException
+ {
+ add(XMLTokenType.END_ELEMENT);
+ }
+
+ public void setDocumentLocator(Locator locator)
+ {
+ this.locator = locator;
+ }
+
+ public void startElement(String uri, String localName, String qName, Attributes attributes)
+ throws SAXException
+ {
+ XMLToken token = add(XMLTokenType.START_ELEMENT);
+
+ token.uri = uri;
+ token.localName = localName;
+ token.qName = qName;
+
+ // The XML parser tends to reuse the same Attributes object, so
+ // capture the data out of it.
+
+ if (attributes.getLength() == 0)
+ {
+ token.attributes = Collections.emptyList();
+ }
+ else
+ {
+ token.attributes = CollectionFactory.newList();
+
+ for (int i = 0; i < attributes.getLength(); i++)
+ {
+ String prefixedName = attributes.getQName(i);
+
+ int lastColon = prefixedName.lastIndexOf(':');
+
+ String prefix = lastColon > 0 ? prefixedName.substring(0, lastColon) : "";
+
+ QName qname = new QName(attributes.getURI(i), attributes.getLocalName(i),
+ prefix);
+
+ token.attributes.add(new AttributeInfo(qname, attributes.getValue(i)));
+ }
+ }
+
+ token.namespaceMappings = CollectionFactory.newList(namespaceMappings);
+
+ namespaceMappings.clear();
+
+ // Any text collected starts here as well:
+
+ textLocation = getLocation();
+ }
+
+ public void startPrefixMapping(String prefix, String uri) throws SAXException
+ {
+ namespaceMappings.add(new NamespaceMapping(prefix, uri));
+ }
+
+ public void endDTD() throws SAXException
+ {
+ insideDTD = false;
+ }
+
+ public void endEntity(String name) throws SAXException
+ {
+ }
+
+ public void startEntity(String name) throws SAXException
+ {
+ }
+
+ public void endPrefixMapping(String prefix) throws SAXException
+ {
+ }
+
+ public void processingInstruction(String target, String data) throws SAXException
+ {
+ }
+
+ public void skippedEntity(String name) throws SAXException
+ {
+ }
+
+ public void startDocument() throws SAXException
+ {
+ }
+ }
+
+ private int cursor = -1;
+
+ private final List<XMLToken> tokens = CollectionFactory.newList();
+
+ private final Resource resource;
+
+ private final Map<String, URL> publicIdToURL;
+
+ private Location exceptionLocation;
+
+ public XMLTokenStream(Resource resource, Map<String, URL> publicIdToURL)
+ {
+ this.resource = resource;
+ this.publicIdToURL = publicIdToURL;
+ }
+
+ public void parse() throws SAXException, IOException
+ {
+ SaxHandler handler = new SaxHandler();
+
+ XMLReader reader = XMLReaderFactory.createXMLReader();
+
+ reader.setContentHandler(handler);
+ reader.setEntityResolver(handler);
+ reader.setProperty("http://xml.org/sax/properties/lexical-handler", handler);
+
+ InputStream stream = resource.openStream();
+
+ try
+ {
+ reader.parse(new InputSource(stream));
+ }
+ catch (IOException ex)
+ {
+ this.exceptionLocation = handler.getLocation();
+
+ throw ex;
+ }
+ catch (SAXException ex)
+ {
+ this.exceptionLocation = handler.getLocation();
+
+ throw ex;
+ }
+ catch (RuntimeException ex)
+ {
+ this.exceptionLocation = handler.getLocation();
+
+ throw ex;
+ }
+ finally
+ {
+ InternalUtils.close(stream);
+ }
+ }
+
+ private XMLToken token()
+ {
+ return tokens.get(cursor);
+ }
+
+ /**
+ * Returns the type of the next token.
+ */
+ public XMLTokenType next()
+ {
+ cursor++;
+
+ // TODO: Check for overflow?
+
+ return getEventType();
+ }
+
+ public int getAttributeCount()
+ {
+ return token().attributes.size();
+ }
+
+ public QName getAttributeName(int i)
+ {
+ return token().attributes.get(i).attributeName;
+ }
+
+ public DTDData getDTDInfo()
+ {
+ return token().dtdData;
+ }
+
+ public XMLTokenType getEventType()
+ {
+ return token().type;
+ }
+
+ public String getLocalName()
+ {
+ return token().localName;
+ }
+
+ public Location getLocation()
+ {
+ if (exceptionLocation != null)
+ return exceptionLocation;
+
+ return token().getLocation();
+ }
+
+ public int getNamespaceCount()
+ {
+ return token().namespaceMappings.size();
+ }
+
+ public String getNamespacePrefix(int i)
+ {
+ return token().namespaceMappings.get(i).prefix;
+ }
+
+ public String getNamespaceURI()
+ {
+ return token().uri;
+ }
+
+ public String getNamespaceURI(int i)
+ {
+ return token().namespaceMappings.get(i).uri;
+ }
+
+ public String getText()
+ {
+ return token().text;
+ }
+
+ public boolean hasNext()
+ {
+ return cursor < tokens.size() - 1;
+ }
+
+ public String getAttributeValue(int i)
+ {
+ return token().attributes.get(i).value;
+ }
+
+}
Propchange: tapestry/tapestry5/trunk/tapestry-core/src/main/java/org/apache/tapestry5/internal/services/XMLTokenStream.java
------------------------------------------------------------------------------
svn:eol-style = native
Added: tapestry/tapestry5/trunk/tapestry-core/src/main/java/org/apache/tapestry5/internal/services/XMLTokenType.java
URL: http://svn.apache.org/viewvc/tapestry/tapestry5/trunk/tapestry-core/src/main/java/org/apache/tapestry5/internal/services/XMLTokenType.java?rev=889446&view=auto
==============================================================================
--- tapestry/tapestry5/trunk/tapestry-core/src/main/java/org/apache/tapestry5/internal/services/XMLTokenType.java (added)
+++ tapestry/tapestry5/trunk/tapestry-core/src/main/java/org/apache/tapestry5/internal/services/XMLTokenType.java Thu Dec 10 22:38:39 2009
@@ -0,0 +1,25 @@
+// 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;
+
+/**
+ * Identifies type of {@link XMLToken}.
+ *
+ * @since 5.2.0
+ */
+enum XMLTokenType
+{
+ DTD, START_ELEMENT, END_ELEMENT, END_DOCUMENT, COMMENT, SPACE, CHARACTERS, CDATA, ENTITY_REFERENCE, ATTRIBUTE, NAMESPACE, NOTATION_DECLARATION, ENTITY_DECLARATION
+}
Propchange: tapestry/tapestry5/trunk/tapestry-core/src/main/java/org/apache/tapestry5/internal/services/XMLTokenType.java
------------------------------------------------------------------------------
svn:eol-style = native
Modified: tapestry/tapestry5/trunk/tapestry-core/src/main/resources/org/apache/tapestry5/internal/services/ServicesStrings.properties
URL: http://svn.apache.org/viewvc/tapestry/tapestry5/trunk/tapestry-core/src/main/resources/org/apache/tapestry5/internal/services/ServicesStrings.properties?rev=889446&r1=889445&r2=889446&view=diff
==============================================================================
--- tapestry/tapestry5/trunk/tapestry-core/src/main/resources/org/apache/tapestry5/internal/services/ServicesStrings.properties (original)
+++ tapestry/tapestry5/trunk/tapestry-core/src/main/resources/org/apache/tapestry5/internal/services/ServicesStrings.properties Thu Dec 10 22:38:39 2009
@@ -21,9 +21,7 @@
field-already-claimed=Field %s of class %s is already claimed by %s and can not be claimed by %s.
no-declared-method=Class %s does not declare method '%s'.
class-not-transformed=Class %s was not transformed for use as a component; this can happen if it is an interface, or was not in a package subject to component transformation.
-new-parser-error=Failure obtaining a SAX parser for resource %s: %s
missing-template-resource=Template resource %s does not exist.
-template-parse-error=Failure parsing template %s: %s
content-inside-body-not-allowed=Content inside a Tapestry body element is not allowed (at %s). The content has been ignored.
method-compile-error=Error compiling method %s (%s): %s
render-queue-error=Render queue error in %s: %s