1/* 2 * Copyright (c) 1997, 2013, 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.message.source; 27 28import com.sun.xml.internal.ws.message.RootElementSniffer; 29import com.sun.xml.internal.ws.streaming.SourceReaderFactory; 30import com.sun.xml.internal.ws.util.xml.XmlUtil; 31import org.w3c.dom.Document; 32import org.w3c.dom.Node; 33 34import javax.xml.namespace.QName; 35import javax.xml.stream.XMLStreamConstants; 36import javax.xml.stream.XMLStreamException; 37import javax.xml.stream.XMLStreamReader; 38import javax.xml.stream.XMLStreamWriter; 39import javax.xml.transform.Source; 40import javax.xml.transform.Transformer; 41import javax.xml.transform.TransformerConfigurationException; 42import javax.xml.transform.TransformerException; 43import javax.xml.transform.dom.DOMSource; 44import javax.xml.transform.sax.SAXResult; 45import javax.xml.transform.sax.SAXSource; 46import javax.xml.transform.stream.StreamSource; 47import javax.xml.ws.WebServiceException; 48 49/** 50 * 51 * @author Vivek Pandey 52 */ 53final class SourceUtils { 54 55 int srcType; 56 57 private static final int domSource = 1; 58 private static final int streamSource = 2; 59 private static final int saxSource=4; 60 61 public SourceUtils(Source src) { 62 if(src instanceof StreamSource){ 63 srcType = streamSource; 64 }else if(src instanceof DOMSource){ 65 srcType = domSource; 66 }else if(src instanceof SAXSource){ 67 srcType = saxSource; 68 } 69 } 70 71 public boolean isDOMSource(){ 72 return (srcType&domSource) == domSource; 73 } 74 75 public boolean isStreamSource(){ 76 return (srcType&streamSource) == streamSource; 77 } 78 79 public boolean isSaxSource(){ 80 return (srcType&saxSource) == saxSource; 81 } 82 83 /** 84 * This would peek into the Source (DOMSource and SAXSource) for the localName and NamespaceURI 85 * of the top-level element. 86 * @param src 87 * @return QName of the payload 88 */ 89 public QName sniff(Source src) { 90 return sniff(src, new RootElementSniffer()); 91 } 92 93 public QName sniff(Source src, RootElementSniffer sniffer){ 94 String localName = null; 95 String namespaceUri = null; 96 97 if(isDOMSource()){ 98 DOMSource domSrc = (DOMSource)src; 99 Node n = domSrc.getNode(); 100 if(n.getNodeType()== Node.DOCUMENT_NODE) { 101 n = ((Document)n).getDocumentElement(); 102 } 103 localName = n.getLocalName(); 104 namespaceUri = n.getNamespaceURI(); 105 }else if(isSaxSource()){ 106 SAXSource saxSrc = (SAXSource)src; 107 SAXResult saxResult = new SAXResult(sniffer); 108 try { 109 Transformer tr = XmlUtil.newTransformer(); 110 tr.transform(saxSrc, saxResult); 111 } catch (TransformerConfigurationException e) { 112 throw new WebServiceException(e); 113 } catch (TransformerException e) { 114 // if it's due to aborting the processing after the first element, 115 // we can safely ignore this exception. 116 // 117 // if it's due to error in the object, the same error will be reported 118 // when the readHeader() method is used, so we don't have to report 119 // an error right now. 120 localName = sniffer.getLocalName(); 121 namespaceUri = sniffer.getNsUri(); 122 } 123 } 124 return new QName(namespaceUri, localName); 125 } 126 127 public static void serializeSource(Source src, XMLStreamWriter writer) throws XMLStreamException { 128 XMLStreamReader reader = SourceReaderFactory.createSourceReader(src, true); 129 int state; 130 do { 131 state = reader.next(); 132 switch (state) { 133 case XMLStreamConstants.START_ELEMENT: 134 /* 135 * TODO: Is this necessary, shouldn't zephyr return "" instead of 136 * null for getNamespaceURI() and getPrefix()? 137 */ 138 String uri = reader.getNamespaceURI(); 139 String prefix = reader.getPrefix(); 140 String localName = reader.getLocalName(); 141 142 if (prefix == null) { 143 if (uri == null) { 144 writer.writeStartElement(localName); 145 } else { 146 writer.writeStartElement(uri, localName); 147 } 148 } else { 149// assert uri != null; 150 151 if(prefix.length() > 0){ 152 /** 153 * Before we write the 154 */ 155 String writerURI = null; 156 if (writer.getNamespaceContext() != null) { 157 writerURI = writer.getNamespaceContext().getNamespaceURI(prefix); 158 } 159 String writerPrefix = writer.getPrefix(uri); 160 if(declarePrefix(prefix, uri, writerPrefix, writerURI)){ 161 writer.writeStartElement(prefix, localName, uri); 162 writer.setPrefix(prefix, uri != null ? uri : ""); 163 writer.writeNamespace(prefix, uri); 164 }else{ 165 writer.writeStartElement(prefix, localName, uri); 166 } 167 }else{ 168 writer.writeStartElement(prefix, localName, uri); 169 } 170 } 171 172 int n = reader.getNamespaceCount(); 173 // Write namespace declarations 174 for (int i = 0; i < n; i++) { 175 String nsPrefix = reader.getNamespacePrefix(i); 176 if (nsPrefix == null) { 177 nsPrefix = ""; 178 } 179 // StAX returns null for default ns 180 String writerURI = null; 181 if (writer.getNamespaceContext() != null) { 182 writerURI = writer.getNamespaceContext().getNamespaceURI(nsPrefix); 183 } 184 185 // Zephyr: Why is this returning null? 186 // Compare nsPrefix with prefix because of [1] (above) 187 String readerURI = reader.getNamespaceURI(i); 188 189 /** 190 * write the namespace in 3 conditions 191 * - when the namespace URI is not bound to the prefix in writer(writerURI == 0) 192 * - when the readerPrefix and writerPrefix are "" 193 * - when readerPrefix and writerPrefix are not equal and the URI bound to them 194 * are different 195 */ 196 if (writerURI == null || ((nsPrefix.length() == 0) || (prefix.length() == 0)) || 197 (!nsPrefix.equals(prefix) && !writerURI.equals(readerURI))) { 198 writer.setPrefix(nsPrefix, readerURI != null ? readerURI : ""); 199 writer.writeNamespace(nsPrefix, readerURI != null ? readerURI : ""); 200 } 201 } 202 203 // Write attributes 204 n = reader.getAttributeCount(); 205 for (int i = 0; i < n; i++) { 206 String attrPrefix = reader.getAttributePrefix(i); 207 String attrURI = reader.getAttributeNamespace(i); 208 209 writer.writeAttribute(attrPrefix != null ? attrPrefix : "", 210 attrURI != null ? attrURI : "", 211 reader.getAttributeLocalName(i), 212 reader.getAttributeValue(i)); 213 // if the attribute prefix is undeclared in current writer scope then declare it 214 setUndeclaredPrefix(attrPrefix, attrURI, writer); 215 } 216 break; 217 case XMLStreamConstants.END_ELEMENT: 218 writer.writeEndElement(); 219 break; 220 case XMLStreamConstants.CHARACTERS: 221 writer.writeCharacters(reader.getText()); 222 break; 223 default: 224 break; 225 } 226 } while (state != XMLStreamConstants.END_DOCUMENT); 227 reader.close(); 228 } 229 230 /** 231 * sets undeclared prefixes on the writer 232 * @param prefix 233 * @param writer 234 * @throws XMLStreamException 235 */ 236 private static void setUndeclaredPrefix(String prefix, String readerURI, XMLStreamWriter writer) throws XMLStreamException { 237 String writerURI = null; 238 if (writer.getNamespaceContext() != null) { 239 writerURI = writer.getNamespaceContext().getNamespaceURI(prefix); 240 } 241 242 if (writerURI == null) { 243 writer.setPrefix(prefix, readerURI != null ? readerURI : ""); 244 writer.writeNamespace(prefix, readerURI != null ? readerURI : ""); 245 } 246 } 247 248 /** 249 * check if we need to declare 250 * @param rPrefix 251 * @param rUri 252 * @param wPrefix 253 * @param wUri 254 */ 255 private static boolean declarePrefix(String rPrefix, String rUri, String wPrefix, String wUri){ 256 if (wUri == null ||((wPrefix != null) && !rPrefix.equals(wPrefix))|| 257 (rUri != null && !wUri.equals(rUri))) { 258 return true; 259 } 260 return false; 261 } 262} 263