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 2008/12/18 02:08:25 UTC

svn commit: r727606 - in /tapestry/tapestry5/branches/hlship-5.0-perf/tapestry-core/src/main/java/org/apache/tapestry5/dom: CData.java Comment.java Document.java Element.java MapHolder.java Node.java Raw.java Text.java

Author: hlship
Date: Wed Dec 17 17:08:25 2008
New Revision: 727606

URL: http://svn.apache.org/viewvc?rev=727606&view=rev
Log:
TAP5-417: Tapestry 5.0 Performance Improvements
- Optimize namespace URI to prefix resolution when rendering markup

Added:
    tapestry/tapestry5/branches/hlship-5.0-perf/tapestry-core/src/main/java/org/apache/tapestry5/dom/MapHolder.java
Modified:
    tapestry/tapestry5/branches/hlship-5.0-perf/tapestry-core/src/main/java/org/apache/tapestry5/dom/CData.java
    tapestry/tapestry5/branches/hlship-5.0-perf/tapestry-core/src/main/java/org/apache/tapestry5/dom/Comment.java
    tapestry/tapestry5/branches/hlship-5.0-perf/tapestry-core/src/main/java/org/apache/tapestry5/dom/Document.java
    tapestry/tapestry5/branches/hlship-5.0-perf/tapestry-core/src/main/java/org/apache/tapestry5/dom/Element.java
    tapestry/tapestry5/branches/hlship-5.0-perf/tapestry-core/src/main/java/org/apache/tapestry5/dom/Node.java
    tapestry/tapestry5/branches/hlship-5.0-perf/tapestry-core/src/main/java/org/apache/tapestry5/dom/Raw.java
    tapestry/tapestry5/branches/hlship-5.0-perf/tapestry-core/src/main/java/org/apache/tapestry5/dom/Text.java

Modified: tapestry/tapestry5/branches/hlship-5.0-perf/tapestry-core/src/main/java/org/apache/tapestry5/dom/CData.java
URL: http://svn.apache.org/viewvc/tapestry/tapestry5/branches/hlship-5.0-perf/tapestry-core/src/main/java/org/apache/tapestry5/dom/CData.java?rev=727606&r1=727605&r2=727606&view=diff
==============================================================================
--- tapestry/tapestry5/branches/hlship-5.0-perf/tapestry-core/src/main/java/org/apache/tapestry5/dom/CData.java (original)
+++ tapestry/tapestry5/branches/hlship-5.0-perf/tapestry-core/src/main/java/org/apache/tapestry5/dom/CData.java Wed Dec 17 17:08:25 2008
@@ -15,6 +15,7 @@
 package org.apache.tapestry5.dom;
 
 import java.io.PrintWriter;
+import java.util.Map;
 
 /**
  * A node that stores parsed character content (CDATA).  For XML documents (as per {@link MarkupModel#isXML()}, this
@@ -32,7 +33,7 @@
     }
 
     @Override
-    void toMarkup(Document document, PrintWriter writer)
+    void toMarkup(Document document, PrintWriter writer, Map<String, String> namespaceURIToPrefix)
     {
         MarkupModel model = document.getMarkupModel();
 

Modified: tapestry/tapestry5/branches/hlship-5.0-perf/tapestry-core/src/main/java/org/apache/tapestry5/dom/Comment.java
URL: http://svn.apache.org/viewvc/tapestry/tapestry5/branches/hlship-5.0-perf/tapestry-core/src/main/java/org/apache/tapestry5/dom/Comment.java?rev=727606&r1=727605&r2=727606&view=diff
==============================================================================
--- tapestry/tapestry5/branches/hlship-5.0-perf/tapestry-core/src/main/java/org/apache/tapestry5/dom/Comment.java (original)
+++ tapestry/tapestry5/branches/hlship-5.0-perf/tapestry-core/src/main/java/org/apache/tapestry5/dom/Comment.java Wed Dec 17 17:08:25 2008
@@ -15,6 +15,7 @@
 package org.apache.tapestry5.dom;
 
 import java.io.PrintWriter;
+import java.util.Map;
 
 /**
  * A node that represents a comment within the DOM.
@@ -31,7 +32,7 @@
     }
 
     @Override
-    void toMarkup(Document document, PrintWriter writer)
+    void toMarkup(Document document, PrintWriter writer, Map<String, String> namespaceURIToPrefix)
     {
         writer.print("<!-- ");
         writer.print(comment);

Modified: tapestry/tapestry5/branches/hlship-5.0-perf/tapestry-core/src/main/java/org/apache/tapestry5/dom/Document.java
URL: http://svn.apache.org/viewvc/tapestry/tapestry5/branches/hlship-5.0-perf/tapestry-core/src/main/java/org/apache/tapestry5/dom/Document.java?rev=727606&r1=727605&r2=727606&view=diff
==============================================================================
--- tapestry/tapestry5/branches/hlship-5.0-perf/tapestry-core/src/main/java/org/apache/tapestry5/dom/Document.java (original)
+++ tapestry/tapestry5/branches/hlship-5.0-perf/tapestry-core/src/main/java/org/apache/tapestry5/dom/Document.java Wed Dec 17 17:08:25 2008
@@ -17,6 +17,8 @@
 import org.apache.tapestry5.ioc.internal.util.Defense;
 
 import java.io.PrintWriter;
+import java.util.Collections;
+import java.util.Map;
 
 /**
  * The root node of a DOM.
@@ -112,7 +114,7 @@
     }
 
     @Override
-    public void toMarkup(Document document, PrintWriter writer)
+    public void toMarkup(Document document, PrintWriter writer, Map<String, String> namespaceURIToPrefix)
     {
         if (rootElement == null) throw new IllegalStateException(DomMessages.noRootElement());
 
@@ -132,7 +134,9 @@
             dtd.toMarkup(writer);
         }
 
-        rootElement.toMarkup(document, writer);
+        Map<String, String> initialNamespaceMap = Collections.emptyMap();
+
+        rootElement.toMarkup(document, writer, initialNamespaceMap);
     }
 
     @Override
@@ -163,4 +167,12 @@
     {
         dtd = new DTD(name, publicId, systemId);
     }
+
+    @Override
+    protected Map<String, String> getNamespaceURIToPrefix()
+    {
+        if (rootElement == null) return Collections.emptyMap();
+
+        return rootElement.getNamespaceURIToPrefix();
+    }
 }

Modified: tapestry/tapestry5/branches/hlship-5.0-perf/tapestry-core/src/main/java/org/apache/tapestry5/dom/Element.java
URL: http://svn.apache.org/viewvc/tapestry/tapestry5/branches/hlship-5.0-perf/tapestry-core/src/main/java/org/apache/tapestry5/dom/Element.java?rev=727606&r1=727605&r2=727606&view=diff
==============================================================================
--- tapestry/tapestry5/branches/hlship-5.0-perf/tapestry-core/src/main/java/org/apache/tapestry5/dom/Element.java (original)
+++ tapestry/tapestry5/branches/hlship-5.0-perf/tapestry-core/src/main/java/org/apache/tapestry5/dom/Element.java Wed Dec 17 17:08:25 2008
@@ -16,10 +16,7 @@
 
 import org.apache.tapestry5.internal.TapestryInternalUtils;
 import org.apache.tapestry5.ioc.internal.util.CollectionFactory;
-import static org.apache.tapestry5.ioc.internal.util.CollectionFactory.newLinkedList;
-import static org.apache.tapestry5.ioc.internal.util.CollectionFactory.newMap;
 import org.apache.tapestry5.ioc.internal.util.Defense;
-import static org.apache.tapestry5.ioc.internal.util.Defense.notBlank;
 import org.apache.tapestry5.ioc.internal.util.InternalUtils;
 
 import java.io.PrintWriter;
@@ -138,11 +135,11 @@
      */
     public Element attribute(String namespace, String name, String value)
     {
-        notBlank(name, "name");
+        Defense.notBlank(name, "name");
 
         if (value == null) return this;
 
-        if (attributes == null) attributes = newMap();
+        if (attributes == null) attributes = CollectionFactory.newMap();
 
         if (!attributes.containsKey(name)) attributes.put(name, new Attribute(namespace, name, value));
 
@@ -174,7 +171,7 @@
      */
     public Element forceAttributes(String... namesAndValues)
     {
-        if (attributes == null) attributes = newMap();
+        if (attributes == null) attributes = CollectionFactory.newMap();
 
         int i = 0;
 
@@ -203,7 +200,7 @@
      */
     public Element element(String name, String... namesAndValues)
     {
-        notBlank(name, "name");
+        Defense.notBlank(name, "name");
 
         Element child = newChild(new Element(this, null, name));
 
@@ -221,14 +218,14 @@
      */
     public Element elementNS(String namespace, String name)
     {
-        notBlank(name, "name");
+        Defense.notBlank(name, "name");
 
         return newChild(new Element(this, namespace, name));
     }
 
     public Element elementAt(int index, String name, String... namesAndValues)
     {
-        notBlank(name, "name");
+        Defense.notBlank(name, "name");
 
         Element child = new Element(this, null, name);
         child.attributes(namesAndValues);
@@ -290,15 +287,15 @@
     }
 
     @Override
-    void toMarkup(Document document, PrintWriter writer)
+    void toMarkup(Document document, PrintWriter writer, Map<String, String> containerNamespacePrefixToURI)
     {
-        Map<String, String> namespaceToPrefixMap = createNamespaceURIToNamespaceMap();
+        Map<String, String> localNamespacePrefixToURI = createNamespaceURIToPrefix(containerNamespacePrefixToURI);
 
         MarkupModel markupModel = document.getMarkupModel();
 
         StringBuilder builder = new StringBuilder();
 
-        String prefixedElementName = toPrefixedName(namespaceToPrefixMap, namespace, name);
+        String prefixedElementName = toPrefixedName(localNamespacePrefixToURI, namespace, name);
 
         builder.append("<").append(prefixedElementName);
 
@@ -308,7 +305,7 @@
         {
             Attribute attribute = attributes.get(key);
 
-            attribute.render(markupModel, builder, namespaceToPrefixMap);
+            attribute.render(markupModel, builder, localNamespacePrefixToURI);
         }
 
         // Next, emit namespace declarations for each namespace.
@@ -343,7 +340,7 @@
 
         writer.print(builder.toString());
 
-        if (hasChildren) writeChildMarkup(document, writer);
+        if (hasChildren) writeChildMarkup(document, writer, localNamespacePrefixToURI);
 
         // Dangerous -- perhaps it should be an error for a tag of type OMIT to even have children!
         // We'll certainly be writing out unbalanced markup in that case.
@@ -383,7 +380,7 @@
     {
         Defense.notNull(id, "id");
 
-        LinkedList<Element> queue = newLinkedList();
+        LinkedList<Element> queue = CollectionFactory.newLinkedList();
 
         queue.add(this);
 
@@ -418,7 +415,7 @@
      */
     public Element find(String path)
     {
-        notBlank(path, "path");
+        Defense.notBlank(path, "path");
 
         Element search = this;
 
@@ -555,28 +552,18 @@
     }
 
     /**
-     * Creates the URI to namespace map for this element, which reflects namespace mappings from containing elements. In
-     * addition, automatic namespaces are defined for any URIs that are not explicitly mapped (this occurs sometimes in
-     * Ajax partial render scenarios).
+     * Creates the URI to namespace prefix map for this element, which reflects namespace mappings from containing
+     * elements. In addition, automatic namespaces are defined for any URIs that are not explicitly mapped (this occurs
+     * sometimes in Ajax partial render scenarios).
      *
      * @return a mapping from namespace URI to namespace prefix
      */
-    private Map<String, String> createNamespaceURIToNamespaceMap()
+    private Map<String, String> createNamespaceURIToPrefix(Map<String, String> containerNamespaceURIToPrefix)
     {
-        Map<String, String> result = CollectionFactory.newMap();
+        MapHolder holder = new MapHolder(containerNamespaceURIToPrefix);
 
-        List<Element> elements = gatherParentElements();
+        holder.putAll(namespaceToPrefix);
 
-        elements.add(this);
-
-        for (Element e : elements)
-        {
-            // Put each namespace map, when present, overwriting child element's mappings
-            // over parent elements (by virtue of order in the list).
-
-            if (e.namespaceToPrefix != null)
-                result.putAll(e.namespaceToPrefix);
-        }
 
         // result now contains all the mappings, including this element's.
 
@@ -587,10 +574,10 @@
 
             // Add the namespace for the element as the default namespace.
 
-            if (!result.containsKey(namespace))
+            if (!holder.getResult().containsKey(namespace))
             {
                 defineNamespace(namespace, "");
-                result.put(namespace, "");
+                holder.put(namespace, "");
             }
         }
 
@@ -599,21 +586,23 @@
         if (attributes != null)
         {
             for (Attribute a : attributes.values())
-                addMappingIfNeeded(result, a.namespace);
+                addMappingIfNeeded(holder, a.namespace);
         }
 
-        return result;
+        return holder.getResult();
     }
 
-    private void addMappingIfNeeded(Map<String, String> masterURItoPrefixMap, String namespace)
+    private void addMappingIfNeeded(MapHolder holder, String namespace)
     {
         if (InternalUtils.isBlank(namespace)) return;
 
-        if (masterURItoPrefixMap.containsKey(namespace)) return;
+        Map<String, String> current = holder.getResult();
+
+        if (current.containsKey(namespace)) return;
 
         // A missing namespace.
 
-        Set<String> prefixes = CollectionFactory.newSet(masterURItoPrefixMap.values());
+        Set<String> prefixes = CollectionFactory.newSet(holder.getResult().values());
 
         // A clumsy way to find a unique id for the new namespace.
 
@@ -624,9 +613,8 @@
 
             if (!prefixes.contains(prefix))
             {
-
                 defineNamespace(namespace, prefix);
-                masterURItoPrefixMap.put(namespace, prefix);
+                holder.put(namespace, prefix);
                 return;
             }
 
@@ -634,6 +622,31 @@
         }
     }
 
+    @Override
+    protected Map<String, String> getNamespaceURIToPrefix()
+    {
+        MapHolder holder = new MapHolder();
+
+        List<Element> elements = CollectionFactory.newList(this);
+
+        Element cursor = parent;
+
+        while (cursor != null)
+        {
+            elements.add(cursor);
+            cursor = cursor.parent;
+        }
+
+        // Reverse the list, so that later elements will overwrite earlier ones.
+
+        Collections.reverse(elements);
+
+        for (Element e : elements)
+            holder.putAll(e.namespaceToPrefix);
+
+        return holder.getResult();
+    }
+
     /**
      * Returns the parent elements containing this element, ordered by depth (the root element is first, the current
      * element's parent is last).

Added: tapestry/tapestry5/branches/hlship-5.0-perf/tapestry-core/src/main/java/org/apache/tapestry5/dom/MapHolder.java
URL: http://svn.apache.org/viewvc/tapestry/tapestry5/branches/hlship-5.0-perf/tapestry-core/src/main/java/org/apache/tapestry5/dom/MapHolder.java?rev=727606&view=auto
==============================================================================
--- tapestry/tapestry5/branches/hlship-5.0-perf/tapestry-core/src/main/java/org/apache/tapestry5/dom/MapHolder.java (added)
+++ tapestry/tapestry5/branches/hlship-5.0-perf/tapestry-core/src/main/java/org/apache/tapestry5/dom/MapHolder.java Wed Dec 17 17:08:25 2008
@@ -0,0 +1,67 @@
+// Copyright 2008 The Apache Software Foundation
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+//     http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+
+package org.apache.tapestry5.dom;
+
+import org.apache.tapestry5.ioc.internal.util.CollectionFactory;
+
+import java.util.Collections;
+import java.util.Map;
+
+/**
+ * Used by {@link org.apache.tapestry5.dom.Element} to construct namespace URI to prefix maps.
+ *
+ * @since 5.0.19
+ */
+class MapHolder
+{
+    private final Map<String, String> startingMap;
+
+    private Map<String, String> localMap;
+
+    MapHolder()
+    {
+        this(Collections.<String, String>emptyMap());
+    }
+
+    MapHolder(Map<String, String> startingMap)
+    {
+        this.startingMap = startingMap;
+    }
+
+    void put(String key, String value)
+    {
+        getMutable().put(key, value);
+    }
+
+    Map<String, String> getMutable()
+    {
+        if (localMap == null)
+            localMap = CollectionFactory.newMap(startingMap);
+
+        return localMap;
+    }
+
+    void putAll(Map<String, String> map)
+    {
+        if (map == null || map.isEmpty()) return;
+
+        getMutable().putAll(map);
+    }
+
+    Map<String, String> getResult()
+    {
+        return localMap != null ? localMap : startingMap;
+    }
+}

Modified: tapestry/tapestry5/branches/hlship-5.0-perf/tapestry-core/src/main/java/org/apache/tapestry5/dom/Node.java
URL: http://svn.apache.org/viewvc/tapestry/tapestry5/branches/hlship-5.0-perf/tapestry-core/src/main/java/org/apache/tapestry5/dom/Node.java?rev=727606&r1=727605&r2=727606&view=diff
==============================================================================
--- tapestry/tapestry5/branches/hlship-5.0-perf/tapestry-core/src/main/java/org/apache/tapestry5/dom/Node.java (original)
+++ tapestry/tapestry5/branches/hlship-5.0-perf/tapestry-core/src/main/java/org/apache/tapestry5/dom/Node.java Wed Dec 17 17:08:25 2008
@@ -21,6 +21,7 @@
 import java.io.PrintWriter;
 import java.util.Collections;
 import java.util.List;
+import java.util.Map;
 
 /**
  * A node within the DOM.
@@ -95,12 +96,12 @@
         return children != null && !children.isEmpty();
     }
 
-    void writeChildMarkup(Document document, PrintWriter writer)
+    void writeChildMarkup(Document document, PrintWriter writer, Map<String, String> namespaceURIToPrefix)
     {
         if (children == null) return;
 
         for (Node child : children)
-            child.toMarkup(writer);
+            child.toMarkup(document, writer, namespaceURIToPrefix);
     }
 
     /**
@@ -110,7 +111,7 @@
     {
         PrintOutCollector collector = new PrintOutCollector();
 
-        writeChildMarkup(getDocument(), collector.getPrintWriter());
+        writeChildMarkup(getDocument(), collector.getPrintWriter(), null);
 
         return collector.getPrintOut();
     }
@@ -146,13 +147,20 @@
      */
     public void toMarkup(PrintWriter writer)
     {
-        toMarkup(getDocument(), writer);
+        toMarkup(getDocument(), writer, getNamespaceURIToPrefix());
+    }
+
+    protected Map<String, String> getNamespaceURIToPrefix()
+    {
+        // For non-Elements, the container (which should be an Element) will provide the mapping.
+
+        return container.getNamespaceURIToPrefix();
     }
 
     /**
      * Implemented by each subclass, with the document passed in for efficiency.
      */
-    abstract void toMarkup(Document document, PrintWriter writer);
+    abstract void toMarkup(Document document, PrintWriter writer, Map<String, String> namespaceURIToPrefix);
 
     /**
      * Moves this node so that it becomes a sibling of the element, ordered just before the element.

Modified: tapestry/tapestry5/branches/hlship-5.0-perf/tapestry-core/src/main/java/org/apache/tapestry5/dom/Raw.java
URL: http://svn.apache.org/viewvc/tapestry/tapestry5/branches/hlship-5.0-perf/tapestry-core/src/main/java/org/apache/tapestry5/dom/Raw.java?rev=727606&r1=727605&r2=727606&view=diff
==============================================================================
--- tapestry/tapestry5/branches/hlship-5.0-perf/tapestry-core/src/main/java/org/apache/tapestry5/dom/Raw.java (original)
+++ tapestry/tapestry5/branches/hlship-5.0-perf/tapestry-core/src/main/java/org/apache/tapestry5/dom/Raw.java Wed Dec 17 17:08:25 2008
@@ -15,6 +15,7 @@
 package org.apache.tapestry5.dom;
 
 import java.io.PrintWriter;
+import java.util.Map;
 
 /**
  * A specialized node in the document tree that contains raw markup to be printed to the client exactly as-is.
@@ -34,7 +35,7 @@
      * Prints the text exactly as is, no translations, filtering, etc.
      */
     @Override
-    void toMarkup(Document document, PrintWriter writer)
+    void toMarkup(Document document, PrintWriter writer, Map<String, String> namespaceURIToPrefix)
     {
         writer.print(text);
     }

Modified: tapestry/tapestry5/branches/hlship-5.0-perf/tapestry-core/src/main/java/org/apache/tapestry5/dom/Text.java
URL: http://svn.apache.org/viewvc/tapestry/tapestry5/branches/hlship-5.0-perf/tapestry-core/src/main/java/org/apache/tapestry5/dom/Text.java?rev=727606&r1=727605&r2=727606&view=diff
==============================================================================
--- tapestry/tapestry5/branches/hlship-5.0-perf/tapestry-core/src/main/java/org/apache/tapestry5/dom/Text.java (original)
+++ tapestry/tapestry5/branches/hlship-5.0-perf/tapestry-core/src/main/java/org/apache/tapestry5/dom/Text.java Wed Dec 17 17:08:25 2008
@@ -15,6 +15,7 @@
 package org.apache.tapestry5.dom;
 
 import java.io.PrintWriter;
+import java.util.Map;
 
 /**
  * A type of node that contains text.
@@ -46,7 +47,7 @@
     }
 
     @Override
-    void toMarkup(Document document, PrintWriter writer)
+    void toMarkup(Document document, PrintWriter writer, Map<String, String> namespaceURIToPrefix)
     {
         String encoded = document.getMarkupModel().encode(buffer.toString());