1 /* 2 * Copyright (c) 2000, 2019, Oracle and/or its affiliates. All rights reserved. 3 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. 4 * 5 * This code is free software; you can redistribute it and/or modify it 6 * under the terms of the GNU General Public License version 2 only, as 7 * published by the Free Software Foundation. Oracle designates this 8 * particular file as subject to the "Classpath" exception as provided 9 * by Oracle in the LICENSE file that accompanied this code. 10 * 11 * This code is distributed in the hope that it will be useful, but WITHOUT 12 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or 13 * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License 14 * version 2 for more details (a copy is included in the LICENSE file that 15 * accompanied this code). 16 * 17 * You should have received a copy of the GNU General Public License version 18 * 2 along with this work; if not, write to the Free Software Foundation, 19 * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. 20 * 21 * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA 22 * or visit www.oracle.com if you need additional information or have any 23 * questions. 24 */ 25 26 package javax.xml.parsers; 27 28 import com.sun.org.apache.xerces.internal.jaxp.SAXParserFactoryImpl; 29 import javax.xml.validation.Schema; 30 import org.xml.sax.SAXException; 31 import org.xml.sax.SAXNotRecognizedException; 32 import org.xml.sax.SAXNotSupportedException; 33 34 /** 35 * Defines a factory API that enables applications to configure and 36 * obtain a SAX based parser to parse XML documents. 37 * 38 * @author Jeff Suttor 39 * @author Neeraj Bajaj 40 * 41 * @since 1.4 42 */ 43 public abstract class SAXParserFactory { 44 private static final String DEFAULT_IMPL = 45 "com.sun.org.apache.xerces.internal.jaxp.SAXParserFactoryImpl"; 46 47 /** 48 * Should Parsers be validating? 49 */ 50 private boolean validating = false; 51 52 /** 53 * Should Parsers be namespace aware? 54 */ 55 private boolean namespaceAware = false; 56 57 /** 58 * Protected constructor to force use of {@link #newInstance()}. 59 */ 60 protected SAXParserFactory () { 61 62 } 63 64 /** 65 * Creates a new NamespaceAware instance of the {@code SAXParserFactory} 66 * builtin system-default implementation. Parsers produced by the factory 67 * instance provides support for XML namespaces by default. 68 * 69 * @implSpec 70 * In addition to creating a factory instance using the same process as 71 * {@link #newDefaultInstance()}, this method must set NamespaceAware to true. 72 * 73 * @return a new instance of the {@code SAXParserFactory} builtin 74 * system-default implementation. 75 * 76 * @since 13 77 */ 78 public static SAXParserFactory newDefaultNSInstance() { 79 return makeNSAware(new SAXParserFactoryImpl()); 80 } 81 82 /** 83 * Creates a new NamespaceAware instance of a {@code SAXParserFactory}. 84 * Parsers produced by the factory instance provides support for XML 85 * namespaces by default. 86 * 87 * @implSpec 88 * In addition to creating a factory instance using the same process as 89 * {@link #newInstance()}, this method must set NamespaceAware to true. 90 * 91 * @return a new instance of the {@code SAXParserFactory} 92 * 93 * @throws FactoryConfigurationError in case of {@linkplain 94 * java.util.ServiceConfigurationError service configuration error} 95 * or if the implementation is not available or cannot be instantiated. 96 * 97 * @since 13 98 */ 99 public static SAXParserFactory newNSInstance() { 100 return makeNSAware(FactoryFinder.find(SAXParserFactory.class, DEFAULT_IMPL)); 101 } 102 103 /** 104 * Creates a new NamespaceAware instance of a {@code SAXParserFactory} from 105 * the class name. Parsers produced by the factory instance provides 106 * support for XML namespaces by default. 107 * 108 * @implSpec 109 * In addition to creating a factory instance using the same process as 110 * {@link #newInstance(java.lang.String, java.lang.ClassLoader)}, this method 111 * must set NamespaceAware to true. 112 * 113 * @param factoryClassName a fully qualified factory class name that provides 114 * implementation of 115 * {@code javax.xml.parsers.SAXParserFactory}. 116 * 117 * @param classLoader the {@code ClassLoader} used to load the factory class. 118 * If it is {@code null}, the current {@code Thread}'s 119 * context classLoader is used to load the factory class. 120 * 121 * @return a new instance of the {@code SAXParserFactory} 122 * 123 * @throws FactoryConfigurationError if {@code factoryClassName} is {@code null}, or 124 * the factory class cannot be loaded, instantiated. 125 * 126 * @since 13 127 */ 128 public static SAXParserFactory newNSInstance(String factoryClassName, 129 ClassLoader classLoader) { 130 return makeNSAware(FactoryFinder.newInstance( 131 SAXParserFactory.class, factoryClassName, classLoader, false)); 132 } 133 134 /** 135 * Creates a new instance of the {@code SAXParserFactory} builtin 136 * system-default implementation. 137 * 138 * @return A new instance of the {@code SAXParserFactory} builtin 139 * system-default implementation. 140 * 141 * @since 9 142 */ 143 public static SAXParserFactory newDefaultInstance() { 144 return new SAXParserFactoryImpl(); 145 } 146 147 /** 148 * Obtain a new instance of a {@code SAXParserFactory}. This 149 * static method creates a new factory instance 150 * This method uses the following ordered lookup procedure to determine 151 * the {@code SAXParserFactory} implementation class to 152 * load: 153 * <ul> 154 * <li> 155 * Use the {@code javax.xml.parsers.SAXParserFactory} system 156 * property. 157 * </li> 158 * <li> 159 * <p> 160 * Use the configuration file "jaxp.properties". The file is in standard 161 * {@link java.util.Properties} format and typically located in the 162 * {@code conf} directory of the Java installation. It contains the fully qualified 163 * name of the implementation class with the key being the system property 164 * defined above. 165 * <p> 166 * The jaxp.properties file is read only once by the JAXP implementation 167 * and its values are then cached for future use. If the file does not exist 168 * when the first attempt is made to read from it, no further attempts are 169 * made to check for its existence. It is not possible to change the value 170 * of any property in jaxp.properties after it has been read for the first time. 171 * </li> 172 * <li> 173 * <p> 174 * Use the service-provider loading facility, defined by the 175 * {@link java.util.ServiceLoader} class, to attempt to locate and load an 176 * implementation of the service using the {@linkplain 177 * java.util.ServiceLoader#load(java.lang.Class) default loading mechanism}: 178 * the service-provider loading facility will use the {@linkplain 179 * java.lang.Thread#getContextClassLoader() current thread's context class loader} 180 * to attempt to load the service. If the context class 181 * loader is null, the {@linkplain 182 * ClassLoader#getSystemClassLoader() system class loader} will be used. 183 * </li> 184 * <li> 185 * <p> 186 * Otherwise, the {@linkplain #newDefaultInstance() system-default} 187 * implementation is returned. 188 * </li> 189 * </ul> 190 * 191 * <p> 192 * Once an application has obtained a reference to a 193 * {@code SAXParserFactory} it can use the factory to 194 * configure and obtain parser instances. 195 * 196 * 197 * 198 * <h4>Tip for Trouble-shooting</h4> 199 * <p> 200 * Setting the {@code jaxp.debug} system property will cause 201 * this method to print a lot of debug messages 202 * to {@code System.err} about what it is doing and where it is looking at. 203 * 204 * <p> 205 * If you have problems loading {@link SAXParser}s, try: 206 * <pre> 207 * java -Djaxp.debug=1 YourProgram .... 208 * </pre> 209 * 210 * 211 * @return A new instance of a SAXParserFactory. 212 * 213 * @throws FactoryConfigurationError in case of {@linkplain 214 * java.util.ServiceConfigurationError service configuration error} or if 215 * the implementation is not available or cannot be instantiated. 216 */ 217 218 public static SAXParserFactory newInstance() { 219 return FactoryFinder.find( 220 /* The default property name according to the JAXP spec */ 221 SAXParserFactory.class, 222 /* The fallback implementation class name */ 223 DEFAULT_IMPL); 224 } 225 226 /** 227 * Obtain a new instance of a {@code SAXParserFactory} from class name. 228 * This function is useful when there are multiple providers in the classpath. 229 * It gives more control to the application as it can specify which provider 230 * should be loaded. 231 * 232 * <p>Once an application has obtained a reference to a {@code SAXParserFactory} 233 * it can use the factory to configure and obtain parser instances. 234 * 235 * 236 * <h4>Tip for Trouble-shooting</h4> 237 * <p>Setting the {@code jaxp.debug} system property will cause 238 * this method to print a lot of debug messages 239 * to {@code System.err} about what it is doing and where it is looking at. 240 * 241 * <p> 242 * If you have problems, try: 243 * <pre> 244 * java -Djaxp.debug=1 YourProgram .... 245 * </pre> 246 * 247 * @param factoryClassName fully qualified factory class name that provides implementation of {@code javax.xml.parsers.SAXParserFactory}. 248 * 249 * @param classLoader {@code ClassLoader} used to load the factory class. If {@code null} 250 * current {@code Thread}'s context classLoader is used to load the factory class. 251 * 252 * @return New instance of a {@code SAXParserFactory} 253 * 254 * @throws FactoryConfigurationError if {@code factoryClassName} is {@code null}, or 255 * the factory class cannot be loaded, instantiated. 256 * 257 * @see #newInstance() 258 * 259 * @since 1.6 260 */ 261 public static SAXParserFactory newInstance(String factoryClassName, ClassLoader classLoader){ 262 //do not fallback if given classloader can't find the class, throw exception 263 return FactoryFinder.newInstance(SAXParserFactory.class, 264 factoryClassName, classLoader, false); 265 } 266 267 private static SAXParserFactory makeNSAware(SAXParserFactory spf) { 268 spf.setNamespaceAware(true); 269 return spf; 270 } 271 272 /** 273 * Creates a new instance of a SAXParser using the currently 274 * configured factory parameters. 275 * 276 * @return A new instance of a SAXParser. 277 * 278 * @throws ParserConfigurationException if a parser cannot 279 * be created which satisfies the requested configuration. 280 * @throws SAXException for SAX errors. 281 */ 282 283 public abstract SAXParser newSAXParser() 284 throws ParserConfigurationException, SAXException; 285 286 287 /** 288 * Specifies that the parser produced by this code will 289 * provide support for XML namespaces. By default the value of this is set 290 * to {@code false}. 291 * 292 * @param awareness true if the parser produced by this code will 293 * provide support for XML namespaces; false otherwise. 294 */ 295 296 public void setNamespaceAware(boolean awareness) { 297 this.namespaceAware = awareness; 298 } 299 300 /** 301 * Specifies that the parser produced by this code will 302 * validate documents as they are parsed. By default the value of this is 303 * set to {@code false}. 304 * 305 * <p> 306 * Note that "the validation" here means 307 * <a href="http://www.w3.org/TR/REC-xml#proc-types">a validating 308 * parser</a> as defined in the XML recommendation. 309 * In other words, it essentially just controls the DTD validation. 310 * (except the legacy two properties defined in JAXP 1.2.) 311 * 312 * <p> 313 * To use modern schema languages such as W3C XML Schema or 314 * RELAX NG instead of DTD, you can configure your parser to be 315 * a non-validating parser by leaving the {@link #setValidating(boolean)} 316 * method {@code false}, then use the {@link #setSchema(Schema)} 317 * method to associate a schema to a parser. 318 * 319 * @param validating true if the parser produced by this code will 320 * validate documents as they are parsed; false otherwise. 321 */ 322 323 public void setValidating(boolean validating) { 324 this.validating = validating; 325 } 326 327 /** 328 * Indicates whether or not the factory is configured to produce 329 * parsers which are namespace aware. 330 * 331 * @return true if the factory is configured to produce 332 * parsers which are namespace aware; false otherwise. 333 */ 334 335 public boolean isNamespaceAware() { 336 return namespaceAware; 337 } 338 339 /** 340 * Indicates whether or not the factory is configured to produce 341 * parsers which validate the XML content during parse. 342 * 343 * @return true if the factory is configured to produce parsers which validate 344 * the XML content during parse; false otherwise. 345 */ 346 347 public boolean isValidating() { 348 return validating; 349 } 350 351 /** 352 * Sets the particular feature in the underlying implementation of 353 * org.xml.sax.XMLReader. 354 * A list of the core features and properties can be found at 355 * <a href="http://www.saxproject.org/">http://www.saxproject.org/</a> 356 * 357 * <p>All implementations are required to support the {@link javax.xml.XMLConstants#FEATURE_SECURE_PROCESSING} feature. 358 * When the feature is 359 * <ul> 360 * <li> 361 * {@code true}: the implementation will limit XML processing to conform to implementation limits. 362 * Examples include entity expansion limits and XML Schema constructs that would consume large amounts of resources. 363 * If XML processing is limited for security reasons, it will be reported via a call to the registered 364 * {@link org.xml.sax.ErrorHandler#fatalError(SAXParseException exception)}. 365 * See {@link SAXParser} {@code parse} methods for handler specification. 366 * </li> 367 * <li> 368 * When the feature is {@code false}, the implementation will processing XML according to the XML specifications without 369 * regard to possible implementation limits. 370 * </li> 371 * </ul> 372 * 373 * @param name The name of the feature to be set. 374 * @param value The value of the feature to be set. 375 * 376 * @throws ParserConfigurationException if a parser cannot 377 * be created which satisfies the requested configuration. 378 * @throws SAXNotRecognizedException When the underlying XMLReader does 379 * not recognize the property name. 380 * @throws SAXNotSupportedException When the underlying XMLReader 381 * recognizes the property name but doesn't support the 382 * property. 383 * @throws NullPointerException If the {@code name} parameter is null. 384 * 385 * @see org.xml.sax.XMLReader#setFeature 386 */ 387 public abstract void setFeature(String name, boolean value) 388 throws ParserConfigurationException, SAXNotRecognizedException, 389 SAXNotSupportedException; 390 391 /** 392 * 393 * Returns the particular property requested for in the underlying 394 * implementation of org.xml.sax.XMLReader. 395 * 396 * @param name The name of the property to be retrieved. 397 * 398 * @return Value of the requested property. 399 * 400 * @throws ParserConfigurationException if a parser cannot be created which satisfies the requested configuration. 401 * @throws SAXNotRecognizedException When the underlying XMLReader does not recognize the property name. 402 * @throws SAXNotSupportedException When the underlying XMLReader recognizes the property name but doesn't support the property. 403 * 404 * @see org.xml.sax.XMLReader#getProperty 405 */ 406 public abstract boolean getFeature(String name) 407 throws ParserConfigurationException, SAXNotRecognizedException, 408 SAXNotSupportedException; 409 410 411 /** 412 * Gets the {@link Schema} object specified through 413 * the {@link #setSchema(Schema schema)} method. 414 * 415 * 416 * @throws UnsupportedOperationException When implementation does not 417 * override this method 418 * 419 * @return 420 * the {@link Schema} object that was last set through 421 * the {@link #setSchema(Schema)} method, or null 422 * if the method was not invoked since a {@link SAXParserFactory} 423 * is created. 424 * 425 * @since 1.5 426 */ 427 public Schema getSchema() { 428 throw new UnsupportedOperationException( 429 "This parser does not support specification \"" 430 + this.getClass().getPackage().getSpecificationTitle() 431 + "\" version \"" 432 + this.getClass().getPackage().getSpecificationVersion() 433 + "\"" 434 ); 435 } 436 437 /** 438 * Set the {@link Schema} to be used by parsers created 439 * from this factory. 440 * 441 * <p>When a {@link Schema} is non-null, a parser will use a validator 442 * created from it to validate documents before it passes information 443 * down to the application. 444 * 445 * <p>When warnings/errors/fatal errors are found by the validator, the parser must 446 * handle them as if those errors were found by the parser itself. 447 * In other words, if the user-specified {@link org.xml.sax.ErrorHandler} 448 * is set, it must receive those errors, and if not, they must be 449 * treated according to the implementation specific 450 * default error handling rules. 451 * 452 * <p>A validator may modify the SAX event stream (for example by 453 * adding default values that were missing in documents), and a parser 454 * is responsible to make sure that the application will receive 455 * those modified event stream. 456 * 457 * <p>Initially, {@code null} is set as the {@link Schema}. 458 * 459 * <p>This processing will take effect even if 460 * the {@link #isValidating()} method returns {@code false}. 461 * 462 * <p>It is an error to use 463 * the {@code http://java.sun.com/xml/jaxp/properties/schemaSource} 464 * property and/or the {@code http://java.sun.com/xml/jaxp/properties/schemaLanguage} 465 * property in conjunction with a non-null {@link Schema} object. 466 * Such configuration will cause a {@link SAXException} 467 * exception when those properties are set on a {@link SAXParser}. 468 * 469 * <h4>Note for implementors</h4> 470 * <p> 471 * A parser must be able to work with any {@link Schema} 472 * implementation. However, parsers and schemas are allowed 473 * to use implementation-specific custom mechanisms 474 * as long as they yield the result described in the specification. 475 * 476 * @param schema {@code Schema} to use, {@code null} to remove a schema. 477 * 478 * @throws UnsupportedOperationException When implementation does not 479 * override this method 480 * 481 * @since 1.5 482 */ 483 public void setSchema(Schema schema) { 484 throw new UnsupportedOperationException( 485 "This parser does not support specification \"" 486 + this.getClass().getPackage().getSpecificationTitle() 487 + "\" version \"" 488 + this.getClass().getPackage().getSpecificationVersion() 489 + "\"" 490 ); 491 } 492 493 /** 494 * Set state of XInclude processing. 495 * 496 * <p>If XInclude markup is found in the document instance, should it be 497 * processed as specified in <a href="http://www.w3.org/TR/xinclude/"> 498 * XML Inclusions (XInclude) Version 1.0</a>. 499 * 500 * <p>XInclude processing defaults to {@code false}. 501 * 502 * @param state Set XInclude processing to {@code true} or 503 * {@code false} 504 * 505 * @throws UnsupportedOperationException When implementation does not 506 * override this method 507 * 508 * @since 1.5 509 */ 510 public void setXIncludeAware(final boolean state) { 511 if (state) { 512 throw new UnsupportedOperationException(" setXIncludeAware " + 513 "is not supported on this JAXP" + 514 " implementation or earlier: " + this.getClass()); 515 } 516 } 517 518 /** 519 * Get state of XInclude processing. 520 * 521 * @return current state of XInclude processing 522 * 523 * @throws UnsupportedOperationException When implementation does not 524 * override this method 525 * 526 * @since 1.5 527 */ 528 public boolean isXIncludeAware() { 529 throw new UnsupportedOperationException( 530 "This parser does not support specification \"" 531 + this.getClass().getPackage().getSpecificationTitle() 532 + "\" version \"" 533 + this.getClass().getPackage().getSpecificationVersion() 534 + "\"" 535 ); 536 } 537 }