Just in case, install an error handler to log anything that's raised.
[java-idp.git] / src / edu / internet2 / middleware / shibboleth / xml / SchemaStore.java
1 /*
2  * Copyright [2005] [University Corporation for Advanced Internet Development, Inc.]
3  *
4  * Licensed under the Apache License, Version 2.0 (the "License");
5  * you may not use this file except in compliance with the License.
6  * You may obtain a copy of the License at
7  *
8  * http://www.apache.org/licenses/LICENSE-2.0
9  *
10  * Unless required by applicable law or agreed to in writing, software
11  * distributed under the License is distributed on an "AS IS" BASIS,
12  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13  * See the License for the specific language governing permissions and
14  * limitations under the License.
15  */
16
17 /*
18  * Load and compile a bunch of XSD files from some repository. Schemas may be stored in a directory on disk, as
19  * resources in the Java classpath, in columns of an XML aware database, or in an XML "catalog" respository. This
20  * interface describes the functions that a SchemaStore must provide. Implementations will have additional properties or
21  * constructor arguments that define file paths, URL's (database, jdbc, jar, ...).
22  */
23
24 package edu.internet2.middleware.shibboleth.xml;
25
26 import java.util.ArrayList;
27 import java.util.HashMap;
28 import java.util.Map;
29
30 import javax.xml.XMLConstants;
31 import javax.xml.transform.Source;
32 import javax.xml.transform.dom.DOMSource;
33 import javax.xml.validation.Schema;
34 import javax.xml.validation.SchemaFactory;
35
36 import org.apache.log4j.Logger;
37 import org.w3c.dom.Document;
38 import org.xml.sax.ErrorHandler;
39 import org.xml.sax.SAXException;
40 import org.xml.sax.SAXParseException;
41
42 /**
43  * Compile a Schema object from a Map of DOM objects representing XSD files keyed by the Namespace that the XSD defines.
44  * <p>
45  * This class is typically subclassed by implementations that obtain the Map of XSD DOMs from some external source.
46  * </p>
47  * 
48  * @author Howard Gilbert
49  */
50 public class SchemaStore implements ErrorHandler {
51
52         private static Logger log = Logger.getLogger(SchemaStore.class);
53
54         protected Map/* <String,Document> */bucket = new HashMap/* <String,Document> */();
55
56         /**
57          * You can create the Map through a subclass and then just get a copy of the Map without compiling. This is useful
58          * when merging sources.
59          * 
60          * @return
61          */
62         public Map/* <String,Document> */getSchemaMap() {
63
64                 return bucket;
65         }
66
67         /**
68          * Can only construct this class from a Map.
69          * 
70          * @param bucket
71          */
72         public SchemaStore(Map/* <String,Document> */bucket) {
73
74                 super();
75                 this.bucket = bucket;
76         }
77
78         protected SchemaStore() {
79
80         }
81
82         /**
83          * Create JAXP 1.3 Schema object from list of namespaces and resource dir
84          * <p>
85          * This is an alternate approach to the Schema building logic used in org.opensaml.XML. That module is driven off a
86          * list of file names. This code reads in all the *.xsd files in a directory, indexes them by the namespace the
87          * schema defines, and then is driven off a list of namespaces. This is more more indirect and requires a bit more
88          * code, but it is more in line with the actual XSD standard where files and filenames are incidental. It can also
89          * be quickly ported to some other schema storage medium (LDAP, Database, ...).
90          * </p>
91          * 
92          * @param namespaces
93          *            Array of required XML namespaces for validation
94          * @param resourcedir
95          *            Resource directory with schema files ("/schemas/")
96          * @return Schema object combining all namespaces.
97          */
98         public Schema compileSchema(String[] namespaces) {
99
100                 Schema schema = null;
101                 ArrayList sources = new ArrayList();
102                 for (int i = 0; i < namespaces.length; i++) {
103                         Document doc = (Document) bucket.get(namespaces[i]);
104                         if (doc == null) {
105                                 log.error("Schema missing for namespace (" + namespaces[i] + ").");
106                         } else {
107                                 sources.add(new DOMSource(doc));
108                         }
109                 }
110                 // Now compile all the XSD files into a single composite Schema object
111                 SchemaFactory factory = SchemaFactory.newInstance(XMLConstants.W3C_XML_SCHEMA_NS_URI);
112                 try {
113                         factory.setErrorHandler(this);
114                         schema = factory.newSchema((Source[]) sources.toArray(new Source[0]));
115                 } catch (SAXException e) {
116                         log.error("Schemas failed to compile, dependencies may be corrupt: " + e);
117                 }
118                 return schema;
119         }
120
121         public void warning(SAXParseException exception) throws SAXException {
122                 log.warn(exception);
123                 
124         }
125
126         public void error(SAXParseException exception) throws SAXException {
127                 log.error(exception);
128                 throw exception;
129         }
130
131         public void fatalError(SAXParseException exception) throws SAXException {
132                 log.error(exception);
133                 throw exception;
134         }
135
136 }