View Javadoc
1 /*
2 * XmlParser.java
3 * Created on August 3, 2003
4 *
5 * The Blues Framework - A lightweight application framework
6 * Copyright (C) 2003 Lonnie Pryor
7 * http://blues.lonniepryor.com
8 *
9 * This library is free software; you can redistribute it and/or modify it under the
10 * terms of the GNU Lesser General Public License as published by the Free Software
11 * Foundation; either version 2.1 of the License, or (at your option) any later
12 * version.
13 *
14 * This library is distributed in the hope that it will be useful, but WITHOUT ANY
15 * WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A
16 * PARTICULAR PURPOSE. See the GNU Lesser General Public License for more details.
17 *
18 * You should have received a copy of the GNU Lesser General Public License along
19 * with this library; if not, write to:
20 *
21 * The Free Software Foundation, Inc.
22 * 59 Temple Place, Suite 330
23 * Boston, MA 02111-1307 USA
24 *
25 */
26 package com.lonniepryor.blues.xml;
27
28 import java.io.IOException;
29 import java.io.InputStream;
30
31 import java.net.URL;
32
33 import java.util.ArrayList;
34 import java.util.Collection;
35 import java.util.Enumeration;
36 import java.util.HashMap;
37 import java.util.Iterator;
38 import java.util.Map;
39 import java.util.Properties;
40
41 import javax.xml.parsers.SAXParser;
42 import javax.xml.parsers.SAXParserFactory;
43
44 import com.lonniepryor.blues.cfg.ApplicationCfg;
45 import com.lonniepryor.blues.cfg.IncludeCfg;
46 import com.lonniepryor.blues.cfg.ModuleCfg;
47
48 /***
49 * Responsible for loading XML Schemas and parsing application and module
50 * configurations. NOTE: this class is NOT thread-safe and instances may only be
51 * used on a single thread at a time.
52 *
53 * @author Lonnie Pryor
54 * @version $Revision: 1.2 $
55 */
56 public class XmlParser {
57 /*** JAXP schema language property. */
58 private static final String jaxpSchemaLanguage = "http://java.sun.com/xml/jaxp/properties/schemaLanguage";
59 /*** JAXP schema source property. */
60 private static final String jaxpSchemaSource = "http://java.sun.com/xml/jaxp/properties/schemaSource";
61 /*** URI of the XML Schema namespace. */
62 private static final String xmlSchemaNamespaceUri = "http://www.w3.org/2001/XMLSchema";
63 /*** Path to schema index documents. */
64 private static final String schemaIndexPath = "META-INF/schemas.blues.properties";
65 /*** The class loader to use. */
66 private final ClassLoader classLoader;
67 /*** The SAX parser to parse documents with. */
68 private final SAXParser schemaValidatingParser;
69
70 /***
71 * Creates a new XmlParser object.
72 *
73 * @param classLoader The class loader to use.
74 */
75 public XmlParser (ClassLoader classLoader) {
76 this(
77 classLoader,
78 createSchemaValidatingParser(classLoader, SAXParserFactory.newInstance()));
79 }
80
81 /***
82 * Creates a new XmlParser object.
83 *
84 * @param classLoader The class loader to use.
85 * @param saxParserFactory FIXME
86 */
87 public XmlParser (ClassLoader classLoader, SAXParserFactory saxParserFactory) {
88 this(classLoader, createSchemaValidatingParser(classLoader, saxParserFactory));
89 }
90
91 /***
92 * Creates a new XmlParser object.
93 *
94 * @param classLoader The class loader to use.
95 * @param schemaValidatingParser FIXME
96 */
97 protected XmlParser (ClassLoader classLoader, SAXParser schemaValidatingParser) {
98 if (classLoader == null)
99 throw new NullPointerException("classLoader");
100 if (schemaValidatingParser == null)
101 throw new NullPointerException("schemaValidatingParser");
102 this.classLoader = classLoader;
103 this.schemaValidatingParser = schemaValidatingParser;
104 }
105
106 /***
107 * Creates a JAXP 1.2 parser that validates according to XML Schema.
108 *
109 * @param classLoader The class loader to load schemas from.
110 * @param saxParserFactory The sax parser factory to construct a parser with.
111 *
112 * @return A JAXP 1.2 parser that validates according to XML Schema.
113 */
114 public static SAXParser createSchemaValidatingParser (
115 ClassLoader classLoader, SAXParserFactory saxParserFactory) {
116 SAXParser schemaValidatingParser = null;
117 try {
118 schemaValidatingParser = saxParserFactory.newSAXParser();
119 } catch (Exception e) {
120 throw new XmlException("Error creating parser instance", e);
121 }
122 try {
123 schemaValidatingParser.setProperty(jaxpSchemaLanguage, xmlSchemaNamespaceUri);
124 schemaValidatingParser.setProperty(
125 jaxpSchemaSource, openAllSchemas(classLoader).toArray());
126 } catch (Exception e) {
127 throw new XmlException("Error initalizing XML schemas", e);
128 }
129 return schemaValidatingParser;
130 }
131
132 /***
133 * Opens an XML Schema document for every namespace uri declared in the schema
134 * index files.
135 *
136 * @param classLoader The class loader to load schemas from.
137 *
138 * @return A Collection of InputStreams pointing to all of the schema documents.
139 *
140 * @throws IOException If the schema loading fails.
141 */
142 private static Collection openAllSchemas (ClassLoader classLoader)
143 throws IOException {
144 Map allSchemas = new HashMap();
145 Properties props = new Properties();
146 for (
147 Enumeration enum = classLoader.getResources(schemaIndexPath);
148 enum.hasMoreElements();) {
149 InputStream in = ((URL)enum.nextElement()).openStream();
150 try {
151 props.load(in);
152 } finally {
153 in.close();
154 }
155 for (Iterator iter = props.entrySet().iterator(); iter.hasNext();) {
156 Map.Entry entry = (Map.Entry)iter.next();
157 if (!allSchemas.containsKey(entry.getValue()))
158 allSchemas.put(entry.getValue(), entry.getKey());
159 }
160 props.clear();
161 }
162 Collection allInputStreams = new ArrayList();
163 try {
164 for (Iterator iter = allSchemas.values().iterator(); iter.hasNext();)
165 allInputStreams.add(
166 classLoader.getResource((String)iter.next()).openStream());
167 } catch (IOException ioe) {
168 for (Iterator iter = allInputStreams.iterator(); iter.hasNext();) {
169 try {
170 ((InputStream)iter.next()).close();
171 } catch (IOException ignore) {
172 ;
173 }
174 }
175 throw ioe;
176 }
177 return allInputStreams;
178 }
179
180 /***
181 * Parses a Blues application configuration file.
182 *
183 * @param documentPath The location of the configuration file.
184 *
185 * @return The assembled application configuration.
186 */
187 public ApplicationCfg parseApplication (String documentPath) {
188 if (documentPath == null)
189 throw new NullPointerException("documentPath");
190 GraphBuilder builder = new GraphBuilder(classLoader);
191 ApplicationCfg appCfg = (ApplicationCfg)builder.buildGraph(
192 schemaValidatingParser, documentPath);
193 ModuleCfg modCfg = appCfg.getRootModule();
194 if (modCfg != null)
195 parseIncludedModules(builder, modCfg, documentPath);
196 return appCfg;
197 }
198
199 /***
200 * Parses a Blues module configuration file.
201 *
202 * @param documentPath The location of the configuration file.
203 *
204 * @return The assembled module configuration.
205 */
206 public ModuleCfg parseModule (String documentPath) {
207 if (documentPath == null)
208 throw new NullPointerException("documentPath");
209 GraphBuilder builder = new GraphBuilder(classLoader);
210 ModuleCfg modCfg = (ModuleCfg)builder.buildGraph(
211 schemaValidatingParser, documentPath);
212 parseIncludedModules(builder, modCfg, documentPath);
213 return modCfg;
214 }
215
216 /***
217 * Loads and initalizes all included modules.
218 *
219 * @param builder The graph builder to use.
220 * @param modCfg The module config to inialize.
221 * @param docPath The path of the document the module was declared in.
222 */
223 private void parseIncludedModules (
224 GraphBuilder builder, ModuleCfg modCfg, String docPath) {
225 String pathBase = docPath.substring(0, docPath.lastIndexOf('/') + 1);
226 IncludeCfg[] includes = modCfg.getIncludes();
227 for (int i = 0; i < includes.length; ++i) {
228 String includedModPath = includes[i].getModulePath().startsWith("/")
229 ? includes[i].getModulePath().substring(1)
230 : (pathBase + includes[i].getModulePath());
231 ModuleCfg includedMod = (ModuleCfg)builder.buildGraph(
232 schemaValidatingParser, includedModPath);
233 parseIncludedModules(builder, includedMod, includedModPath);
234 includes[i].initIncludedModule(includedMod);
235 }
236 }
237 }
This page was automatically generated by Maven