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.util.xml;
038:
039: import javax.xml.stream.XMLStreamConstants;
040: import javax.xml.stream.XMLStreamException;
041: import javax.xml.stream.XMLStreamReader;
042: import javax.xml.stream.XMLStreamWriter;
043: import javax.xml.XMLConstants;
044:
045: /**
046: * Reads a sub-tree from {@link XMLStreamReader} and writes to {@link XMLStreamWriter}
047: * as-is.
048: *
049: * <p>
050: * This class can be sub-classed to implement a simple transformation logic.
051: *
052: * @author Kohsuke Kawaguchi
053: * @author Ryan Shoemaker
054: */
055: public class XMLStreamReaderToXMLStreamWriter {
056:
057: protected XMLStreamReader in;
058: protected XMLStreamWriter out;
059:
060: /**
061: * Reads one subtree and writes it out.
062: *
063: * <p>
064: * The {@link XMLStreamWriter} never receives a start/end document event.
065: * Those need to be written separately by the caller.
066: */
067: public void bridge(XMLStreamReader in, XMLStreamWriter out)
068: throws XMLStreamException {
069: assert in != null && out != null;
070: this .in = in;
071: this .out = out;
072:
073: // remembers the nest level of elements to know when we are done.
074: int depth = 0;
075:
076: // if the parser is at the start tag, proceed to the first element
077: int event = in.getEventType();
078: if (event == XMLStreamConstants.START_DOCUMENT) {
079: // nextTag doesn't correctly handle DTDs
080: while (!in.isStartElement()) {
081: event = in.next();
082: if (event == XMLStreamConstants.COMMENT)
083: handleComment();
084: }
085: }
086:
087: if (event != XMLStreamConstants.START_ELEMENT)
088: throw new IllegalStateException(
089: "The current event is not START_ELEMENT\n but "
090: + event);
091:
092: do {
093: // These are all of the events listed in the javadoc for
094: // XMLEvent.
095: // The spec only really describes 11 of them.
096: switch (event) {
097: case XMLStreamConstants.START_ELEMENT:
098: depth++;
099: handleStartElement();
100: break;
101: case XMLStreamConstants.END_ELEMENT:
102: handleEndElement();
103: depth--;
104: if (depth == 0)
105: return;
106: break;
107: case XMLStreamConstants.CHARACTERS:
108: handleCharacters();
109: break;
110: case XMLStreamConstants.ENTITY_REFERENCE:
111: handleEntityReference();
112: break;
113: case XMLStreamConstants.PROCESSING_INSTRUCTION:
114: handlePI();
115: break;
116: case XMLStreamConstants.COMMENT:
117: handleComment();
118: break;
119: case XMLStreamConstants.DTD:
120: handleDTD();
121: break;
122: case XMLStreamConstants.CDATA:
123: handleCDATA();
124: break;
125: case XMLStreamConstants.SPACE:
126: handleSpace();
127: break;
128: default:
129: throw new InternalError("processing event: " + event);
130: }
131:
132: event = in.next();
133: } while (depth != 0);
134: }
135:
136: protected void handlePI() throws XMLStreamException {
137: out
138: .writeProcessingInstruction(in.getPITarget(), in
139: .getPIData());
140: }
141:
142: protected void handleCharacters() throws XMLStreamException {
143: out.writeCharacters(in.getTextCharacters(), in.getTextStart(),
144: in.getTextLength());
145: }
146:
147: protected void handleEndElement() throws XMLStreamException {
148: out.writeEndElement();
149: }
150:
151: protected void handleStartElement() throws XMLStreamException {
152: String nsUri = in.getNamespaceURI();
153: if (nsUri == null)
154: out.writeStartElement(in.getLocalName());
155: else
156: out.writeStartElement(fixNull(in.getPrefix()), in
157: .getLocalName(), nsUri);
158:
159: // start namespace bindings
160: int nsCount = in.getNamespaceCount();
161: for (int i = 0; i < nsCount; i++) {
162: out.writeNamespace(in.getNamespacePrefix(i), fixNull(in
163: .getNamespaceURI(i))); // zephyr doesn't like null, I don't know what is correct, so just fix null to "" for now
164: }
165:
166: // write attributes
167: int attCount = in.getAttributeCount();
168: for (int i = 0; i < attCount; i++) {
169: handleAttribute(i);
170: }
171: }
172:
173: /**
174: * Writes out the {@code i}-th attribute of the current element.
175: *
176: * <p>
177: * Used from {@link #handleStartElement()}.
178: */
179: protected void handleAttribute(int i) throws XMLStreamException {
180: String nsUri = in.getAttributeNamespace(i);
181: String prefix = in.getAttributePrefix(i);
182: if (fixNull(nsUri).equals(XMLConstants.XMLNS_ATTRIBUTE_NS_URI)) {
183: //Its a namespace decl, ignore as it is already written.
184: return;
185: }
186:
187: if (nsUri == null || prefix == null || prefix.equals("")) {
188: out.writeAttribute(in.getAttributeLocalName(i), in
189: .getAttributeValue(i));
190: } else {
191: out.writeAttribute(prefix, nsUri, in
192: .getAttributeLocalName(i), in.getAttributeValue(i));
193: }
194: }
195:
196: protected void handleDTD() throws XMLStreamException {
197: out.writeDTD(in.getText());
198: }
199:
200: protected void handleComment() throws XMLStreamException {
201: out.writeComment(in.getText());
202: }
203:
204: protected void handleEntityReference() throws XMLStreamException {
205: out.writeEntityRef(in.getText());
206: }
207:
208: protected void handleSpace() throws XMLStreamException {
209: handleCharacters();
210: }
211:
212: protected void handleCDATA() throws XMLStreamException {
213: out.writeCData(in.getText());
214: }
215:
216: private static String fixNull(String s) {
217: if (s == null)
218: return "";
219: else
220: return s;
221: }
222: }
|