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