View Javadoc

1   /*
2    * Copyright 2010 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  package org.opensaml.xml.schema;
18  
19  import java.io.File;
20  import java.io.InputStream;
21  import java.util.ArrayList;
22  import java.util.List;
23  
24  import javax.xml.XMLConstants;
25  import javax.xml.transform.Source;
26  import javax.xml.transform.stream.StreamSource;
27  import javax.xml.validation.Schema;
28  import javax.xml.validation.SchemaFactory;
29  
30  import org.opensaml.xml.parse.LoggingErrorHandler;
31  import org.slf4j.Logger;
32  import org.slf4j.LoggerFactory;
33  import org.xml.sax.SAXException;
34  
35  /** A helper class for building {@link Schema} from a set of input. */
36  public final class SchemaBuilder {
37  
38      /** Language of the schema files. */
39      public static enum SchemaLanguage {
40  
41          /** W3 XML Schema. */
42          XML("xsd"),
43  
44          /** OASIS RELAX NG Schema. */
45          RELAX("rng");
46  
47          /** File extension used for the schema files. */
48          private String schemaFileExtension;
49  
50          /**
51           * Constructor.
52           * 
53           * @param extension file extension used for the schema files
54           */
55          private SchemaLanguage(String extension) {
56              schemaFileExtension = extension;
57          }
58  
59          /**
60           * Gets the file extension used for the schema files.
61           * 
62           * @return file extension used for the schema files
63           */
64          public String getSchemaFileExtension() {
65              return schemaFileExtension;
66          }
67      };
68      
69      /** Constructor. */
70      private SchemaBuilder() {}
71  
72      /**
73       * Builds a schema from the given schema source.
74       * 
75       * @param lang schema language, must not be null
76       * @param schemaFileOrDirectory file or directory which contains schema sources
77       * 
78       * @return the constructed schema
79       * 
80       * @throws SAXException thrown if there is a problem converting the schema sources in to a schema
81       */
82      public static Schema buildSchema(SchemaLanguage lang, String schemaFileOrDirectory) throws SAXException {
83          if(schemaFileOrDirectory == null){
84              return null;
85          }
86          
87          return buildSchema(lang, new File(schemaFileOrDirectory));
88      }
89  
90      /**
91       * Builds a schema from the given schema sources.
92       * 
93       * @param lang schema language, must not be null
94       * @param schemaFilesOrDirectories files or directories which contains schema sources
95       * 
96       * @return the constructed schema
97       * 
98       * @throws SAXException thrown if there is a problem converting the schema sources in to a schema
99       */
100     public static Schema buildSchema(SchemaLanguage lang, String[] schemaFilesOrDirectories) throws SAXException {
101         if(schemaFilesOrDirectories == null || schemaFilesOrDirectories.length == 0){
102             return null;
103         }
104         
105         return buildSchema(lang, schemaFilesOrDirectories);
106     }
107 
108     /**
109      * Builds a schema from the given schema source.
110      * 
111      * @param lang schema language, must not be null
112      * @param schemaFileOrDirectory file or directory which contains schema sources
113      * 
114      * @return the constructed schema
115      * 
116      * @throws SAXException thrown if there is a problem converting the schema sources in to a schema
117      */
118     public static Schema buildSchema(SchemaLanguage lang, File schemaFileOrDirectory) throws SAXException {
119         if(schemaFileOrDirectory == null){
120             return null;
121         }
122         
123         return buildSchema(lang, new File[]{schemaFileOrDirectory});
124     }
125 
126     /**
127      * Builds a schema from the given schema sources.
128      * 
129      * @param lang schema language, must not be null
130      * @param schemaFilesOrDirectories files or directories which contains schema sources
131      * 
132      * @return the constructed schema
133      * 
134      * @throws SAXException thrown if there is a problem converting the schema sources in to a schema
135      */
136     public static Schema buildSchema(SchemaLanguage lang, File[] schemaFilesOrDirectories) throws SAXException {
137         if(schemaFilesOrDirectories == null || schemaFilesOrDirectories.length == 0){
138             return null;
139         }
140         
141         ArrayList<File> schemaFiles = new ArrayList<File>();
142         getSchemaFiles(lang, schemaFilesOrDirectories, schemaFiles);
143         
144         if(schemaFiles.isEmpty()){
145             return null;
146         }
147         
148         ArrayList<Source> schemaSources = new ArrayList<Source>();
149         for(File schemaFile : schemaFiles){
150             schemaSources.add(new StreamSource(schemaFile));
151         }
152         return buildSchema(lang, schemaSources.toArray(new Source[]{}));
153     }
154 
155     /**
156      * Builds a schema from the given schema source.
157      * 
158      * @param lang schema language, must not be null
159      * @param schemaSource schema source
160      * 
161      * @return the constructed schema
162      * 
163      * @throws SAXException thrown if there is a problem converting the schema sources in to a schema
164      */
165     public static Schema buildSchema(SchemaLanguage lang, InputStream schemaSource) throws SAXException {
166         if(schemaSource == null){
167             return null;
168         }
169         
170         return buildSchema(lang, new StreamSource[] { new StreamSource(schemaSource) });
171     }
172 
173     /**
174      * Builds a schema from the given schema sources.
175      * 
176      * @param lang schema language, must not be null
177      * @param schemaSources schema sources
178      * 
179      * @return the constructed schema
180      * 
181      * @throws SAXException thrown if there is a problem converting the schema sources in to a schema
182      */
183     public static Schema buildSchema(SchemaLanguage lang, InputStream[] schemaSources) throws SAXException {
184         if(schemaSources == null || schemaSources.length == 0){
185             return null;
186         }
187         
188         ArrayList<StreamSource> sources = new ArrayList<StreamSource>();
189         for (InputStream schemaSource : schemaSources) {
190             if (schemaSource == null) {
191                 continue;
192             }
193             sources.add(new StreamSource(schemaSource));
194         }
195 
196         if (sources.isEmpty()) {
197             return null;
198         }
199 
200         return buildSchema(lang, sources.toArray(new Source[] {}));
201     }
202 
203     /**
204      * Gets all of the schema files in the given set of readable files, directories or subdirectories.
205      * 
206      * @param lang schema language, must not be null
207      * @param schemaFilesOrDirectories files and directories which may contain schema files
208      * @param accumulatedSchemaFiles list that accumulates the schema files
209      */
210     protected static void getSchemaFiles(SchemaLanguage lang, File[] schemaFilesOrDirectories,
211             List<File> accumulatedSchemaFiles) {
212         Logger log = getLogger();
213         
214         if(lang == null){
215             throw new IllegalArgumentException("Schema language may not be null");
216         }
217         
218         if (schemaFilesOrDirectories == null || schemaFilesOrDirectories.length == 0) {
219             return;
220         }
221 
222         for (File handle : schemaFilesOrDirectories) {
223             if (handle == null) {
224                 continue;
225             }
226 
227             if (!handle.canRead()) {
228                 log.debug("Ignoring '{}', no read permission", handle.getAbsolutePath());
229             }
230 
231             if (handle.isFile() && handle.getName().endsWith(lang.getSchemaFileExtension())) {
232                 log.debug("Added schema source '{}'", handle.getAbsolutePath());
233                 accumulatedSchemaFiles.add(handle);
234             }
235 
236             if (handle.isDirectory()) {
237                 getSchemaFiles(lang, handle.listFiles(), accumulatedSchemaFiles);
238             }
239         }
240     }
241 
242     /**
243      * Builds a schema from the given schema sources.
244      * 
245      * @param lang schema language, must not be null
246      * @param schemaSources schema sources, must not be null
247      * 
248      * @return the constructed schema
249      * 
250      * @throws SAXException thrown if there is a problem converting the schema sources in to a schema
251      */
252     protected static Schema buildSchema(SchemaLanguage lang, Source[] schemaSources) throws SAXException {
253         if(lang == null){
254             throw new IllegalArgumentException("Schema language may not be null");
255         }
256         
257         if(schemaSources == null){
258             throw new IllegalArgumentException("Schema sources may not be null");
259         }
260         
261         SchemaFactory schemaFactory;
262 
263         if (lang == SchemaLanguage.XML) {
264             schemaFactory = SchemaFactory.newInstance(XMLConstants.W3C_XML_SCHEMA_NS_URI);
265         } else {
266             schemaFactory = SchemaFactory.newInstance(XMLConstants.RELAXNG_NS_URI);
267         }
268 
269         schemaFactory.setErrorHandler(new LoggingErrorHandler(LoggerFactory.getLogger(SchemaBuilder.class)));
270         return schemaFactory.newSchema(schemaSources);
271     }
272     
273     /**
274      * Get an SLF4J Logger.
275      * 
276      * @return a Logger instance
277      */
278     private static Logger getLogger() {
279         return LoggerFactory.getLogger(SchemaBuilder.class);
280     }
281 }