1 /* 2 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. 3 * 4 * This code is free software; you can redistribute it and/or modify it 5 * under the terms of the GNU General Public License version 2 only, as 6 * published by the Free Software Foundation. Oracle designates this 7 * particular file as subject to the "Classpath" exception as provided 8 * by Oracle in the LICENSE file that accompanied this code. 9 * 10 * This code is distributed in the hope that it will be useful, but WITHOUT 11 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or 12 * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License 13 * version 2 for more details (a copy is included in the LICENSE file that 14 * accompanied this code). 15 * 16 * You should have received a copy of the GNU General Public License version 17 * 2 along with this work; if not, write to the Free Software Foundation, 18 * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. 19 * 20 * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA 21 * or visit www.oracle.com if you need additional information or have any 22 * questions. 23 */ 24 25 /* 26 * Copyright (c) 2009, 2013, by Oracle Corporation. All Rights Reserved. 27 */ 28 29 package javax.xml.stream; 30 31 import com.sun.xml.internal.stream.XMLOutputFactoryImpl; 32 import javax.xml.transform.Result; 33 34 /** 35 * Defines an abstract implementation of a factory for 36 * getting XMLEventWriters and XMLStreamWriters. 37 * 38 * The following table defines the standard properties of this specification. 39 * Each property varies in the level of support required by each implementation. 40 * The level of support required is described in the 'Required' column. 41 * 42 * <table border="2" rules="all" cellpadding="4"> 43 * <thead> 44 * <tr> 45 * <th align="center" colspan="2"> 46 * Configuration parameters 47 * </th> 48 * </tr> 49 * </thead> 50 * <tbody> 51 * <tr> 52 * <th>Property Name</th> 53 * <th>Behavior</th> 54 * <th>Return type</th> 55 * <th>Default Value</th> 56 * <th>Required</th> 57 * </tr> 58 * <tr><td>javax.xml.stream.isRepairingNamespaces</td><td>defaults prefixes 59 * on the output side</td><td>Boolean</td><td>False</td><td>Yes</td></tr> 60 * </tbody> 61 * </table> 62 * 63 * <p>The following paragraphs describe the namespace and prefix repair algorithm: 64 * 65 * <p>The property can be set with the following code line: 66 * {@code setProperty("javax.xml.stream.isRepairingNamespaces", new Boolean(true|false));} 67 * 68 * <p>This property specifies that the writer default namespace prefix declarations. 69 * The default value is false. 70 * 71 * <p>If a writer isRepairingNamespaces it will create a namespace declaration 72 * on the current StartElement for 73 * any attribute that does not 74 * currently have a namespace declaration in scope. If the StartElement 75 * has a uri but no prefix specified a prefix will be assigned, if the prefix 76 * has not been declared in a parent of the current StartElement it will be declared 77 * on the current StartElement. If the defaultNamespace is bound and in scope 78 * and the default namespace matches the URI of the attribute or StartElement 79 * QName no prefix will be assigned. 80 * 81 * <p>If an element or attribute name has a prefix, but is not 82 * bound to any namespace URI, then the prefix will be removed 83 * during serialization. 84 * 85 * <p>If element and/or attribute names in the same start or 86 * empty-element tag are bound to different namespace URIs and 87 * are using the same prefix then the element or the first 88 * occurring attribute retains the original prefix and the 89 * following attributes have their prefixes replaced with a 90 * new prefix that is bound to the namespace URIs of those 91 * attributes. 92 * 93 * <p>If an element or attribute name uses a prefix that is 94 * bound to a different URI than that inherited from the 95 * namespace context of the parent of that element and there 96 * is no namespace declaration in the context of the current 97 * element then such a namespace declaration is added. 98 * 99 * <p>If an element or attribute name is bound to a prefix and 100 * there is a namespace declaration that binds that prefix 101 * to a different URI then that namespace declaration is 102 * either removed if the correct mapping is inherited from 103 * the parent context of that element, or changed to the 104 * namespace URI of the element or attribute using that prefix. 105 * 106 * @version 1.2 107 * @author Copyright (c) 2009, 2015 by Oracle Corporation. All Rights Reserved. 108 * @see XMLInputFactory 109 * @see XMLEventWriter 110 * @see XMLStreamWriter 111 * @since 1.6 112 */ 113 public abstract class XMLOutputFactory { 114 /** 115 * Property used to set prefix defaulting on the output side 116 */ 117 public static final String IS_REPAIRING_NAMESPACES= 118 "javax.xml.stream.isRepairingNamespaces"; 119 120 static final String DEFAULIMPL = "com.sun.xml.internal.stream.XMLOutputFactoryImpl"; 121 122 protected XMLOutputFactory(){} 123 124 /** 125 * Creates a new instance of the {@code XMLOutputFactory} builtin 126 * system-default implementation. 127 * 128 * @return A new instance of the {@code XMLOutputFactory} builtin 129 * system-default implementation. 130 * 131 * @since 9 132 */ 133 public static XMLOutputFactory newDefaultFactory() { 134 return new XMLOutputFactoryImpl(); 135 } 136 137 /** 138 * Creates a new instance of the factory in exactly the same manner as the 139 * {@link #newFactory()} method. 140 * @throws FactoryConfigurationError if an instance of this factory cannot be loaded 141 */ 142 public static XMLOutputFactory newInstance() 143 throws FactoryConfigurationError 144 { 145 return FactoryFinder.find(XMLOutputFactory.class, DEFAULIMPL); 146 } 147 148 /** 149 * Create a new instance of the factory. 150 * <p> 151 * This static method creates a new factory instance. This method uses the 152 * following ordered lookup procedure to determine the XMLOutputFactory 153 * implementation class to load: 154 * <ul> 155 * <li> 156 * Use the javax.xml.stream.XMLOutputFactory system property. 157 * </li> 158 * <li> 159 * <p> 160 * Use the configuration file "stax.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 * 166 * <p> 167 * The stax.properties file is read only once by the implementation 168 * and its values are then cached for future use. If the file does not exist 169 * when the first attempt is made to read from it, no further attempts are 170 * made to check for its existence. It is not possible to change the value 171 * of any property in stax.properties after it has been read for the first time. 172 * 173 * <p> 174 * Use the jaxp configuration file "jaxp.properties". The file is in the same 175 * format as stax.properties and will only be read if stax.properties does 176 * not exist. 177 * </li> 178 * <li> 179 * <p> 180 * Use the service-provider loading facility, defined by the 181 * {@link java.util.ServiceLoader} class, to attempt to locate and load an 182 * implementation of the service using the {@linkplain 183 * java.util.ServiceLoader#load(java.lang.Class) default loading mechanism}: 184 * the service-provider loading facility will use the {@linkplain 185 * java.lang.Thread#getContextClassLoader() current thread's context class loader} 186 * to attempt to load the service. If the context class 187 * loader is null, the {@linkplain 188 * ClassLoader#getSystemClassLoader() system class loader} will be used. 189 * </li> 190 * <li> 191 * <p> 192 * Otherwise, the {@linkplain #newDefaultFactory() system-default} 193 * implementation is returned. 194 * </li> 195 * </ul> 196 * <p> 197 * Once an application has obtained a reference to a XMLOutputFactory it 198 * can use the factory to configure and obtain stream instances. 199 * <p> 200 * Note that this is a new method that replaces the deprecated newInstance() method. 201 * No changes in behavior are defined by this replacement method relative to the 202 * deprecated method. 203 * 204 * @throws FactoryConfigurationError in case of {@linkplain 205 * java.util.ServiceConfigurationError service configuration error} or if 206 * the implementation is not available or cannot be instantiated. 207 */ 208 public static XMLOutputFactory newFactory() 209 throws FactoryConfigurationError 210 { 211 return FactoryFinder.find(XMLOutputFactory.class, DEFAULIMPL); 212 } 213 214 /** 215 * Create a new instance of the factory. 216 * 217 * @param factoryId Name of the factory to find, same as 218 * a property name 219 * @param classLoader classLoader to use 220 * @return the factory implementation 221 * @throws FactoryConfigurationError if an instance of this factory cannot be loaded 222 * 223 * @deprecated This method has been deprecated because it returns an 224 * instance of XMLInputFactory, which is of the wrong class. 225 * Use the new method {@link #newFactory(java.lang.String, 226 * java.lang.ClassLoader)} instead. 227 */ 228 public static XMLInputFactory newInstance(String factoryId, 229 ClassLoader classLoader) 230 throws FactoryConfigurationError { 231 //do not fallback if given classloader can't find the class, throw exception 232 return FactoryFinder.find(XMLInputFactory.class, factoryId, classLoader, null); 233 } 234 235 /** 236 * Create a new instance of the factory. 237 * If the classLoader argument is null, then the ContextClassLoader is used. 238 * <p> 239 * This method uses the following ordered lookup procedure to determine 240 * the XMLOutputFactory implementation class to load: 241 * <ul> 242 * <li> 243 * Use the value of the system property identified by {@code factoryId}. 244 * </li> 245 * <li> 246 * <p> 247 * Use the configuration file "stax.properties". The file is in standard 248 * {@link java.util.Properties} format and typically located in the 249 * {@code conf} directory of the Java installation. It contains the fully qualified 250 * name of the implementation class with the key being the system property 251 * defined above. 252 * 253 * <p> 254 * The stax.properties file is read only once by the implementation 255 * and its values are then cached for future use. If the file does not exist 256 * when the first attempt is made to read from it, no further attempts are 257 * made to check for its existence. It is not possible to change the value 258 * of any property in stax.properties after it has been read for the first time. 259 * 260 * <p> 261 * Use the jaxp configuration file "jaxp.properties". The file is in the same 262 * format as stax.properties and will only be read if stax.properties does 263 * not exist. 264 * </li> 265 * <li> 266 * <p> 267 * If {@code factoryId} is "javax.xml.stream.XMLOutputFactory", 268 * use the service-provider loading facility, defined by the 269 * {@link java.util.ServiceLoader} class, to attempt to {@linkplain 270 * java.util.ServiceLoader#load(java.lang.Class, java.lang.ClassLoader) locate and load} 271 * an implementation of the service using the specified {@code ClassLoader}. 272 * If {@code classLoader} is null, the {@linkplain 273 * java.util.ServiceLoader#load(java.lang.Class) default loading mechanism} will apply: 274 * That is, the service-provider loading facility will use the {@linkplain 275 * java.lang.Thread#getContextClassLoader() current thread's context class loader} 276 * to attempt to load the service. If the context class 277 * loader is null, the {@linkplain 278 * ClassLoader#getSystemClassLoader() system class loader} will be used. 279 * </li> 280 * <li> 281 * <p> 282 * Otherwise, throws a {@link FactoryConfigurationError}. 283 * </li> 284 * </ul> 285 * 286 * @apiNote The parameter factoryId defined here is inconsistent with that 287 * of other JAXP factories where the first parameter is fully qualified 288 * factory class name that provides implementation of the factory. 289 * 290 * <p> 291 * Note that this is a new method that replaces the deprecated 292 * {@link #newInstance(java.lang.String, java.lang.ClassLoader) 293 * newInstance(String factoryId, ClassLoader classLoader)} method. 294 * The original method was incorrectly defined to return XMLInputFactory. 295 * 296 * 297 * @param factoryId Name of the factory to find, same as 298 * a property name 299 * @param classLoader classLoader to use 300 * @return the factory implementation 301 * @throws FactoryConfigurationError in case of {@linkplain 302 * java.util.ServiceConfigurationError service configuration error} or if 303 * the implementation is not available or cannot be instantiated. 304 */ 305 public static XMLOutputFactory newFactory(String factoryId, 306 ClassLoader classLoader) 307 throws FactoryConfigurationError { 308 //do not fallback if given classloader can't find the class, throw exception 309 return FactoryFinder.find(XMLOutputFactory.class, factoryId, classLoader, null); 310 } 311 312 /** 313 * Create a new XMLStreamWriter that writes to a writer 314 * @param stream the writer to write to 315 * @throws XMLStreamException 316 */ 317 public abstract XMLStreamWriter createXMLStreamWriter(java.io.Writer stream) throws XMLStreamException; 318 319 /** 320 * Create a new XMLStreamWriter that writes to a stream 321 * @param stream the stream to write to 322 * @throws XMLStreamException 323 */ 324 public abstract XMLStreamWriter createXMLStreamWriter(java.io.OutputStream stream) throws XMLStreamException; 325 326 /** 327 * Create a new XMLStreamWriter that writes to a stream 328 * @param stream the stream to write to 329 * @param encoding the encoding to use 330 * @throws XMLStreamException 331 */ 332 public abstract XMLStreamWriter createXMLStreamWriter(java.io.OutputStream stream, 333 String encoding) throws XMLStreamException; 334 335 /** 336 * Create a new XMLStreamWriter that writes to a JAXP result. This method is optional. 337 * @param result the result to write to 338 * @throws UnsupportedOperationException if this method is not 339 * supported by this XMLOutputFactory 340 * @throws XMLStreamException 341 */ 342 public abstract XMLStreamWriter createXMLStreamWriter(Result result) throws XMLStreamException; 343 344 345 /** 346 * Create a new XMLEventWriter that writes to a JAXP result. This method is optional. 347 * @param result the result to write to 348 * @throws UnsupportedOperationException if this method is not 349 * supported by this XMLOutputFactory 350 * @throws XMLStreamException 351 */ 352 public abstract XMLEventWriter createXMLEventWriter(Result result) throws XMLStreamException; 353 354 /** 355 * Create a new XMLEventWriter that writes to a stream 356 * @param stream the stream to write to 357 * @throws XMLStreamException 358 */ 359 public abstract XMLEventWriter createXMLEventWriter(java.io.OutputStream stream) throws XMLStreamException; 360 361 362 363 /** 364 * Create a new XMLEventWriter that writes to a stream 365 * @param stream the stream to write to 366 * @param encoding the encoding to use 367 * @throws XMLStreamException 368 */ 369 public abstract XMLEventWriter createXMLEventWriter(java.io.OutputStream stream, 370 String encoding) throws XMLStreamException; 371 372 /** 373 * Create a new XMLEventWriter that writes to a writer 374 * @param stream the stream to write to 375 * @throws XMLStreamException 376 */ 377 public abstract XMLEventWriter createXMLEventWriter(java.io.Writer stream) throws XMLStreamException; 378 379 /** 380 * Allows the user to set specific features/properties on the underlying implementation. 381 * @param name The name of the property 382 * @param value The value of the property 383 * @throws java.lang.IllegalArgumentException if the property is not supported 384 */ 385 public abstract void setProperty(java.lang.String name, 386 Object value) 387 throws IllegalArgumentException; 388 389 /** 390 * Get a feature/property on the underlying implementation 391 * @param name The name of the property 392 * @return The value of the property 393 * @throws java.lang.IllegalArgumentException if the property is not supported 394 */ 395 public abstract Object getProperty(java.lang.String name) 396 throws IllegalArgumentException; 397 398 /** 399 * Query the set of properties that this factory supports. 400 * 401 * @param name The name of the property (may not be null) 402 * @return true if the property is supported and false otherwise 403 */ 404 public abstract boolean isPropertySupported(String name); 405 }