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.XMLConstants;
53 import javax.xml.parsers.DocumentBuilder;
54 import javax.xml.parsers.DocumentBuilderFactory;
55 import javax.xml.parsers.ParserConfigurationException;
56 import javax.xml.parsers.SAXParserFactory;
57 
58 
59 /**
60  * DOM bootstrapping API, for use with JAXP.
61  *
62  * @see Consumer
63  *
64  * @author David Brownell
65  */
66 public final class JAXPFactory
67   extends DocumentBuilderFactory
68 {
69 
70   private static final String   PROPERTY = "http://xml.org/sax/properties/";
71   private static final String   FEATURE = "http://xml.org/sax/features/";
72 
73   private SAXParserFactory      pf;
74   private boolean secureProcessing;
75 
76   /**
77    * Default constructor.
78    */
JAXPFactory()79   public JAXPFactory()
80   {
81   }
82 
83   /**
84    * Constructs a JAXP document builder which uses the default
85    * JAXP SAX2 parser and the DOM implementation in this package.
86    */
newDocumentBuilder()87   public DocumentBuilder newDocumentBuilder()
88     throws ParserConfigurationException
89   {
90     if (pf == null)
91       {
92         // Force use of AElfred2 since not all JAXP parsers
93         // conform very well to the SAX2 API spec ...
94         pf = new gnu.xml.aelfred2.JAXPFactory();
95         // pf = SAXParserFactory.newInstance ();
96       }
97 
98     // JAXP default: false
99     pf.setValidating(isValidating());
100 
101     // FIXME:  this namespace setup may cause errors in some
102     // conformant SAX2 parsers, which we CAN patch up by
103     // splicing a "NSFilter" stage up front ...
104 
105     // JAXP default: false
106     pf.setNamespaceAware(isNamespaceAware());
107 
108     try
109       {
110         // undo rude "namespace-prefixes=false" default
111         pf.setFeature(FEATURE + "namespace-prefixes", true);
112 
113         return new JAXPBuilder(pf.newSAXParser().getXMLReader(), this);
114       }
115     catch (SAXException e)
116       {
117         String msg = "can't create JAXP DocumentBuilder: " + e.getMessage();
118         throw new ParserConfigurationException(msg);
119       }
120   }
121 
122   /** There seems to be no useful specification for attribute names */
setAttribute(String name, Object value)123   public void setAttribute(String name, Object value)
124     throws IllegalArgumentException
125   {
126     if ("http://java.sun.com/xml/jaxp/properties/schemaLanguage".equals(name))
127       {
128         // TODO
129       }
130     else
131       {
132         throw new IllegalArgumentException(name);
133       }
134   }
135 
136   /** There seems to be no useful specification for attribute names */
getAttribute(String name)137   public Object getAttribute(String name)
138     throws IllegalArgumentException
139   {
140     throw new IllegalArgumentException(name);
141   }
142 
setFeature(String name, boolean value)143   public void setFeature(String name, boolean value)
144     throws ParserConfigurationException
145   {
146     if (name == null)
147       throw new NullPointerException();
148     if (XMLConstants.FEATURE_SECURE_PROCESSING.equals(name))
149       {
150         secureProcessing = true;
151         return;
152       }
153     throw new ParserConfigurationException(name);
154   }
155 
getFeature(String name)156   public boolean getFeature(String name)
157     throws ParserConfigurationException
158   {
159     if (XMLConstants.FEATURE_SECURE_PROCESSING.equals(name))
160       return secureProcessing;
161     throw new ParserConfigurationException(name);
162   }
163 
164   static final class JAXPBuilder
165     extends DocumentBuilder
166     implements ErrorHandler
167   {
168 
169     private Consumer    consumer;
170     private XMLReader   producer;
171     private DomImpl             impl;
172 
JAXPBuilder(XMLReader parser, JAXPFactory factory)173     JAXPBuilder(XMLReader parser, JAXPFactory factory)
174       throws ParserConfigurationException
175     {
176       impl = new DomImpl();
177 
178       // set up consumer side
179       try
180         {
181           consumer = new Consumer();
182         }
183       catch (SAXException e)
184         {
185           throw new ParserConfigurationException(e.getMessage());
186         }
187 
188       // JAXP defaults: true, noise nodes are good (bleech)
189       consumer.setHidingReferences(factory.isExpandEntityReferences());
190       consumer.setHidingComments(factory.isIgnoringComments());
191       consumer.setHidingWhitespace(factory.isIgnoringElementContentWhitespace());
192       consumer.setHidingCDATA(factory.isCoalescing());
193 
194       // set up producer side
195       producer = parser;
196       producer.setContentHandler(consumer.getContentHandler());
197       producer.setDTDHandler(consumer.getDTDHandler());
198 
199       try
200         {
201           String        id;
202 
203           // if validating, report validity errors, and default
204           // to treating them as fatal
205           if (factory.isValidating ())
206             {
207               producer.setFeature(FEATURE + "validation", true);
208               producer.setErrorHandler(this);
209             }
210 
211           // always save prefix info, maybe do namespace processing
212           producer.setFeature(FEATURE + "namespace-prefixes", true);
213           producer.setFeature(FEATURE + "namespaces",
214                               factory.isNamespaceAware());
215 
216           // set important handlers
217           id = PROPERTY + "lexical-handler";
218           producer.setProperty(id, consumer.getProperty(id));
219 
220           id = PROPERTY + "declaration-handler";
221           producer.setProperty(id, consumer.getProperty(id));
222 
223         }
224       catch (SAXException e)
225         {
226           throw new ParserConfigurationException(e.getMessage());
227         }
228     }
229 
parse(InputSource source)230     public Document parse(InputSource source)
231       throws SAXException, IOException
232     {
233       producer.parse(source);
234       Document doc = consumer.getDocument();
235       // TODO inputEncoding
236       doc.setDocumentURI(source.getSystemId());
237       return doc;
238     }
239 
isNamespaceAware()240     public boolean isNamespaceAware()
241     {
242       try
243         {
244           return producer.getFeature(FEATURE + "namespaces");
245         }
246       catch (SAXException e)
247         {
248           // "can't happen"
249           throw new RuntimeException(e.getMessage());
250         }
251     }
252 
isValidating()253     public boolean isValidating()
254     {
255       try
256         {
257           return producer.getFeature(FEATURE + "validation");
258         }
259       catch (SAXException e)
260         {
261           // "can't happen"
262           throw new RuntimeException(e.getMessage());
263         }
264     }
265 
setEntityResolver(EntityResolver resolver)266     public void setEntityResolver(EntityResolver resolver)
267     {
268       producer.setEntityResolver(resolver);
269     }
270 
setErrorHandler(ErrorHandler handler)271     public void setErrorHandler(ErrorHandler handler)
272     {
273       producer.setErrorHandler(handler);
274       consumer.setErrorHandler(handler);
275     }
276 
getDOMImplementation()277     public DOMImplementation getDOMImplementation()
278     {
279       return impl;
280     }
281 
newDocument()282     public Document newDocument()
283     {
284       return new DomDocument();
285     }
286 
287     // implementation of error handler that's used when validating
fatalError(SAXParseException e)288     public void fatalError(SAXParseException e)
289       throws SAXException
290     {
291       throw e;
292     }
293 
error(SAXParseException e)294     public void error(SAXParseException e)
295       throws SAXException
296     {
297       throw e;
298     }
299 
warning(SAXParseException e)300     public void warning(SAXParseException e)
301       throws SAXException
302     {
303       /* ignore */
304     }
305 
306   }
307 
308 }
309