| /******************************************************************************* |
| * Copyright (c) 2003, 2007 IBM Corporation and others. |
| * All rights reserved. This program and the accompanying materials |
| * are made available under the terms of the Eclipse Public License v1.0 |
| * which accompanies this distribution, and is available at |
| * http://www.eclipse.org/legal/epl-v10.html |
| * |
| * Contributors: |
| * IBM Corporation - Initial API and implementation |
| *******************************************************************************/ |
| package org.eclipse.jst.server.tomcat.core.internal.xml; |
| |
| import java.util.LinkedHashMap; |
| import java.util.Map; |
| |
| import org.w3c.dom.*; |
| /** |
| * An XML element. |
| */ |
| public class XMLElement { |
| private Element xmlElement; |
| protected Factory factory; |
| |
| public XMLElement() { |
| // do nothing |
| } |
| |
| public Element getElementNode() { |
| return xmlElement; |
| } |
| |
| public Attr addAttribute(String s, String s1) { |
| Attr attr = factory.createAttribute(s, xmlElement); |
| attr.setValue(s1); |
| return attr; |
| } |
| |
| public XMLElement createElement(int index, String s) { |
| return factory.createElement(index, s, xmlElement); |
| } |
| |
| public XMLElement createElement(String s) { |
| return factory.createElement(s, xmlElement); |
| } |
| |
| public XMLElement findElement(String s) { |
| NodeList nodelist = xmlElement.getElementsByTagName(s); |
| int i = nodelist == null ? 0 : nodelist.getLength(); |
| for (int j = 0; j < i; j++) { |
| Node node = nodelist.item(j); |
| String s1 = node.getNodeName().trim(); |
| if (s1.equals(s)) |
| return factory.newInstance((Element) node); |
| } |
| |
| return createElement(s); |
| } |
| |
| public XMLElement findElement(String s, int i) { |
| NodeList nodelist = xmlElement.getElementsByTagName(s); |
| int j = nodelist == null ? 0 : nodelist.getLength(); |
| for (int k = 0; k < j; k++) { |
| Node node = nodelist.item(k); |
| String s1 = node.getNodeName().trim(); |
| if (s1.equals(s) && k == i) |
| return factory.newInstance((Element) node); |
| } |
| |
| return createElement(s); |
| } |
| |
| public String getAttributeValue(String s) { |
| Attr attr = xmlElement.getAttributeNode(s); |
| if (attr != null) |
| return attr.getValue(); |
| |
| return null; |
| } |
| |
| public Map getAttributes() { |
| Map attributes = new LinkedHashMap(); |
| NamedNodeMap attrs = xmlElement.getAttributes(); |
| if (null != attrs) { |
| for (int i = 0; i < attrs.getLength(); i++) { |
| Node attr = attrs.item(i); |
| String name = attr.getNodeName(); |
| String value = attr.getNodeValue(); |
| attributes.put(name, value); |
| } |
| } |
| return attributes; |
| } |
| |
| public String getElementName() { |
| return xmlElement.getNodeName(); |
| } |
| |
| public String getElementValue() { |
| return getElementValue(xmlElement); |
| } |
| |
| protected static String getElementValue(Element element) { |
| String s = element.getNodeValue(); |
| if (s != null) |
| return s; |
| NodeList nodelist = element.getChildNodes(); |
| for (int i = 0; i < nodelist.getLength(); i++) |
| if (nodelist.item(i) instanceof Text) |
| return ((Text) nodelist.item(i)).getData(); |
| |
| return null; |
| } |
| |
| public Element getSubElement(String s) { |
| NodeList nodelist = xmlElement.getElementsByTagName(s); |
| int i = nodelist == null ? 0 : nodelist.getLength(); |
| for (int j = 0; j < i; j++) { |
| Node node = nodelist.item(j); |
| String s1 = node.getNodeName().trim(); |
| if (s1.equals(s)) |
| return (Element) node; |
| } |
| |
| return null; |
| } |
| |
| public String getSubElementValue(String s) { |
| Element element = getSubElement(s); |
| if (element == null) |
| return null; |
| |
| String value = getElementValue(element); |
| if (value == null) |
| return null; |
| |
| return value.trim(); |
| } |
| |
| public boolean removeAttribute(String s) { |
| try { |
| xmlElement.removeAttribute(s); |
| return true; |
| } catch (Exception ex) { |
| return false; |
| } |
| } |
| |
| public boolean removeElement(String s, int i) { |
| NodeList nodelist = xmlElement.getElementsByTagName(s); |
| int j = nodelist == null ? 0 : nodelist.getLength(); |
| for (int k = 0; k < j; k++) { |
| Node node = nodelist.item(k); |
| String s1 = node.getNodeName().trim(); |
| if (s1.equals(s) && k == i) { |
| xmlElement.removeChild(node); |
| return true; |
| } |
| } |
| |
| return false; |
| } |
| |
| public void setAttributeValue(String s, String s1) { |
| Attr attr = xmlElement.getAttributeNode(s); |
| if (attr == null) |
| attr = addAttribute(s, s1); |
| else |
| attr.setValue(s1); |
| } |
| |
| void setElement(Element element) { |
| xmlElement = element; |
| } |
| |
| protected static void setElementValue(Element element, String value) { |
| String s = element.getNodeValue(); |
| if (s != null) { |
| element.setNodeValue(value); |
| return; |
| } |
| NodeList nodelist = element.getChildNodes(); |
| for (int i = 0; i < nodelist.getLength(); i++) |
| if (nodelist.item(i) instanceof Text) { |
| Text text = (Text) nodelist.item(i); |
| text.setData(value); |
| return; |
| } |
| |
| return; |
| } |
| |
| void setFactory(Factory factory1) { |
| factory = factory1; |
| } |
| |
| public void setSubElementValue(String s, String value) { |
| Element element = getSubElement(s); |
| if (element == null) { |
| element = factory.document.createElement(s); |
| element.appendChild(factory.document.createTextNode("temp")); |
| xmlElement.appendChild(element); |
| } |
| setElementValue(element, value); |
| } |
| |
| public int sizeOfElement(String s) { |
| NodeList nodelist = xmlElement.getElementsByTagName(s); |
| int i = nodelist == null ? 0 : nodelist.getLength(); |
| return i; |
| } |
| |
| public void updateElementValue(String s) { |
| try { |
| xmlElement.setNodeValue(s); |
| } catch (DOMException ex) { |
| NodeList nodelist = xmlElement.getChildNodes(); |
| int i = nodelist == null ? 0 : nodelist.getLength(); |
| if (i > 0) { |
| for (int j = 0; j < i; j++) |
| if (nodelist.item(j) instanceof Text) { |
| ((Text) nodelist.item(j)).setData(s); |
| return; |
| } |
| } else { |
| xmlElement.appendChild(factory.document.createTextNode(s)); |
| } |
| } |
| } |
| |
| public boolean hasChildNodes() { |
| return xmlElement.hasChildNodes(); |
| } |
| |
| public void removeChildren() |
| { |
| while (xmlElement.hasChildNodes()) { |
| xmlElement.removeChild(xmlElement.getFirstChild()); |
| } |
| } |
| |
| public void copyChildrenTo(XMLElement destination) { |
| NodeList nodelist = xmlElement.getChildNodes(); |
| int len = nodelist == null ? 0 : nodelist.getLength(); |
| for (int i = 0; i < len; i++) { |
| Node node = nodelist.item(i); |
| destination.importNode(node, true); |
| } |
| } |
| |
| public void importNode(Node node, boolean deep) { |
| xmlElement.appendChild(xmlElement.getOwnerDocument().importNode(node, deep)); |
| } |
| |
| /** |
| * This method tries to compare two XMLElements for equivalence. Due to |
| * the lack of normalization, they aren't compared for equality. Elements |
| * are required to have the same attributes or the same node value |
| * if attributes aren't present. Attributes and node value are assumed |
| * to be mutually exclusive for Tomcat configuration XML files. The |
| * same non-text child nodes are required to be present in an element |
| * and appear in the same order. If a node type other than element or |
| * comment is encountered, this method punts and returns false. |
| * |
| * @param obj XMLElement to compare |
| * @return true if the elements are equivalent |
| */ |
| public boolean isEquivalent(XMLElement obj) { |
| if (obj != null) { |
| try { |
| return elementsAreEquivalent(xmlElement, obj.getElementNode()); |
| } |
| catch (Exception e) { |
| // Catch and ignore just to be safe |
| } |
| } |
| return false; |
| } |
| |
| /** |
| * Same as isEquivalent() but doesn't ignore exceptions for test purposes. |
| * This avoids hiding an expected mismatch behind an unexpected exception. |
| * |
| * @param obj XMLElement to compare |
| * @return true if the elements are equivalent |
| */ |
| public boolean isEquivalentTest(XMLElement obj) { |
| if (obj != null) { |
| return elementsAreEquivalent(xmlElement, obj.getElementNode()); |
| } |
| return false; |
| } |
| |
| private static boolean elementsAreEquivalent(Element element, Element otherElement) { |
| if (element == otherElement) |
| return true; |
| |
| if (!element.getNodeName().equals(otherElement.getNodeName())) |
| return false; |
| |
| if (element.hasChildNodes()) { |
| if (otherElement.hasChildNodes() && attributesAreEqual(element, otherElement)) { |
| // Compare child nodes |
| NodeList nodelist = element.getChildNodes(); |
| NodeList otherNodelist = otherElement.getChildNodes(); |
| if (nodelist.getLength() == otherNodelist.getLength()) { |
| Node node = nextNonTextNode(element.getFirstChild()); |
| Node otherNode = nextNonTextNode(otherElement.getFirstChild()); |
| while (node != null) { |
| if (otherNode == null) |
| return false; |
| short nextNodeType = node.getNodeType(); |
| if (nextNodeType != otherNode.getNodeType()) |
| return false; |
| // If elements, compare |
| if (nextNodeType == Node.ELEMENT_NODE) { |
| if (!elementsAreEquivalent((Element)node, (Element)otherNode)) |
| return false; |
| } |
| // Else if comment, compare |
| else if (nextNodeType == Node.COMMENT_NODE) { |
| if (!nodeValuesAreEqual(node, otherNode)) |
| return false; |
| } |
| // Else punt on other node types |
| else { |
| return false; |
| } |
| node = nextNonTextNode(node.getNextSibling()); |
| otherNode = nextNonTextNode(otherNode.getNextSibling()); |
| } |
| // If also at end of other children, return equal |
| if (otherNode == null) |
| return true; |
| } |
| } |
| } |
| else if (!otherElement.hasChildNodes()) { |
| return attributesAreEqual(element, otherElement); |
| } |
| return false; |
| } |
| |
| private static Node nextNonTextNode(Node node) { |
| while (node != null && node.getNodeType() == Node.TEXT_NODE) |
| node = node.getNextSibling(); |
| return node; |
| } |
| |
| private static boolean attributesAreEqual(Element element, Element otherElement) { |
| NamedNodeMap attrs = element.getAttributes(); |
| NamedNodeMap otherAttrs = otherElement.getAttributes(); |
| if (attrs == null && otherAttrs == null) { |
| // Return comparison of element values if there are no attributes |
| return nodeValuesAreEqual(element, otherElement); |
| } |
| |
| if (attrs.getLength() == otherAttrs.getLength()) { |
| if (attrs.getLength() == 0) |
| // Return comparison of element values if there are no attributes |
| return nodeValuesAreEqual(element, otherElement); |
| |
| for (int i = 0; i < attrs.getLength(); i++) { |
| Node attr = attrs.item(i); |
| Node otherAttr = otherAttrs.getNamedItem(attr.getNodeName()); |
| if (!nodeValuesAreEqual(attr, otherAttr)) |
| return false; |
| } |
| return true; |
| } |
| return false; |
| } |
| |
| private static boolean nodeValuesAreEqual(Node node, Node otherNode) { |
| String value = node.getNodeValue(); |
| String otherValue = otherNode.getNodeValue(); |
| if (value != null && otherValue != null) { |
| if (value.equals(otherValue)) |
| return true; |
| } |
| else if (value == null && otherValue == null) |
| return true; |
| return false; |
| } |
| } |