You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@mina.apache.org by ng...@apache.org on 2009/11/23 16:47:53 UTC

svn commit: r883380 - in /mina/sandbox/vysper/trunk: nbxml/src/main/java/org/apache/vysper/xmpp/xmlfragment/ nbxml/src/test/java/org/apache/vysper/xmpp/xmlfragment/ server/core/src/test/java/org/apache/vysper/xmpp/modules/extension/xep0199_xmppping/ se...

Author: ngn
Date: Mon Nov 23 15:47:53 2009
New Revision: 883380

URL: http://svn.apache.org/viewvc?rev=883380&view=rev
Log:
Further changes to make Renderer namespace aware. Now support namespace inheritance

Added:
    mina/sandbox/vysper/trunk/nbxml/src/main/java/org/apache/vysper/xmpp/xmlfragment/StackNamespaceResolver.java
    mina/sandbox/vysper/trunk/nbxml/src/test/java/org/apache/vysper/xmpp/xmlfragment/StackNamespaceResolverTestCase.java
Modified:
    mina/sandbox/vysper/trunk/nbxml/src/main/java/org/apache/vysper/xmpp/xmlfragment/Renderer.java
    mina/sandbox/vysper/trunk/nbxml/src/main/java/org/apache/vysper/xmpp/xmlfragment/XMLElementBuilder.java
    mina/sandbox/vysper/trunk/nbxml/src/test/java/org/apache/vysper/xmpp/xmlfragment/RendererTestCase.java
    mina/sandbox/vysper/trunk/nbxml/src/test/java/org/apache/vysper/xmpp/xmlfragment/XMLElementTestCase.java
    mina/sandbox/vysper/trunk/server/core/src/test/java/org/apache/vysper/xmpp/modules/extension/xep0199_xmppping/XmppPingIQHandlerTestCase.java
    mina/sandbox/vysper/trunk/server/extensions/xep0045-muc/src/main/java/org/apache/vysper/xmpp/modules/extension/xep0045_muc/handler/MUCHandlerHelper.java
    mina/sandbox/vysper/trunk/server/extensions/xep0045-muc/src/main/java/org/apache/vysper/xmpp/modules/extension/xep0045_muc/stanzas/X.java
    mina/sandbox/vysper/trunk/server/extensions/xep0045-muc/src/test/java/org/apache/vysper/xmpp/modules/extension/xep0045_muc/handler/AbstractMUCHandlerTestCase.java
    mina/sandbox/vysper/trunk/server/extensions/xep0045-muc/src/test/java/org/apache/vysper/xmpp/modules/extension/xep0045_muc/handler/MUCPresenceHandlerChangeNickTestCase.java
    mina/sandbox/vysper/trunk/server/extensions/xep0045-muc/src/test/java/org/apache/vysper/xmpp/modules/extension/xep0045_muc/handler/MUCPresenceHandlerEnterRoomTestCase.java

Modified: mina/sandbox/vysper/trunk/nbxml/src/main/java/org/apache/vysper/xmpp/xmlfragment/Renderer.java
URL: http://svn.apache.org/viewvc/mina/sandbox/vysper/trunk/nbxml/src/main/java/org/apache/vysper/xmpp/xmlfragment/Renderer.java?rev=883380&r1=883379&r2=883380&view=diff
==============================================================================
--- mina/sandbox/vysper/trunk/nbxml/src/main/java/org/apache/vysper/xmpp/xmlfragment/Renderer.java (original)
+++ mina/sandbox/vysper/trunk/nbxml/src/main/java/org/apache/vysper/xmpp/xmlfragment/Renderer.java Mon Nov 23 15:47:53 2009
@@ -20,6 +20,9 @@
 
 package org.apache.vysper.xmpp.xmlfragment;
 
+import java.util.Map;
+import java.util.Map.Entry;
+
 /**
  * TODO support namespaces (inherited from outer/inheriting for inner elements)
  *
@@ -35,8 +38,9 @@
 
     public Renderer(XMLElement element) {
         this.topElement = element;
-        renderXMLElement(topElement, openElementBuffer, elementContentBuffer, closeElementBuffer);
-
+        
+        StackNamespaceResolver nsResolver = new StackNamespaceResolver();
+        renderXMLElement(topElement, nsResolver, openElementBuffer, elementContentBuffer, closeElementBuffer);
     }
 
     public String getOpeningElement() {
@@ -55,20 +59,39 @@
         return openElementBuffer.toString() + elementContentBuffer.toString() + closeElementBuffer.toString();
     }
 
-    private void renderXMLElement(XMLElement element, StringBuilder openElementBuffer, StringBuilder elementContentBuffer, StringBuilder closeElementBuffer) {
-        String name = element.getName();
-        String namespacePrefix = element.getNamespacePrefix();
-
-        openElementBuffer.append("<");
-        renderElementName(openElementBuffer, element, namespacePrefix, name);
+    private void renderXMLElement(XMLElement element, StackNamespaceResolver nsResolver, StringBuilder openElementBuffer, StringBuilder elementContentBuffer, StringBuilder closeElementBuffer) {
+        nsResolver.push(element);
+    	
+    	openElementBuffer.append("<");
+        renderElementName(openElementBuffer, element, nsResolver);
+        
+        // render namespace delcarations
+        Map<String, String> nsAttrs = nsResolver.getNamespaceDeclarations();
+        for(Entry<String, String> nsAttr : nsAttrs.entrySet()) {
+    		openElementBuffer.append(" ");
+    		String name;
+    		if(nsAttr.getKey().length() == 0) {
+    			name = "xmlns";
+    		} else {
+    			name = "xmlns:" + nsAttr.getKey();
+    		}
+    		renderAttribute(openElementBuffer, name, nsAttr.getValue());
+        }
+        
         for (Attribute attribute : element.getAttributes()) {
-            openElementBuffer.append(" ");
-            renderAttribute(openElementBuffer, attribute, element.getNamespaceResolver());
+        	// make sure we do not render namespace attributes, 
+        	// nor normal attributes containing namespace declarations (probably due to
+        	// the parser not correctly creating namespace attributes for these which are then 
+        	// copied into for example error responses)
+        	if(!(attribute instanceof NamespaceAttribute) && !hasXmlnsReservedName(attribute)) {
+        		openElementBuffer.append(" ");
+        		renderAttribute(openElementBuffer, attribute, nsResolver);
+        	}
         }
         openElementBuffer.append(">");
 
         for (XMLFragment xmlFragment : element.getInnerFragments()) {
-            if (xmlFragment instanceof XMLElement) renderXMLElement((XMLElement) xmlFragment, elementContentBuffer, elementContentBuffer, elementContentBuffer);
+            if (xmlFragment instanceof XMLElement) renderXMLElement((XMLElement) xmlFragment, nsResolver, elementContentBuffer, elementContentBuffer, elementContentBuffer);
             else if (xmlFragment instanceof XMLText) {
                 elementContentBuffer.append(escapeTextValue(((XMLText) xmlFragment).getText()));
             } else {
@@ -77,18 +100,31 @@
         }
 
         closeElementBuffer.append("</");
-        renderElementName(closeElementBuffer, element, namespacePrefix, name);
+        renderElementName(closeElementBuffer, element, nsResolver);
         closeElementBuffer.append(">");
-
+        
+        // remove this element from the NS resolver stack
+        nsResolver.pop();
     }
 
-    private void renderElementName(StringBuilder buffer, XMLElement element, String namespacePrefix, String name) {
+    private boolean hasXmlnsReservedName(Attribute attribute) {
+    	String name = attribute.getName();
+    	return name.equals("xmlns") || name.startsWith("xmlns:");
+    }
+    
+    private void renderElementName(StringBuilder buffer, XMLElement element, NamespaceResolver nsResolver) {
         // if the element has a namespace prefix, retrieves the prefix from the defining attribute
-        if (namespacePrefix != null && namespacePrefix.length() > 0) {
-            buffer.append(namespacePrefix).append(COLON);
+        if (element.getNamespacePrefix().length() > 0) {
+            buffer.append(element.getNamespacePrefix()).append(COLON);
+        } else if(element.getNamespaceURI().length() > 0) {
+        	// element is in a namespace, but without a declared prefix, we need to resolve the prefix
+        	String prefix = nsResolver.resolvePrefix(element.getNamespaceURI());
+        	if(prefix != null && prefix.length() > 0) {
+        		buffer.append(prefix).append(COLON);
+        	}
         }
 
-        buffer.append(name);
+        buffer.append(element.getName());
     }
 
     private void renderAttribute(StringBuilder buffer, Attribute attribute, NamespaceResolver nsResolver) {
@@ -100,8 +136,11 @@
     		qname = attribute.getName();
     	}
     	
-    	
-        buffer.append(qname).append("=\"").append(escapeAttributeValue(attribute.getValue())).append("\"");
+    	renderAttribute(buffer, qname, attribute.getValue());
+    }
+    
+    private void renderAttribute(StringBuilder buffer, String qname, String value) {
+        buffer.append(qname).append("=\"").append(escapeAttributeValue(value)).append("\"");
     }
     
     private String escapeAttributeValue(String value) {

Added: mina/sandbox/vysper/trunk/nbxml/src/main/java/org/apache/vysper/xmpp/xmlfragment/StackNamespaceResolver.java
URL: http://svn.apache.org/viewvc/mina/sandbox/vysper/trunk/nbxml/src/main/java/org/apache/vysper/xmpp/xmlfragment/StackNamespaceResolver.java?rev=883380&view=auto
==============================================================================
--- mina/sandbox/vysper/trunk/nbxml/src/main/java/org/apache/vysper/xmpp/xmlfragment/StackNamespaceResolver.java (added)
+++ mina/sandbox/vysper/trunk/nbxml/src/main/java/org/apache/vysper/xmpp/xmlfragment/StackNamespaceResolver.java Mon Nov 23 15:47:53 2009
@@ -0,0 +1,173 @@
+/*
+ *  Licensed to the Apache Software Foundation (ASF) under one
+ *  or more contributor license agreements.  See the NOTICE file
+ *  distributed with this work for additional information
+ *  regarding copyright ownership.  The ASF licenses this file
+ *  to you 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.vysper.xmpp.xmlfragment;
+
+import java.util.HashMap;
+import java.util.Map;
+import java.util.Stack;
+
+
+/**
+ * Naive implementation, will be replaced in later stages of this change
+ */
+public class StackNamespaceResolver implements NamespaceResolver {
+	
+	private Stack<XMLElement> elements = new Stack<XMLElement>();
+	
+	public StackNamespaceResolver() {
+	}
+
+	public void push(XMLElement elm) {
+		elements.push(elm);
+	}
+
+	public void pop() {
+		elements.pop();
+	}
+
+	public Map<String, String> getNamespaceDeclarations() {
+		Map<String, String> ns = new HashMap<String, String>();
+		if(!elements.isEmpty()) {
+			XMLElement topElm = elements.peek();
+			for(Attribute attribute : topElm.getAttributes()) {
+				if(attribute instanceof NamespaceAttribute) {
+					NamespaceAttribute nsAttr = (NamespaceAttribute) attribute;
+					ns.put(nsAttr.getPrefix(), nsAttr.getValue());
+				}
+			}
+			
+			// look for any generated prefixes for attributes
+			for(Attribute attribute : topElm.getAttributes()) {
+				if(!(attribute instanceof NamespaceAttribute)) {
+					String attrNs = attribute.getNamespaceUri();
+					if(attrNs.length() > 0 && resolvePrefix(attrNs, false) == null) {
+						// attribute is in a namespace, and that namespace is not declared
+						ns.put(resolvePrefix(attrNs), attrNs);						
+					}
+				}
+			}
+			
+			
+			// add the element declaration as well, if not already defined
+			if(topElm.getNamespaceURI().length() > 0) {
+				// declared in a namespace
+				if(!ns.containsValue(topElm.getNamespaceURI())) {
+					// the namespace is not declared as an attribute on topElm
+					// is it declared on a parent?
+					// pop the element to test for declaration on the parent
+					pop();
+					if(resolvePrefix(topElm.getNamespaceURI(), false) == null) {
+						ns.put(topElm.getNamespacePrefix(), topElm.getNamespaceURI());
+					}
+					// restore stack
+					push(topElm);
+				}
+			}
+		}		
+		
+		return ns;
+	}
+	
+	public String resolveUri(String prefix) {
+		// check for the reserved xml namespace
+		if(prefix.equals("xml")) {
+			return NamespaceURIs.XML;
+		} else {
+			for(int i = elements.size() - 1; i>=0; i--) {
+				String uri = resolveUri(elements.get(i), prefix);
+				if(uri != null) {
+					return uri;
+				}
+			}
+		}
+		
+		// is the current element declared with this prefix, 
+		// if so, return the declared namespace
+		if(!elements.isEmpty() && prefix.equals(elements.peek().getNamespacePrefix())) {
+			// the namespace URI must not be defined for another prefix
+			String uri = elements.peek().getNamespaceURI();
+			String resolvedPrefix = resolvePrefix(uri, false); 
+			if(resolvedPrefix == null || resolvedPrefix.equals(prefix)) {
+				return uri;
+			}
+		}
+		
+		// could not resolve URI
+		return null;
+	}
+	
+	private String resolveUri(XMLElement elm, String prefix) {
+		for(Attribute attribute : elm.getAttributes()) {
+			if(attribute instanceof NamespaceAttribute) {
+				NamespaceAttribute nsAttr = (NamespaceAttribute) attribute;
+				if(nsAttr.getPrefix().equals(prefix)) {
+					return nsAttr.getValue();
+				}
+			}
+		}
+		
+		return null;
+	}
+	
+	public String resolvePrefix(String uri) {
+		return resolvePrefix(uri, true);
+	}
+	
+	private String resolvePrefix(String uri, boolean generatePrefix) {
+		// check for the reserved xml namespace
+		if(uri.equals(NamespaceURIs.XML)) {
+			return "xml";
+		} else {
+			for(int i = elements.size() - 1; i>=0; i--) {
+				String prefix = resolvePrefix(elements.get(i), uri);
+				if(prefix != null) {
+					return prefix;
+				}
+			}
+		}
+		
+		// is the current element in this namespace, if so, return the default prefix
+		if(!elements.isEmpty() && uri.equals(elements.peek().getNamespaceURI())) {
+			return elements.peek().getNamespacePrefix();
+		}
+
+		if(generatePrefix) {
+			// TODO replace with prefix generation
+			return "ns1";
+		} else {
+			return null;
+		}
+		
+	}
+	
+	private String resolvePrefix(XMLElement elm, String uri) {
+		for(Attribute attribute : elm.getAttributes()) {
+			if(attribute instanceof NamespaceAttribute) {
+				NamespaceAttribute nsAttr = (NamespaceAttribute) attribute;
+				if(nsAttr.getValue().equals(uri)) {
+					return nsAttr.getPrefix();
+				}
+			}
+		}
+		
+		return null;
+	}
+}

Modified: mina/sandbox/vysper/trunk/nbxml/src/main/java/org/apache/vysper/xmpp/xmlfragment/XMLElementBuilder.java
URL: http://svn.apache.org/viewvc/mina/sandbox/vysper/trunk/nbxml/src/main/java/org/apache/vysper/xmpp/xmlfragment/XMLElementBuilder.java?rev=883380&r1=883379&r2=883380&view=diff
==============================================================================
--- mina/sandbox/vysper/trunk/nbxml/src/main/java/org/apache/vysper/xmpp/xmlfragment/XMLElementBuilder.java (original)
+++ mina/sandbox/vysper/trunk/nbxml/src/main/java/org/apache/vysper/xmpp/xmlfragment/XMLElementBuilder.java Mon Nov 23 15:47:53 2009
@@ -70,15 +70,6 @@
         element.element = new XMLElement(namespaceURI, name, namespacePrefix, element.attributes, element.innerFragments);
 
         currentElement = element;
-        
-        // must be done after set as currentElement
-        if(namespaceURI != null && namespaceURI.length() > 0) {
-            if(namespacePrefix == null || namespacePrefix.length() == 0) {
-                addNamespaceAttribute(namespaceURI);
-            } else {
-                addNamespaceAttribute(namespacePrefix, namespaceURI);
-            }
-        }
     }
 
 

Modified: mina/sandbox/vysper/trunk/nbxml/src/test/java/org/apache/vysper/xmpp/xmlfragment/RendererTestCase.java
URL: http://svn.apache.org/viewvc/mina/sandbox/vysper/trunk/nbxml/src/test/java/org/apache/vysper/xmpp/xmlfragment/RendererTestCase.java?rev=883380&r1=883379&r2=883380&view=diff
==============================================================================
--- mina/sandbox/vysper/trunk/nbxml/src/test/java/org/apache/vysper/xmpp/xmlfragment/RendererTestCase.java (original)
+++ mina/sandbox/vysper/trunk/nbxml/src/test/java/org/apache/vysper/xmpp/xmlfragment/RendererTestCase.java Mon Nov 23 15:47:53 2009
@@ -25,35 +25,35 @@
 
 	public void testRenderAttribute() {
 		XMLElement elm = new XMLElement(null, "foo", null, new Attribute[]{new Attribute("attr1", "value1")}, null);
-		assertEquals("<foo attr1=\"value1\"></foo>", new Renderer(elm).getComplete());
+		assertRendering("<foo attr1=\"value1\"></foo>", elm);
 	}
 
 	// & must be escaped
 	public void testRenderAttributeWithAmpersand() {
 		XMLElement elm = new XMLElement(null, "foo", null, new Attribute[]{new Attribute("attr1", "val&ue1")}, null);
-		assertEquals("<foo attr1=\"val&amp;ue1\"></foo>", new Renderer(elm).getComplete());
+		assertRendering("<foo attr1=\"val&amp;ue1\"></foo>", elm);
 	}
 
 	public void testRenderAttributeWithQuot() {
 		XMLElement elm = new XMLElement(null, "foo", null, new Attribute[]{new Attribute("attr1", "val\"ue1")}, null);
-		assertEquals("<foo attr1=\"val&quot;ue1\"></foo>", new Renderer(elm).getComplete());
+		assertRendering("<foo attr1=\"val&quot;ue1\"></foo>", elm);
 	}
 
 	public void testRenderAttributeWithApos() {
 		XMLElement elm = new XMLElement(null, "foo", null, new Attribute[]{new Attribute("attr1", "val'ue1")}, null);
-		assertEquals("<foo attr1=\"val'ue1\"></foo>", new Renderer(elm).getComplete());
+		assertRendering("<foo attr1=\"val'ue1\"></foo>", elm);
 	}
 
 	// > is not required to be escaped, but we do so to make sure
 	public void testRenderAttributeWithGt() {
 		XMLElement elm = new XMLElement(null, "foo", null, new Attribute[]{new Attribute("attr1", "val>ue1")}, null);
-		assertEquals("<foo attr1=\"val&gt;ue1\"></foo>", new Renderer(elm).getComplete());
+		assertRendering("<foo attr1=\"val&gt;ue1\"></foo>", elm);
 	}
 
 	// < must be escaped
 	public void testRenderAttributeWithLt() {
 		XMLElement elm = new XMLElement(null, "foo", null, new Attribute[]{new Attribute("attr1", "val<ue1")}, null);
-		assertEquals("<foo attr1=\"val&lt;ue1\"></foo>", new Renderer(elm).getComplete());
+		assertRendering("<foo attr1=\"val&lt;ue1\"></foo>", elm);
 	}
 
 	public void testRenderNamespacedAttribute() {
@@ -61,7 +61,7 @@
 				new Attribute("http://example.com", "attr1", "value1"),
 				new NamespaceAttribute("pr1", "http://example.com")
 				}, null);
-		assertEquals("<foo pr1:attr1=\"value1\" xmlns:pr1=\"http://example.com\"></foo>", new Renderer(elm).getComplete());
+		assertRendering("<foo xmlns:pr1=\"http://example.com\" pr1:attr1=\"value1\"></foo>", elm);
 	}
 
 	// make sure we render the xml namespace correctly, e.g for xml:lang
@@ -69,68 +69,96 @@
 		XMLElement elm = new XMLElement(null, "foo", null, new Attribute[]{
 				new Attribute(NamespaceURIs.XML, "lang", "sv")
 				}, null);
-		assertEquals("<foo xml:lang=\"sv\"></foo>", new Renderer(elm).getComplete());
+		assertRendering("<foo xml:lang=\"sv\"></foo>", elm);
 	}
 	
 	public void testRenderUndeclaredNamespacedAttribute() {
 		XMLElement elm = new XMLElement(null, "foo", null, new Attribute[]{
 				new Attribute("http://example.com", "attr1", "value1")
 				}, null);
-		try {
-			new Renderer(elm).getComplete();
-			fail("Must throw IllegalStateException");
-		} catch (IllegalStateException e) {
-			// ok
-		}
+		
+		assertRendering("<foo xmlns:ns1=\"http://example.com\" ns1:attr1=\"value1\"></foo>", elm);
 	}
+
+//	public void testRenderEmptyElement() {
+//		XMLElement elm = new XMLElement(null, "foo", null, (Attribute[])null, null);
+//		assertRendering("<foo />", elm);
+//	}
+//
+//	public void testRenderEmptyElementWithAttribute() {
+//		XMLElement elm = new XMLElementBuilder("foo").addAttribute("attr", "value").getFinalElement();
+//
+//		assertRendering("<foo attr=\"value\" />", elm);
+//	}
 	
 	public void testRenderNonNamespaceElement() {
 		XMLElement elm = new XMLElement(null, "foo", null, (Attribute[])null, null);
-		assertEquals("<foo></foo>", new Renderer(elm).getComplete());
+		assertRendering("<foo></foo>", elm);
 	}
 	
 	public void testRenderDefaultNamespaceElement() {
 		XMLElement elm = new XMLElement(null, "foo", null, new Attribute[]{
 				new NamespaceAttribute("http://example.com")
 		}, null);
-		assertEquals("<foo xmlns=\"http://example.com\"></foo>", new Renderer(elm).getComplete());
+		assertRendering("<foo xmlns=\"http://example.com\"></foo>", elm);
 	}
 
-	public void testRenderPrefixedNamespaceElement() {
-		XMLElement elm = new XMLElement(null, "foo", "pr", new Attribute[]{
+	public void testRenderPrefixedNamespaceWithDeclarationElement() {
+		XMLElement elm = new XMLElement("http://example.com", "foo", "pr", new Attribute[]{
 				new NamespaceAttribute("pr", "http://example.com")
 		}, null);
-		assertEquals("<pr:foo xmlns:pr=\"http://example.com\"></pr:foo>", new Renderer(elm).getComplete());
+		assertRendering("<pr:foo xmlns:pr=\"http://example.com\"></pr:foo>", elm);
+	}
+
+	public void testRenderPrefixedNamespaceElement() {
+		XMLElement elm = new XMLElement("http://example.com", "foo", "pr", (Attribute[])null, null);
+		assertRendering("<pr:foo xmlns:pr=\"http://example.com\"></pr:foo>", elm);
+	}
+
+	public void testRenderDeclaredNamespaceElement() {
+		XMLElementBuilder builder = new XMLElementBuilder("foo", "http://example.com");
+		builder.addNamespaceAttribute("pr", "http://example.com");
+		assertRendering("<pr:foo xmlns:pr=\"http://example.com\"></pr:foo>", builder.getFinalElement());
+	}
+
+	public void testRenderInnerNamespacedElement() {
+		XMLElementBuilder builder = new XMLElementBuilder("foo", "http://example.com");
+		builder.addNamespaceAttribute("pr", "http://other.com");
+		builder.startInnerElement("bar", "http://other.com");
+		assertRendering("<foo xmlns=\"http://example.com\" xmlns:pr=\"http://other.com\"><pr:bar></pr:bar></foo>", builder.getFinalElement());
 	}
 
 	public void testRenderSimpleText() {
 		XMLElement elm = new XMLElement(null, "foo", null, null, new XMLFragment[]{
 				new XMLText("bar")
 		});
-		assertEquals("<foo>bar</foo>", new Renderer(elm).getComplete());
+		assertRendering("<foo>bar</foo>", elm);
 	}
 
 	public void testRenderTextWithAmpersand() {
 		XMLElement elm = new XMLElement(null, "foo", null, null, new XMLFragment[]{
 				new XMLText("ba&r")
 		});
-		assertEquals("<foo>ba&amp;r</foo>", new Renderer(elm).getComplete());
+		assertRendering("<foo>ba&amp;r</foo>", elm);
 	}
 
 	public void testRenderTextWithGt() {
 		XMLElement elm = new XMLElement(null, "foo", null, null, new XMLFragment[]{
 				new XMLText("ba>r")
 		});
-		assertEquals("<foo>ba&gt;r</foo>", new Renderer(elm).getComplete());
+		assertRendering("<foo>ba&gt;r</foo>", elm);
 	}
 
 	public void testRenderTextWithLt() {
 		XMLElement elm = new XMLElement(null, "foo", null, null, new XMLFragment[]{
 				new XMLText("ba<r")
 		});
-		assertEquals("<foo>ba&lt;r</foo>", new Renderer(elm).getComplete());
+		assertRendering("<foo>ba&lt;r</foo>", elm);
 	}
 
+	private void assertRendering(String expected, XMLElement elm) {
+		assertEquals(expected, new Renderer(elm).getComplete());
+	}
 	
 	// TODO test allowed Unicode characters ranged in element name attribute name, attributes values, text
 }

Added: mina/sandbox/vysper/trunk/nbxml/src/test/java/org/apache/vysper/xmpp/xmlfragment/StackNamespaceResolverTestCase.java
URL: http://svn.apache.org/viewvc/mina/sandbox/vysper/trunk/nbxml/src/test/java/org/apache/vysper/xmpp/xmlfragment/StackNamespaceResolverTestCase.java?rev=883380&view=auto
==============================================================================
--- mina/sandbox/vysper/trunk/nbxml/src/test/java/org/apache/vysper/xmpp/xmlfragment/StackNamespaceResolverTestCase.java (added)
+++ mina/sandbox/vysper/trunk/nbxml/src/test/java/org/apache/vysper/xmpp/xmlfragment/StackNamespaceResolverTestCase.java Mon Nov 23 15:47:53 2009
@@ -0,0 +1,128 @@
+/*
+ *  Licensed to the Apache Software Foundation (ASF) under one
+ *  or more contributor license agreements.  See the NOTICE file
+ *  distributed with this work for additional information
+ *  regarding copyright ownership.  The ASF licenses this file
+ *  to you 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.vysper.xmpp.xmlfragment;
+
+import junit.framework.TestCase;
+
+/**
+ */
+public class StackNamespaceResolverTestCase extends TestCase {
+
+	private StackNamespaceResolver resolver = new StackNamespaceResolver();
+
+	public void testPushSingleElement() {
+		XMLElement elm = new XMLElementBuilder("foo")
+			.addNamespaceAttribute("pr1", "url1")
+			.addNamespaceAttribute("pr2", "url2").getFinalElement();
+		
+		resolver.push(elm);
+		
+		assertEquals("url1", resolver.resolveUri("pr1"));
+		assertEquals("url2", resolver.resolveUri("pr2"));
+		assertNull(resolver.resolveUri("pr3"));
+
+		assertEquals("pr1", resolver.resolvePrefix("url1"));
+		assertEquals("pr2", resolver.resolvePrefix("url2"));
+	}
+
+	public void testImplicitNamespace() {
+		XMLElement elm = new XMLElement("url1", "foo", "pr1", (Attribute[])null, null);
+		
+		resolver.push(elm);
+		
+		assertEquals("url1", resolver.resolveUri("pr1"));
+		assertEquals("pr1", resolver.resolvePrefix("url1"));
+	}
+
+	public void testDefaultImplicitNamespace() {
+		XMLElement elm = new XMLElement("url1", "foo", null, (Attribute[])null, null);
+		
+		resolver.push(elm);
+		
+		assertEquals("url1", resolver.resolveUri(""));
+
+		assertEquals("", resolver.resolvePrefix("url1"));
+	}
+
+	
+	public void testPushSingleNamespacedElement() {
+		XMLElement elm = new XMLElementBuilder("foo", "defaulturl")
+			.addNamespaceAttribute("pr1", "url1")
+			.addNamespaceAttribute("pr2", "url2").getFinalElement();
+		
+		resolver.push(elm);
+		
+		assertEquals("defaulturl", resolver.resolveUri(""));
+		assertEquals("url1", resolver.resolveUri("pr1"));
+		assertEquals("url2", resolver.resolveUri("pr2"));
+
+		assertEquals("", resolver.resolvePrefix("defaulturl"));
+		assertEquals("pr1", resolver.resolvePrefix("url1"));
+		assertEquals("pr2", resolver.resolvePrefix("url2"));
+	}
+	
+	public void testSimpleInheritance() {
+		XMLElement elm = new XMLElementBuilder("foo", "defaulturl").getFinalElement();
+		XMLElement innerElm = new XMLElementBuilder("inner", "innerdefaulturl").getFinalElement(); 
+		
+		resolver.push(elm);
+		
+		assertEquals("defaulturl", resolver.resolveUri(""));
+		
+		resolver.push(innerElm);
+		
+		assertEquals("innerdefaulturl", resolver.resolveUri(""));
+		
+		resolver.pop();
+		
+		assertEquals("defaulturl", resolver.resolveUri(""));
+	}
+
+	public void testPrefixedInheritance() {
+		XMLElement elm = new XMLElementBuilder("foo", "url1")
+		.addNamespaceAttribute("pr1", "url1")
+		.getFinalElement();
+		XMLElement innerElm = new XMLElementBuilder("inner", "url1").getFinalElement(); 
+		
+		resolver.push(elm);
+		
+		assertEquals("url1", resolver.resolveUri("pr1"));
+		assertEquals("pr1", resolver.resolvePrefix("url1"));
+		assertNull(resolver.resolveUri(""));
+		
+		resolver.push(innerElm);
+		
+		assertEquals("url1", resolver.resolveUri("pr1"));
+		assertEquals("pr1", resolver.resolvePrefix("url1"));
+		assertNull(resolver.resolveUri(""));
+		
+		resolver.pop();
+		
+		assertEquals("url1", resolver.resolveUri("pr1"));
+		assertEquals("pr1", resolver.resolvePrefix("url1"));
+		assertNull(resolver.resolveUri(""));
+	}
+
+
+	public void testPushXmlNamespace() {
+		assertEquals(NamespaceURIs.XML, resolver.resolveUri("xml"));
+		assertEquals("xml", resolver.resolvePrefix(NamespaceURIs.XML));
+	}
+}

Modified: mina/sandbox/vysper/trunk/nbxml/src/test/java/org/apache/vysper/xmpp/xmlfragment/XMLElementTestCase.java
URL: http://svn.apache.org/viewvc/mina/sandbox/vysper/trunk/nbxml/src/test/java/org/apache/vysper/xmpp/xmlfragment/XMLElementTestCase.java?rev=883380&r1=883379&r2=883380&view=diff
==============================================================================
--- mina/sandbox/vysper/trunk/nbxml/src/test/java/org/apache/vysper/xmpp/xmlfragment/XMLElementTestCase.java (original)
+++ mina/sandbox/vysper/trunk/nbxml/src/test/java/org/apache/vysper/xmpp/xmlfragment/XMLElementTestCase.java Mon Nov 23 15:47:53 2009
@@ -45,8 +45,7 @@
         List<Attribute> list = xmlElement.getAttributes();
         assertNotNull(list);
         
-        // 3 added attributes + namespace attribute
-        assertEquals(4, list.size());
+        assertEquals(3, list.size());
     }
 
     public void testInnerTextGetters() {

Modified: mina/sandbox/vysper/trunk/server/core/src/test/java/org/apache/vysper/xmpp/modules/extension/xep0199_xmppping/XmppPingIQHandlerTestCase.java
URL: http://svn.apache.org/viewvc/mina/sandbox/vysper/trunk/server/core/src/test/java/org/apache/vysper/xmpp/modules/extension/xep0199_xmppping/XmppPingIQHandlerTestCase.java?rev=883380&r1=883379&r2=883380&view=diff
==============================================================================
--- mina/sandbox/vysper/trunk/server/core/src/test/java/org/apache/vysper/xmpp/modules/extension/xep0199_xmppping/XmppPingIQHandlerTestCase.java (original)
+++ mina/sandbox/vysper/trunk/server/core/src/test/java/org/apache/vysper/xmpp/modules/extension/xep0199_xmppping/XmppPingIQHandlerTestCase.java Mon Nov 23 15:47:53 2009
@@ -49,7 +49,7 @@
 
         
         StanzaBuilder stanzaBuilder = StanzaBuilder.createIQStanza(boundClient, server, IQStanzaType.GET, IQ_ID);
-        stanzaBuilder.startInnerElement("ping").addNamespaceAttribute(NamespaceURIs.URN_XMPP_PING).endInnerElement();
+        stanzaBuilder.startInnerElement("ping", NamespaceURIs.URN_XMPP_PING).endInnerElement();
 
         Stanza requestStanza = stanzaBuilder.getFinalStanza();
         ResponseStanzaContainer resp = handler.execute(requestStanza, sessionContext.getServerRuntimeContext(), true, sessionContext, null);

Modified: mina/sandbox/vysper/trunk/server/extensions/xep0045-muc/src/main/java/org/apache/vysper/xmpp/modules/extension/xep0045_muc/handler/MUCHandlerHelper.java
URL: http://svn.apache.org/viewvc/mina/sandbox/vysper/trunk/server/extensions/xep0045-muc/src/main/java/org/apache/vysper/xmpp/modules/extension/xep0045_muc/handler/MUCHandlerHelper.java?rev=883380&r1=883379&r2=883380&view=diff
==============================================================================
--- mina/sandbox/vysper/trunk/server/extensions/xep0045-muc/src/main/java/org/apache/vysper/xmpp/modules/extension/xep0045_muc/handler/MUCHandlerHelper.java (original)
+++ mina/sandbox/vysper/trunk/server/extensions/xep0045-muc/src/main/java/org/apache/vysper/xmpp/modules/extension/xep0045_muc/handler/MUCHandlerHelper.java Mon Nov 23 15:47:53 2009
@@ -78,7 +78,7 @@
         
         if(innerElements != null) {
             for(XMLElement innerElement : innerElements) {
-                   builder.addPreparedElement(innerElement);
+               builder.addPreparedElement(innerElement);
             }
         }
         

Modified: mina/sandbox/vysper/trunk/server/extensions/xep0045-muc/src/main/java/org/apache/vysper/xmpp/modules/extension/xep0045_muc/stanzas/X.java
URL: http://svn.apache.org/viewvc/mina/sandbox/vysper/trunk/server/extensions/xep0045-muc/src/main/java/org/apache/vysper/xmpp/modules/extension/xep0045_muc/stanzas/X.java?rev=883380&r1=883379&r2=883380&view=diff
==============================================================================
--- mina/sandbox/vysper/trunk/server/extensions/xep0045-muc/src/main/java/org/apache/vysper/xmpp/modules/extension/xep0045_muc/stanzas/X.java (original)
+++ mina/sandbox/vysper/trunk/server/extensions/xep0045-muc/src/main/java/org/apache/vysper/xmpp/modules/extension/xep0045_muc/stanzas/X.java Mon Nov 23 15:47:53 2009
@@ -23,8 +23,6 @@
 
 import org.apache.vysper.xmpp.protocol.NamespaceURIs;
 import org.apache.vysper.xmpp.stanza.Stanza;
-import org.apache.vysper.xmpp.xmlfragment.Attribute;
-import org.apache.vysper.xmpp.xmlfragment.NamespaceAttribute;
 import org.apache.vysper.xmpp.xmlfragment.XMLElement;
 import org.apache.vysper.xmpp.xmlfragment.XMLSemanticError;
 
@@ -52,8 +50,7 @@
     }
 
     public X(String ns, XMLElement...elements) {
-        super(ns, "x", null, new Attribute[]{
-            new NamespaceAttribute(ns)}, elements);
+        super(ns, "x", null, null, elements);
     }
     
     public X(List<XMLElement> elements) {
@@ -61,10 +58,9 @@
     }
 
     public X(String ns, List<XMLElement> elements) {
-        super(ns, "x", null, new Attribute[]{
-            new NamespaceAttribute(ns)}, elements.toArray(new XMLElement[]{}));
+        super(ns, "x", null, null, elements.toArray(new XMLElement[]{}));
     }
-
+    
     public Invite getInvite() {
         try {
             XMLElement inviteElm = getSingleInnerElementsNamed("invite");

Modified: mina/sandbox/vysper/trunk/server/extensions/xep0045-muc/src/test/java/org/apache/vysper/xmpp/modules/extension/xep0045_muc/handler/AbstractMUCHandlerTestCase.java
URL: http://svn.apache.org/viewvc/mina/sandbox/vysper/trunk/server/extensions/xep0045-muc/src/test/java/org/apache/vysper/xmpp/modules/extension/xep0045_muc/handler/AbstractMUCHandlerTestCase.java?rev=883380&r1=883379&r2=883380&view=diff
==============================================================================
--- mina/sandbox/vysper/trunk/server/extensions/xep0045-muc/src/test/java/org/apache/vysper/xmpp/modules/extension/xep0045_muc/handler/AbstractMUCHandlerTestCase.java (original)
+++ mina/sandbox/vysper/trunk/server/extensions/xep0045-muc/src/test/java/org/apache/vysper/xmpp/modules/extension/xep0045_muc/handler/AbstractMUCHandlerTestCase.java Mon Nov 23 15:47:53 2009
@@ -13,7 +13,6 @@
 import org.apache.vysper.xmpp.protocol.StanzaHandler;
 import org.apache.vysper.xmpp.server.TestSessionContext;
 import org.apache.vysper.xmpp.stanza.Stanza;
-import org.apache.vysper.xmpp.xmlfragment.Renderer;
 import org.apache.vysper.xmpp.xmlfragment.XMLElement;
 
 /**
@@ -74,9 +73,6 @@
         int index = 0;
         if(expectedInnerElements != null) {
             for(XMLElement expectedInnerElement : expectedInnerElements) {
-            	System.out.println(new Renderer(expectedInnerElement).getComplete());
-            	System.out.println(new Renderer(innerElements.get(index)).getComplete());
-            	
                 assertEquals(expectedInnerElement, innerElements.get(index));
                 index++;
             }

Modified: mina/sandbox/vysper/trunk/server/extensions/xep0045-muc/src/test/java/org/apache/vysper/xmpp/modules/extension/xep0045_muc/handler/MUCPresenceHandlerChangeNickTestCase.java
URL: http://svn.apache.org/viewvc/mina/sandbox/vysper/trunk/server/extensions/xep0045-muc/src/test/java/org/apache/vysper/xmpp/modules/extension/xep0045_muc/handler/MUCPresenceHandlerChangeNickTestCase.java?rev=883380&r1=883379&r2=883380&view=diff
==============================================================================
--- mina/sandbox/vysper/trunk/server/extensions/xep0045-muc/src/test/java/org/apache/vysper/xmpp/modules/extension/xep0045_muc/handler/MUCPresenceHandlerChangeNickTestCase.java (original)
+++ mina/sandbox/vysper/trunk/server/extensions/xep0045-muc/src/test/java/org/apache/vysper/xmpp/modules/extension/xep0045_muc/handler/MUCPresenceHandlerChangeNickTestCase.java Mon Nov 23 15:47:53 2009
@@ -26,7 +26,7 @@
 
     private Stanza changeNick(Entity occupantJid, Entity roomWithNickJid) throws ProtocolException {
         StanzaBuilder stanzaBuilder = StanzaBuilder.createPresenceStanza(occupantJid, roomWithNickJid, null, null, null, null);
-        stanzaBuilder.startInnerElement("x").addNamespaceAttribute(NamespaceURIs.XEP0045_MUC);
+        stanzaBuilder.startInnerElement("x", NamespaceURIs.XEP0045_MUC);
         
         stanzaBuilder.endInnerElement();
         Stanza presenceStanza = stanzaBuilder.getFinalStanza();

Modified: mina/sandbox/vysper/trunk/server/extensions/xep0045-muc/src/test/java/org/apache/vysper/xmpp/modules/extension/xep0045_muc/handler/MUCPresenceHandlerEnterRoomTestCase.java
URL: http://svn.apache.org/viewvc/mina/sandbox/vysper/trunk/server/extensions/xep0045-muc/src/test/java/org/apache/vysper/xmpp/modules/extension/xep0045_muc/handler/MUCPresenceHandlerEnterRoomTestCase.java?rev=883380&r1=883379&r2=883380&view=diff
==============================================================================
--- mina/sandbox/vysper/trunk/server/extensions/xep0045-muc/src/test/java/org/apache/vysper/xmpp/modules/extension/xep0045_muc/handler/MUCPresenceHandlerEnterRoomTestCase.java (original)
+++ mina/sandbox/vysper/trunk/server/extensions/xep0045-muc/src/test/java/org/apache/vysper/xmpp/modules/extension/xep0045_muc/handler/MUCPresenceHandlerEnterRoomTestCase.java Mon Nov 23 15:47:53 2009
@@ -1,5 +1,6 @@
 package org.apache.vysper.xmpp.modules.extension.xep0045_muc.handler;
 
+import java.util.ArrayList;
 import java.util.Arrays;
 import java.util.List;
 
@@ -10,6 +11,8 @@
 import org.apache.vysper.xmpp.modules.extension.xep0045_muc.model.Room;
 import org.apache.vysper.xmpp.modules.extension.xep0045_muc.model.RoomType;
 import org.apache.vysper.xmpp.modules.extension.xep0045_muc.stanzas.History;
+import org.apache.vysper.xmpp.modules.extension.xep0045_muc.stanzas.Password;
+import org.apache.vysper.xmpp.modules.extension.xep0045_muc.stanzas.X;
 import org.apache.vysper.xmpp.protocol.NamespaceURIs;
 import org.apache.vysper.xmpp.protocol.ProtocolException;
 import org.apache.vysper.xmpp.protocol.ResponseStanzaContainer;
@@ -44,15 +47,14 @@
         
         StanzaBuilder stanzaBuilder = StanzaBuilder.createPresenceStanza(occupantJid, roomJid, null, null, null, null);
         if(!oldProtocol) {
-            stanzaBuilder.startInnerElement("x").addNamespaceAttribute(NamespaceURIs.XEP0045_MUC);
+        	List<XMLElement> xInnerElms = new ArrayList<XMLElement>();
             if(password != null) {
-                stanzaBuilder.startInnerElement("password").addText(password).endInnerElement();
+            	xInnerElms.add(new Password(password));
             }
             if(history != null) {
-                stanzaBuilder.addPreparedElement(history);
+            	xInnerElms.add(history);
             }
-            
-            stanzaBuilder.endInnerElement();
+            stanzaBuilder.addPreparedElement(new X(xInnerElms));
         }
         Stanza presenceStanza = stanzaBuilder.getFinalStanza();
         ResponseStanzaContainer container = handler.execute(presenceStanza, userSessionContext.getServerRuntimeContext(), true, userSessionContext, null);