You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@tapestry.apache.org by hl...@apache.org on 2007/12/30 03:55:02 UTC

svn commit: r607501 [1/2] - in /tapestry/tapestry5/trunk: tapestry-core/src/main/java/org/apache/tapestry/ tapestry-core/src/main/java/org/apache/tapestry/annotations/ tapestry-core/src/main/java/org/apache/tapestry/corelib/mixins/ tapestry-core/src/ma...

Author: hlship
Date: Sat Dec 29 18:54:55 2007
New Revision: 607501

URL: http://svn.apache.org/viewvc?rev=607501&view=rev
Log:
TAPESTRY-1600: Cannot render XML from page templates: XML declaration and namespaces are removed

Added:
    tapestry/tapestry5/trunk/tapestry-core/src/main/java/org/apache/tapestry/dom/CData.java
    tapestry/tapestry5/trunk/tapestry-core/src/main/java/org/apache/tapestry/dom/DomMessages.java
    tapestry/tapestry5/trunk/tapestry-core/src/main/java/org/apache/tapestry/dom/XMLMarkupModel.java
      - copied, changed from r594319, tapestry/tapestry5/trunk/tapestry-core/src/test/java/org/apache/tapestry/dom/XMLMarkupModel.java
    tapestry/tapestry5/trunk/tapestry-core/src/main/java/org/apache/tapestry/internal/parser/DefineNamespacePrefixToken.java
    tapestry/tapestry5/trunk/tapestry-core/src/main/resources/org/apache/tapestry/dom/
    tapestry/tapestry5/trunk/tapestry-core/src/main/resources/org/apache/tapestry/dom/DomStrings.properties
    tapestry/tapestry5/trunk/tapestry-core/src/test/app1/XMLContent.tml
    tapestry/tapestry5/trunk/tapestry-core/src/test/java/org/apache/tapestry/integration/app1/pages/XMLContent.java
    tapestry/tapestry5/trunk/tapestry-core/src/test/resources/org/apache/tapestry/dom/namespaced_elements.txt
    tapestry/tapestry5/trunk/tapestry-core/src/test/resources/org/apache/tapestry/internal/services/namespaced_element.tml
Removed:
    tapestry/tapestry5/trunk/tapestry-core/src/test/java/org/apache/tapestry/dom/XMLMarkupModel.java
Modified:
    tapestry/tapestry5/trunk/tapestry-core/src/main/java/org/apache/tapestry/MarkupWriter.java
    tapestry/tapestry5/trunk/tapestry-core/src/main/java/org/apache/tapestry/annotations/ApplicationState.java
    tapestry/tapestry5/trunk/tapestry-core/src/main/java/org/apache/tapestry/corelib/mixins/Autocomplete.java
    tapestry/tapestry5/trunk/tapestry-core/src/main/java/org/apache/tapestry/corelib/pages/ExceptionReport.java
    tapestry/tapestry5/trunk/tapestry-core/src/main/java/org/apache/tapestry/corelib/pages/ServiceStatus.java
    tapestry/tapestry5/trunk/tapestry-core/src/main/java/org/apache/tapestry/dom/DTD.java
    tapestry/tapestry5/trunk/tapestry-core/src/main/java/org/apache/tapestry/dom/DefaultMarkupModel.java
    tapestry/tapestry5/trunk/tapestry-core/src/main/java/org/apache/tapestry/dom/Document.java
    tapestry/tapestry5/trunk/tapestry-core/src/main/java/org/apache/tapestry/dom/Element.java
    tapestry/tapestry5/trunk/tapestry-core/src/main/java/org/apache/tapestry/dom/MarkupModel.java
    tapestry/tapestry5/trunk/tapestry-core/src/main/java/org/apache/tapestry/internal/parser/AttributeToken.java
    tapestry/tapestry5/trunk/tapestry-core/src/main/java/org/apache/tapestry/internal/parser/CDATAToken.java
    tapestry/tapestry5/trunk/tapestry-core/src/main/java/org/apache/tapestry/internal/parser/StartElementToken.java
    tapestry/tapestry5/trunk/tapestry-core/src/main/java/org/apache/tapestry/internal/parser/TokenType.java
    tapestry/tapestry5/trunk/tapestry-core/src/main/java/org/apache/tapestry/internal/services/AjaxPartialResponseRendererImpl.java
    tapestry/tapestry5/trunk/tapestry-core/src/main/java/org/apache/tapestry/internal/services/MarkupWriterFactoryImpl.java
    tapestry/tapestry5/trunk/tapestry-core/src/main/java/org/apache/tapestry/internal/services/MarkupWriterImpl.java
    tapestry/tapestry5/trunk/tapestry-core/src/main/java/org/apache/tapestry/internal/services/PageElementFactoryImpl.java
    tapestry/tapestry5/trunk/tapestry-core/src/main/java/org/apache/tapestry/internal/services/PageLoaderProcessor.java
    tapestry/tapestry5/trunk/tapestry-core/src/main/java/org/apache/tapestry/internal/services/PageResponseRendererImpl.java
    tapestry/tapestry5/trunk/tapestry-core/src/main/java/org/apache/tapestry/internal/services/TemplateParserImpl.java
    tapestry/tapestry5/trunk/tapestry-core/src/main/java/org/apache/tapestry/internal/structure/Page.java
    tapestry/tapestry5/trunk/tapestry-core/src/main/java/org/apache/tapestry/internal/structure/StartElementPageElement.java
    tapestry/tapestry5/trunk/tapestry-core/src/main/java/org/apache/tapestry/internal/test/InternalBaseTestCase.java
    tapestry/tapestry5/trunk/tapestry-core/src/main/java/org/apache/tapestry/internal/test/TestableMarkupWriterFactoryImpl.java
    tapestry/tapestry5/trunk/tapestry-core/src/main/java/org/apache/tapestry/services/MarkupWriterFactory.java
    tapestry/tapestry5/trunk/tapestry-core/src/test/app1/Start.tml
    tapestry/tapestry5/trunk/tapestry-core/src/test/java/org/apache/tapestry/dom/DOMTest.java
    tapestry/tapestry5/trunk/tapestry-core/src/test/java/org/apache/tapestry/integration/IntegrationTests.java
    tapestry/tapestry5/trunk/tapestry-core/src/test/java/org/apache/tapestry/internal/DefaultValidationDecoratorTest.java
    tapestry/tapestry5/trunk/tapestry-core/src/test/java/org/apache/tapestry/internal/services/DocumentHeadBuilderImplTest.java
    tapestry/tapestry5/trunk/tapestry-core/src/test/java/org/apache/tapestry/internal/services/MarkupWriterImplTest.java
    tapestry/tapestry5/trunk/tapestry-core/src/test/java/org/apache/tapestry/internal/services/PageElementFactoryImplTest.java
    tapestry/tapestry5/trunk/tapestry-core/src/test/java/org/apache/tapestry/internal/services/TemplateParserImplTest.java
    tapestry/tapestry5/trunk/tapestry-core/src/test/resources/org/apache/tapestry/corelib/components/disabled_option.html
    tapestry/tapestry5/trunk/tapestry-core/src/test/resources/org/apache/tapestry/corelib/components/just_options.html
    tapestry/tapestry5/trunk/tapestry-core/src/test/resources/org/apache/tapestry/corelib/components/option_attributes.html
    tapestry/tapestry5/trunk/tapestry-core/src/test/resources/org/apache/tapestry/corelib/components/option_group_attributes.html
    tapestry/tapestry5/trunk/tapestry-core/src/test/resources/org/apache/tapestry/corelib/components/option_groups.html
    tapestry/tapestry5/trunk/tapestry-core/src/test/resources/org/apache/tapestry/corelib/components/option_groups_precede_ungroup_options.html
    tapestry/tapestry5/trunk/tapestry-core/src/test/resources/org/apache/tapestry/dom/nested_elements.txt
    tapestry/tapestry5/trunk/tapestry-core/src/test/resources/org/apache/tapestry/internal/services/add_script_links.txt
    tapestry/tapestry5/trunk/tapestry-core/src/test/resources/org/apache/tapestry/internal/services/add_style_links.txt
    tapestry/tapestry5/trunk/tapestry-core/src/test/resources/org/apache/tapestry/internal/services/duplicate_scripts_ignored_first_media_wins.txt
    tapestry/tapestry5/trunk/tapestry-core/src/test/resources/org/apache/tapestry/internal/services/existing_head_used_if_present.txt
    tapestry/tapestry5/trunk/tapestry-core/src/test/resources/org/apache/tapestry/internal/services/no_body_element.txt
    tapestry/tapestry5/trunk/tapestry-ioc/src/main/java/org/apache/tapestry/ioc/internal/util/OneShotLock.java
    tapestry/tapestry5/trunk/tapestry-ioc/src/site/apt/pipeline.apt

Modified: tapestry/tapestry5/trunk/tapestry-core/src/main/java/org/apache/tapestry/MarkupWriter.java
URL: http://svn.apache.org/viewvc/tapestry/tapestry5/trunk/tapestry-core/src/main/java/org/apache/tapestry/MarkupWriter.java?rev=607501&r1=607500&r2=607501&view=diff
==============================================================================
--- tapestry/tapestry5/trunk/tapestry-core/src/main/java/org/apache/tapestry/MarkupWriter.java (original)
+++ tapestry/tapestry5/trunk/tapestry-core/src/main/java/org/apache/tapestry/MarkupWriter.java Sat Dec 29 18:54:55 2007
@@ -54,8 +54,6 @@
 
     /**
      * Writes the text as a child of the current element.
-     * <p/>
-     * TODO: Filtering of XML entities.
      */
 
     void write(String text);
@@ -81,6 +79,15 @@
      */
     void comment(String text);
 
+
+    /**
+     * Adds parsed character content. This will be enclosed in a CDATA block if supported.  When not supported,
+     * this is the same as {@link #write(String)}.
+     *
+     * @param content pre-parsed content
+     */
+    void cdata(String content);
+
     /**
      * Adds a series of attributes and values. Null values are quietly skipped. If a name already
      * has a value, then the new value is <em>ignored</em>.
@@ -102,4 +109,35 @@
      * Returns the currently active element.
      */
     Element getElement();
+
+    /**
+     * Defines a namespace for the currently active element. The namespace URI will be mapped
+     * to the provided namespace prefix within the Element.
+     *
+     * @param namespace       the namespace URI
+     * @param namespacePrefix the prefix for elements and attributes associated with the namespace    (may
+     *                        be the empty string for the default namespace)
+     * @return the currently active element
+     */
+    Element defineNamespace(String namespace, String namespacePrefix);
+
+    /**
+     * Starts an element within the given namespace. The correct namespace prefix will be identified and used.
+     * Must be balanced by a call to {@link #end()}.
+     *
+     * @param namespace   URI containing the element
+     * @param elementName name of the element within the namespace
+     * @return the new Element
+     */
+    Element elementNS(String namespace, String elementName);
+
+    /**
+     * Creates an attribute within the namespace for the current element.
+     *
+     * @param namespace      URI containing the element
+     * @param attributeName  name of the attribute within the namespace
+     * @param attributeValue the value for the attribute
+     * @return the currently active element
+     */
+    Element attributeNS(String namespace, String attributeName, String attributeValue);
 }

Modified: tapestry/tapestry5/trunk/tapestry-core/src/main/java/org/apache/tapestry/annotations/ApplicationState.java
URL: http://svn.apache.org/viewvc/tapestry/tapestry5/trunk/tapestry-core/src/main/java/org/apache/tapestry/annotations/ApplicationState.java?rev=607501&r1=607500&r2=607501&view=diff
==============================================================================
--- tapestry/tapestry5/trunk/tapestry-core/src/main/java/org/apache/tapestry/annotations/ApplicationState.java (original)
+++ tapestry/tapestry5/trunk/tapestry-core/src/main/java/org/apache/tapestry/annotations/ApplicationState.java Sat Dec 29 18:54:55 2007
@@ -30,7 +30,7 @@
  * If another field exists with the same name, suffixed with "Exists" (i.e., "_aso" for the ASO
  * field, and "_asoExists" for the companion field) and the type of that field is boolean, then access
  * to the field will determine whether the ASO has already been created. This is necessary because
- * even a null check ("_aso != null") will force the ASO to be created. Instead, check te companion
+ * even a null check ("_aso != null") will force the ASO to be created. Instead, check the companion
  * boolean field ("_asoExists").
  */
 @Target(FIELD)

Modified: tapestry/tapestry5/trunk/tapestry-core/src/main/java/org/apache/tapestry/corelib/mixins/Autocomplete.java
URL: http://svn.apache.org/viewvc/tapestry/tapestry5/trunk/tapestry-core/src/main/java/org/apache/tapestry/corelib/mixins/Autocomplete.java?rev=607501&r1=607500&r2=607501&view=diff
==============================================================================
--- tapestry/tapestry5/trunk/tapestry-core/src/main/java/org/apache/tapestry/corelib/mixins/Autocomplete.java (original)
+++ tapestry/tapestry5/trunk/tapestry-core/src/main/java/org/apache/tapestry/corelib/mixins/Autocomplete.java Sat Dec 29 18:54:55 2007
@@ -193,7 +193,7 @@
 
         _resources.triggerEvent("providecompletions", new Object[]{input}, handler);
 
-        MarkupWriter writer = _factory.newMarkupWriter();
+        MarkupWriter writer = _factory.newMarkupWriter(null);
 
         // T4.1 has more flexibility, it can decorate the options with icons, etc.
         // But this will do for now.  The Autocompleter widget will display

Modified: tapestry/tapestry5/trunk/tapestry-core/src/main/java/org/apache/tapestry/corelib/pages/ExceptionReport.java
URL: http://svn.apache.org/viewvc/tapestry/tapestry5/trunk/tapestry-core/src/main/java/org/apache/tapestry/corelib/pages/ExceptionReport.java?rev=607501&r1=607500&r2=607501&view=diff
==============================================================================
--- tapestry/tapestry5/trunk/tapestry-core/src/main/java/org/apache/tapestry/corelib/pages/ExceptionReport.java (original)
+++ tapestry/tapestry5/trunk/tapestry-core/src/main/java/org/apache/tapestry/corelib/pages/ExceptionReport.java Sat Dec 29 18:54:55 2007
@@ -14,6 +14,7 @@
 
 package org.apache.tapestry.corelib.pages;
 
+import org.apache.tapestry.annotations.Meta;
 import org.apache.tapestry.ioc.annotations.Inject;
 import org.apache.tapestry.ioc.services.ExceptionAnalysis;
 import org.apache.tapestry.ioc.services.ExceptionAnalyzer;
@@ -28,6 +29,7 @@
  * Responsible for reporting runtime exceptions. This page is quite verbose and is usually
  * overridden in a production application.
  */
+@Meta("tapestry.response-content-type=text/html")
 public class ExceptionReport implements ExceptionReporter
 {
     private List<ExceptionInfo> _stack;

Modified: tapestry/tapestry5/trunk/tapestry-core/src/main/java/org/apache/tapestry/corelib/pages/ServiceStatus.java
URL: http://svn.apache.org/viewvc/tapestry/tapestry5/trunk/tapestry-core/src/main/java/org/apache/tapestry/corelib/pages/ServiceStatus.java?rev=607501&r1=607500&r2=607501&view=diff
==============================================================================
--- tapestry/tapestry5/trunk/tapestry-core/src/main/java/org/apache/tapestry/corelib/pages/ServiceStatus.java (original)
+++ tapestry/tapestry5/trunk/tapestry-core/src/main/java/org/apache/tapestry/corelib/pages/ServiceStatus.java Sat Dec 29 18:54:55 2007
@@ -15,6 +15,7 @@
 package org.apache.tapestry.corelib.pages;
 
 import org.apache.tapestry.ComponentResources;
+import org.apache.tapestry.annotations.Meta;
 import org.apache.tapestry.beaneditor.BeanModel;
 import org.apache.tapestry.ioc.Registry;
 import org.apache.tapestry.ioc.annotations.Inject;
@@ -31,6 +32,7 @@
  * <p/>
  * TODO: Disable this page if in production mode (or not, as it does no harm).
  */
+@Meta("tapestry.response-content-type=text/html")
 public class ServiceStatus
 {
     @Inject

Added: tapestry/tapestry5/trunk/tapestry-core/src/main/java/org/apache/tapestry/dom/CData.java
URL: http://svn.apache.org/viewvc/tapestry/tapestry5/trunk/tapestry-core/src/main/java/org/apache/tapestry/dom/CData.java?rev=607501&view=auto
==============================================================================
--- tapestry/tapestry5/trunk/tapestry-core/src/main/java/org/apache/tapestry/dom/CData.java (added)
+++ tapestry/tapestry5/trunk/tapestry-core/src/main/java/org/apache/tapestry/dom/CData.java Sat Dec 29 18:54:55 2007
@@ -0,0 +1,59 @@
+// Copyright 2007 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.tapestry.dom;
+
+import java.io.PrintWriter;
+
+/**
+ * A node that stores parsed character content (CDATA).  For XML documents (as per {@link MarkupModel#isXML()},
+ * this will be writtens as a CDATA section.
+ * For non-XML documents, the content is filtered as it is written out.
+ */
+public class CData extends Node
+{
+    private final String _content;
+    private final Document _document;
+
+    public CData(Node container, Document document, String content)
+    {
+        super(container);
+
+        _document = document;
+        _content = content;
+    }
+
+
+    public void toMarkup(PrintWriter writer)
+    {
+        MarkupModel model = _document.getMarkupModel();
+
+        if (model.isXML())
+        {
+            writer.print("<![CDATA[");
+            writer.print(_content);
+            writer.print("]]>");
+            return;
+        }
+
+        // CDATA not supported, so write it normally, with entities escaped.  Create a working
+        // buffer that's plenty big even if a lot of characters need escaping.
+
+        StringBuilder builder = new StringBuilder(2 * _content.length());
+
+        model.encode(_content, builder);
+
+        writer.print(builder.toString());
+    }
+}

Modified: tapestry/tapestry5/trunk/tapestry-core/src/main/java/org/apache/tapestry/dom/DTD.java
URL: http://svn.apache.org/viewvc/tapestry/tapestry5/trunk/tapestry-core/src/main/java/org/apache/tapestry/dom/DTD.java?rev=607501&r1=607500&r2=607501&view=diff
==============================================================================
--- tapestry/tapestry5/trunk/tapestry-core/src/main/java/org/apache/tapestry/dom/DTD.java (original)
+++ tapestry/tapestry5/trunk/tapestry-core/src/main/java/org/apache/tapestry/dom/DTD.java Sat Dec 29 18:54:55 2007
@@ -35,21 +35,6 @@
         _systemId = systemId;
     }
 
-    public String getName()
-    {
-        return _name;
-    }
-
-    public String getPublicId()
-    {
-        return _publicId;
-    }
-
-    public String getSystemId()
-    {
-        return _systemId;
-    }
-
     public void toMarkup(PrintWriter writer)
     {
         if (_publicId != null)

Modified: tapestry/tapestry5/trunk/tapestry-core/src/main/java/org/apache/tapestry/dom/DefaultMarkupModel.java
URL: http://svn.apache.org/viewvc/tapestry/tapestry5/trunk/tapestry-core/src/main/java/org/apache/tapestry/dom/DefaultMarkupModel.java?rev=607501&r1=607500&r2=607501&view=diff
==============================================================================
--- tapestry/tapestry5/trunk/tapestry-core/src/main/java/org/apache/tapestry/dom/DefaultMarkupModel.java (original)
+++ tapestry/tapestry5/trunk/tapestry-core/src/main/java/org/apache/tapestry/dom/DefaultMarkupModel.java Sat Dec 29 18:54:55 2007
@@ -25,18 +25,8 @@
  */
 public class DefaultMarkupModel implements MarkupModel
 {
-    private final Set<String> EMPTY_ELEMENTS = newSet(
-            "base",
-            "br",
-            "col",
-            "frame",
-            "hr",
-            "img",
-            "input",
-            "link",
-            "meta",
-            "option",
-            "param");
+    private final Set<String> EMPTY_ELEMENTS = newSet("base", "br", "col", "frame", "hr", "img", "input", "link",
+                                                      "meta", "option", "param");
 
     /**
      * Passes all characters but '&lt;', '&gt;' and '&amp;' through unchanged.
@@ -91,4 +81,11 @@
         return isEmpty ? EndTagStyle.OMIT : EndTagStyle.REQUIRE;
     }
 
+    /**
+     * Returns false.
+     */
+    public boolean isXML()
+    {
+        return false;
+    }
 }

Modified: tapestry/tapestry5/trunk/tapestry-core/src/main/java/org/apache/tapestry/dom/Document.java
URL: http://svn.apache.org/viewvc/tapestry/tapestry5/trunk/tapestry-core/src/main/java/org/apache/tapestry/dom/Document.java?rev=607501&r1=607500&r2=607501&view=diff
==============================================================================
--- tapestry/tapestry5/trunk/tapestry-core/src/main/java/org/apache/tapestry/dom/Document.java (original)
+++ tapestry/tapestry5/trunk/tapestry-core/src/main/java/org/apache/tapestry/dom/Document.java Sat Dec 29 18:54:55 2007
@@ -29,10 +29,19 @@
 
     private final MarkupModel _model;
 
+    private final String _encoding;
+
     public Document(MarkupModel model)
     {
+        this(model, null);
+    }
+
+    public Document(MarkupModel model, String encoding)
+    {
         super(null);
+
         _model = model;
+        _encoding = encoding;
     }
 
     Document getDocument()
@@ -80,7 +89,21 @@
      */
     public Element newRootElement(String name)
     {
-        _rootElement = new Element(this, name);
+        _rootElement = new Element(this, null, name);
+
+        return _rootElement;
+    }
+
+    /**
+     * Creates a new root element within a namespace.
+     *
+     * @param namespace URI of namespace containing the element
+     * @param name      name of element with namespace
+     * @return the root element
+     */
+    public Element newRootElement(String namespace, String name)
+    {
+        _rootElement = new Element(this, namespace, name);
 
         return _rootElement;
     }
@@ -88,8 +111,17 @@
     @Override
     public void toMarkup(PrintWriter writer)
     {
-        if (_rootElement == null)
-            throw new IllegalStateException("No root element has been defined.");
+        if (_rootElement == null) throw new IllegalStateException(DomMessages.noRootElement());
+
+
+        if (_model.isXML())
+        {
+            writer.print("<?xml version=\"1.0\"");
+
+            if (_encoding != null) writer.printf(" encoding=\"%s\"", _encoding);
+
+            writer.print("?>\n");
+        }
 
         // TODO: lead-in comments, directives.
         if (_dtd != null)
@@ -128,5 +160,4 @@
     {
         _dtd = new DTD(name, publicId, systemId);
     }
-
 }

Added: tapestry/tapestry5/trunk/tapestry-core/src/main/java/org/apache/tapestry/dom/DomMessages.java
URL: http://svn.apache.org/viewvc/tapestry/tapestry5/trunk/tapestry-core/src/main/java/org/apache/tapestry/dom/DomMessages.java?rev=607501&view=auto
==============================================================================
--- tapestry/tapestry5/trunk/tapestry-core/src/main/java/org/apache/tapestry/dom/DomMessages.java (added)
+++ tapestry/tapestry5/trunk/tapestry-core/src/main/java/org/apache/tapestry/dom/DomMessages.java Sat Dec 29 18:54:55 2007
@@ -0,0 +1,34 @@
+// Copyright 2007 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.tapestry.dom;
+
+import org.apache.tapestry.ioc.Messages;
+import org.apache.tapestry.ioc.internal.util.MessagesImpl;
+
+final class DomMessages
+{
+    private static final Messages MESSAGES = MessagesImpl.forClass(DomMessages.class);
+
+
+    static String noRootElement()
+    {
+        return MESSAGES.get("no-root-element");
+    }
+
+    static String namespaceURINotMappedToPrefix(String namespace)
+    {
+        return MESSAGES.format("namespace-uri-not-mapped-to-prefix", namespace);
+    }
+}

Modified: tapestry/tapestry5/trunk/tapestry-core/src/main/java/org/apache/tapestry/dom/Element.java
URL: http://svn.apache.org/viewvc/tapestry/tapestry5/trunk/tapestry-core/src/main/java/org/apache/tapestry/dom/Element.java?rev=607501&r1=607500&r2=607501&view=diff
==============================================================================
--- tapestry/tapestry5/trunk/tapestry-core/src/main/java/org/apache/tapestry/dom/Element.java (original)
+++ tapestry/tapestry5/trunk/tapestry-core/src/main/java/org/apache/tapestry/dom/Element.java Sat Dec 29 18:54:55 2007
@@ -14,13 +14,17 @@
 
 package org.apache.tapestry.dom;
 
-import static org.apache.tapestry.ioc.internal.util.CollectionFactory.*;
+import org.apache.tapestry.ioc.internal.util.CollectionFactory;
+import static org.apache.tapestry.ioc.internal.util.CollectionFactory.newLinkedList;
+import static org.apache.tapestry.ioc.internal.util.CollectionFactory.newMap;
 import org.apache.tapestry.ioc.internal.util.Defense;
 import static org.apache.tapestry.ioc.internal.util.Defense.notBlank;
 import org.apache.tapestry.ioc.internal.util.InternalUtils;
 
 import java.io.PrintWriter;
-import java.util.*;
+import java.util.LinkedList;
+import java.util.List;
+import java.util.Map;
 
 /**
  * An element that will render with a begin tag and attributes, a body, and an end tag. Also acts as
@@ -30,9 +34,37 @@
  */
 public final class Element extends Node
 {
+    class Attribute
+    {
+        private final String _namespace;
+        private final String _name;
+        private final String _value;
+
+        public Attribute(String namespace, String name, String value)
+        {
+            _namespace = namespace;
+            _name = name;
+            _value = value;
+        }
+
+        public String getValue()
+        {
+            return _value;
+        }
+
+        void render(MarkupModel model, StringBuilder builder)
+        {
+            builder.append(" ");
+            builder.append(toPrefixedName(_namespace, _name));
+            builder.append("=\"");
+            model.encodeQuoted(_value, builder);
+            builder.append('"');
+        }
+    }
+
     private final String _name;
 
-    private Map<String, String> _attributes;
+    private Map<String, Attribute> _attributes;
 
     private Element _parent;
 
@@ -40,19 +72,36 @@
 
     private static final String CLASS_ATTRIBUTE = "class";
 
-    Element(Document container, String name)
+    /**
+     * URI of the namespace which contains the element.  A quirk in XML is that the element may be in a namespace
+     * it defines itself, so resolving the namespace to a prefix must wait until render time (since the Element is
+     * created before the namespaces for it are defined).
+     */
+    private final String _namespace;
+
+    private Map<String, String> _namespaceToPrefix;
+
+    /**
+     * Constructor for a root element.
+     */
+    Element(Document container, String namespace, String name)
     {
         super(container);
 
         _document = container;
+        _namespace = namespace;
         _name = name;
     }
 
-    Element(Element parent, String name)
+    /**
+     * Constructor for a nested element.
+     */
+    Element(Element parent, String namespace, String name)
     {
         super(parent);
 
         _parent = parent;
+        _namespace = namespace;
         _name = name;
 
         _document = parent.getDocument();
@@ -81,15 +130,29 @@
      */
     public void attribute(String name, String value)
     {
+        attribute(null, name, value);
+    }
+
+    /**
+     * Adds a namespaced attribute to the element, but only if the attribute name does not already exist.
+     *
+     * @param namespace the namespace to contain the attribute, or null
+     * @param name      the name of the attribute to add
+     * @param value     the value for the attribute. A value of null is allowed, and no attribute will be
+     *                  added to the element.
+     */
+    public void attribute(String namespace, String name, String value)
+    {
         notBlank(name, "name");
 
         if (value == null) return;
 
         if (_attributes == null) _attributes = newMap();
 
-        if (!_attributes.containsKey(name)) _attributes.put(name, value);
+        if (!_attributes.containsKey(name)) _attributes.put(name, new Attribute(namespace, name, value));
     }
 
+
     /**
      * Convenience for invoking {@link #attribute(String, String)} multiple times.
      *
@@ -128,7 +191,7 @@
                 continue;
             }
 
-            _attributes.put(name, value);
+            _attributes.put(name, new Attribute(null, name, value));
         }
     }
 
@@ -142,18 +205,32 @@
     {
         notBlank(name, "name");
 
-        Element child = newChild(new Element(this, name));
+        Element child = newChild(new Element(this, null, name));
 
         child.attributes(namesAndValues);
 
         return child;
     }
 
+    /**
+     * Creates and returns a new Element within a namespace as a child of this node.
+     *
+     * @param namespace namespace to contain the element, or null
+     * @param name      element name to create within the namespace
+     * @return the newly created element
+     */
+    public Element elementNS(String namespace, String name)
+    {
+        notBlank(name, "name");
+
+        return newChild(new Element(this, namespace, name));
+    }
+
     public Element elementAt(int index, String name, String... namesAndValues)
     {
         notBlank(name, "name");
 
-        Element child = new Element(this, name);
+        Element child = new Element(this, null, name);
         child.attributes(namesAndValues);
 
         insertChildAt(index, child);
@@ -193,6 +270,18 @@
         return newChild(new Text(this, _document, text));
     }
 
+    /**
+     * Adds an returns a new CDATA node.
+     *
+     * @param content the content to be rendered by the node
+     * @return the newly created node
+     */
+    public CData cdata(String content)
+    {
+        return newChild(new CData(this, _document, content));
+    }
+
+
     private <T extends Node> T newChild(T child)
     {
         addChild(child);
@@ -203,28 +292,48 @@
     @Override
     public void toMarkup(PrintWriter writer)
     {
-        StringBuilder buffer = new StringBuilder();
+        StringBuilder builder = new StringBuilder();
 
-        Formatter formatter = new Formatter(buffer);
+        String prefixedElementName = toPrefixedName(_namespace, _name);
 
-        formatter.format("<%s", _name);
+        builder.append("<").append(prefixedElementName);
 
         MarkupModel markupModel = _document.getMarkupModel();
 
         if (_attributes != null)
         {
-            List<String> keys = newList(_attributes.keySet());
-            Collections.sort(keys);
+            List<String> keys = InternalUtils.sortedKeys(_attributes);
 
             for (String key : keys)
             {
-                String value = _attributes.get(key);
+                Attribute attribute = _attributes.get(key);
+
+                attribute.render(markupModel, builder);
+            }
+        }
+
+        // Next, emit namespace declarations for each namespace.
+
+        if (_namespaceToPrefix != null)
+        {
+            List<String> namespaces = InternalUtils.sortedKeys(_namespaceToPrefix);
+
+            for (String namespace : namespaces)
+            {
+                String prefix = _namespaceToPrefix.get(namespace);
+
+                builder.append(" xmlns");
 
-                formatter.format(" %s=\"", key);
+                if (!prefix.equals(""))
+                {
+                    builder.append(":").append(prefix);
+                }
 
-                markupModel.encodeQuoted(value, buffer);
+                builder.append("=\"");
 
-                buffer.append('"');
+                markupModel.encodeQuoted(namespace, builder);
+
+                builder.append('"');
             }
         }
 
@@ -234,9 +343,9 @@
 
         String close = (!hasChildren && style == EndTagStyle.ABBREVIATE) ? "/>" : ">";
 
-        formatter.format(close);
+        builder.append(close);
 
-        writer.print(buffer.toString());
+        writer.print(builder.toString());
 
         if (hasChildren) writeChildMarkup(writer);
 
@@ -245,7 +354,20 @@
 
         if (style == EndTagStyle.OMIT) return;
 
-        if (hasChildren || style == EndTagStyle.REQUIRE) writer.printf("</%s>", _name);
+        if (hasChildren || style == EndTagStyle.REQUIRE) writer.printf("</%s>", prefixedElementName);
+    }
+
+    private String toPrefixedName(String namespace, String name)
+    {
+        if (namespace == null || namespace.equals("")) return name;
+
+        String prefix = toNamespacePrefix(namespace);
+
+        // The empty string indicates the default namespace which doesn't use a prefix.
+
+        if (prefix.equals("")) return name;
+
+        return prefix + ":" + name;
     }
 
     /**
@@ -323,7 +445,9 @@
 
     public String getAttribute(String attributeName)
     {
-        return InternalUtils.get(_attributes, attributeName);
+        Attribute attribute = InternalUtils.get(_attributes, attributeName);
+
+        return attribute == null ? null : attribute.getValue();
     }
 
     public String getName()
@@ -367,4 +491,38 @@
 
         return this;
     }
+
+    String toNamespacePrefix(String namespaceURI)
+    {
+        String prefix = InternalUtils.get(_namespaceToPrefix, namespaceURI);
+
+        if (prefix != null) return prefix;
+
+        if (_parent == null) throw new RuntimeException(DomMessages.namespaceURINotMappedToPrefix(namespaceURI));
+
+        return _parent.toNamespacePrefix(namespaceURI);
+    }
+
+    /**
+     * Defines a namespace for this element, mapping a URI to a prefix.   This will affect
+     * how namespaced elements and attributes nested within the element are rendered, and will
+     * also cause <code>xmlns:</code> attributes (to define the namespace and prefix) to
+     * be rendered.
+     *
+     * @param namespace       URI of the namespace
+     * @param namespacePrefix prefix
+     * @return this element
+     */
+    public Element defineNamespace(String namespace, String namespacePrefix)
+    {
+        Defense.notNull(namespace, "namespace");
+        Defense.notNull(namespacePrefix, "namespacePrefix");
+
+        if (_namespaceToPrefix == null) _namespaceToPrefix = CollectionFactory.newMap();
+
+        _namespaceToPrefix.put(namespace, namespacePrefix);
+
+        return this;
+    }
+
 }

Modified: tapestry/tapestry5/trunk/tapestry-core/src/main/java/org/apache/tapestry/dom/MarkupModel.java
URL: http://svn.apache.org/viewvc/tapestry/tapestry5/trunk/tapestry-core/src/main/java/org/apache/tapestry/dom/MarkupModel.java?rev=607501&r1=607500&r2=607501&view=diff
==============================================================================
--- tapestry/tapestry5/trunk/tapestry-core/src/main/java/org/apache/tapestry/dom/MarkupModel.java (original)
+++ tapestry/tapestry5/trunk/tapestry-core/src/main/java/org/apache/tapestry/dom/MarkupModel.java Sat Dec 29 18:54:55 2007
@@ -16,7 +16,10 @@
 
 /**
  * Used by a the DOM to determine how to produce markup. Delegates details about converted entities
- * and some formatting details.
+ * and some formatting details.  This exists to handle the differences between traditional HTML
+ * output (which is SGML based, meaning there can be elements that are valid without a close tag) and
+ * "modern" XML, such as XHTML.  Generally speaking, for XHTML it is vital that a !DOCTYPE be included
+ * in the rendered response, or the browser will be unable to display the result properly.
  */
 public interface MarkupModel
 {
@@ -43,4 +46,13 @@
      * For a given element, determines how the end tag for the element should be rendered.
      */
     EndTagStyle getEndTagStyle(String element);
+
+    /**
+     * Returns true if the document markup is XML, which is used to determine
+     * the need for an XML declaration at the start of the document,
+     * and whether CDATA sections are supported.
+     *
+     * @return true for XML output, false for HTML (SGML) output
+     */
+    boolean isXML();
 }

Copied: tapestry/tapestry5/trunk/tapestry-core/src/main/java/org/apache/tapestry/dom/XMLMarkupModel.java (from r594319, tapestry/tapestry5/trunk/tapestry-core/src/test/java/org/apache/tapestry/dom/XMLMarkupModel.java)
URL: http://svn.apache.org/viewvc/tapestry/tapestry5/trunk/tapestry-core/src/main/java/org/apache/tapestry/dom/XMLMarkupModel.java?p2=tapestry/tapestry5/trunk/tapestry-core/src/main/java/org/apache/tapestry/dom/XMLMarkupModel.java&p1=tapestry/tapestry5/trunk/tapestry-core/src/test/java/org/apache/tapestry/dom/XMLMarkupModel.java&r1=594319&r2=607501&rev=607501&view=diff
==============================================================================
--- tapestry/tapestry5/trunk/tapestry-core/src/test/java/org/apache/tapestry/dom/XMLMarkupModel.java (original)
+++ tapestry/tapestry5/trunk/tapestry-core/src/main/java/org/apache/tapestry/dom/XMLMarkupModel.java Sat Dec 29 18:54:55 2007
@@ -15,7 +15,7 @@
 package org.apache.tapestry.dom;
 
 /**
- * Used for some testing where we want a model with XML style semantics.
+ * Markup model used when generating any form of XML markup.
  */
 public final class XMLMarkupModel extends DefaultMarkupModel
 {
@@ -27,5 +27,14 @@
     public EndTagStyle getEndTagStyle(String element)
     {
         return EndTagStyle.ABBREVIATE;
+    }
+
+    /**
+     * Returns true.
+     */
+    @Override
+    public boolean isXML()
+    {
+        return true;
     }
 }

Modified: tapestry/tapestry5/trunk/tapestry-core/src/main/java/org/apache/tapestry/internal/parser/AttributeToken.java
URL: http://svn.apache.org/viewvc/tapestry/tapestry5/trunk/tapestry-core/src/main/java/org/apache/tapestry/internal/parser/AttributeToken.java?rev=607501&r1=607500&r2=607501&view=diff
==============================================================================
--- tapestry/tapestry5/trunk/tapestry-core/src/main/java/org/apache/tapestry/internal/parser/AttributeToken.java (original)
+++ tapestry/tapestry5/trunk/tapestry-core/src/main/java/org/apache/tapestry/internal/parser/AttributeToken.java Sat Dec 29 18:54:55 2007
@@ -21,14 +21,17 @@
  */
 public class AttributeToken extends TemplateToken
 {
+    private final String _namespaceURI;
+
     private final String _name;
 
     private final String _value;
 
-    public AttributeToken(String name, String value, Location location)
+    public AttributeToken(String namespaceURI, String name, String value, Location location)
     {
         super(TokenType.ATTRIBUTE, location);
 
+        _namespaceURI = namespaceURI;
         _name = name;
         _value = value;
     }
@@ -49,9 +52,18 @@
         return _value;
     }
 
+    /**
+     * Returns the namespace URI containing the attribute, or the empty string
+     * for the default namespace.
+     */
+    public String getNamespaceURI()
+    {
+        return _namespaceURI;
+    }
+
     @Override
     public String toString()
     {
-        return String.format("Attribute[%s=%s]", _name, _value);
+        return String.format("Attribute[%s %s=%s]", _namespaceURI, _name, _value);
     }
 }

Modified: tapestry/tapestry5/trunk/tapestry-core/src/main/java/org/apache/tapestry/internal/parser/CDATAToken.java
URL: http://svn.apache.org/viewvc/tapestry/tapestry5/trunk/tapestry-core/src/main/java/org/apache/tapestry/internal/parser/CDATAToken.java?rev=607501&r1=607500&r2=607501&view=diff
==============================================================================
--- tapestry/tapestry5/trunk/tapestry-core/src/main/java/org/apache/tapestry/internal/parser/CDATAToken.java (original)
+++ tapestry/tapestry5/trunk/tapestry-core/src/main/java/org/apache/tapestry/internal/parser/CDATAToken.java Sat Dec 29 18:54:55 2007
@@ -22,23 +22,23 @@
  */
 public class CDATAToken extends TemplateToken
 {
-    private final String _text;
+    private final String _content;
 
-    public CDATAToken(String text, Location location)
+    public CDATAToken(String content, Location location)
     {
         super(TokenType.CDATA, location);
 
-        _text = text;
+        _content = content;
     }
 
-    public String getText()
+    public String getContent()
     {
-        return _text;
+        return _content;
     }
 
     @Override
     public String toString()
     {
-        return String.format("CDATA[%s]", _text);
+        return String.format("CDATA[%s]", _content);
     }
 }

Added: tapestry/tapestry5/trunk/tapestry-core/src/main/java/org/apache/tapestry/internal/parser/DefineNamespacePrefixToken.java
URL: http://svn.apache.org/viewvc/tapestry/tapestry5/trunk/tapestry-core/src/main/java/org/apache/tapestry/internal/parser/DefineNamespacePrefixToken.java?rev=607501&view=auto
==============================================================================
--- tapestry/tapestry5/trunk/tapestry-core/src/main/java/org/apache/tapestry/internal/parser/DefineNamespacePrefixToken.java (added)
+++ tapestry/tapestry5/trunk/tapestry-core/src/main/java/org/apache/tapestry/internal/parser/DefineNamespacePrefixToken.java Sat Dec 29 18:54:55 2007
@@ -0,0 +1,56 @@
+// Copyright 2007 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.tapestry.internal.parser;
+
+import org.apache.tapestry.ioc.Location;
+
+/**
+ * A token from a template that defines a namespace prefix. This will always follow
+ * a {@link org.apache.tapestry.internal.parser.StartComponentToken} or
+ * {@link org.apache.tapestry.internal.parser.StartElementToken} (and come before
+ * {@link org.apache.tapestry.internal.parser.AttributeToken}) and applies to the
+ * component or element.
+ *
+ * @see org.apache.tapestry.dom.Element#defineNamespace(String, String)
+ */
+public class DefineNamespacePrefixToken extends TemplateToken
+{
+    private final String _namespaceURI;
+    private final String _namespacePrefix;
+
+    public DefineNamespacePrefixToken(String namespaceURI, String namespacePrefix, Location location)
+    {
+        super(TokenType.DEFINE_NAMESPACE_PREFIX, location);
+
+        _namespacePrefix = namespacePrefix;
+        _namespaceURI = namespaceURI;
+    }
+
+    public String getNamespacePrefix()
+    {
+        return _namespacePrefix;
+    }
+
+    public String getNamespaceURI()
+    {
+        return _namespaceURI;
+    }
+
+    @Override
+    public String toString()
+    {
+        return String.format("DefineNamespacePrefix[%s=%s]", _namespacePrefix, _namespaceURI);
+    }
+}

Modified: tapestry/tapestry5/trunk/tapestry-core/src/main/java/org/apache/tapestry/internal/parser/StartElementToken.java
URL: http://svn.apache.org/viewvc/tapestry/tapestry5/trunk/tapestry-core/src/main/java/org/apache/tapestry/internal/parser/StartElementToken.java?rev=607501&r1=607500&r2=607501&view=diff
==============================================================================
--- tapestry/tapestry5/trunk/tapestry-core/src/main/java/org/apache/tapestry/internal/parser/StartElementToken.java (original)
+++ tapestry/tapestry5/trunk/tapestry-core/src/main/java/org/apache/tapestry/internal/parser/StartElementToken.java Sat Dec 29 18:54:55 2007
@@ -27,12 +27,14 @@
  */
 public class StartElementToken extends TemplateToken
 {
+    private final String _namespaceURI;
     private final String _name;
 
-    public StartElementToken(String name, Location location)
+    public StartElementToken(String namespaceURI, String name, Location location)
     {
         super(TokenType.START_ELEMENT, location);
 
+        _namespaceURI = namespaceURI;
         _name = name;
     }
 
@@ -44,9 +46,17 @@
         return _name;
     }
 
+    /**
+     * @return the namespace URI for the element, or the empty string for the default namespace
+     */
+    public String getNamespaceURI()
+    {
+        return _namespaceURI;
+    }
+
     @Override
     public String toString()
     {
-        return String.format("Start[%s]", _name);
+        return String.format("Start[%s %s]", _namespaceURI, _name);
     }
 }

Modified: tapestry/tapestry5/trunk/tapestry-core/src/main/java/org/apache/tapestry/internal/parser/TokenType.java
URL: http://svn.apache.org/viewvc/tapestry/tapestry5/trunk/tapestry-core/src/main/java/org/apache/tapestry/internal/parser/TokenType.java?rev=607501&r1=607500&r2=607501&view=diff
==============================================================================
--- tapestry/tapestry5/trunk/tapestry-core/src/main/java/org/apache/tapestry/internal/parser/TokenType.java (original)
+++ tapestry/tapestry5/trunk/tapestry-core/src/main/java/org/apache/tapestry/internal/parser/TokenType.java Sat Dec 29 18:54:55 2007
@@ -21,5 +21,6 @@
 public enum TokenType
 {
 
-    ATTRIBUTE, CDATA, COMMENT, END_ELEMENT, START_COMPONENT, START_ELEMENT, TEXT, BODY, EXPANSION, PARAMETER, BLOCK, DTD
+    ATTRIBUTE, CDATA, COMMENT, END_ELEMENT, START_COMPONENT, START_ELEMENT, TEXT, BODY, EXPANSION, PARAMETER, BLOCK, DTD,
+    DEFINE_NAMESPACE_PREFIX
 }

Modified: tapestry/tapestry5/trunk/tapestry-core/src/main/java/org/apache/tapestry/internal/services/AjaxPartialResponseRendererImpl.java
URL: http://svn.apache.org/viewvc/tapestry/tapestry5/trunk/tapestry-core/src/main/java/org/apache/tapestry/internal/services/AjaxPartialResponseRendererImpl.java?rev=607501&r1=607500&r2=607501&view=diff
==============================================================================
--- tapestry/tapestry5/trunk/tapestry-core/src/main/java/org/apache/tapestry/internal/services/AjaxPartialResponseRendererImpl.java (original)
+++ tapestry/tapestry5/trunk/tapestry-core/src/main/java/org/apache/tapestry/internal/services/AjaxPartialResponseRendererImpl.java Sat Dec 29 18:54:55 2007
@@ -64,7 +64,7 @@
 
         ContentType contentType = new ContentType("text/javascript");
 
-        MarkupWriter writer = _factory.newMarkupWriter();
+        MarkupWriter writer = _factory.newMarkupWriter(null);
 
         JSONObject reply = new JSONObject();
 

Modified: tapestry/tapestry5/trunk/tapestry-core/src/main/java/org/apache/tapestry/internal/services/MarkupWriterFactoryImpl.java
URL: http://svn.apache.org/viewvc/tapestry/tapestry5/trunk/tapestry-core/src/main/java/org/apache/tapestry/internal/services/MarkupWriterFactoryImpl.java?rev=607501&r1=607500&r2=607501&view=diff
==============================================================================
--- tapestry/tapestry5/trunk/tapestry-core/src/main/java/org/apache/tapestry/internal/services/MarkupWriterFactoryImpl.java (original)
+++ tapestry/tapestry5/trunk/tapestry-core/src/main/java/org/apache/tapestry/internal/services/MarkupWriterFactoryImpl.java Sat Dec 29 18:54:55 2007
@@ -16,17 +16,27 @@
 
 import org.apache.tapestry.MarkupWriter;
 import org.apache.tapestry.dom.DefaultMarkupModel;
+import org.apache.tapestry.dom.MarkupModel;
+import org.apache.tapestry.dom.XMLMarkupModel;
+import org.apache.tapestry.internal.util.ContentType;
 import org.apache.tapestry.services.MarkupWriterFactory;
 
 public class MarkupWriterFactoryImpl implements MarkupWriterFactory
 {
-    public MarkupWriter newMarkupWriter()
+    private final MarkupModel _htmlModel = new DefaultMarkupModel();
+
+    private final MarkupModel _xmlModel = new XMLMarkupModel();
+
+    public MarkupWriter newMarkupWriter(ContentType contentType)
     {
-        // TODO: Analyze the response type to determine the correct model? Maybe ContentType should
-        // be passed into to make this determination. DefaultMarkupModel is for SGML style (legacy)
-        // HTML.
+        boolean isHTML = contentType.getMimeType().equalsIgnoreCase("text/html");
+
+        MarkupModel model = isHTML ? _htmlModel : _xmlModel;
+
+        // The charset parameter sets the encoding attribute of the XML declaration, if
+        // not null and if using the XML model.
 
-        return new MarkupWriterImpl(new DefaultMarkupModel());
+        return new MarkupWriterImpl(model, contentType.getParameter("charset"));
     }
 
 }

Modified: tapestry/tapestry5/trunk/tapestry-core/src/main/java/org/apache/tapestry/internal/services/MarkupWriterImpl.java
URL: http://svn.apache.org/viewvc/tapestry/tapestry5/trunk/tapestry-core/src/main/java/org/apache/tapestry/internal/services/MarkupWriterImpl.java?rev=607501&r1=607500&r2=607501&view=diff
==============================================================================
--- tapestry/tapestry5/trunk/tapestry-core/src/main/java/org/apache/tapestry/internal/services/MarkupWriterImpl.java (original)
+++ tapestry/tapestry5/trunk/tapestry-core/src/main/java/org/apache/tapestry/internal/services/MarkupWriterImpl.java Sat Dec 29 18:54:55 2007
@@ -35,7 +35,12 @@
 
     public MarkupWriterImpl(MarkupModel model)
     {
-        _document = new Document(model);
+        this(model, null);
+    }
+
+    public MarkupWriterImpl(MarkupModel model, String encoding)
+    {
+        _document = new Document(model, encoding);
     }
 
     public void toMarkup(PrintWriter writer)
@@ -59,6 +64,15 @@
         return _current;
     }
 
+    public void cdata(String content)
+    {
+        ensureCurrentElement();
+
+        _current.cdata(content);
+
+        _currentText = null;
+    }
+
     public void write(String text)
     {
         // Whitespace before and after the root element is quietly ignored.
@@ -151,4 +165,31 @@
         _currentText = null;
     }
 
+    public Element attributeNS(String namespace, String attributeName, String attributeValue)
+    {
+        ensureCurrentElement();
+
+        _current.attribute(namespace, attributeName, attributeValue);
+
+        return _current;
+    }
+
+    public Element defineNamespace(String namespace, String namespacePrefix)
+    {
+        ensureCurrentElement();
+
+        _current.defineNamespace(namespace, namespacePrefix);
+
+        return _current;
+    }
+
+    public Element elementNS(String namespace, String elementName)
+    {
+        if (_current == null) _current = _document.newRootElement(namespace, elementName);
+        else _current = _current.elementNS(namespace, elementName);
+
+        _currentText = null;
+
+        return _current;
+    }
 }

Modified: tapestry/tapestry5/trunk/tapestry-core/src/main/java/org/apache/tapestry/internal/services/PageElementFactoryImpl.java
URL: http://svn.apache.org/viewvc/tapestry/tapestry5/trunk/tapestry-core/src/main/java/org/apache/tapestry/internal/services/PageElementFactoryImpl.java?rev=607501&r1=607500&r2=607501&view=diff
==============================================================================
--- tapestry/tapestry5/trunk/tapestry-core/src/main/java/org/apache/tapestry/internal/services/PageElementFactoryImpl.java (original)
+++ tapestry/tapestry5/trunk/tapestry-core/src/main/java/org/apache/tapestry/internal/services/PageElementFactoryImpl.java Sat Dec 29 18:54:55 2007
@@ -92,7 +92,7 @@
 
     public PageElement newStartElement(StartElementToken token)
     {
-        return new StartElementPageElement(token.getName());
+        return new StartElementPageElement(token.getNamespaceURI(), token.getName());
     }
 
     public PageElement newTextElement(TextToken token)
@@ -105,27 +105,25 @@
         return _endElement;
     }
 
-    public PageElement newAttributeElement(ComponentResources componentResources,
-                                           final AttributeToken token)
+    public PageElement newAttributeElement(ComponentResources componentResources, AttributeToken token)
     {
-        final StringProvider provider = parseAttributeExpansionExpression(
-                token.getValue(),
-                componentResources,
-                token.getLocation());
+        final StringProvider provider = parseAttributeExpansionExpression(token.getValue(), componentResources,
+                                                                          token.getLocation());
 
+        final String namespace = token.getNamespaceURI();
         final String name = token.getName();
 
         return new PageElement()
         {
             public void render(MarkupWriter writer, RenderQueue queue)
             {
-                writer.attributes(name, provider.provideString());
+                writer.attributeNS(namespace, name, provider.provideString());
             }
         };
     }
 
-    private StringProvider parseAttributeExpansionExpression(String expression,
-                                                             ComponentResources resources, final Location location)
+    private StringProvider parseAttributeExpansionExpression(String expression, ComponentResources resources,
+                                                             final Location location)
     {
         final List<StringProvider> providers = newList();
 
@@ -152,19 +150,13 @@
 
             int endx = expression.indexOf("}", expansionx);
 
-            if (endx < 0)
-                throw new TapestryException(ServicesMessages
-                        .unclosedAttributeExpression(expression), location, null);
+            if (endx < 0) throw new TapestryException(ServicesMessages
+                    .unclosedAttributeExpression(expression), location, null);
 
             String expansion = expression.substring(expansionx + 2, endx);
 
-            final Binding binding = _bindingSource.newBinding(
-                    "attribute expansion",
-                    resources,
-                    resources,
-                    PROP_BINDING_PREFIX,
-                    expansion,
-                    location);
+            final Binding binding = _bindingSource.newBinding("attribute expansion", resources, resources,
+                                                              PROP_BINDING_PREFIX, expansion, location);
 
             final StringProvider provider = new StringProvider()
             {
@@ -210,23 +202,16 @@
 
     }
 
-    public PageElement newExpansionElement(ComponentResources componentResources,
-                                           ExpansionToken token)
+    public PageElement newExpansionElement(ComponentResources componentResources, ExpansionToken token)
     {
-        Binding binding = _bindingSource.newBinding(
-                "expansion",
-                componentResources,
-                componentResources,
-                PROP_BINDING_PREFIX,
-                token.getExpression(),
-                token.getLocation());
+        Binding binding = _bindingSource.newBinding("expansion", componentResources, componentResources,
+                                                    PROP_BINDING_PREFIX, token.getExpression(), token.getLocation());
 
         return new ExpansionPageElement(binding, _typeCoercer);
     }
 
-    public ComponentPageElement newComponentElement(Page page, ComponentPageElement container,
-                                                    String id, String componentType, String componentClassName,
-                                                    String elementName,
+    public ComponentPageElement newComponentElement(Page page, ComponentPageElement container, String id,
+                                                    String componentType, String componentClassName, String elementName,
                                                     Location location)
     {
         try
@@ -267,9 +252,9 @@
             // how the component elements are nested within the loading component's
             // template.
 
-            ComponentPageElementImpl result = new ComponentPageElementImpl(page, container, id,
-                                                                           elementName, instantiator, _typeCoercer,
-                                                                           _messagesSource, location);
+            ComponentPageElementImpl result = new ComponentPageElementImpl(page, container, id, elementName,
+                                                                           instantiator, _typeCoercer, _messagesSource,
+                                                                           location);
 
             page.addLifecycleListener(result);
 
@@ -285,8 +270,7 @@
         }
     }
 
-    private void checkForRecursion(String componentClassName, ComponentPageElement container,
-                                   Location location)
+    private void checkForRecursion(String componentClassName, ComponentPageElement container, Location location)
     {
         // Container may be null for a root element;
 
@@ -297,8 +281,7 @@
         while (resources != null)
         {
             if (resources.getComponentModel().getComponentClassName().equals(componentClassName))
-                throw new TapestryException(
-                        ServicesMessages.componentRecursion(componentClassName), location, null);
+                throw new TapestryException(ServicesMessages.componentRecursion(componentClassName), location, null);
 
             resources = resources.getContainerResources();
         }
@@ -308,8 +291,8 @@
     {
         Instantiator instantiator = _componentInstantiatorSource.findInstantiator(componentType);
 
-        ComponentPageElementImpl result = new ComponentPageElementImpl(page, instantiator,
-                                                                       _typeCoercer, _messagesSource);
+        ComponentPageElementImpl result = new ComponentPageElementImpl(page, instantiator, _typeCoercer,
+                                                                       _messagesSource);
 
         addMixins(result, instantiator);
 
@@ -374,20 +357,13 @@
 
         if (expression.contains(EXPANSION_START))
         {
-            StringProvider provider = parseAttributeExpansionExpression(
-                    expression,
-                    loadingComponentResources,
-                    location);
+            StringProvider provider = parseAttributeExpansionExpression(expression, loadingComponentResources,
+                                                                        location);
 
             return new AttributeExpansionBinding(provider, location);
         }
 
-        return _bindingSource.newBinding(
-                "parameter " + parameterName,
-                loadingComponentResources,
-                embeddedComponentResources,
-                defaultBindingPrefix,
-                expression,
-                location);
+        return _bindingSource.newBinding("parameter " + parameterName, loadingComponentResources,
+                                         embeddedComponentResources, defaultBindingPrefix, expression, location);
     }
 }

Modified: tapestry/tapestry5/trunk/tapestry-core/src/main/java/org/apache/tapestry/internal/services/PageLoaderProcessor.java
URL: http://svn.apache.org/viewvc/tapestry/tapestry5/trunk/tapestry-core/src/main/java/org/apache/tapestry/internal/services/PageLoaderProcessor.java?rev=607501&r1=607500&r2=607501&view=diff
==============================================================================
--- tapestry/tapestry5/trunk/tapestry-core/src/main/java/org/apache/tapestry/internal/services/PageLoaderProcessor.java (original)
+++ tapestry/tapestry5/trunk/tapestry-core/src/main/java/org/apache/tapestry/internal/services/PageLoaderProcessor.java Sat Dec 29 18:54:55 2007
@@ -16,6 +16,7 @@
 
 import org.apache.tapestry.Binding;
 import org.apache.tapestry.ComponentResources;
+import org.apache.tapestry.MarkupWriter;
 import org.apache.tapestry.TapestryConstants;
 import org.apache.tapestry.internal.bindings.LiteralBinding;
 import org.apache.tapestry.internal.parser.*;
@@ -30,6 +31,7 @@
 import org.apache.tapestry.ioc.util.Stack;
 import org.apache.tapestry.model.ComponentModel;
 import org.apache.tapestry.model.EmbeddedComponentModel;
+import org.apache.tapestry.runtime.RenderQueue;
 import org.apache.tapestry.services.BindingSource;
 import org.apache.tapestry.services.PersistentFieldManager;
 import org.slf4j.Logger;
@@ -42,6 +44,9 @@
  */
 class PageLoaderProcessor
 {
+    /**
+     * Special prefix for parameters that are inherited from named parameters of their container.
+     */
     private static final String INHERIT_PREFIX = "inherit:";
 
     private static final Runnable NO_OP = new Runnable()
@@ -467,6 +472,14 @@
                     dtd((DTDToken) token);
                     break;
 
+                case DEFINE_NAMESPACE_PREFIX:
+                    defineNamespacePrefix((DefineNamespacePrefixToken) token);
+                    break;
+
+                case CDATA:
+                    cdata((CDATAToken) token);
+                    break;
+
                 default:
                     throw new IllegalStateException("Not implemented yet: " + token);
             }
@@ -478,6 +491,34 @@
 
         // TODO: Check that all stacks are empty. That should never happen, as long
         // as the ComponentTemplate is valid.
+    }
+
+    private void cdata(CDATAToken token)
+    {
+        final String content = token.getContent();
+
+        PageElement element = new PageElement()
+        {
+            public void render(MarkupWriter writer, RenderQueue queue)
+            {
+                writer.cdata(content);
+            }
+        };
+
+        addToBody(element);
+    }
+
+    private void defineNamespacePrefix(final DefineNamespacePrefixToken token)
+    {
+        PageElement element = new PageElement()
+        {
+            public void render(MarkupWriter writer, RenderQueue queue)
+            {
+                writer.defineNamespace(token.getNamespaceURI(), token.getNamespacePrefix());
+            }
+        };
+
+        addToBody(element);
     }
 
     private void parameter(ParameterToken token)

Modified: tapestry/tapestry5/trunk/tapestry-core/src/main/java/org/apache/tapestry/internal/services/PageResponseRendererImpl.java
URL: http://svn.apache.org/viewvc/tapestry/tapestry5/trunk/tapestry-core/src/main/java/org/apache/tapestry/internal/services/PageResponseRendererImpl.java?rev=607501&r1=607500&r2=607501&view=diff
==============================================================================
--- tapestry/tapestry5/trunk/tapestry-core/src/main/java/org/apache/tapestry/internal/services/PageResponseRendererImpl.java (original)
+++ tapestry/tapestry5/trunk/tapestry-core/src/main/java/org/apache/tapestry/internal/services/PageResponseRendererImpl.java Sat Dec 29 18:54:55 2007
@@ -51,7 +51,7 @@
         // Eventually we'll have to do work to figure out the correct markup type, content type,
         // whatever. Right now its defaulting to plain HTML.
 
-        MarkupWriter writer = _markupWriterFactory.newMarkupWriter();
+        MarkupWriter writer = _markupWriterFactory.newMarkupWriter(contentType);
 
         _markupRenderer.renderPageMarkup(page, writer);
 

Modified: tapestry/tapestry5/trunk/tapestry-core/src/main/java/org/apache/tapestry/internal/services/TemplateParserImpl.java
URL: http://svn.apache.org/viewvc/tapestry/tapestry5/trunk/tapestry-core/src/main/java/org/apache/tapestry/internal/services/TemplateParserImpl.java?rev=607501&r1=607500&r2=607501&view=diff
==============================================================================
--- tapestry/tapestry5/trunk/tapestry-core/src/main/java/org/apache/tapestry/internal/services/TemplateParserImpl.java (original)
+++ tapestry/tapestry5/trunk/tapestry-core/src/main/java/org/apache/tapestry/internal/services/TemplateParserImpl.java Sat Dec 29 18:54:55 2007
@@ -65,6 +65,14 @@
 
     private final List<TemplateToken> _tokens = newList();
 
+    /**
+     * Because {@link org.xml.sax.ContentHandler#startPrefixMapping(String, String)} events arrive before the
+     * corresponding {@link org.xml.sax.ContentHandler#startElement(String, String, String, org.xml.sax.Attributes)}
+     * events, we need to accumlate the {@link org.apache.tapestry.internal.parser.DefineNamespacePrefixToken}s
+     * ahead of time to get the correct ordering in the output tokens list.
+     */
+    private final List<DefineNamespacePrefixToken> _defineNamespaceTokens = newList();
+
     // Non-blank ids from start component elements
 
     private final Set<String> _componentIds = newSet();
@@ -110,7 +118,9 @@
     // expansions on the same text line into a single large
     // but invalid expansion.
 
-    private final Pattern EXPANSION_PATTERN = Pattern.compile("\\$\\{\\s*(.*?)\\s*}", Pattern.MULTILINE);
+    private static final String EXPANSION_REGEXP = "\\$\\{\\s*(.*?)\\s*}";
+
+    private static final Pattern EXPANSION_PATTERN = Pattern.compile(EXPANSION_REGEXP, Pattern.MULTILINE);
 
     public TemplateParserImpl(Logger logger, Map<String, URL> configuration)
     {
@@ -123,6 +133,7 @@
     private void reset()
     {
         _tokens.clear();
+        _defineNamespaceTokens.clear();
         _componentIds.clear();
         _templateResource = null;
         _locator = null;
@@ -291,7 +302,7 @@
             return;
         }
 
-        startPossibleComponent(attributes, localName, null);
+        startPossibleComponent(attributes, uri, localName, null);
     }
 
     /**
@@ -349,7 +360,7 @@
         String componentType = localName.replace('.', '/');
 
         // With a component type specified, it's not just possibly a component ...
-        startPossibleComponent(attributes, null, componentType);
+        startPossibleComponent(attributes, null, null, componentType);
     }
 
     private void startContainer()
@@ -411,12 +422,13 @@
 
     /**
      * @param attributes     the attributes for the element
+     * @param namespaceURI   the namespace URI for the element (or the empty string)
      * @param elementName    the name of the element (to be assigned to the new token), may be null for a
      *                       component in the Tapestry namespace
      * @param identifiedType the type of the element, usually null, but may be the component type derived from
-     *                       the element name (for an element in the Tapestry namespace)
      */
-    private void startPossibleComponent(Attributes attributes, String elementName, String identifiedType)
+    private void startPossibleComponent(Attributes attributes, String namespaceURI, String elementName,
+                                        String identifiedType)
     {
         String id = null;
         String type = identifiedType;
@@ -464,7 +476,7 @@
                 // not part of the template's doctype for the element being instrumented.
             }
 
-            attributeTokens.add(new AttributeToken(name, value, location));
+            attributeTokens.add(new AttributeToken(uri, name, value, location));
         }
 
         boolean isComponent = (id != null || type != null);
@@ -480,9 +492,11 @@
         }
         else
         {
-            _tokens.add(new StartElementToken(elementName, location));
+            _tokens.add(new StartElementToken(namespaceURI, elementName, location));
         }
 
+        addDefineNamespaceTokens();
+
         _tokens.addAll(attributeTokens);
 
         if (id != null) _componentIds.add(id);
@@ -537,6 +551,17 @@
                 .getColumnNumber());
     }
 
+    /**
+     * Adds any namespace tokens accumulated from just before the current element. The list of namespace tokens is then
+     * cleared.
+     */
+    private void addDefineNamespaceTokens()
+    {
+        _tokens.addAll(_defineNamespaceTokens);
+
+        _defineNamespaceTokens.clear();
+    }
+
     public void comment(char[] ch, int start, int length) throws SAXException
     {
         if (_ignoreEvents || insideBody()) return;
@@ -619,9 +644,6 @@
     {
     }
 
-    public void endPrefixMapping(String prefix) throws SAXException
-    {
-    }
 
     public void ignorableWhitespace(char[] ch, int start, int length) throws SAXException
     {
@@ -640,6 +662,20 @@
     }
 
     public void startPrefixMapping(String prefix, String uri) throws SAXException
+    {
+        // Not interested in the Tapestry namespace (that is never sent to the client).
+
+        if (uri.equals(TAPESTRY_SCHEMA_5_0_0)) return;
+
+        // The prefix may be blank, which happens when the xmlns attribute is used to define the
+        // namespace for the default namespace, and when a document has an explicit DOCTYPE.
+
+        DefineNamespacePrefixToken token = new DefineNamespacePrefixToken(uri, prefix, getCurrentLocation());
+
+        _defineNamespaceTokens.add(token);
+    }
+
+    public void endPrefixMapping(String prefix) throws SAXException
     {
     }
 

Modified: tapestry/tapestry5/trunk/tapestry-core/src/main/java/org/apache/tapestry/internal/structure/Page.java
URL: http://svn.apache.org/viewvc/tapestry/tapestry5/trunk/tapestry-core/src/main/java/org/apache/tapestry/internal/structure/Page.java?rev=607501&r1=607500&r2=607501&view=diff
==============================================================================
--- tapestry/tapestry5/trunk/tapestry-core/src/main/java/org/apache/tapestry/internal/structure/Page.java (original)
+++ tapestry/tapestry5/trunk/tapestry-core/src/main/java/org/apache/tapestry/internal/structure/Page.java Sat Dec 29 18:54:55 2007
@@ -108,6 +108,7 @@
 
     /**
      * Retrieves a component element by its nested id (a sequence of simple ids, separated by dots).
+     * The individual names in the nested id are matched without regards to case.
      * A nested id of '' (the empty string) returns the root element of the page.
      *
      * @throws IllegalArgumentException if the nestedId does not correspond to a component

Modified: tapestry/tapestry5/trunk/tapestry-core/src/main/java/org/apache/tapestry/internal/structure/StartElementPageElement.java
URL: http://svn.apache.org/viewvc/tapestry/tapestry5/trunk/tapestry-core/src/main/java/org/apache/tapestry/internal/structure/StartElementPageElement.java?rev=607501&r1=607500&r2=607501&view=diff
==============================================================================
--- tapestry/tapestry5/trunk/tapestry-core/src/main/java/org/apache/tapestry/internal/structure/StartElementPageElement.java (original)
+++ tapestry/tapestry5/trunk/tapestry-core/src/main/java/org/apache/tapestry/internal/structure/StartElementPageElement.java Sat Dec 29 18:54:55 2007
@@ -22,21 +22,25 @@
  */
 public class StartElementPageElement implements PageElement
 {
+    private final String _namespaceURI;
+
     private final String _name;
 
-    public StartElementPageElement(String name)
+    public StartElementPageElement(String namespaceURI, String name)
     {
+        _namespaceURI = namespaceURI;
+
         _name = name;
     }
 
     public void render(MarkupWriter writer, RenderQueue queue)
     {
-        writer.element(_name);
+        writer.elementNS(_namespaceURI, _name);
     }
 
     @Override
     public String toString()
     {
-        return String.format("Start[%s]", _name);
+        return String.format("Start[%s %s]", _namespaceURI, _name);
     }
 }

Modified: tapestry/tapestry5/trunk/tapestry-core/src/main/java/org/apache/tapestry/internal/test/InternalBaseTestCase.java
URL: http://svn.apache.org/viewvc/tapestry/tapestry5/trunk/tapestry-core/src/main/java/org/apache/tapestry/internal/test/InternalBaseTestCase.java?rev=607501&r1=607500&r2=607501&view=diff
==============================================================================
--- tapestry/tapestry5/trunk/tapestry-core/src/main/java/org/apache/tapestry/internal/test/InternalBaseTestCase.java (original)
+++ tapestry/tapestry5/trunk/tapestry-core/src/main/java/org/apache/tapestry/internal/test/InternalBaseTestCase.java Sat Dec 29 18:54:55 2007
@@ -474,7 +474,7 @@
      *
      * @param trim trim each line of whitespace
      */
-    protected final String readFile(String file, boolean trim) throws Exception
+    protected final String readFile(String file) throws Exception
     {
         InputStream is = getClass().getResourceAsStream(file);
         is = new BufferedInputStream(is);
@@ -489,16 +489,14 @@
 
             if (line == null) break;
 
-            if (trim) line = line.trim();
-
             buffer.append(line);
 
-            if (!trim) buffer.append("\n");
+            buffer.append("\n");
         }
 
         in.close();
 
-        return buffer.toString();
+        return buffer.toString().trim();
     }
 
     protected final DocumentHeadBuilder mockDocumentScriptBuilder()

Modified: tapestry/tapestry5/trunk/tapestry-core/src/main/java/org/apache/tapestry/internal/test/TestableMarkupWriterFactoryImpl.java
URL: http://svn.apache.org/viewvc/tapestry/tapestry5/trunk/tapestry-core/src/main/java/org/apache/tapestry/internal/test/TestableMarkupWriterFactoryImpl.java?rev=607501&r1=607500&r2=607501&view=diff
==============================================================================
--- tapestry/tapestry5/trunk/tapestry-core/src/main/java/org/apache/tapestry/internal/test/TestableMarkupWriterFactoryImpl.java (original)
+++ tapestry/tapestry5/trunk/tapestry-core/src/main/java/org/apache/tapestry/internal/test/TestableMarkupWriterFactoryImpl.java Sat Dec 29 18:54:55 2007
@@ -15,6 +15,7 @@
 package org.apache.tapestry.internal.test;
 
 import org.apache.tapestry.MarkupWriter;
+import org.apache.tapestry.internal.util.ContentType;
 import static org.apache.tapestry.ioc.IOCConstants.PERTHREAD_SCOPE;
 import org.apache.tapestry.ioc.annotations.Scope;
 import org.apache.tapestry.services.Core;
@@ -28,11 +29,10 @@
     private MarkupWriter _lastCreated;
 
     /**
-     * Using Builtin to reference to framework-provided version, which this implementation wraps
+     * Using Core annotation to reference to framework-provided version, which this implementation wraps
      * around.
      */
-    public TestableMarkupWriterFactoryImpl(@Core
-    MarkupWriterFactory delegate)
+    public TestableMarkupWriterFactoryImpl(@Core MarkupWriterFactory delegate)
     {
         _delegate = delegate;
     }
@@ -42,9 +42,9 @@
         return _lastCreated;
     }
 
-    public MarkupWriter newMarkupWriter()
+    public MarkupWriter newMarkupWriter(ContentType contentType)
     {
-        MarkupWriter result = _delegate.newMarkupWriter();
+        MarkupWriter result = _delegate.newMarkupWriter(contentType);
 
         _lastCreated = result;
 

Modified: tapestry/tapestry5/trunk/tapestry-core/src/main/java/org/apache/tapestry/services/MarkupWriterFactory.java
URL: http://svn.apache.org/viewvc/tapestry/tapestry5/trunk/tapestry-core/src/main/java/org/apache/tapestry/services/MarkupWriterFactory.java?rev=607501&r1=607500&r2=607501&view=diff
==============================================================================
--- tapestry/tapestry5/trunk/tapestry-core/src/main/java/org/apache/tapestry/services/MarkupWriterFactory.java (original)
+++ tapestry/tapestry5/trunk/tapestry-core/src/main/java/org/apache/tapestry/services/MarkupWriterFactory.java Sat Dec 29 18:54:55 2007
@@ -1,20 +1,21 @@
-// Copyright 2006 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.
-
+// Copyright 2006 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.tapestry.services;
 
 import org.apache.tapestry.MarkupWriter;
+import org.apache.tapestry.internal.util.ContentType;
 
 /**
  * Source for {@link org.apache.tapestry.MarkupWriter} instances.
@@ -23,6 +24,8 @@
 {
     /**
      * This will likely expand in the future to control things like output format and encoding, etc.
+     *
+     * @param contentType
      */
-    MarkupWriter newMarkupWriter();
+    MarkupWriter newMarkupWriter(ContentType contentType);
 }

Added: tapestry/tapestry5/trunk/tapestry-core/src/main/resources/org/apache/tapestry/dom/DomStrings.properties
URL: http://svn.apache.org/viewvc/tapestry/tapestry5/trunk/tapestry-core/src/main/resources/org/apache/tapestry/dom/DomStrings.properties?rev=607501&view=auto
==============================================================================
--- tapestry/tapestry5/trunk/tapestry-core/src/main/resources/org/apache/tapestry/dom/DomStrings.properties (added)
+++ tapestry/tapestry5/trunk/tapestry-core/src/main/resources/org/apache/tapestry/dom/DomStrings.properties Sat Dec 29 18:54:55 2007
@@ -0,0 +1,16 @@
+# Copyright 2007 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.
+
+no-root-element=No root element has been defined.
+namespace-uri-not-mapped-to-prefix=Namespace prefix for URI '%s' is not defined.