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 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      /** Class logger. */
70      private static final Logger LOG = LoggerFactory.getLogger(SchemaBuilder.class);
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         
213         if(lang == null){
214             throw new IllegalArgumentException("Schema language may not be null");
215         }
216         
217         if (schemaFilesOrDirectories == null || schemaFilesOrDirectories.length == 0) {
218             return;
219         }
220 
221         for (File handle : schemaFilesOrDirectories) {
222             if (handle == null) {
223                 continue;
224             }
225 
226             if (!handle.canRead()) {
227                 LOG.debug("Ignoring '{}', no read permission", handle.getAbsolutePath());
228             }
229 
230             if (handle.isFile() && handle.getName().endsWith(lang.getSchemaFileExtension())) {
231                 LOG.debug("Added schema source '{}'", handle.getAbsolutePath());
232                 accumulatedSchemaFiles.add(handle);
233             }
234 
235             if (handle.isDirectory()) {
236                 getSchemaFiles(lang, handle.listFiles(), accumulatedSchemaFiles);
237             }
238         }
239     }
240 
241     /**
242      * Builds a schema from the given schema sources.
243      * 
244      * @param lang schema language, must not be null
245      * @param schemaSources schema sources, must not be null
246      * 
247      * @return the constructed schema
248      * 
249      * @throws SAXException thrown if there is a problem converting the schema sources in to a schema
250      */
251     protected static Schema buildSchema(SchemaLanguage lang, Source[] schemaSources) throws SAXException {
252         if(lang == null){
253             throw new IllegalArgumentException("Schema language may not be null");
254         }
255         
256         if(schemaSources == null){
257             throw new IllegalArgumentException("Schema sources may not be null");
258         }
259         
260         SchemaFactory schemaFactory;
261 
262         if (lang == SchemaLanguage.XML) {
263             schemaFactory = SchemaFactory.newInstance(XMLConstants.W3C_XML_SCHEMA_NS_URI);
264         } else {
265             schemaFactory = SchemaFactory.newInstance(XMLConstants.RELAXNG_NS_URI);
266         }
267 
268         schemaFactory.setErrorHandler(new LoggingErrorHandler(LoggerFactory.getLogger(SchemaBuilder.class)));
269         return schemaFactory.newSchema(schemaSources);
270     }
271 }