001: /*
002: * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS HEADER.
003: *
004: * Copyright 1997-2007 Sun Microsystems, Inc. All rights reserved.
005: *
006: * The contents of this file are subject to the terms of either the GNU
007: * General Public License Version 2 only ("GPL") or the Common Development
008: * and Distribution License("CDDL") (collectively, the "License"). You
009: * may not use this file except in compliance with the License. You can obtain
010: * a copy of the License at https://glassfish.dev.java.net/public/CDDL+GPL.html
011: * or glassfish/bootstrap/legal/LICENSE.txt. See the License for the specific
012: * language governing permissions and limitations under the License.
013: *
014: * When distributing the software, include this License Header Notice in each
015: * file and include the License file at glassfish/bootstrap/legal/LICENSE.txt.
016: * Sun designates this particular file as subject to the "Classpath" exception
017: * as provided by Sun in the GPL Version 2 section of the License file that
018: * accompanied this code. If applicable, add the following below the License
019: * Header, with the fields enclosed by brackets [] replaced by your own
020: * identifying information: "Portions Copyrighted [year]
021: * [name of copyright owner]"
022: *
023: * Contributor(s):
024: *
025: * If you wish your version of this file to be governed by only the CDDL or
026: * only the GPL Version 2, indicate your decision by adding "[Contributor]
027: * elects to include this software in this distribution under the [CDDL or GPL
028: * Version 2] license." If you don't indicate a single choice of license, a
029: * recipient has the option to distribute your version of this file under
030: * either the CDDL, the GPL Version 2 or to extend the choice of license to
031: * its licensees as provided above. However, if you add GPL Version 2 code
032: * and therefore, elected the GPL Version 2 license, then the option applies
033: * only if the new code is made subject to such option by the copyright
034: * holder.
035: */
036:
037: package com.sun.xml.ws.message.source;
038:
039: import com.sun.xml.ws.message.RootElementSniffer;
040: import com.sun.xml.ws.streaming.SourceReaderFactory;
041: import com.sun.xml.ws.util.xml.XmlUtil;
042: import org.w3c.dom.Document;
043: import org.w3c.dom.Node;
044:
045: import javax.xml.namespace.QName;
046: import javax.xml.stream.XMLStreamConstants;
047: import javax.xml.stream.XMLStreamException;
048: import javax.xml.stream.XMLStreamReader;
049: import javax.xml.stream.XMLStreamWriter;
050: import javax.xml.transform.Source;
051: import javax.xml.transform.Transformer;
052: import javax.xml.transform.TransformerConfigurationException;
053: import javax.xml.transform.TransformerException;
054: import javax.xml.transform.dom.DOMSource;
055: import javax.xml.transform.sax.SAXResult;
056: import javax.xml.transform.sax.SAXSource;
057: import javax.xml.transform.stream.StreamSource;
058: import javax.xml.ws.WebServiceException;
059:
060: /**
061: *
062: * @author Vivek Pandey
063: */
064: final class SourceUtils {
065:
066: int srcType;
067:
068: private final int domSource = 1;
069: private final int streamSource = 2;
070: private final int saxSource = 4;
071:
072: public SourceUtils(Source src) {
073: if (src instanceof StreamSource) {
074: srcType = streamSource;
075: } else if (src instanceof DOMSource) {
076: srcType = domSource;
077: } else if (src instanceof SAXSource) {
078: srcType = saxSource;
079: }
080: }
081:
082: public boolean isDOMSource() {
083: return (srcType & domSource) == domSource;
084: }
085:
086: public boolean isStreamSource() {
087: return (srcType & streamSource) == streamSource;
088: }
089:
090: public boolean isSaxSource() {
091: return (srcType & saxSource) == saxSource;
092: }
093:
094: /**
095: * This would peek into the Source (DOMSource and SAXSource) for the localName and NamespaceURI
096: * of the top-level element.
097: * @param src
098: * @return QName of the payload
099: */
100: public QName sniff(Source src) {
101: return sniff(src, new RootElementSniffer());
102: }
103:
104: public QName sniff(Source src, RootElementSniffer sniffer) {
105: String localName = null;
106: String namespaceUri = null;
107:
108: if (isDOMSource()) {
109: DOMSource domSource = (DOMSource) src;
110: Node n = domSource.getNode();
111: if (n.getNodeType() == Node.DOCUMENT_NODE) {
112: n = ((Document) n).getDocumentElement();
113: }
114: localName = n.getLocalName();
115: namespaceUri = n.getNamespaceURI();
116: } else if (isSaxSource()) {
117: SAXSource saxSrc = (SAXSource) src;
118: SAXResult saxResult = new SAXResult(sniffer);
119: try {
120: Transformer tr = XmlUtil.newTransformer();
121: tr.transform(saxSrc, saxResult);
122: } catch (TransformerConfigurationException e) {
123: throw new WebServiceException(e);
124: } catch (TransformerException e) {
125: // if it's due to aborting the processing after the first element,
126: // we can safely ignore this exception.
127: //
128: // if it's due to error in the object, the same error will be reported
129: // when the readHeader() method is used, so we don't have to report
130: // an error right now.
131: localName = sniffer.getLocalName();
132: namespaceUri = sniffer.getNsUri();
133: }
134: }
135: return new QName(namespaceUri, localName);
136: }
137:
138: public static void serializeSource(Source src,
139: XMLStreamWriter writer) throws XMLStreamException {
140: XMLStreamReader reader = SourceReaderFactory
141: .createSourceReader(src, true);
142: int state;
143: do {
144: state = reader.next();
145: switch (state) {
146: case XMLStreamConstants.START_ELEMENT:
147: /*
148: * TODO: Is this necessary, shouldn't zephyr return "" instead of
149: * null for getNamespaceURI() and getPrefix()?
150: */
151: String uri = reader.getNamespaceURI();
152: String prefix = reader.getPrefix();
153: String localName = reader.getLocalName();
154:
155: if (prefix == null) {
156: if (uri == null) {
157: writer.writeStartElement(localName);
158: } else {
159: writer.writeStartElement(uri, localName);
160: }
161: } else {
162: assert uri != null;
163:
164: if (prefix.length() > 0) {
165: /**
166: * Before we write the
167: */
168: String writerURI = null;
169: if (writer.getNamespaceContext() != null)
170: writerURI = writer.getNamespaceContext()
171: .getNamespaceURI(prefix);
172: String writerPrefix = writer.getPrefix(uri);
173: if (declarePrefix(prefix, uri, writerPrefix,
174: writerURI)) {
175: writer.writeStartElement(prefix, localName,
176: uri);
177: writer.setPrefix(prefix, uri != null ? uri
178: : "");
179: writer.writeNamespace(prefix, uri);
180: } else {
181: writer.writeStartElement(prefix, localName,
182: uri);
183: }
184: } else {
185: writer
186: .writeStartElement(prefix, localName,
187: uri);
188: }
189: }
190:
191: int n = reader.getNamespaceCount();
192: // Write namespace declarations
193: for (int i = 0; i < n; i++) {
194: String nsPrefix = reader.getNamespacePrefix(i);
195: if (nsPrefix == null)
196: nsPrefix = "";
197: // StAX returns null for default ns
198: String writerURI = null;
199: if (writer.getNamespaceContext() != null)
200: writerURI = writer.getNamespaceContext()
201: .getNamespaceURI(nsPrefix);
202:
203: // Zephyr: Why is this returning null?
204: // Compare nsPrefix with prefix because of [1] (above)
205: String readerURI = reader.getNamespaceURI(i);
206:
207: /**
208: * write the namespace in 3 conditions
209: * - when the namespace URI is not bound to the prefix in writer(writerURI == 0)
210: * - when the readerPrefix and writerPrefix are ""
211: * - when readerPrefix and writerPrefix are not equal and the URI bound to them
212: * are different
213: */
214: if (writerURI == null
215: || ((nsPrefix.length() == 0) || (prefix
216: .length() == 0))
217: || (!nsPrefix.equals(prefix) && !writerURI
218: .equals(readerURI))) {
219: writer.setPrefix(nsPrefix,
220: readerURI != null ? readerURI : "");
221: writer.writeNamespace(nsPrefix,
222: readerURI != null ? readerURI : "");
223: }
224: }
225:
226: // Write attributes
227: n = reader.getAttributeCount();
228: for (int i = 0; i < n; i++) {
229: String attrPrefix = reader.getAttributePrefix(i);
230: String attrURI = reader.getAttributeNamespace(i);
231:
232: writer.writeAttribute(
233: attrPrefix != null ? attrPrefix : "",
234: attrURI != null ? attrURI : "", reader
235: .getAttributeLocalName(i), reader
236: .getAttributeValue(i));
237: // if the attribute prefix is undeclared in current writer scope then declare it
238: setUndeclaredPrefix(attrPrefix, attrURI, writer);
239: }
240: break;
241: case XMLStreamConstants.END_ELEMENT:
242: writer.writeEndElement();
243: break;
244: case XMLStreamConstants.CHARACTERS:
245: writer.writeCharacters(reader.getText());
246: }
247: } while (state != XMLStreamConstants.END_DOCUMENT);
248: reader.close();
249: }
250:
251: /**
252: * sets undeclared prefixes on the writer
253: * @param prefix
254: * @param writer
255: * @throws XMLStreamException
256: */
257: private static void setUndeclaredPrefix(String prefix,
258: String readerURI, XMLStreamWriter writer)
259: throws XMLStreamException {
260: String writerURI = null;
261: if (writer.getNamespaceContext() != null)
262: writerURI = writer.getNamespaceContext().getNamespaceURI(
263: prefix);
264:
265: if (writerURI == null) {
266: writer
267: .setPrefix(prefix, readerURI != null ? readerURI
268: : "");
269: writer.writeNamespace(prefix, readerURI != null ? readerURI
270: : "");
271: }
272: }
273:
274: /**
275: * check if we need to declare
276: * @param rPrefix
277: * @param rUri
278: * @param wPrefix
279: * @param wUri
280: */
281: private static boolean declarePrefix(String rPrefix, String rUri,
282: String wPrefix, String wUri) {
283: if (wUri == null
284: || ((wPrefix != null) && !rPrefix.equals(wPrefix))
285: || (rUri != null && !wUri.equals(rUri)))
286: return true;
287: return false;
288: }
289: }
|