001 /* XMLOutputFactory.java -- 002 Copyright (C) 2005,2006,2009 Free Software Foundation, Inc. 003 004 This file is part of GNU Classpath. 005 006 GNU Classpath is free software; you can redistribute it and/or modify 007 it under the terms of the GNU General Public License as published by 008 the Free Software Foundation; either version 2, or (at your option) 009 any later version. 010 011 GNU Classpath is distributed in the hope that it will be useful, but 012 WITHOUT ANY WARRANTY; without even the implied warranty of 013 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 014 General Public License for more details. 015 016 You should have received a copy of the GNU General Public License 017 along with GNU Classpath; see the file COPYING. If not, write to the 018 Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 019 02110-1301 USA. 020 021 Linking this library statically or dynamically with other modules is 022 making a combined work based on this library. Thus, the terms and 023 conditions of the GNU General Public License cover the whole 024 combination. 025 026 As a special exception, the copyright holders of this library give you 027 permission to link this library with independent modules to produce an 028 executable, regardless of the license terms of these independent 029 modules, and to copy and distribute the resulting executable under 030 terms of your choice, provided that you also meet, for each linked 031 independent module, the terms and conditions of the license of that 032 module. An independent module is a module which is not derived from 033 or based on this library. If you modify this library, you may extend 034 this exception to your version of the library, but you are not 035 obligated to do so. If you do not wish to do so, delete this 036 exception statement from your version. */ 037 038 package javax.xml.stream; 039 040 import java.io.BufferedReader; 041 import java.io.File; 042 import java.io.FileInputStream; 043 import java.io.InputStream; 044 import java.io.InputStreamReader; 045 import java.io.IOException; 046 import java.io.OutputStream; 047 import java.io.Writer; 048 import java.util.Properties; 049 import javax.xml.transform.Result; 050 051 /** 052 * Factory for obtaining XML stream and event writers for various kinds of 053 * output sink. 054 * <h3>Configuration</h3> 055 * <table> 056 * <tr> 057 * <th>Name</th> 058 * <th>Description</th> 059 * <th>Type</th> 060 * <th>Default</th> 061 * <th>Required</th> 062 * </tr> 063 * <tr> 064 * <td>javax.xml.stream.isRepairingNamespaces</td> 065 * <td>default namespace prefixes</td> 066 * <td>Boolean</td> 067 * <td>Boolean.FALSE</td> 068 * <td>yes</td> 069 * </tr> 070 * </table> 071 */ 072 public abstract class XMLOutputFactory 073 { 074 075 /** 076 * Property used to control whether to default namespace prefixes. 077 * If true, the writer will create a namespace declaration for any 078 * attribute that doesn't have a namespace declaration in scope. 079 */ 080 public static final java.lang.String IS_REPAIRING_NAMESPACES = 081 "javax.xml.stream.isRepairingNamespaces"; 082 083 protected XMLOutputFactory() 084 { 085 } 086 087 /** 088 * Creates a new <b>output</b> factory. 089 * @see #newInstance(String,ClassLoader) 090 */ 091 public static XMLOutputFactory newInstance() 092 throws FactoryConfigurationError 093 { 094 return newInstance(null, null); 095 } 096 097 /** 098 * Creates a new <b>output</b> factory. 099 * The implementation class to load is the first found in the following 100 * locations: 101 * <ol> 102 * <li>the <code>javax.xml.stream.XMLOutputFactory</code> system 103 * property</li> 104 * <li>the above named property value in the 105 * <code><i>$JAVA_HOME</i>/lib/stax.properties</code> file</li> 106 * <li>the class name specified in the 107 * <code>META-INF/services/javax.xml.stream.XMLOutputFactory</code> 108 * system resource</li> 109 * <li>the default factory class</li> 110 * </ol> 111 * @param factoryId the name of the factory, same as the property 112 * @param classLoader the class loader to use 113 * @return a new factory instance 114 * @exception FactoryConfigurationError if an instance of this factory 115 * could not be loaded 116 */ 117 public static XMLOutputFactory newInstance(String factoryId, 118 ClassLoader classLoader) 119 throws FactoryConfigurationError 120 { 121 if (classLoader == null) 122 { 123 classLoader = Thread.currentThread().getContextClassLoader(); 124 } 125 if (classLoader == null) 126 { 127 classLoader = XMLOutputFactory.class.getClassLoader(); 128 } 129 String className = null; 130 int count = 0; 131 do 132 { 133 className = getFactoryClassName(classLoader, count++); 134 if (className != null) 135 { 136 try 137 { 138 Class<?> t = (classLoader != null) ? 139 classLoader.loadClass(className) : 140 Class.forName(className); 141 return (XMLOutputFactory) t.newInstance(); 142 } 143 catch (ClassNotFoundException e) 144 { 145 className = null; 146 } 147 catch (Exception e) 148 { 149 throw new FactoryConfigurationError(e, 150 "error instantiating class " + className); 151 } 152 } 153 } 154 while (className == null && count < 3); 155 return new gnu.xml.stream.XMLOutputFactoryImpl(); 156 } 157 158 private static String getFactoryClassName(ClassLoader loader, int attempt) 159 { 160 final String propertyName = "javax.xml.stream.XMLOutputFactory"; 161 switch (attempt) 162 { 163 case 0: 164 return System.getProperty(propertyName); 165 case 1: 166 try 167 { 168 File file = new File(System.getProperty("java.home")); 169 file = new File(file, "lib"); 170 file = new File(file, "stax.properties"); 171 InputStream in = new FileInputStream(file); 172 Properties props = new Properties(); 173 props.load(in); 174 in.close(); 175 return props.getProperty(propertyName); 176 } 177 catch (IOException e) 178 { 179 return null; 180 } 181 case 2: 182 try 183 { 184 String serviceKey = "/META-INF/services/" + propertyName; 185 InputStream in = (loader != null) ? 186 loader.getResourceAsStream(serviceKey) : 187 XMLOutputFactory.class.getResourceAsStream(serviceKey); 188 if (in != null) 189 { 190 BufferedReader r = 191 new BufferedReader(new InputStreamReader(in)); 192 String ret = r.readLine(); 193 r.close(); 194 return ret; 195 } 196 } 197 catch (IOException e) 198 { 199 } 200 return null; 201 default: 202 return null; 203 } 204 } 205 206 /** 207 * Creates a new stream writer. 208 */ 209 public abstract XMLStreamWriter createXMLStreamWriter(Writer stream) 210 throws XMLStreamException; 211 212 /** 213 * Creates a new stream writer. 214 */ 215 public abstract XMLStreamWriter createXMLStreamWriter(OutputStream stream) 216 throws XMLStreamException; 217 218 /** 219 * Creates a new stream writer. 220 */ 221 public abstract XMLStreamWriter createXMLStreamWriter(OutputStream stream, 222 String encoding) 223 throws XMLStreamException; 224 225 /** 226 * Creates a new stream writer. 227 * @exception UnsupportedOperationException if this method is not 228 * supported 229 */ 230 public abstract XMLStreamWriter createXMLStreamWriter(Result result) 231 throws XMLStreamException; 232 233 /** 234 * Creates a new event writer. 235 * @exception UnsupportedOperationException if this method is not 236 * supported 237 */ 238 public abstract XMLEventWriter createXMLEventWriter(Result result) 239 throws XMLStreamException; 240 241 /** 242 * Creates a new event writer. 243 */ 244 public abstract XMLEventWriter createXMLEventWriter(OutputStream stream) 245 throws XMLStreamException; 246 247 /** 248 * Creates a new event writer. 249 */ 250 public abstract XMLEventWriter createXMLEventWriter(OutputStream stream, 251 String encoding) 252 throws XMLStreamException; 253 254 /** 255 * Creates a new event writer. 256 */ 257 public abstract XMLEventWriter createXMLEventWriter(Writer stream) 258 throws XMLStreamException; 259 260 /** 261 * Sets the implementation-specific property of the given name. 262 * @exception IllegalArgumentException if the property is not supported 263 */ 264 public abstract void setProperty(String name, Object value) 265 throws IllegalArgumentException; 266 267 /** 268 * Returns the implementation-specific property of the given name. 269 * @exception IllegalArgumentException if the property is not supported 270 */ 271 public abstract Object getProperty(String name) 272 throws IllegalArgumentException; 273 274 /** 275 * Indicates whether the specified property is supported. 276 */ 277 public abstract boolean isPropertySupported(String name); 278 279 }