001 /**
002 * Licensed to the Apache Software Foundation (ASF) under one
003 * or more contributor license agreements. See the NOTICE file
004 * distributed with this work for additional information
005 * regarding copyright ownership. The ASF licenses this file
006 * to you under the Apache License, Version 2.0 (the
007 * "License"); you may not use this file except in compliance
008 * with the License. You may obtain a copy of the License at
009 *
010 * http://www.apache.org/licenses/LICENSE-2.0
011 *
012 * Unless required by applicable law or agreed to in writing,
013 * software distributed under the License is distributed on an
014 * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
015 * KIND, either express or implied. See the License for the
016 * specific language governing permissions and limitations
017 * under the License.
018 */
019
020 package org.apache.geronimo.testsupport;
021
022 import java.io.StringReader;
023
024 import javax.xml.parsers.DocumentBuilder;
025 import javax.xml.parsers.DocumentBuilderFactory;
026 import javax.xml.parsers.ParserConfigurationException;
027
028 import org.w3c.dom.Attr;
029 import org.w3c.dom.Document;
030 import org.w3c.dom.Element;
031 import org.w3c.dom.NamedNodeMap;
032 import org.w3c.dom.Node;
033 import org.w3c.dom.NodeList;
034 import org.w3c.dom.Text;
035 import org.xml.sax.InputSource;
036
037 /**
038 * @version $Rev: 706640 $ $Date: 2008-10-21 14:44:05 +0000 (Tue, 21 Oct 2008) $
039 */
040 public class DOMUtils {
041
042 public static Document load(String xml) throws Exception {
043 DocumentBuilder builder = getDocumentBuilder();
044 Document document = builder.parse(new InputSource(new StringReader(xml)));
045 return document;
046 }
047
048 public static DocumentBuilder getDocumentBuilder() throws ParserConfigurationException {
049 DocumentBuilderFactory builderFactory = DocumentBuilderFactory.newInstance();
050 builderFactory.setNamespaceAware(true);
051 DocumentBuilder builder = builderFactory.newDocumentBuilder();
052 return builder;
053 }
054
055 public static void compareNodes(Node expected, Node actual) throws Exception {
056 if (expected.getNodeType() != actual.getNodeType()) {
057 throw new Exception("Different types of nodes: " + expected + " " + actual);
058 }
059 if (expected instanceof Document) {
060 Document expectedDoc = (Document)expected;
061 Document actualDoc = (Document)actual;
062 compareNodes(expectedDoc.getDocumentElement(), actualDoc.getDocumentElement());
063 } else if (expected instanceof Element) {
064 Element expectedElement = (Element)expected;
065 Element actualElement = (Element)actual;
066
067 // compare element names
068 if (!expectedElement.getLocalName().equals(actualElement.getLocalName())) {
069 throw new Exception("Element names do not match: " + expectedElement.getLocalName() + " " + actualElement.getLocalName());
070 }
071 // compare element ns
072 String expectedNS = expectedElement.getNamespaceURI();
073 String actualNS = actualElement.getNamespaceURI();
074 if ((expectedNS == null && actualNS != null) || (expectedNS != null && !expectedNS.equals(actualNS))) {
075 throw new Exception("Element namespaces names do not match: " + expectedNS + " " + actualNS);
076 }
077
078 String elementName = "{" + expectedElement.getNamespaceURI() + "}" + actualElement.getLocalName();
079
080 // compare attributes
081 NamedNodeMap expectedAttrs = expectedElement.getAttributes();
082 NamedNodeMap actualAttrs = actualElement.getAttributes();
083 if (countNonNamespaceAttribures(expectedAttrs) != countNonNamespaceAttribures(actualAttrs)) {
084 throw new Exception(elementName + ": Number of attributes do not match up: " + countNonNamespaceAttribures(expectedAttrs) + " " + countNonNamespaceAttribures(actualAttrs));
085 }
086 for (int i = 0; i < expectedAttrs.getLength(); i++) {
087 Attr expectedAttr = (Attr)expectedAttrs.item(i);
088 if (expectedAttr.getName().startsWith("xmlns")) {
089 continue;
090 }
091 Attr actualAttr = null;
092 if (expectedAttr.getNamespaceURI() == null) {
093 actualAttr = (Attr)actualAttrs.getNamedItem(expectedAttr.getName());
094 } else {
095 actualAttr = (Attr)actualAttrs.getNamedItemNS(expectedAttr.getNamespaceURI(), expectedAttr.getLocalName());
096 }
097 if (actualAttr == null) {
098 throw new Exception(elementName + ": No attribute found:" + expectedAttr);
099 }
100 if (!expectedAttr.getValue().equals(actualAttr.getValue())) {
101 throw new Exception(elementName + ": Attribute values do not match: " + expectedAttr.getValue() + " " + actualAttr.getValue());
102 }
103 }
104
105 // compare children
106 NodeList expectedChildren = expectedElement.getChildNodes();
107 NodeList actualChildren = actualElement.getChildNodes();
108 if (expectedChildren.getLength() != actualChildren.getLength()) {
109 throw new Exception(elementName + ": Number of children do not match up: " + expectedChildren.getLength() + " " + actualChildren.getLength());
110 }
111 for (int i = 0; i < expectedChildren.getLength(); i++) {
112 Node expectedChild = expectedChildren.item(i);
113 Node actualChild = actualChildren.item(i);
114 compareNodes(expectedChild, actualChild);
115 }
116 } else if (expected instanceof Text) {
117 String expectedData = ((Text)expected).getData();
118 String actualData = ((Text)actual).getData();
119
120 if (!expectedData.equals(actualData)) {
121 throw new Exception("Text does not match: " + expectedData + " " + actualData);
122 }
123 }
124 }
125
126 private static int countNonNamespaceAttribures(NamedNodeMap attrs) {
127 int n = 0;
128 for (int i = 0; i< attrs.getLength(); i++ ) {
129 Attr attr = (Attr) attrs.item(i);
130 if (!attr.getName().startsWith("xmlns")) {
131 n++;
132 }
133 }
134 return n;
135 }
136
137 }