Source code: gnu/xml/dom/JAXPFactory.java
1 /* JAXPFactory.java --
2 Copyright (C) 2001 Free Software Foundation, Inc.
3
4 This file is part of GNU Classpath.
5
6 GNU Classpath is free software; you can redistribute it and/or modify
7 it under the terms of the GNU General Public License as published by
8 the Free Software Foundation; either version 2, or (at your option)
9 any later version.
10
11 GNU Classpath is distributed in the hope that it will be useful, but
12 WITHOUT ANY WARRANTY; without even the implied warranty of
13 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
14 General Public License for more details.
15
16 You should have received a copy of the GNU General Public License
17 along with GNU Classpath; see the file COPYING. If not, write to the
18 Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
19 02110-1301 USA.
20
21 Linking this library statically or dynamically with other modules is
22 making a combined work based on this library. Thus, the terms and
23 conditions of the GNU General Public License cover the whole
24 combination.
25
26 As a special exception, the copyright holders of this library give you
27 permission to link this library with independent modules to produce an
28 executable, regardless of the license terms of these independent
29 modules, and to copy and distribute the resulting executable under
30 terms of your choice, provided that you also meet, for each linked
31 independent module, the terms and conditions of the license of that
32 module. An independent module is a module which is not derived from
33 or based on this library. If you modify this library, you may extend
34 this exception to your version of the library, but you are not
35 obligated to do so. If you do not wish to do so, delete this
36 exception statement from your version. */
37
38 package gnu.xml.dom;
39
40 import java.io.IOException;
41
42 import org.w3c.dom.Document;
43 import org.w3c.dom.DOMImplementation;
44
45 import org.xml.sax.EntityResolver;
46 import org.xml.sax.ErrorHandler;
47 import org.xml.sax.InputSource;
48 import org.xml.sax.XMLReader;
49 import org.xml.sax.SAXException;
50 import org.xml.sax.SAXParseException;
51
52 import javax.xml.parsers.DocumentBuilder;
53 import javax.xml.parsers.DocumentBuilderFactory;
54 import javax.xml.parsers.ParserConfigurationException;
55 import javax.xml.parsers.SAXParserFactory;
56
57
58 /**
59 * DOM bootstrapping API, for use with JAXP.
60 *
61 * @see Consumer
62 *
63 * @author David Brownell
64 */
65 public final class JAXPFactory
66 extends DocumentBuilderFactory
67 {
68
69 private static final String PROPERTY = "http://xml.org/sax/properties/";
70 private static final String FEATURE = "http://xml.org/sax/features/";
71
72 private SAXParserFactory pf;
73
74 /**
75 * Default constructor.
76 */
77 public JAXPFactory()
78 {
79 }
80
81 /**
82 * Constructs a JAXP document builder which uses the default
83 * JAXP SAX2 parser and the DOM implementation in this package.
84 */
85 public DocumentBuilder newDocumentBuilder()
86 throws ParserConfigurationException
87 {
88 if (pf == null)
89 {
90 // Force use of AElfred2 since not all JAXP parsers
91 // conform very well to the SAX2 API spec ...
92 pf = new gnu.xml.aelfred2.JAXPFactory();
93 // pf = SAXParserFactory.newInstance ();
94 }
95
96 // JAXP default: false
97 pf.setValidating(isValidating());
98
99 // FIXME: this namespace setup may cause errors in some
100 // conformant SAX2 parsers, which we CAN patch up by
101 // splicing a "NSFilter" stage up front ...
102
103 // JAXP default: false
104 pf.setNamespaceAware(isNamespaceAware());
105
106 try
107 {
108 // undo rude "namespace-prefixes=false" default
109 pf.setFeature(FEATURE + "namespace-prefixes", true);
110
111 return new JAXPBuilder(pf.newSAXParser().getXMLReader(), this);
112 }
113 catch (SAXException e)
114 {
115 String msg = "can't create JAXP DocumentBuilder: " + e.getMessage();
116 throw new ParserConfigurationException(msg);
117 }
118 }
119
120 /** There seems to be no useful specification for attribute names */
121 public void setAttribute(String name, Object value)
122 throws IllegalArgumentException
123 {
124 if ("http://java.sun.com/xml/jaxp/properties/schemaLanguage".equals(name))
125 {
126 // TODO
127 }
128 else
129 {
130 throw new IllegalArgumentException(name);
131 }
132 }
133
134 /** There seems to be no useful specification for attribute names */
135 public Object getAttribute(String name)
136 throws IllegalArgumentException
137 {
138 throw new IllegalArgumentException(name);
139 }
140
141 static final class JAXPBuilder
142 extends DocumentBuilder
143 implements ErrorHandler
144 {
145
146 private Consumer consumer;
147 private XMLReader producer;
148 private DomImpl impl;
149
150 JAXPBuilder(XMLReader parser, JAXPFactory factory)
151 throws ParserConfigurationException
152 {
153 impl = new DomImpl();
154
155 // set up consumer side
156 try
157 {
158 consumer = new Consumer();
159 }
160 catch (SAXException e)
161 {
162 throw new ParserConfigurationException(e.getMessage());
163 }
164
165 // JAXP defaults: true, noise nodes are good (bleech)
166 consumer.setHidingReferences(factory.isExpandEntityReferences());
167 consumer.setHidingComments(factory.isIgnoringComments());
168 consumer.setHidingWhitespace(factory.isIgnoringElementContentWhitespace());
169 consumer.setHidingCDATA(factory.isCoalescing());
170
171 // set up producer side
172 producer = parser;
173 producer.setContentHandler(consumer.getContentHandler());
174 producer.setDTDHandler(consumer.getDTDHandler());
175
176 try
177 {
178 String id;
179
180 // if validating, report validity errors, and default
181 // to treating them as fatal
182 if (factory.isValidating ())
183 {
184 producer.setFeature(FEATURE + "validation", true);
185 producer.setErrorHandler(this);
186 }
187
188 // always save prefix info, maybe do namespace processing
189 producer.setFeature(FEATURE + "namespace-prefixes", true);
190 producer.setFeature(FEATURE + "namespaces",
191 factory.isNamespaceAware());
192
193 // set important handlers
194 id = PROPERTY + "lexical-handler";
195 producer.setProperty(id, consumer.getProperty(id));
196
197 id = PROPERTY + "declaration-handler";
198 producer.setProperty(id, consumer.getProperty(id));
199
200 }
201 catch (SAXException e)
202 {
203 throw new ParserConfigurationException(e.getMessage());
204 }
205 }
206
207 public Document parse(InputSource source)
208 throws SAXException, IOException
209 {
210 producer.parse(source);
211 Document doc = consumer.getDocument();
212 // TODO inputEncoding
213 doc.setDocumentURI(source.getSystemId());
214 return doc;
215 }
216
217 public boolean isNamespaceAware()
218 {
219 try
220 {
221 return producer.getFeature(FEATURE + "namespaces");
222 }
223 catch (SAXException e)
224 {
225 // "can't happen"
226 throw new RuntimeException(e.getMessage());
227 }
228 }
229
230 public boolean isValidating()
231 {
232 try
233 {
234 return producer.getFeature(FEATURE + "validation");
235 }
236 catch (SAXException e)
237 {
238 // "can't happen"
239 throw new RuntimeException(e.getMessage());
240 }
241 }
242
243 public void setEntityResolver(EntityResolver resolver)
244 {
245 producer.setEntityResolver(resolver);
246 }
247
248 public void setErrorHandler(ErrorHandler handler)
249 {
250 producer.setErrorHandler(handler);
251 consumer.setErrorHandler(handler);
252 }
253
254 public DOMImplementation getDOMImplementation()
255 {
256 return impl;
257 }
258
259 public Document newDocument()
260 {
261 return new DomDocument();
262 }
263
264 // implementation of error handler that's used when validating
265 public void fatalError(SAXParseException e)
266 throws SAXException
267 {
268 throw e;
269 }
270
271 public void error(SAXParseException e)
272 throws SAXException
273 {
274 throw e;
275 }
276
277 public void warning(SAXParseException e)
278 throws SAXException
279 {
280 /* ignore */
281 }
282
283 }
284
285 }
286