KickJava   Java API By Example, From Geeks To Geeks.

Java > Open Source Codes > org > sape > carbon > core > config > format > jdom > JDOMConfigurationFactory


1 /*
2  * The contents of this file are subject to the Sapient Public License
3  * Version 1.0 (the "License"); you may not use this file except in compliance
4  * with the License. You may obtain a copy of the License at
5  * http://carbon.sf.net/License.html.
6  *
7  * Software distributed under the License is distributed on an "AS IS" basis,
8  * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License for
9  * the specific language governing rights and limitations under the License.
10  *
11  * The Original Code is The Carbon Component Framework.
12  *
13  * The Initial Developer of the Original Code is Sapient Corporation
14  *
15  * Copyright (C) 2003 Sapient Corporation. All Rights Reserved.
16  */

17
18 package org.sape.carbon.core.config.format.jdom;
19
20 import java.io.IOException JavaDoc;
21 import java.io.InputStream JavaDoc;
22 import java.io.InputStreamReader JavaDoc;
23 import java.io.OutputStream JavaDoc;
24 import java.io.StringReader JavaDoc;
25 import java.util.Iterator JavaDoc;
26 import java.util.List JavaDoc;
27
28 import javax.xml.parsers.SAXParser JavaDoc;
29 import javax.xml.parsers.SAXParserFactory JavaDoc;
30
31 import org.sape.carbon.core.config.format.ConfigurationDataFormatService;
32 import org.sape.carbon.core.config.format.ConfigurationFormatException;
33 import org.sape.carbon.core.exception.ExceptionUtility;
34
35 import org.apache.commons.logging.Log;
36 import org.apache.commons.logging.LogFactory;
37 import org.jdom.Document;
38 import org.jdom.Element;
39 import org.jdom.JDOMException;
40 import org.jdom.Namespace;
41 import org.jdom.input.SAXBuilder;
42 import org.jdom.output.XMLOutputter;
43
44 /**
45  * <p>This factory implementation constructs the appropriate Configuration
46  * implementation, through the Dynamic Proxy facility of the JDK, for the
47  * particular Configuration interface requested.
48  * </p>
49  *
50  * Copyright 2002 Sapient
51  * @since carbon 1.0
52  * @author Greg Hinkle, January 2002
53  * @version $Revision: 1.21 $($Author: dvoet $ / $Date: 2003/05/05 21:21:17 $)
54  */

55 public class JDOMConfigurationFactory
56     implements ConfigurationDataFormatService {
57
58     /**
59      * Provides a handle to Apache-commons logger
60      */

61     private Log log = LogFactory.getLog(this.getClass());
62
63     /** Name of the feature URI to turn on schema validation in xerces. */
64     private static final String JavaDoc SCHEMA_URI =
65         "http://www.w3.org/2001/XMLSchema-instance";
66
67     /** Name of the xerces sax parser used to do schema validation. */
68     private static final String JavaDoc XERCES_SAX_PARSER =
69         "org.apache.xerces.jaxp.SAXParserImpl";
70
71     /**
72      * <P>Loads a <code>org.jdom.Document</code> object from the given
73      * <code>InputStream</code>. This node object will represent
74      * the full object-graph depiction of a live configuration.</P>
75      *
76      * @param name The name of the configuration node
77      * @param in the {@link java.io.InputStream} from which
78      * the configuration will be read
79      * @throws ConfigurationFormatException when there is a formatting error
80      * with the input stream
81      * @return The Document object representing a live
82      * object graph of the data from the input stream
83      */

84     public Document readConfigurationStreamToData(String JavaDoc name, InputStream JavaDoc in)
85             throws ConfigurationFormatException {
86
87         Document document = null;
88         ConfigEntityResolver configEntityResolver =
89             new ConfigEntityResolver(name);
90
91         // Configuration may be read twice if it fails to validate
92
// the first time. Therefore this method must read
93
// over the input stream twice. Because JDOM closes
94
// the input stream after reading it, it must be
95
// copied out of the normal stream into a form where it
96
// can be used to build a new input stream for the
97
// two reads by JDOM.
98
String JavaDoc inputStreamString = convertStreamToString(name, in);
99
100         try {
101             // First use a validating builder. Ideally all
102
// the JDOM XML should validate.
103
SAXBuilder validatingBuilder = new SAXBuilder(true);
104             validatingBuilder.setEntityResolver(configEntityResolver);
105
106             // turn on schema validation
107
if (XERCES_SAX_PARSER.equals(getSaxParserClassName())) {
108                 validatingBuilder.setFeature(
109                     "http://apache.org/xml/features/validation/schema", true);
110             }
111
112
113             StringReader JavaDoc stringReader = new StringReader JavaDoc(inputStreamString);
114             document = validatingBuilder.build(stringReader);
115
116             if (log.isTraceEnabled()) {
117                 log.trace("Validated configuration [" + name
118                     + "]");
119             }
120
121         } catch (JDOMException jde) {
122             // Likely indicates validation of the document failed.
123
// Try again with a non-validating parser.
124

125             try {
126                 SAXBuilder nonvalidatingBuilder = new SAXBuilder(false);
127                 nonvalidatingBuilder.setEntityResolver(configEntityResolver);
128                 StringReader JavaDoc stringReader = new StringReader JavaDoc(inputStreamString);
129                 document = nonvalidatingBuilder.build(stringReader);
130
131                 // The document has been read and is well-formed, so
132
// if the document contained information it was suppose
133
// to validate against, give a warning.
134
// If there was no validating document, merely log
135
// a trace message.
136
if (containsValidatingDocument(document)) {
137                     if (log.isWarnEnabled()) {
138                         log.warn(
139                             "Validation failed for configuration [" + name
140                             + "]: " + jde);
141                     }
142                 } else {
143                     if (log.isTraceEnabled()) {
144                         log.trace("No validating document supplied for "
145                         + "configuration ["
146                         + name
147                         + "]");
148                     }
149                 }
150
151             } catch (JDOMException jde2) {
152                 throw new ConfigurationFormatException(
153                     this.getClass(),
154                     "Unable to parse Configuration Data from input stream.",
155                     jde);
156             }
157         }
158         return document;
159     }
160
161     /**
162      * Checks if the given JDOM Document contains a document for validation
163      * against. This can be a inline/external DTD or a Schema.
164      *
165      * @param document the document to check against
166      * @return if the document has a validation document associated
167      */

168     protected boolean containsValidatingDocument(Document document) {
169         return (containsDtd(document) || containsSchema(document));
170     }
171
172     /**
173      * Checks if the given JDOM Document contains a DTD for validation
174      * against.
175      *
176      * @param document the document to check against
177      * @return if the document has a DTD associated
178      */

179     protected boolean containsDtd(Document document) {
180         return (document.getDocType() != null);
181     }
182
183     /**
184      * Checks if the given JDOM Document contains a Schema for validation
185      * against.
186      *
187      * @param document the document to check against
188      * @return if the document has a Schema associated
189      */

190     protected boolean containsSchema(Document document) {
191         boolean containsSchema = false;
192
193         Element rootElement = document.getRootElement();
194         List JavaDoc additionalNamespaces = rootElement.getAdditionalNamespaces();
195         if (additionalNamespaces != null) {
196             Iterator JavaDoc additionalNamespacesIterator =
197                 additionalNamespaces.iterator();
198
199             while (additionalNamespacesIterator.hasNext()) {
200                 Namespace namespace =
201                     (Namespace) additionalNamespacesIterator.next();
202
203                 if (SCHEMA_URI.equals(namespace.getURI())) {
204                     // If a schema URI exists check for an internal
205
// and external schema which this document tried
206
// to validate against
207

208                     String JavaDoc noNamespaceSchemaLocation =
209                         rootElement.getAttributeValue(
210                             "noNamespaceSchemaLocation", namespace);
211
212                     String JavaDoc schemaLocation =
213                         rootElement.getAttributeValue(
214                             "schemaLocation", namespace);
215
216                     if (noNamespaceSchemaLocation != null
217                             || schemaLocation != null) {
218
219                         containsSchema = true;
220                     }
221                 }
222             }
223         }
224
225         return containsSchema;
226     }
227
228     /**
229      * Converts a given input stream into a String.
230      *
231      * @param name the name of the input string to convert. Used for logging.
232      * @param in the input stream to convert
233      * @return a string representation of the InputStream
234      * @throws ConfigurationFormatException indicates an error converting
235      * the input stream into a string. Generally used to wrap
236      * an IOException
237      */

238     protected String JavaDoc convertStreamToString(String JavaDoc name, InputStream JavaDoc in)
239             throws ConfigurationFormatException {
240
241         InputStreamReader JavaDoc inputStreamReader = new
242             InputStreamReader JavaDoc(in);
243
244         StringBuffer JavaDoc inputStreamStringBuffer = new StringBuffer JavaDoc();
245
246         try {
247             char[] cbuf = new char[8096];
248             int charRead;
249             String JavaDoc characters;
250
251
252             charRead = inputStreamReader.read(cbuf, 0, cbuf.length);
253             while (charRead >= 0) {
254                 characters = new String JavaDoc(cbuf, 0, charRead);
255                 inputStreamStringBuffer.append(characters);
256                 charRead = inputStreamReader.read(cbuf, 0, cbuf.length);
257             }
258         } catch (IOException JavaDoc ioe) {
259             throw new ConfigurationFormatException(
260                 this.getClass(),
261                 "Unable to convert configuration [" + name
262                     + "] into a StringReader: "
263                     + ExceptionUtility.printStackTracesToString(ioe));
264
265         }
266
267         return inputStreamStringBuffer.toString();
268     }
269
270     /**
271      * Returns a string representation of the parser in the system or
272      * null if an error occurs.
273      *
274      * @return name of the system sax parser or null for an error
275      */

276     protected static String JavaDoc getSaxParserClassName() {
277         try {
278             SAXParserFactory JavaDoc saxParserFactory = SAXParserFactory.newInstance();
279             SAXParser JavaDoc saxParser = saxParserFactory.newSAXParser();
280             return saxParser.getClass().getName();
281         } catch (Exception JavaDoc e) {
282             return null;
283         }
284     }
285
286
287     /**
288      * <P>Stores the raw version of the provided <code>org.jdom.Document</code>
289      * object in the format that this format service implementation
290      * understands. The format of this implementation is strict XML.</P>
291      *
292      * @param out The output stream to which the raw configuration
293      * data should be written
294      * @param document the document to output
295      * @throws ConfigurationFormatException When unable to write a
296      * node's raw format to the output stream
297      */

298     public void writeConfigurationStreamToData(
299         Document document,
300         OutputStream JavaDoc out)
301     throws ConfigurationFormatException {
302
303         try {
304             XMLOutputter outputter = new XMLOutputter(" ", true);
305
306             outputter.output(document, out);
307         } catch (IOException JavaDoc ioe) {
308             throw new ConfigurationFormatException(
309                 this.getClass(),
310                 "Failed to write configuration document to output stream "
311                 + "in xml format.", ioe);
312         }
313     }
314
315 }
Popular Tags