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.writers; 27 28 import java.util.Iterator; 29 import javax.xml.namespace.NamespaceContext; 30 import javax.xml.namespace.QName; 31 import javax.xml.stream.XMLEventReader; 32 import javax.xml.stream.XMLEventWriter; 33 import javax.xml.stream.XMLStreamException; 34 import javax.xml.stream.XMLStreamWriter; 35 import javax.xml.stream.events.Attribute; 36 import javax.xml.stream.events.Characters; 37 import javax.xml.stream.events.Comment; 38 import javax.xml.stream.events.DTD; 39 import javax.xml.stream.events.EntityReference; 40 import javax.xml.stream.events.Namespace; 41 import javax.xml.stream.events.ProcessingInstruction; 42 import javax.xml.stream.events.StartDocument; 43 import javax.xml.stream.events.StartElement; 44 import javax.xml.stream.events.XMLEvent; 45 46 /** 47 * 48 * @author Neeraj Bajaj, Sun Microsystems. 49 * 50 */ 51 public class XMLEventWriterImpl implements XMLEventWriter { 52 53 //delegate everything to XMLStreamWriter.. 54 private final XMLStreamWriter fStreamWriter; 55 private static final boolean DEBUG = false; 56 57 /** 58 * Constructs an XMLEventWriterImpl that implements the standard XMLStreamWriter 59 * interface. 60 * @param streamWriter 61 */ XMLEventWriterImpl(XMLStreamWriter streamWriter)62 public XMLEventWriterImpl(XMLStreamWriter streamWriter) { 63 fStreamWriter = streamWriter; 64 } 65 66 /** 67 * 68 * @param xMLEventReader 69 * @throws XMLStreamException 70 */ add(XMLEventReader xMLEventReader)71 public void add(XMLEventReader xMLEventReader) throws XMLStreamException { 72 if (xMLEventReader == null) { 73 throw new XMLStreamException("Event reader shouldn't be null"); 74 } 75 while (xMLEventReader.hasNext()) { 76 add(xMLEventReader.nextEvent()); 77 } 78 } 79 80 /** 81 * 82 * @param xMLEvent 83 * @throws XMLStreamException 84 */ add(XMLEvent xMLEvent)85 public void add(XMLEvent xMLEvent) throws XMLStreamException { 86 int type = xMLEvent.getEventType(); 87 switch (type) { 88 case XMLEvent.DTD: { 89 DTD dtd = (DTD) xMLEvent; 90 if (DEBUG) { 91 System.out.println("Adding DTD = " + dtd.toString()); 92 } 93 fStreamWriter.writeDTD(dtd.getDocumentTypeDeclaration()); 94 break; 95 } 96 case XMLEvent.START_DOCUMENT: { 97 StartDocument startDocument = (StartDocument) xMLEvent; 98 if (DEBUG) { 99 System.out.println("Adding StartDocument = " + startDocument.toString()); 100 } 101 try { 102 if (XMLStreamWriterBase.class.isAssignableFrom(fStreamWriter.getClass())) { 103 // internal impl uses the extended interface 104 ((XMLStreamWriterBase)fStreamWriter).writeStartDocument( 105 startDocument.getCharacterEncodingScheme(), 106 startDocument.getVersion(), 107 startDocument.isStandalone(), 108 startDocument.standaloneSet()); 109 } else { 110 fStreamWriter.writeStartDocument( 111 startDocument.getCharacterEncodingScheme(), 112 startDocument.getVersion()); 113 } 114 } catch (XMLStreamException e) { 115 fStreamWriter.writeStartDocument(startDocument.getVersion()); 116 } 117 break; 118 } 119 case XMLEvent.START_ELEMENT: { 120 StartElement startElement = xMLEvent.asStartElement(); 121 if (DEBUG) { 122 System.out.println("Adding startelement = " + startElement.toString()); 123 } 124 QName qname = startElement.getName(); 125 fStreamWriter.writeStartElement(qname.getPrefix(), qname.getLocalPart(), 126 qname.getNamespaceURI()); 127 128 /* 129 getNamespaces() Returns an Iterator of namespaces declared on this element. 130 This Iterator does not contain previously declared namespaces unless they 131 appear on the current START_ELEMENT. Therefore this list may contain redeclared 132 namespaces and duplicate namespace declarations. Use the getNamespaceContext() 133 method to get the current context of namespace declarations. We should be 134 using getNamespaces() to write namespace declarations for this START_ELEMENT 135 */ 136 Iterator<? extends Namespace> iterator = startElement.getNamespaces(); 137 while (iterator.hasNext()) { 138 Namespace namespace = iterator.next(); 139 fStreamWriter.writeNamespace(namespace.getPrefix(), namespace.getNamespaceURI()); 140 } 141 //REVISIT: What about writing attributes ? 142 Iterator<? extends Attribute> attributes = startElement.getAttributes(); 143 while (attributes.hasNext()) { 144 Attribute attribute = attributes.next(); 145 QName aqname = attribute.getName(); 146 fStreamWriter.writeAttribute(aqname.getPrefix(), aqname.getNamespaceURI(), 147 aqname.getLocalPart(), attribute.getValue()); 148 } 149 break; 150 } 151 case XMLEvent.NAMESPACE: { 152 Namespace namespace = (Namespace) xMLEvent; 153 if (DEBUG) { 154 System.out.println("Adding namespace = " + namespace.toString()); 155 } 156 fStreamWriter.writeNamespace(namespace.getPrefix(), namespace.getNamespaceURI()); 157 break; 158 } 159 case XMLEvent.COMMENT: { 160 Comment comment = (Comment) xMLEvent; 161 if (DEBUG) { 162 System.out.println("Adding comment = " + comment.toString()); 163 } 164 fStreamWriter.writeComment(comment.getText()); 165 break; 166 } 167 case XMLEvent.PROCESSING_INSTRUCTION: { 168 ProcessingInstruction processingInstruction = (ProcessingInstruction) xMLEvent; 169 if (DEBUG) { 170 System.out.println("Adding processing instruction = " + processingInstruction.toString()); 171 } 172 fStreamWriter.writeProcessingInstruction(processingInstruction.getTarget(), 173 processingInstruction.getData()); 174 break; 175 } 176 case XMLEvent.CHARACTERS: { 177 Characters characters = xMLEvent.asCharacters(); 178 if (DEBUG) { 179 System.out.println("Adding characters = " + characters.toString()); 180 } 181 //check if the CHARACTERS are CDATA 182 if (characters.isCData()) { 183 fStreamWriter.writeCData(characters.getData()); 184 } else { 185 fStreamWriter.writeCharacters(characters.getData()); 186 } 187 break; 188 } 189 case XMLEvent.ENTITY_REFERENCE: { 190 EntityReference entityReference = (EntityReference) xMLEvent; 191 if (DEBUG) { 192 System.out.println("Adding Entity Reference = " + entityReference.toString()); 193 } 194 fStreamWriter.writeEntityRef(entityReference.getName()); 195 break; 196 } 197 case XMLEvent.ATTRIBUTE: { 198 Attribute attribute = (Attribute) xMLEvent; 199 if (DEBUG) { 200 System.out.println("Adding Attribute = " + attribute.toString()); 201 } 202 QName qname = attribute.getName(); 203 fStreamWriter.writeAttribute(qname.getPrefix(), qname.getNamespaceURI(), 204 qname.getLocalPart(), attribute.getValue()); 205 break; 206 } 207 case XMLEvent.CDATA: { 208 //there is no separate CDATA datatype but CDATA event can be reported 209 //by using vendor specific CDATA property. 210 Characters characters = (Characters) xMLEvent; 211 if (DEBUG) { 212 System.out.println("Adding characters = " + characters.toString()); 213 } 214 if (characters.isCData()) { 215 fStreamWriter.writeCData(characters.getData()); 216 } 217 break; 218 } 219 //xxx: Why there isn't any event called Notation. 220 //case XMLEvent.NOTATION_DECLARATION:{ 221 //} 222 223 case XMLEvent.END_ELEMENT: { 224 fStreamWriter.writeEndElement(); 225 break; 226 } 227 case XMLEvent.END_DOCUMENT: { 228 fStreamWriter.writeEndDocument(); 229 break; 230 } 231 //throw new XMLStreamException("Unknown Event type = " + type); 232 }; 233 234 } 235 236 /** 237 * 238 * @throws XMLStreamException 239 */ close()240 public void close() throws XMLStreamException { 241 fStreamWriter.close(); 242 } 243 244 /** 245 * 246 * @throws XMLStreamException will inturn call flush on the stream to which 247 * data is being written. 248 */ flush()249 public void flush() throws XMLStreamException { 250 fStreamWriter.flush(); 251 } 252 253 /** 254 * 255 * @return 256 */ getNamespaceContext()257 public NamespaceContext getNamespaceContext() { 258 return fStreamWriter.getNamespaceContext(); 259 } 260 261 /** 262 * 263 * @param namespaceURI Namespace URI 264 * @throws XMLStreamException 265 * @return prefix associated with the URI. 266 */ getPrefix(String namespaceURI)267 public String getPrefix(String namespaceURI) throws XMLStreamException { 268 return fStreamWriter.getPrefix(namespaceURI); 269 } 270 271 /** 272 * 273 * @param uri Namespace URI 274 * @throws XMLStreamException 275 */ setDefaultNamespace(String uri)276 public void setDefaultNamespace(String uri) throws XMLStreamException { 277 fStreamWriter.setDefaultNamespace(uri); 278 } 279 280 /** 281 * 282 * @param namespaceContext Namespace Context 283 * @throws XMLStreamException 284 */ setNamespaceContext(NamespaceContext namespaceContext)285 public void setNamespaceContext(NamespaceContext namespaceContext) 286 throws XMLStreamException { 287 fStreamWriter.setNamespaceContext(namespaceContext); 288 } 289 290 /** 291 * 292 * @param prefix namespace prefix associated with the uri. 293 * @param uri Namespace URI 294 * @throws XMLStreamException 295 */ setPrefix(String prefix, String uri)296 public void setPrefix(String prefix, String uri) throws XMLStreamException { 297 fStreamWriter.setPrefix(prefix, uri); 298 } 299 300 }//XMLEventWriterImpl 301