1/* 2 * Copyright (c) 1997, 2015, 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 26package com.sun.xml.internal.ws.util.xml; 27 28import java.io.IOException; 29 30import javax.xml.bind.attachment.AttachmentMarshaller; 31import javax.xml.stream.XMLStreamConstants; 32import javax.xml.stream.XMLStreamException; 33import javax.xml.stream.XMLStreamReader; 34import javax.xml.stream.XMLStreamWriter; 35import javax.xml.XMLConstants; 36 37import com.sun.xml.internal.ws.streaming.MtomStreamWriter; 38import com.sun.xml.internal.org.jvnet.staxex.Base64Data; 39import com.sun.xml.internal.org.jvnet.staxex.XMLStreamReaderEx; 40import com.sun.xml.internal.org.jvnet.staxex.XMLStreamWriterEx; 41 42/** 43 * Reads a sub-tree from {@link XMLStreamReader} and writes to {@link XMLStreamWriter} 44 * as-is. 45 * 46 * <p> 47 * This class can be sub-classed to implement a simple transformation logic. 48 * 49 * @author Kohsuke Kawaguchi 50 * @author Ryan Shoemaker 51 * 52 * @deprecated use com.sun.xml.internal.org.jvnet.staxex.util.XMLStreamReaderToXMLStreamWriter 53 */ 54public class XMLStreamReaderToXMLStreamWriter { 55 56 private static final int BUF_SIZE = 4096; 57 58 protected XMLStreamReader in; 59 protected XMLStreamWriter out; 60 61 private char[] buf; 62 63 boolean optimizeBase64Data = false; 64 65 AttachmentMarshaller mtomAttachmentMarshaller; 66 67 /** 68 * Reads one subtree and writes it out. 69 * 70 * <p> 71 * The {@link XMLStreamWriter} never receives a start/end document event. 72 * Those need to be written separately by the caller. 73 */ 74 public void bridge(XMLStreamReader in, XMLStreamWriter out) throws XMLStreamException { 75 assert in!=null && out!=null; 76 this.in = in; 77 this.out = out; 78 79 optimizeBase64Data = (in instanceof XMLStreamReaderEx); 80 81 if (out instanceof XMLStreamWriterEx && out instanceof MtomStreamWriter) { 82 mtomAttachmentMarshaller = ((MtomStreamWriter) out).getAttachmentMarshaller(); 83 } 84 // remembers the nest level of elements to know when we are done. 85 int depth=0; 86 87 buf = new char[BUF_SIZE]; 88 89 // if the parser is at the start tag, proceed to the first element 90 int event = in.getEventType(); 91 if(event == XMLStreamConstants.START_DOCUMENT) { 92 // nextTag doesn't correctly handle DTDs 93 while( !in.isStartElement() ) { 94 event = in.next(); 95 if (event == XMLStreamConstants.COMMENT) 96 handleComment(); 97 } 98 } 99 100 101 if( event!=XMLStreamConstants.START_ELEMENT) 102 throw new IllegalStateException("The current event is not START_ELEMENT\n but " + event); 103 104 do { 105 // These are all of the events listed in the javadoc for 106 // XMLEvent. 107 // The spec only really describes 11 of them. 108 switch (event) { 109 case XMLStreamConstants.START_ELEMENT : 110 depth++; 111 handleStartElement(); 112 break; 113 case XMLStreamConstants.END_ELEMENT : 114 handleEndElement(); 115 depth--; 116 if(depth==0) 117 return; 118 break; 119 case XMLStreamConstants.CHARACTERS : 120 handleCharacters(); 121 break; 122 case XMLStreamConstants.ENTITY_REFERENCE : 123 handleEntityReference(); 124 break; 125 case XMLStreamConstants.PROCESSING_INSTRUCTION : 126 handlePI(); 127 break; 128 case XMLStreamConstants.COMMENT : 129 handleComment(); 130 break; 131 case XMLStreamConstants.DTD : 132 handleDTD(); 133 break; 134 case XMLStreamConstants.CDATA : 135 handleCDATA(); 136 break; 137 case XMLStreamConstants.SPACE : 138 handleSpace(); 139 break; 140 case XMLStreamConstants.END_DOCUMENT: 141 throw new XMLStreamException("Malformed XML at depth="+depth+", Reached EOF. Event="+event); 142 default : 143 throw new XMLStreamException("Cannot process event: " + event); 144 } 145 146 event=in.next(); 147 } while (depth!=0); 148 } 149 150 protected void handlePI() throws XMLStreamException { 151 out.writeProcessingInstruction( 152 in.getPITarget(), 153 in.getPIData()); 154 } 155 156 157 protected void handleCharacters() throws XMLStreamException { 158 159 CharSequence c = null; 160 161 if (optimizeBase64Data) { 162 c = ((XMLStreamReaderEx)in).getPCDATA(); 163 } 164 165 if ((c != null) && (c instanceof Base64Data)) { 166 if (mtomAttachmentMarshaller != null) { 167 Base64Data b64d = (Base64Data) c; 168 ((XMLStreamWriterEx)out).writeBinary(b64d.getDataHandler()); 169 } else { 170 try { 171 ((Base64Data)c).writeTo(out); 172 } catch (IOException e) { 173 throw new XMLStreamException(e); 174 } 175 } 176 } else { 177 for (int start=0,read=buf.length; read == buf.length; start+=buf.length) { 178 read = in.getTextCharacters(start, buf, 0, buf.length); 179 out.writeCharacters(buf, 0, read); 180 } 181 } 182 } 183 184 protected void handleEndElement() throws XMLStreamException { 185 out.writeEndElement(); 186 } 187 188 protected void handleStartElement() throws XMLStreamException { 189 String nsUri = in.getNamespaceURI(); 190 out.writeStartElement( 191 fixNull(in.getPrefix()), 192 in.getLocalName(), 193 fixNull(nsUri) 194 ); 195 196 // start namespace bindings 197 int nsCount = in.getNamespaceCount(); 198 for (int i = 0; i < nsCount; i++) { 199 out.writeNamespace( 200 in.getNamespacePrefix(i), 201 fixNull(in.getNamespaceURI(i))); // zephyr doesn't like null, I don't know what is correct, so just fix null to "" for now 202 } 203 204 // write attributes 205 int attCount = in.getAttributeCount(); 206 for (int i = 0; i < attCount; i++) { 207 handleAttribute(i); 208 } 209 } 210 211 /** 212 * Writes out the {@code i}-th attribute of the current element. 213 * 214 * <p> 215 * Used from {@link #handleStartElement()}. 216 */ 217 protected void handleAttribute(int i) throws XMLStreamException { 218 String nsUri = in.getAttributeNamespace(i); 219 String prefix = in.getAttributePrefix(i); 220 if (fixNull(nsUri).equals(XMLConstants.XMLNS_ATTRIBUTE_NS_URI)) { 221 //Its a namespace decl, ignore as it is already written. 222 return; 223 } 224 225 if(nsUri==null || prefix == null || prefix.equals("")) { 226 out.writeAttribute( 227 in.getAttributeLocalName(i), 228 in.getAttributeValue(i) 229 ); 230 } else { 231 out.writeAttribute( 232 prefix, 233 nsUri, 234 in.getAttributeLocalName(i), 235 in.getAttributeValue(i) 236 ); 237 } 238 } 239 240 protected void handleDTD() throws XMLStreamException { 241 out.writeDTD(in.getText()); 242 } 243 244 protected void handleComment() throws XMLStreamException { 245 out.writeComment(in.getText()); 246 } 247 248 protected void handleEntityReference() throws XMLStreamException { 249 out.writeEntityRef(in.getText()); 250 } 251 252 protected void handleSpace() throws XMLStreamException { 253 handleCharacters(); 254 } 255 256 protected void handleCDATA() throws XMLStreamException { 257 out.writeCData(in.getText()); 258 } 259 260 private static String fixNull(String s) { 261 if(s==null) return ""; 262 else return s; 263 } 264} 265