1 /* 2 * Copyright (c) 2005, 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 com.sun.xml.internal.stream; 27 28 import java.io.IOException; 29 import java.io.OutputStream; 30 import java.io.Writer; 31 import javax.xml.stream.XMLEventWriter; 32 import javax.xml.stream.XMLOutputFactory; 33 import javax.xml.stream.XMLStreamException; 34 import javax.xml.stream.XMLStreamWriter; 35 import javax.xml.transform.Result; 36 import javax.xml.transform.dom.DOMResult; 37 import javax.xml.transform.stream.StreamResult; 38 import javax.xml.transform.stax.StAXResult; 39 import com.sun.org.apache.xerces.internal.impl.Constants; 40 import com.sun.org.apache.xerces.internal.impl.PropertyManager; 41 import com.sun.xml.internal.stream.writers.XMLDOMWriterImpl; 42 import com.sun.xml.internal.stream.writers.XMLEventWriterImpl; 43 import com.sun.xml.internal.stream.writers.XMLStreamWriterImpl; 44 45 /** 46 * This class provides the implementation of XMLOutputFactory. 47 * 48 * @author Neeraj Bajaj, 49 * @author k venugopal 50 */ 51 public class XMLOutputFactoryImpl extends XMLOutputFactory { 52 53 //List of supported properties and default values. 54 private PropertyManager fPropertyManager = new PropertyManager(PropertyManager.CONTEXT_WRITER); 55 56 //cache the instance of XMLStreamWriterImpl 57 private XMLStreamWriterImpl fStreamWriter = null; 58 59 /** 60 * TODO: at the current time, XMLStreamWriters are not Thread safe. 61 */ 62 boolean fReuseInstance = false; 63 64 /** 65 * Creates a new instance of XMLOutputFactory 66 */ XMLOutputFactoryImpl()67 public XMLOutputFactoryImpl() { 68 } 69 createXMLEventWriter(OutputStream outputStream)70 public XMLEventWriter createXMLEventWriter(OutputStream outputStream) 71 throws XMLStreamException { 72 return createXMLEventWriter(outputStream, null); 73 } 74 createXMLEventWriter(OutputStream outputStream, String encoding)75 public XMLEventWriter createXMLEventWriter(OutputStream outputStream, String encoding) 76 throws XMLStreamException { 77 return new XMLEventWriterImpl(createXMLStreamWriter(outputStream, encoding)); 78 } 79 createXMLEventWriter(Result result)80 public XMLEventWriter createXMLEventWriter(Result result) 81 throws XMLStreamException { 82 83 if (result instanceof StAXResult && ((StAXResult) result).getXMLEventWriter() != null) { 84 return ((StAXResult) result).getXMLEventWriter(); 85 } 86 87 return new XMLEventWriterImpl(createXMLStreamWriter(result)); 88 } 89 createXMLEventWriter(java.io.Writer writer)90 public XMLEventWriter createXMLEventWriter(java.io.Writer writer) 91 throws XMLStreamException { 92 return new XMLEventWriterImpl(createXMLStreamWriter(writer)); 93 } 94 createXMLStreamWriter(Result result)95 public XMLStreamWriter createXMLStreamWriter(Result result) 96 throws XMLStreamException { 97 98 if (result instanceof StreamResult) { 99 return createXMLStreamWriter((StreamResult) result, null); 100 } else if (result instanceof DOMResult) { 101 return new XMLDOMWriterImpl((DOMResult) result); 102 } else if (result instanceof StAXResult) { 103 if (((StAXResult) result).getXMLStreamWriter() != null) { 104 return ((StAXResult) result).getXMLStreamWriter(); 105 } else { 106 throw new UnsupportedOperationException( 107 "Result of type " + result + " is not supported"); 108 } 109 } else if (result.getSystemId() != null) { 110 //this is not correct impl of SAXResult. Keep it for now for compatibility 111 return createXMLStreamWriter(new StreamResult(result.getSystemId())); 112 } else { 113 throw new UnsupportedOperationException( 114 "Result of type " + result + " is not supported. Supported result " 115 + "types are: DOMResult, StAXResult and StreamResult."); 116 } 117 118 } 119 createXMLStreamWriter(java.io.Writer writer)120 public XMLStreamWriter createXMLStreamWriter(java.io.Writer writer) 121 throws XMLStreamException { 122 return createXMLStreamWriter(toStreamResult(null, writer, null), null); 123 } 124 createXMLStreamWriter(OutputStream outputStream)125 public XMLStreamWriter createXMLStreamWriter(OutputStream outputStream) 126 throws XMLStreamException { 127 return createXMLStreamWriter(outputStream, null); 128 } 129 createXMLStreamWriter(OutputStream outputStream, String encoding)130 public XMLStreamWriter createXMLStreamWriter(OutputStream outputStream, String encoding) 131 throws XMLStreamException { 132 return createXMLStreamWriter(toStreamResult(outputStream, null, null), encoding); 133 } 134 getProperty(String name)135 public Object getProperty(String name) 136 throws IllegalArgumentException { 137 if (name == null) { 138 throw new IllegalArgumentException("Property not supported"); 139 } 140 if (fPropertyManager.containsProperty(name)) { 141 return fPropertyManager.getProperty(name); 142 } 143 throw new IllegalArgumentException("Property not supported"); 144 } 145 isPropertySupported(String name)146 public boolean isPropertySupported(String name) { 147 if (name == null) { 148 return false; 149 } else { 150 return fPropertyManager.containsProperty(name); 151 } 152 } 153 setProperty(String name, Object value)154 public void setProperty(String name, Object value) 155 throws IllegalArgumentException { 156 if (name == null || value == null || !fPropertyManager.containsProperty(name)) { 157 throw new IllegalArgumentException("Property " + name + "is not supported"); 158 } 159 if (name == Constants.REUSE_INSTANCE || name.equals(Constants.REUSE_INSTANCE)) { 160 fReuseInstance = (Boolean)value; 161 if (DEBUG) { 162 System.out.println("fReuseInstance is set to " + fReuseInstance); 163 } 164 165 // TODO: XMLStreamWriters are not Thread safe, 166 // don't let application think it is optimizing 167 if (fReuseInstance) { 168 throw new IllegalArgumentException( 169 "Property " 170 + name 171 + " is not supported: XMLStreamWriters are not Thread safe"); 172 } 173 } else {//for any other property set the flag 174 //REVISIT: Even in this case instance can be reused, by passing PropertyManager 175 fPropertyChanged = true; 176 } 177 fPropertyManager.setProperty(name, value); 178 } 179 180 /** 181 * StreamResult object is re-used and the values are set appropriately. 182 */ toStreamResult(OutputStream os, Writer writer, String systemId)183 StreamResult toStreamResult(OutputStream os, Writer writer, String systemId) { 184 StreamResult sr = new StreamResult(); 185 sr.setOutputStream(os); 186 sr.setWriter(writer); 187 sr.setSystemId(systemId); 188 return sr; 189 } 190 createXMLStreamWriter(StreamResult sr, String encoding)191 XMLStreamWriter createXMLStreamWriter(StreamResult sr, String encoding) 192 throws XMLStreamException { 193 //if factory is configured to reuse the instance & this instance can be reused 194 //& the setProperty() hasn't been called 195 try { 196 if (fReuseInstance && fStreamWriter != null && fStreamWriter.canReuse() 197 && !fPropertyChanged) { 198 fStreamWriter.reset(); 199 fStreamWriter.setOutput(sr, encoding); 200 if (DEBUG) { 201 System.out.println("reusing instance, object id : " + fStreamWriter); 202 } 203 return fStreamWriter; 204 } 205 return fStreamWriter = new XMLStreamWriterImpl(sr, encoding, 206 new PropertyManager(fPropertyManager)); 207 } catch (IOException io) { 208 throw new XMLStreamException(io); 209 } 210 }//createXMLStreamWriter(StreamResult,String) 211 212 private static final boolean DEBUG = false; 213 214 /** 215 * This flag indicates the change of property. If true, 216 * <code>PropertyManager</code> should be passed when creating 217 * <code>XMLStreamWriterImpl</code> 218 */ 219 private boolean fPropertyChanged; 220 }//XMLOutputFactory 221