4 * Validating and non-validating XML parsing using JAXP 1.3.
6 * Previous versions of the code directly used the Xerces DOMParser
7 * class. This class has been hidden in the Sun XML stack, and the
8 * public interface is to use DocumentBuilderFactory. This module
9 * requires the DOM 3 and JAXP 1.3 support built into J2SE 5.0 and
10 * distributed separately for earlier releases of Java from
11 * https://jaxp.dev.java.net/. It should also work with Xerces 2.7.0
12 * when that release becomes available.
14 * The org.opensaml.XML class already has most of the parsing code,
15 * but it uses a subset of the required Schemas. Here we build a
16 * wider Schema object, set it as the default SAML schema (because
17 * some Shibboleth namespace fields appear in SAML statements), and
18 * demand that Schema for every parser (DocumentBuilder) we request.
20 * Currently, this class exposes static methods. Should a real
21 * framework be installed, it would become a singleton object.
23 package edu.internet2.middleware.shibboleth.xml;
25 import java.io.IOException;
26 import java.io.InputStream;
27 import java.io.StringWriter;
29 import javax.xml.transform.OutputKeys;
30 import javax.xml.transform.Transformer;
31 import javax.xml.transform.TransformerConfigurationException;
32 import javax.xml.transform.TransformerException;
33 import javax.xml.transform.TransformerFactory;
34 import javax.xml.transform.dom.DOMSource;
35 import javax.xml.transform.stream.StreamResult;
36 import javax.xml.validation.Schema;
38 import org.apache.log4j.Logger;
39 import org.opensaml.SAMLException;
40 import org.w3c.dom.Document;
41 import org.w3c.dom.Node;
42 import org.xml.sax.InputSource;
43 import org.xml.sax.SAXException;
46 * Obtain schema validating and non-validating XML parsers.
48 * @author Howard Gilbert
51 private static Logger log = Logger.getLogger(Parser.class);
55 * All the namespaces used by any part of Shibboleth
57 * Note: The current Schema compiler requires that dependencies
58 * (imports) be listed before the namespace of the schema
61 private static String[] namespaces = new String[]{
62 "http://www.w3.org/2000/09/xmldsig#",
63 "http://www.w3.org/2001/04/xmlenc#",
64 "urn:oasis:names:tc:SAML:1.0:assertion",
65 "urn:oasis:names:tc:SAML:2.0:assertion",
66 "http://www.w3.org/XML/1998/namespace",
67 "http://schemas.xmlsoap.org/soap/envelope/",
68 "urn:mace:shibboleth:credentials:1.0",
69 "urn:oasis:names:tc:SAML:1.0:protocol",
70 "urn:mace:shibboleth:namemapper:1.0",
71 "urn:mace:shibboleth:idp:config:1.0",
72 "urn:mace:shibboleth:arp:1.0",
73 "urn:mace:shibboleth:resolver:1.0",
74 "urn:oasis:names:tc:SAML:2.0:metadata",
75 "urn:mace:shibboleth:target:config:1.0",
76 "urn:mace:shibboleth:trust:1.0",
77 "urn:mace:shibboleth:metadata:1.0",
78 "urn:mace:shibboleth:1.0",
79 "http://schemas.xmlsoap.org/soap/envelope/"
82 // If there were a real Framework here (like Spring) then
83 // the schemaBuilder would be inserted
84 private static SchemasDirectoryImpl schemaBuilder = new SchemasDirectoryImpl();
85 private static Schema schema = schemaBuilder.compileSchema(namespaces);
86 private static Schema schemaOldSAML= schemaBuilder.compileSchema(namespaces,"/schemas/saml-1.0/");
89 * Load a DOM from a wrapped byte stream.
91 * @param ins InputSource The XML document
92 * @param validate If true, use Schema. Otherwise, its raw XML.
93 * @return A DOM 3 tree
95 public static Document loadDom(InputSource ins, boolean validate) throws SAMLException, SAXException, IOException {
98 log.debug("Loading XML from (" + ins.getSystemId() + ")" + (validate ? " with Schema validation" : ""));
100 doc = org.opensaml.XML.parserPool.parse(ins, schema);
102 doc = org.opensaml.XML.parserPool.parse(ins, null);
109 * A dummy class that pretends to be an old Xerces DOMParser to simplify conversion of existing code.
111 public static class DOMParser {
113 boolean validate = false;
115 public DOMParser(boolean validate) {
116 this.validate=validate;
119 public Document parse(InputSource ins) throws SAXException, IOException, SAMLException {
120 doc = loadDom(ins,true);
124 public Document getDocument() {
130 * Write a DOM out to a character stream (for debugging and logging)
132 * @param dom The DOM tree to write
133 * @return A string containing the XML in character form.
135 public static String serialize(Node dom) {
138 TransformerFactory factory = TransformerFactory.newInstance();
139 Transformer transformer = null;
140 DOMSource source = new DOMSource(dom);
142 transformer = factory.newTransformer();
143 transformer.setOutputProperty(OutputKeys.INDENT, "yes");
144 } catch (TransformerConfigurationException e) {
147 StringWriter stringWriter = new StringWriter();
148 StreamResult result = new StreamResult(stringWriter);
150 transformer.transform(source, result);
151 } catch (TransformerException e1) {
154 return stringWriter.toString();
158 * Version of loadDom where the file is specified as a resource name
160 * @param configFilePath input resource
161 * @param validate if true, use Schema
164 public static Document loadDom(String configFilePath,boolean validate) throws SAMLException, SAXException, IOException
167 String schemaCannonicalFilePath;
169 InputStream resourceAsStream = Parser.class.getResourceAsStream(configFilePath);
170 insrc = new InputSource(resourceAsStream);
171 insrc.setSystemId(configFilePath);
172 } catch (Exception e1) {
173 log.error("Configuration file "+configFilePath+" could not be located.");
177 return loadDom(insrc,validate); // Now pass on to the main routine
182 * Override the OpenSAML default schema from SAML 1.1 to
183 * SAML 1.1 plus Shibboleth (and some SAML 2.0).
186 //org.opensaml.XML.parserPool.setDefaultSchema(schema);
187 org.opensaml.XML.parserPool.setDefaultSchemas(schemaOldSAML,schema);