Added stand-alone query role.
[java-idp.git] / src / edu / internet2 / middleware / shibboleth / xml / Parser.java
index d7e63cb..8ae7d5b 100644 (file)
  * 
  * Currently, this class exposes static methods. Should a real 
  * framework be installed, it would become a singleton object.
+ * --------------------
+ * Copyright 2002, 2004 
+ * University Corporation for Advanced Internet Development, Inc. 
+ * All rights reserved
+ * [Thats all we have to say to protect ourselves]
+ * Your permission to use this code is governed by "The Shibboleth License".
+ * A copy may be found at http://shibboleth.internet2.edu/license.html
+ * [Nothing in copyright law requires license text in every file.]
  */
 package edu.internet2.middleware.shibboleth.xml;
 
 import java.io.IOException;
 import java.io.InputStream;
 import java.io.StringWriter;
+import java.util.Iterator;
+import java.util.Map;
 
 import javax.xml.transform.OutputKeys;
 import javax.xml.transform.Transformer;
@@ -36,6 +46,9 @@ import javax.xml.transform.stream.StreamResult;
 import javax.xml.validation.Schema;
 
 import org.apache.log4j.Logger;
+import org.apache.xml.security.c14n.CanonicalizationException;
+import org.apache.xml.security.c14n.Canonicalizer;
+import org.apache.xml.security.c14n.InvalidCanonicalizerException;
 import org.opensaml.SAMLException;
 import org.w3c.dom.Document;
 import org.w3c.dom.Node;
@@ -71,19 +84,76 @@ public class Parser {
             "urn:mace:shibboleth:idp:config:1.0",
             "urn:mace:shibboleth:arp:1.0",
             "urn:mace:shibboleth:resolver:1.0",
+            "urn:oasis:names:tc:SAML:2.0:metadata",
+            "urn:oasis:names:tc:SAML:metadata:extension",
             "urn:mace:shibboleth:target:config:1.0",
             "urn:mace:shibboleth:trust:1.0",
             "urn:mace:shibboleth:metadata:1.0",
             "urn:mace:shibboleth:1.0",
-            "http://schemas.xmlsoap.org/soap/envelope/",
-            "urn:oasis:names:tc:SAML:2.0:metadata"
+            "http://schemas.xmlsoap.org/soap/envelope/"
       };
     
+    private static String[] resources = new String[]{
+            "credentials.xsd",
+            "cs-sstc-schema-assertion-1.1.xsd",
+            "cs-sstc-schema-protocol-1.1.xsd",
+            "namemapper.xsd",
+            "saml-schema-assertion-2.0.xsd",
+            "saml-schema-metadata-2.0.xsd",
+            "saml-schema-metadata-ext.xsd",
+            "shibboleth-arp-1.0.xsd",
+            "shibboleth-idpconfig-1.0.xsd",
+            "shibboleth-metadata-1.0.xsd",
+            "shibboleth-resolver-1.0.xsd",
+            "shibboleth-targetconfig-1.0.xsd",
+            "shibboleth-trust-1.0.xsd",
+            "shibboleth.xsd",
+            "soap-envelope.xsd",
+            "wayfconfig.xsd",
+            "xenc-schema.xsd",
+            "xml.xsd",
+            "xmldsig-core-schema.xsd"
+       };
+    private static String[] oldResources = new String[]{
+            "cs-sstc-schema-assertion-01.xsd",
+            "cs-sstc-schema-protocol-01.xsd"
+       };
+    
     // If there were a real Framework here (like Spring) then
     // the schemaBuilder would be inserted 
-    private static SchemasDirectoryImpl schemaBuilder = new SchemasDirectoryImpl();
+    private static String defaultDirectory = "/schemas/";
+    private static String oldSchemasDir = "/schemas/saml-1.0/";
+    private static final boolean useResourceBuilder=true;
+    
+    private static SchemaStore schemaBuilder = 
+        (useResourceBuilder?
+            (SchemaStore)
+                new SchemasResourceListImpl(defaultDirectory,resources):
+            (SchemaStore)
+                new SchemasDirectoryImpl(defaultDirectory));
+    private static SchemaStore oldSchemasBuilder = 
+        (useResourceBuilder?
+                (SchemaStore)
+                    new SchemasResourceListImpl(oldSchemasDir,oldResources):
+                (SchemaStore)
+                       new SchemasDirectoryImpl(oldSchemasDir));
+    
     private static Schema schema = schemaBuilder.compileSchema(namespaces);
-       private static Schema schemaOldSAML= schemaBuilder.compileSchema(namespaces,"/schemas/saml-1.0/");
+    static {
+        // Merge in the XSDs defining non-conflicting namespaces
+        // A non-replacing putAll()
+        Map/*<String,Document>*/ source = schemaBuilder.getSchemaMap();
+        Map/*<String,Document>*/ sink   = oldSchemasBuilder.getSchemaMap();
+        Iterator/*<String>*/ nsi = source.keySet().iterator();
+        while (nsi.hasNext()) {
+            String namespace = (String) nsi.next();
+            if (!sink.containsKey(namespace)) {
+                sink.put(namespace,source.get(namespace));
+            }
+        }
+    }
+       private static Schema schemaOldSAML= 
+           oldSchemasBuilder.compileSchema(namespaces);
     
     /**
      * Load a DOM from a wrapped byte stream.
@@ -155,6 +225,32 @@ public class Parser {
     }
     
     /**
+     *  Serializes the XML representation of the SAML object to a stream
+     *
+     * @param  out                      Stream to use for output
+     * @exception  java.io.IOException  Raised if an I/O problem is detected
+     * @exception  SAMLException Raised if the object is incompletely defined 
+     */
+    public static String serializeC14N(Node root){
+       byte[] bs = null;
+        try
+        {
+            Canonicalizer c = Canonicalizer.getInstance(Canonicalizer.ALGO_ID_C14N_EXCL_OMIT_COMMENTS);
+            bs = c.canonicalizeSubtree(root, "#default saml samlp ds xsd xsi code kind rw typens");
+        }
+        catch (InvalidCanonicalizerException e)
+        {
+            return null;
+        }
+        catch (CanonicalizationException e)
+        {
+            return null;
+        }
+        return new String(bs);
+    }
+
+    
+    /**
      * Version of loadDom where the file is specified as a resource name
      * 
      * @param configFilePath input resource