5c099afa7c9361afc2f4477fec0e3018588d7840Allan Foster * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS HEADER.
5c099afa7c9361afc2f4477fec0e3018588d7840Allan Foster * Copyright (c) 2006 Sun Microsystems Inc. All Rights Reserved
5c099afa7c9361afc2f4477fec0e3018588d7840Allan Foster * The contents of this file are subject to the terms
5c099afa7c9361afc2f4477fec0e3018588d7840Allan Foster * of the Common Development and Distribution License
5c099afa7c9361afc2f4477fec0e3018588d7840Allan Foster * (the License). You may not use this file except in
5c099afa7c9361afc2f4477fec0e3018588d7840Allan Foster * compliance with the License.
5c099afa7c9361afc2f4477fec0e3018588d7840Allan Foster * You can obtain a copy of the License at
5c099afa7c9361afc2f4477fec0e3018588d7840Allan Foster * https://opensso.dev.java.net/public/CDDLv1.0.html or
5c099afa7c9361afc2f4477fec0e3018588d7840Allan Foster * See the License for the specific language governing
5c099afa7c9361afc2f4477fec0e3018588d7840Allan Foster * permission and limitations under the License.
5c099afa7c9361afc2f4477fec0e3018588d7840Allan Foster * When distributing Covered Code, include this CDDL
5c099afa7c9361afc2f4477fec0e3018588d7840Allan Foster * Header Notice in each file and include the License file
5c099afa7c9361afc2f4477fec0e3018588d7840Allan Foster * If applicable, add the following below the CDDL Header,
5c099afa7c9361afc2f4477fec0e3018588d7840Allan Foster * with the fields enclosed by brackets [] replaced by
5c099afa7c9361afc2f4477fec0e3018588d7840Allan Foster * your own identifying information:
5c099afa7c9361afc2f4477fec0e3018588d7840Allan Foster * "Portions Copyrighted [year] [name of copyright owner]"
5c099afa7c9361afc2f4477fec0e3018588d7840Allan Foster * $Id: XMLUtils.java,v 1.15 2009/10/19 18:19:20 asyhuang Exp $
3286da3756e1d2f07709aafdbc5419b26ff71dffPhill Cunnington * Portions Copyrighted 2011-2014 ForgeRock AS.
5c099afa7c9361afc2f4477fec0e3018588d7840Allan Fosterimport com.sun.identity.shared.configuration.SystemPropertiesManager;
5c099afa7c9361afc2f4477fec0e3018588d7840Allan Fosterimport com.sun.identity.shared.datastruct.OrderedSet;
9c1ec205dd4a7c6a5a2b06fa7385cf5b33274208Neil Maddenimport org.forgerock.openam.utils.DocumentBuilderProvider;
9c1ec205dd4a7c6a5a2b06fa7385cf5b33274208Neil Maddenimport org.forgerock.openam.utils.SAXParserProvider;
9c1ec205dd4a7c6a5a2b06fa7385cf5b33274208Neil Maddenimport javax.xml.parsers.ParserConfigurationException;
564945e59b60a40c3b9458177b2ff63e2947686cPeter Majorimport org.forgerock.openam.utils.TransformerFactoryProvider;
5c099afa7c9361afc2f4477fec0e3018588d7840Allan Foster * This class contains utilities to parse XML documents
5c099afa7c9361afc2f4477fec0e3018588d7840Allan Foster private static final Map EMPTY_MAP = Collections
5c099afa7c9361afc2f4477fec0e3018588d7840Allan Foster // property to see if XML document validating is needed. The validating
5c099afa7c9361afc2f4477fec0e3018588d7840Allan Foster // is turned on only if the value for com.iplanet.am.util.xml.validating
5c099afa7c9361afc2f4477fec0e3018588d7840Allan Foster // property is set to "on" and value for com.iplanet.services.debug.level
5c099afa7c9361afc2f4477fec0e3018588d7840Allan Foster // property is set to "warning" or "message".
5c099afa7c9361afc2f4477fec0e3018588d7840Allan Foster "com_sun_identity_opensso_base64_encoded";
5c099afa7c9361afc2f4477fec0e3018588d7840Allan Foster private static int ATTR_BASE64_ENCODED_LENGTH =
2abcab75a7045a74128f7995dce24aa2e6a28e01Jon Jonthomas private static final String INVALID_XML_CHARACTERS = "[\u0000-\u0008\u000b-\u001f\ufffe\uffff]";
5c099afa7c9361afc2f4477fec0e3018588d7840Allan Foster String debugLevel = SystemPropertiesManager.get(
5c099afa7c9361afc2f4477fec0e3018588d7840Allan Foster (debugLevel.trim().equalsIgnoreCase("warning") ||
5c099afa7c9361afc2f4477fec0e3018588d7840Allan Foster // ignore since there is not debug class here
9c1ec205dd4a7c6a5a2b06fa7385cf5b33274208Neil Madden * Size of document builder cache.
564945e59b60a40c3b9458177b2ff63e2947686cPeter Major private static final int DOCBUILDER_CACHE_SIZE =
564945e59b60a40c3b9458177b2ff63e2947686cPeter Major SystemPropertiesManager.getAsInt(Constants.XML_DOCUMENT_BUILDER_CACHE_SIZE, 500);
9c1ec205dd4a7c6a5a2b06fa7385cf5b33274208Neil Madden * Size of the SAXParser cache. Defaults to same size as document builder cache.
564945e59b60a40c3b9458177b2ff63e2947686cPeter Major SystemPropertiesManager.getAsInt(Constants.XML_SAXPARSER_CACHE_SIZE, DOCBUILDER_CACHE_SIZE);
564945e59b60a40c3b9458177b2ff63e2947686cPeter Major private static final int TRANSFORMER_FACTORY_CACHE_SIZE =
564945e59b60a40c3b9458177b2ff63e2947686cPeter Major SystemPropertiesManager.getAsInt(Constants.XML_TRANSFORMER_FACTORY_CACHE_SIZE, 500);
9c1ec205dd4a7c6a5a2b06fa7385cf5b33274208Neil Madden * Provider for DocumentBuilder instances. Caches in an LRU cache per thread.
564945e59b60a40c3b9458177b2ff63e2947686cPeter Major private static final DocumentBuilderProvider DOCUMENT_BUILDER_PROVIDER =
564945e59b60a40c3b9458177b2ff63e2947686cPeter Major Providers.documentBuilderProvider(DOCBUILDER_CACHE_SIZE);
564945e59b60a40c3b9458177b2ff63e2947686cPeter Major * Provider for SAXParser instances. Caches in a per-thread LRU cache.
9c1ec205dd4a7c6a5a2b06fa7385cf5b33274208Neil Madden private static final SAXParserProvider SAX_PARSER_PROVIDER = Providers.saxParserProvider(SAXPARSER_CACHE_SIZE);
564945e59b60a40c3b9458177b2ff63e2947686cPeter Major * Provider for TransformerFactory instances. Caches in a per-thread LRU cache.
564945e59b60a40c3b9458177b2ff63e2947686cPeter Major private static final TransformerFactoryProvider TRANSFORMER_FACTORY_PROVIDER =
564945e59b60a40c3b9458177b2ff63e2947686cPeter Major Providers.transformerFactoryProvider(TRANSFORMER_FACTORY_CACHE_SIZE);
5c099afa7c9361afc2f4477fec0e3018588d7840Allan Foster * Converts the XML document from a String format to DOM Document format.
5c099afa7c9361afc2f4477fec0e3018588d7840Allan Foster * @param xmlString
5c099afa7c9361afc2f4477fec0e3018588d7840Allan Foster * is the XML document in a String format
5c099afa7c9361afc2f4477fec0e3018588d7840Allan Foster * @param debug
5c099afa7c9361afc2f4477fec0e3018588d7840Allan Foster * is the debug object used for logging debug info
5c099afa7c9361afc2f4477fec0e3018588d7840Allan Foster * @return Document is the DOM object obtained by converting the String XML
5c099afa7c9361afc2f4477fec0e3018588d7840Allan Foster * Returns null if xmlString is null. Returns null if there are any
5c099afa7c9361afc2f4477fec0e3018588d7840Allan Foster * parser errores.
5c099afa7c9361afc2f4477fec0e3018588d7840Allan Foster public static Document toDOMDocument(String xmlString, Debug debug) {
5c099afa7c9361afc2f4477fec0e3018588d7840Allan Foster if ((xmlString == null) || (xmlString.length() == 0)) {
5c099afa7c9361afc2f4477fec0e3018588d7840Allan Foster ByteArrayInputStream is = new ByteArrayInputStream(xmlString
5c099afa7c9361afc2f4477fec0e3018588d7840Allan Foster debug.warning("Can't parse the XML document:\n" + xmlString,
5c099afa7c9361afc2f4477fec0e3018588d7840Allan Foster * Converts the XML document from an input stream to DOM Document format.
5c099afa7c9361afc2f4477fec0e3018588d7840Allan Foster * is the InputStream that contains XML document
5c099afa7c9361afc2f4477fec0e3018588d7840Allan Foster * @return Document is the DOM object obtained by parsing the input stream.
5c099afa7c9361afc2f4477fec0e3018588d7840Allan Foster * Returns null if there are any parser errores.
5c099afa7c9361afc2f4477fec0e3018588d7840Allan Foster public static Document toDOMDocument(InputStream is, Debug debug) {
5c099afa7c9361afc2f4477fec0e3018588d7840Allan Foster // Assign new debug object
23e304384f98fca4ab2e6f9f07a53465c1bfc645Peter Major documentBuilder = getSafeDocumentBuilder(validating);
23e304384f98fca4ab2e6f9f07a53465c1bfc645Peter Major debug.error("XMLUtils.DocumentBuilder init failed", pe);
5c099afa7c9361afc2f4477fec0e3018588d7840Allan Foster debug.error("XMLUtils.toDOM : null builder instance");
5c099afa7c9361afc2f4477fec0e3018588d7840Allan Foster documentBuilder.setErrorHandler(new ValidationErrorHandler(
5c099afa7c9361afc2f4477fec0e3018588d7840Allan Foster // Since there may potentially be several invalid XML documents
5c099afa7c9361afc2f4477fec0e3018588d7840Allan Foster // that are mostly client-side errors, only a warning is logged for
5c099afa7c9361afc2f4477fec0e3018588d7840Allan Foster // efficiency reasons.
5c099afa7c9361afc2f4477fec0e3018588d7840Allan Foster debug.warning("Can't parse the XML document", e);
5c099afa7c9361afc2f4477fec0e3018588d7840Allan Foster * This method parse an Attributes tag, DTD for Attribute is as follows.
5c099afa7c9361afc2f4477fec0e3018588d7840Allan Foster * < !-- This DTD defines the DPro Attribute tag.
5c099afa7c9361afc2f4477fec0e3018588d7840Allan Foster * Unique Declaration name for DOCTYPE tag:
5c099afa7c9361afc2f4477fec0e3018588d7840Allan Foster * "Directory Pro 5.0 Attributes DTD"
5c099afa7c9361afc2f4477fec0e3018588d7840Allan Foster * < !ELEMENT Attributes (Attribute)+>
5c099afa7c9361afc2f4477fec0e3018588d7840Allan Foster * < !ELEMENT Attribute EMPTY>
5c099afa7c9361afc2f4477fec0e3018588d7840Allan Foster * < !ATTLIST Attribute
5c099afa7c9361afc2f4477fec0e3018588d7840Allan Foster * name NMTOKEN #REQUIRED
5c099afa7c9361afc2f4477fec0e3018588d7840Allan Foster * @return Set Set of the attribute names
5c099afa7c9361afc2f4477fec0e3018588d7840Allan Foster // get Attribute node list
5c099afa7c9361afc2f4477fec0e3018588d7840Allan Foster final int numAttributes = attributes.getLength();
5c099afa7c9361afc2f4477fec0e3018588d7840Allan Foster // get next attribute
5c099afa7c9361afc2f4477fec0e3018588d7840Allan Foster // need error handling
5c099afa7c9361afc2f4477fec0e3018588d7840Allan Foster set.add(((Element) attr).getAttribute("name"));
5c099afa7c9361afc2f4477fec0e3018588d7840Allan Foster * @param parentNode
5c099afa7c9361afc2f4477fec0e3018588d7840Allan Foster * is the element tag that contains all the AttirbuteValuePair
5c099afa7c9361afc2f4477fec0e3018588d7840Allan Foster * tags as children
5c099afa7c9361afc2f4477fec0e3018588d7840Allan Foster * @return Map Returns the AV pairs in a Map where each entry in the Map is
5c099afa7c9361afc2f4477fec0e3018588d7840Allan Foster * an AV pair. The key is the attribute name and the value is a Set
5c099afa7c9361afc2f4477fec0e3018588d7840Allan Foster * of String objects.
3541688024dba67a647e29de859a327fc1018b05Andrew Forrest public static Map<String, Set<String>> parseAttributeValuePairTags(Node parentNode) {
3541688024dba67a647e29de859a327fc1018b05Andrew Forrest NodeList keyValueList = parentNode.getChildNodes();
3541688024dba67a647e29de859a327fc1018b05Andrew Forrest if (keyValueNode.getNodeType() != Node.ELEMENT_NODE ||
3541688024dba67a647e29de859a327fc1018b05Andrew Forrest !keyValueNode.getNodeName().equals("AttributeValuePair")) {
3541688024dba67a647e29de859a327fc1018b05Andrew Forrest NodeList keyValueEntryList = keyValueNode.getChildNodes();
3541688024dba67a647e29de859a327fc1018b05Andrew Forrest int keyValueEntrySize = keyValueEntryList.getLength();
5c099afa7c9361afc2f4477fec0e3018588d7840Allan Foster // TODO: More error handling required later for missing
3541688024dba67a647e29de859a327fc1018b05Andrew Forrest // 'Attribute' or 'Value' tags.
3541688024dba67a647e29de859a327fc1018b05Andrew Forrest // Since Attribute tag is always the first leaf node as per the DTD, and values can one or more,
3541688024dba67a647e29de859a327fc1018b05Andrew Forrest // Attribute tag can be parsed first and then iterate over the values, if any.
3541688024dba67a647e29de859a327fc1018b05Andrew Forrest for (int i = 0; i < keyValueEntrySize; i++) {
3541688024dba67a647e29de859a327fc1018b05Andrew Forrest if (keyNode.getNodeType() == Node.ELEMENT_NODE &&
3541688024dba67a647e29de859a327fc1018b05Andrew Forrest final String key = ((Element)keyNode).getAttribute("name");
3541688024dba67a647e29de859a327fc1018b05Andrew Forrest // Now parse the Value tags. If there are not 'Value' tags, ignore this key
5c099afa7c9361afc2f4477fec0e3018588d7840Allan Foster // TODO: More error handling required later for zero 'Value' tags.
3541688024dba67a647e29de859a327fc1018b05Andrew Forrest for (int m = 0; m < keyValueEntrySize; m++) {
3541688024dba67a647e29de859a327fc1018b05Andrew Forrest if (valueNode.getNodeType() != Node.ELEMENT_NODE
5c099afa7c9361afc2f4477fec0e3018588d7840Allan Foster // TODO: Error handling required here
5c099afa7c9361afc2f4477fec0e3018588d7840Allan Foster // No 'Value' tags found. So ignore this key.
5c099afa7c9361afc2f4477fec0e3018588d7840Allan Foster // TODO: More error handling required later for zero
3541688024dba67a647e29de859a327fc1018b05Andrew Forrest // 'Value' tags.
3541688024dba67a647e29de859a327fc1018b05Andrew Forrest resultMap = new HashMap<String, Set<String>>();
3541688024dba67a647e29de859a327fc1018b05Andrew Forrest return resultMap == null ? EMPTY_MAP : resultMap;
5c099afa7c9361afc2f4477fec0e3018588d7840Allan Foster * Obtains a new instance of a DOM Document object
5c099afa7c9361afc2f4477fec0e3018588d7840Allan Foster * @return a new instance of a DOM Document object
5c099afa7c9361afc2f4477fec0e3018588d7840Allan Foster * @exception Exception
5c099afa7c9361afc2f4477fec0e3018588d7840Allan Foster * if an error occurs while constructing a new document
5c099afa7c9361afc2f4477fec0e3018588d7840Allan Foster public static Document newDocument() throws ParserConfigurationException {
23e304384f98fca4ab2e6f9f07a53465c1bfc645Peter Major return getSafeDocumentBuilder(validating).newDocument();
5c099afa7c9361afc2f4477fec0e3018588d7840Allan Foster public static Document getXMLDocument(InputStream in) throws Exception {
23e304384f98fca4ab2e6f9f07a53465c1bfc645Peter Major DocumentBuilder builder = getSafeDocumentBuilder(validating);
5c099afa7c9361afc2f4477fec0e3018588d7840Allan Foster Object params[] = { new Integer(pe.getLineNumber()) };
23e304384f98fca4ab2e6f9f07a53465c1bfc645Peter Major throw new Exception(msg + "XMLUtils.parser_error" + params);
23e304384f98fca4ab2e6f9f07a53465c1bfc645Peter Major throw new Exception("XMLUtils.exception_message" + params);
23e304384f98fca4ab2e6f9f07a53465c1bfc645Peter Major throw new Exception("XMLUtils.invalid_xml_document" + params);
23e304384f98fca4ab2e6f9f07a53465c1bfc645Peter Major throw new Exception("XMLUtils.invalid_input_stream" + params);
5c099afa7c9361afc2f4477fec0e3018588d7840Allan Foster public static Node getRootNode(Document doc, String nodeName) {
5c099afa7c9361afc2f4477fec0e3018588d7840Allan Foster NodeList nodes = doc.getElementsByTagName(nodeName);
5c099afa7c9361afc2f4477fec0e3018588d7840Allan Foster public static Node getChildNode(Node parentNode, String childName) {
5c099afa7c9361afc2f4477fec0e3018588d7840Allan Foster NodeList children = parentNode.getChildNodes();
5c099afa7c9361afc2f4477fec0e3018588d7840Allan Foster for (int i = 0; i < children.getLength(); i++) {
5c099afa7c9361afc2f4477fec0e3018588d7840Allan Foster if (node.getNodeName().equalsIgnoreCase(childName))
5c099afa7c9361afc2f4477fec0e3018588d7840Allan Foster * Checks if a node has a child of ELEMENT type.
5c099afa7c9361afc2f4477fec0e3018588d7840Allan Foster * @param node
5c099afa7c9361afc2f4477fec0e3018588d7840Allan Foster * @return true if the node has a child of ELEMENT type
5c099afa7c9361afc2f4477fec0e3018588d7840Allan Foster public static boolean hasElementChild(Node node) {
5c099afa7c9361afc2f4477fec0e3018588d7840Allan Foster if (child.getNodeType() == Node.ELEMENT_NODE) {
5c099afa7c9361afc2f4477fec0e3018588d7840Allan Foster return true;
5c099afa7c9361afc2f4477fec0e3018588d7840Allan Foster return false;
5c099afa7c9361afc2f4477fec0e3018588d7840Allan Foster * Returns a child node that has the given node name and give attribute name
5c099afa7c9361afc2f4477fec0e3018588d7840Allan Foster * and value.
5c099afa7c9361afc2f4477fec0e3018588d7840Allan Foster public static Node getNamedChildNode(Node parentNode, String childNodeName,
5c099afa7c9361afc2f4477fec0e3018588d7840Allan Foster NodeList children = parentNode.getChildNodes();
5c099afa7c9361afc2f4477fec0e3018588d7840Allan Foster for (int i = 0; i < children.getLength(); i++) {
5c099afa7c9361afc2f4477fec0e3018588d7840Allan Foster if (childNodeName.equalsIgnoreCase(node.getNodeName())) {
5c099afa7c9361afc2f4477fec0e3018588d7840Allan Foster if (getNodeAttributeValue(node, attrName).equalsIgnoreCase(
5c099afa7c9361afc2f4477fec0e3018588d7840Allan Foster public static Set getChildNodes(Node parentNode, String childName) {
5c099afa7c9361afc2f4477fec0e3018588d7840Allan Foster NodeList children = parentNode.getChildNodes();
5c099afa7c9361afc2f4477fec0e3018588d7840Allan Foster for (int i = 0; i < children.getLength(); i++) {
5c099afa7c9361afc2f4477fec0e3018588d7840Allan Foster if (node.getNodeName().equalsIgnoreCase(childName)) {
5c099afa7c9361afc2f4477fec0e3018588d7840Allan Foster * Gets the value of an element. This method returns a concatenated String
5c099afa7c9361afc2f4477fec0e3018588d7840Allan Foster * from all its TEXT children.
5c099afa7c9361afc2f4477fec0e3018588d7840Allan Foster * @param element
5c099afa7c9361afc2f4477fec0e3018588d7840Allan Foster * a DOM tree element.
5c099afa7c9361afc2f4477fec0e3018588d7840Allan Foster * @return A String that contained in its TEXT children; or null if an error
5c099afa7c9361afc2f4477fec0e3018588d7840Allan Foster public static String getElementValue(Element element) {
5c099afa7c9361afc2f4477fec0e3018588d7840Allan Foster * Gets the children value of an element. This method returns a
5c099afa7c9361afc2f4477fec0e3018588d7840Allan Foster * concatenated String from all its children.
5c099afa7c9361afc2f4477fec0e3018588d7840Allan Foster * @param element a DOM tree element.
5c099afa7c9361afc2f4477fec0e3018588d7840Allan Foster * @return A String that contained in its TEXT children;
5c099afa7c9361afc2f4477fec0e3018588d7840Allan Foster * or null if an error occurred.
5c099afa7c9361afc2f4477fec0e3018588d7840Allan Foster public static String getChildrenValue(Element element) {
5c099afa7c9361afc2f4477fec0e3018588d7840Allan Foster * Gets the value of an element. This method returns a concatenated String
5c099afa7c9361afc2f4477fec0e3018588d7840Allan Foster * from all its TEXT children.
5c099afa7c9361afc2f4477fec0e3018588d7840Allan Foster * @param element
5c099afa7c9361afc2f4477fec0e3018588d7840Allan Foster * a DOM tree element.
5c099afa7c9361afc2f4477fec0e3018588d7840Allan Foster * @return A String that contained in its TEXT children; or null if an error
5c099afa7c9361afc2f4477fec0e3018588d7840Allan Foster * occurred or the input contain non Node.TEXT_NODE node.
5c099afa7c9361afc2f4477fec0e3018588d7840Allan Foster public static String getElementString(Element element) {
5c099afa7c9361afc2f4477fec0e3018588d7840Allan Foster for (int i = 0, length = nl.getLength(); i < length; i++) {
5c099afa7c9361afc2f4477fec0e3018588d7840Allan Foster public static String getNodeAttributeValue(Node node, String attrName) {
5c099afa7c9361afc2f4477fec0e3018588d7840Allan Foster * Gets attribute value of a node.
5c099afa7c9361afc2f4477fec0e3018588d7840Allan Foster * @param node
5c099afa7c9361afc2f4477fec0e3018588d7840Allan Foster * @param namespaceURI
5c099afa7c9361afc2f4477fec0e3018588d7840Allan Foster * attribute namespace URI
5c099afa7c9361afc2f4477fec0e3018588d7840Allan Foster * @param attrName
5c099afa7c9361afc2f4477fec0e3018588d7840Allan Foster * attribute name
5c099afa7c9361afc2f4477fec0e3018588d7840Allan Foster * @return attribute value
5c099afa7c9361afc2f4477fec0e3018588d7840Allan Foster public static String getNodeAttributeValueNS(Node node,
5c099afa7c9361afc2f4477fec0e3018588d7840Allan Foster Node value = attrs.getNamedItemNS(namespaceURI, attrName);
5c099afa7c9361afc2f4477fec0e3018588d7840Allan Foster * Method to get Values within AttributeValuePair as a java.util.Set
5c099afa7c9361afc2f4477fec0e3018588d7840Allan Foster public static Set getAttributeValuePair(Node node) {
5c099afa7c9361afc2f4477fec0e3018588d7840Allan Foster * Method to get Values within AttributeValuePair as a java.util.Set
5c099afa7c9361afc2f4477fec0e3018588d7840Allan Foster * If <class>unescape<class> is set to false, xml escaped chars will not
5c099afa7c9361afc2f4477fec0e3018588d7840Allan Foster * be unescaped.
5c099afa7c9361afc2f4477fec0e3018588d7840Allan Foster public static Set getAttributeValuePair(Node node, boolean unescape) {
5c099afa7c9361afc2f4477fec0e3018588d7840Allan Foster if (!node.getNodeName().equals(ATTR_VALUE_PAIR_NODE)) {
5c099afa7c9361afc2f4477fec0e3018588d7840Allan Foster for (int i = 0; i < children.getLength(); i++) {
5c099afa7c9361afc2f4477fec0e3018588d7840Allan Foster if (n.getNodeName().equalsIgnoreCase(VALUE_NODE)) {
5c099afa7c9361afc2f4477fec0e3018588d7840Allan Foster * Method to get the value of "Value" node
5c099afa7c9361afc2f4477fec0e3018588d7840Allan Foster public static String getValueOfValueNode(Node n) {
5c099afa7c9361afc2f4477fec0e3018588d7840Allan Foster return (getValueOfValueNode(n, true));
5c099afa7c9361afc2f4477fec0e3018588d7840Allan Foster * Method to get the value of "Value" node
5c099afa7c9361afc2f4477fec0e3018588d7840Allan Foster * If <class>unescape<class> is set to false, xml escaped chars will not
5c099afa7c9361afc2f4477fec0e3018588d7840Allan Foster * be unescaped.
5c099afa7c9361afc2f4477fec0e3018588d7840Allan Foster public static String getValueOfValueNode(Node n, boolean unescape) {
5c099afa7c9361afc2f4477fec0e3018588d7840Allan Foster return getValueOfValueNodeNoTrim(n, unescape).trim();
5c099afa7c9361afc2f4477fec0e3018588d7840Allan Foster * Method to get the value of "Value" node
5c099afa7c9361afc2f4477fec0e3018588d7840Allan Foster public static String getValueOfValueNodeNoTrim(Node n) {
5c099afa7c9361afc2f4477fec0e3018588d7840Allan Foster return (getValueOfValueNodeNoTrim(n, true));
5c099afa7c9361afc2f4477fec0e3018588d7840Allan Foster * Method to get the value of "Value" node
5c099afa7c9361afc2f4477fec0e3018588d7840Allan Foster * If <class>unescape<class> is set to false, xml escaped chars will not
5c099afa7c9361afc2f4477fec0e3018588d7840Allan Foster * be unescaped.
5c099afa7c9361afc2f4477fec0e3018588d7840Allan Foster public static String getValueOfValueNodeNoTrim(Node n, boolean unescape) {
5c099afa7c9361afc2f4477fec0e3018588d7840Allan Foster for (int j = 0; j < textNodes.getLength(); j++) {
5c099afa7c9361afc2f4477fec0e3018588d7840Allan Foster if (textNode.getNodeType() == Node.TEXT_NODE) {
5c099afa7c9361afc2f4477fec0e3018588d7840Allan Foster } else if (textNode.getNodeType() == Node.ELEMENT_NODE) {
5c099afa7c9361afc2f4477fec0e3018588d7840Allan Foster * This method searches children of Element element for element with tagName
5c099afa7c9361afc2f4477fec0e3018588d7840Allan Foster * and namespaceURI nsName. It searchs one level down only.
5c099afa7c9361afc2f4477fec0e3018588d7840Allan Foster * @param element
5c099afa7c9361afc2f4477fec0e3018588d7840Allan Foster * The root element
5c099afa7c9361afc2f4477fec0e3018588d7840Allan Foster * @param nsName
5c099afa7c9361afc2f4477fec0e3018588d7840Allan Foster * NamespaceURI
5c099afa7c9361afc2f4477fec0e3018588d7840Allan Foster * @param tagName
5c099afa7c9361afc2f4477fec0e3018588d7840Allan Foster * A String representing the name of the tag to be searched for.
5c099afa7c9361afc2f4477fec0e3018588d7840Allan Foster * @return A List of elements that meet the criterial.
5c099afa7c9361afc2f4477fec0e3018588d7840Allan Foster if ((childName != null) && (childName.equals(tagName))
5c099afa7c9361afc2f4477fec0e3018588d7840Allan Foster && (childNS != null) && (childNS.equals(nsName))) {
5c099afa7c9361afc2f4477fec0e3018588d7840Allan Foster * Print SAML Attribute Element and replace its prefix with the input
5c099afa7c9361afc2f4477fec0e3018588d7840Allan Foster * @param node
5c099afa7c9361afc2f4477fec0e3018588d7840Allan Foster * A DOM tree Node
5c099afa7c9361afc2f4477fec0e3018588d7840Allan Foster * @param prefix
5c099afa7c9361afc2f4477fec0e3018588d7840Allan Foster * A String representing the new prefix
5c099afa7c9361afc2f4477fec0e3018588d7840Allan Foster * @return An xml String representation of the DOM tree.
5c099afa7c9361afc2f4477fec0e3018588d7840Allan Foster public static String printAttributeValue(Element node, String prefix) {
5c099afa7c9361afc2f4477fec0e3018588d7840Allan Foster xml.append(prefix).append(node.getLocalName());
5c099afa7c9361afc2f4477fec0e3018588d7840Allan Foster // xml.append(normalize(attr.getNodeValue()));
5c099afa7c9361afc2f4477fec0e3018588d7840Allan Foster xml.append(prefix).append(node.getLocalName());
5c099afa7c9361afc2f4477fec0e3018588d7840Allan Foster * Print a Node tree recursively using UTF-8 encoding.
5c099afa7c9361afc2f4477fec0e3018588d7840Allan Foster * @param node
5c099afa7c9361afc2f4477fec0e3018588d7840Allan Foster * A DOM tree Node
5c099afa7c9361afc2f4477fec0e3018588d7840Allan Foster * @return An xml String representation of the DOM tree.
5c099afa7c9361afc2f4477fec0e3018588d7840Allan Foster * Prints a Node tree recursively.
5c099afa7c9361afc2f4477fec0e3018588d7840Allan Foster * @param node A DOM tree Node
5c099afa7c9361afc2f4477fec0e3018588d7840Allan Foster * @param encoding character encoding
5c099afa7c9361afc2f4477fec0e3018588d7840Allan Foster * @return An xml String representation of the DOM tree.
5c099afa7c9361afc2f4477fec0e3018588d7840Allan Foster public static String print(Node node, String encoding) {
5bdd6bf9211505ff52afc7e32bdc49cdfacf4879Charles Sparey TransformerFactory tFactory = TransformerFactory.newInstance();
5c099afa7c9361afc2f4477fec0e3018588d7840Allan Foster Transformer transformer = tFactory.newTransformer();
5c099afa7c9361afc2f4477fec0e3018588d7840Allan Foster transformer.setOutputProperty("omit-xml-declaration", "yes");
5c099afa7c9361afc2f4477fec0e3018588d7840Allan Foster transformer.setOutputProperty("encoding", encoding);
5c099afa7c9361afc2f4477fec0e3018588d7840Allan Foster ByteArrayOutputStream os = new ByteArrayOutputStream(2000);
5c099afa7c9361afc2f4477fec0e3018588d7840Allan Foster * Returns unescape special character text.
5c099afa7c9361afc2f4477fec0e3018588d7840Allan Foster * @param text String to be unescaped.
5c099afa7c9361afc2f4477fec0e3018588d7840Allan Foster * @return unescape special character text.
5c099afa7c9361afc2f4477fec0e3018588d7840Allan Foster public static String unescapeSpecialCharacters(String text) {
f1e82b18ba6b6dd5dfc2569f2a83040b923233caPeter Major * Removes invalid XML characters from the input text and then replaces XML special character <code>&</code>,
f1e82b18ba6b6dd5dfc2569f2a83040b923233caPeter Major * <code><</code>, <code>></code>, <code>"</code>, <code>'</code> with corresponding entity references.
f1e82b18ba6b6dd5dfc2569f2a83040b923233caPeter Major * @param text The input that needs to be escaped. May be null.
f1e82b18ba6b6dd5dfc2569f2a83040b923233caPeter Major * @return String with the special characters replaced with entity references. May be null.
5c099afa7c9361afc2f4477fec0e3018588d7840Allan Foster public static String escapeSpecialCharacters(String text) {
f1e82b18ba6b6dd5dfc2569f2a83040b923233caPeter Major final StringBuilder sb = new StringBuilder(text.length());
f1e82b18ba6b6dd5dfc2569f2a83040b923233caPeter Major switch (c) {
5c099afa7c9361afc2f4477fec0e3018588d7840Allan Foster private static boolean invalidXMLCharExists(String st) {
2abcab75a7045a74128f7995dce24aa2e6a28e01Jon Jonthomas * Remove invalid XML characters from a string.
2abcab75a7045a74128f7995dce24aa2e6a28e01Jon Jonthomas * @param text the text to cleanse.
2abcab75a7045a74128f7995dce24aa2e6a28e01Jon Jonthomas * @return cleansed text or the original string if it is null or empty
f1e82b18ba6b6dd5dfc2569f2a83040b923233caPeter Major public static String removeInvalidXMLChars(String text) {
f1e82b18ba6b6dd5dfc2569f2a83040b923233caPeter Major return text.replaceAll(INVALID_XML_CHARACTERS, "");
5c099afa7c9361afc2f4477fec0e3018588d7840Allan Foster public static Set encodeAttributeSet(Set set, Debug debug) {
5c099afa7c9361afc2f4477fec0e3018588d7840Allan Foster if ((debug != null) && (debug.warningEnabled())) {
5c099afa7c9361afc2f4477fec0e3018588d7840Allan Foster debug.warning("XMLUtils.encodeAttributeSet invalid XML characters get Base64 encoded to be : " + st);
5c099afa7c9361afc2f4477fec0e3018588d7840Allan Foster public static Set decodeAttributeSet(Set set) {
5c099afa7c9361afc2f4477fec0e3018588d7840Allan Foster public static String removeNullCharAtEnd(String st) {
5c099afa7c9361afc2f4477fec0e3018588d7840Allan Foster if (c == '\u0000') {
23e304384f98fca4ab2e6f9f07a53465c1bfc645Peter Major * Provides a secure DocumentBuilder implementation, which is protected against
23e304384f98fca4ab2e6f9f07a53465c1bfc645Peter Major * different types of entity expansion attacks and makes sure that only locally
23e304384f98fca4ab2e6f9f07a53465c1bfc645Peter Major * available DTDs can be referenced within the XML document.
23e304384f98fca4ab2e6f9f07a53465c1bfc645Peter Major * @param validating Whether the returned DocumentBuilder should validate input.
23e304384f98fca4ab2e6f9f07a53465c1bfc645Peter Major * @return A secure DocumentBuilder instance.
23e304384f98fca4ab2e6f9f07a53465c1bfc645Peter Major * @throws ParserConfigurationException In case xerces does not support one
23e304384f98fca4ab2e6f9f07a53465c1bfc645Peter Major * of the required features.
23e304384f98fca4ab2e6f9f07a53465c1bfc645Peter Major public static DocumentBuilder getSafeDocumentBuilder(boolean validating) throws ParserConfigurationException {
9c1ec205dd4a7c6a5a2b06fa7385cf5b33274208Neil Madden return DOCUMENT_BUILDER_PROVIDER.getDocumentBuilder(validating);
23e304384f98fca4ab2e6f9f07a53465c1bfc645Peter Major * Provides a secure SAXParser instance, which is protected against different
23e304384f98fca4ab2e6f9f07a53465c1bfc645Peter Major * types of entity expension, DoS attacks and makes sure that only locally
23e304384f98fca4ab2e6f9f07a53465c1bfc645Peter Major * available DTDs can be referenced within the XML document.
23e304384f98fca4ab2e6f9f07a53465c1bfc645Peter Major * @param validating Whether the returned DocumentBuilder should validate input.
23e304384f98fca4ab2e6f9f07a53465c1bfc645Peter Major * @return A secure SAXParser instance.
23e304384f98fca4ab2e6f9f07a53465c1bfc645Peter Major * @throws ParserConfigurationException In case Xerces does not support one of
23e304384f98fca4ab2e6f9f07a53465c1bfc645Peter Major * the required features.
23e304384f98fca4ab2e6f9f07a53465c1bfc645Peter Major * @throws SAXException In case Xerces does not support one of the required
23e304384f98fca4ab2e6f9f07a53465c1bfc645Peter Major public static SAXParser getSafeSAXParser(boolean validating) throws ParserConfigurationException, SAXException {
9c1ec205dd4a7c6a5a2b06fa7385cf5b33274208Neil Madden return SAX_PARSER_PROVIDER.getSAXParser(validating);
564945e59b60a40c3b9458177b2ff63e2947686cPeter Major * Provides a cached {@link TransformerFactory} instance for the current thread.
564945e59b60a40c3b9458177b2ff63e2947686cPeter Major * @return A cached {@link TransformerFactory} instance.
564945e59b60a40c3b9458177b2ff63e2947686cPeter Major public static TransformerFactory getTransformerFactory() {
564945e59b60a40c3b9458177b2ff63e2947686cPeter Major return TRANSFORMER_FACTORY_PROVIDER.getTransformerFactory();
23e304384f98fca4ab2e6f9f07a53465c1bfc645Peter Major * Creates a SAXSource instance based on the incoming InputSource, which
23e304384f98fca4ab2e6f9f07a53465c1bfc645Peter Major * later on can be safely used by JAXB unmarshalling. The SAXSource will be
23e304384f98fca4ab2e6f9f07a53465c1bfc645Peter Major * protected against different types of entity expansion, DoS attacks and
23e304384f98fca4ab2e6f9f07a53465c1bfc645Peter Major * makes sure that only locally available DTDs can be referenced within the
23e304384f98fca4ab2e6f9f07a53465c1bfc645Peter Major * XML document.
23e304384f98fca4ab2e6f9f07a53465c1bfc645Peter Major * @param source The InputSource to be unmarshalled by JAXB
23e304384f98fca4ab2e6f9f07a53465c1bfc645Peter Major * @return A safe SAXSource instance
23e304384f98fca4ab2e6f9f07a53465c1bfc645Peter Major * @throws JAXBException In case an error occurs while creating the SAXSource
23e304384f98fca4ab2e6f9f07a53465c1bfc645Peter Major public static SAXSource createSAXSource(InputSource source) throws JAXBException{
23e304384f98fca4ab2e6f9f07a53465c1bfc645Peter Major return new SAXSource(saxParser.getXMLReader(), source);
23e304384f98fca4ab2e6f9f07a53465c1bfc645Peter Major //Let's convert the exception to a JAXBException, so the unmarshalling
23e304384f98fca4ab2e6f9f07a53465c1bfc645Peter Major //codes can handle the failure.
23e304384f98fca4ab2e6f9f07a53465c1bfc645Peter Major throw new JAXBException("Unable to create SAXSource", ex);
5c099afa7c9361afc2f4477fec0e3018588d7840Allan Foster private static String ATTR_VALUE_PAIR_NODE = "AttributeValuePair";
5c099afa7c9361afc2f4477fec0e3018588d7840Allan Fosterclass ValidationErrorHandler implements ErrorHandler {
5c099afa7c9361afc2f4477fec0e3018588d7840Allan Foster public void fatalError(SAXParseException spe) throws SAXParseException {
5c099afa7c9361afc2f4477fec0e3018588d7840Allan Foster public void error(SAXParseException spe) throws SAXParseException {
5c099afa7c9361afc2f4477fec0e3018588d7840Allan Foster public void warning(SAXParseException spe) throws SAXParseException {
5c099afa7c9361afc2f4477fec0e3018588d7840Allan Foster if ((debug != null) && (debug.warningEnabled())) {