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: package com.sun.xml.ws.message.stream;
037:
038: import com.sun.istack.FinalArrayList;
039: import com.sun.istack.NotNull;
040: import com.sun.xml.stream.buffer.XMLStreamBuffer;
041: import com.sun.xml.stream.buffer.XMLStreamBufferSource;
042: import com.sun.xml.ws.api.SOAPVersion;
043: import com.sun.xml.ws.api.addressing.AddressingVersion;
044: import com.sun.xml.ws.api.addressing.WSEndpointReference;
045: import com.sun.xml.ws.api.message.Header;
046: import com.sun.xml.ws.message.AbstractHeaderImpl;
047: import org.w3c.dom.Node;
048: import org.xml.sax.ContentHandler;
049: import org.xml.sax.ErrorHandler;
050: import org.xml.sax.SAXException;
051:
052: import javax.xml.soap.SOAPException;
053: import javax.xml.soap.SOAPHeader;
054: import javax.xml.soap.SOAPMessage;
055: import javax.xml.stream.XMLStreamException;
056: import javax.xml.stream.XMLStreamReader;
057: import javax.xml.stream.XMLStreamWriter;
058: import javax.xml.transform.Transformer;
059: import javax.xml.transform.TransformerFactory;
060: import javax.xml.transform.dom.DOMResult;
061: import java.util.List;
062: import java.util.Set;
063:
064: /**
065: * {@link Header} whose physical data representation is an XMLStreamBuffer.
066: *
067: * @author Paul.Sandoz@Sun.Com
068: */
069: public abstract class StreamHeader extends AbstractHeaderImpl {
070: protected final XMLStreamBuffer _mark;
071:
072: protected boolean _isMustUnderstand;
073:
074: /**
075: * Role or actor value.
076: */
077: protected @NotNull
078: String _role;
079:
080: protected boolean _isRelay;
081:
082: protected String _localName;
083:
084: protected String _namespaceURI;
085:
086: /**
087: * Keep the information about an attribute on the header element.
088: *
089: * TODO: this whole attribute handling could be done better, I think.
090: */
091: protected static final class Attribute {
092: /**
093: * Can be empty but never null.
094: */
095: final String nsUri;
096: final String localName;
097: final String value;
098:
099: public Attribute(String nsUri, String localName, String value) {
100: this .nsUri = fixNull(nsUri);
101: this .localName = localName;
102: this .value = value;
103: }
104: }
105:
106: /**
107: * The attributes on the header element.
108: * We expect there to be only a small number of them,
109: * so the use of {@link List} would be justified.
110: *
111: * Null if no attribute is present.
112: */
113: private final FinalArrayList<Attribute> attributes;
114:
115: /**
116: * Creates a {@link StreamHeader}.
117: *
118: * @param reader
119: * The parser pointing at the start of the mark.
120: * Technically this information is redundant,
121: * but it achieves a better performance.
122: * @param mark
123: * The start of the buffered header content.
124: */
125: protected StreamHeader(XMLStreamReader reader, XMLStreamBuffer mark) {
126: assert reader != null && mark != null;
127: _mark = mark;
128: _localName = reader.getLocalName();
129: _namespaceURI = reader.getNamespaceURI();
130: attributes = processHeaderAttributes(reader);
131: }
132:
133: /**
134: * Creates a {@link StreamHeader}.
135: *
136: * @param reader
137: * The parser that points to the start tag of the header.
138: * By the end of this method, the parser will point at
139: * the end tag of this element.
140: */
141: protected StreamHeader(XMLStreamReader reader)
142: throws XMLStreamException {
143: _localName = reader.getLocalName();
144: _namespaceURI = reader.getNamespaceURI();
145: attributes = processHeaderAttributes(reader);
146: // cache the body
147: _mark = XMLStreamBuffer
148: .createNewBufferFromXMLStreamReader(reader);
149: }
150:
151: public final boolean isIgnorable(@NotNull
152: SOAPVersion soapVersion, @NotNull
153: Set<String> roles) {
154: // check mustUnderstand
155: if (!_isMustUnderstand)
156: return true;
157:
158: if (roles == null)
159: return true;
160:
161: // now role
162: return !roles.contains(_role);
163: }
164:
165: public @NotNull
166: String getRole(@NotNull
167: SOAPVersion soapVersion) {
168: assert _role != null;
169: return _role;
170: }
171:
172: public boolean isRelay() {
173: return _isRelay;
174: }
175:
176: public @NotNull
177: String getNamespaceURI() {
178: return _namespaceURI;
179: }
180:
181: public @NotNull
182: String getLocalPart() {
183: return _localName;
184: }
185:
186: public String getAttribute(String nsUri, String localName) {
187: if (attributes != null) {
188: for (int i = attributes.size() - 1; i >= 0; i--) {
189: Attribute a = attributes.get(i);
190: if (a.localName.equals(localName)
191: && a.nsUri.equals(nsUri))
192: return a.value;
193: }
194: }
195: return null;
196: }
197:
198: /**
199: * Reads the header as a {@link XMLStreamReader}
200: */
201: public XMLStreamReader readHeader() throws XMLStreamException {
202: return _mark.readAsXMLStreamReader();
203: }
204:
205: public void writeTo(XMLStreamWriter w) throws XMLStreamException {
206: // TODO what about in-scope namespaces
207: _mark.writeToXMLStreamWriter(w);
208: }
209:
210: public void writeTo(SOAPMessage saaj) throws SOAPException {
211: try {
212: // TODO what about in-scope namespaces
213: // Not very efficient consider implementing a stream buffer
214: // processor that produces a DOM node from the buffer.
215: TransformerFactory tf = TransformerFactory.newInstance();
216: Transformer t = tf.newTransformer();
217: XMLStreamBufferSource source = new XMLStreamBufferSource(
218: _mark);
219: DOMResult result = new DOMResult();
220: t.transform(source, result);
221: Node d = result.getNode();
222: if (d.getNodeType() == Node.DOCUMENT_NODE)
223: d = d.getFirstChild();
224: SOAPHeader header = saaj.getSOAPHeader();
225: Node node = header.getOwnerDocument().importNode(d, true);
226: header.appendChild(node);
227: } catch (Exception e) {
228: throw new SOAPException(e);
229: }
230: }
231:
232: public void writeTo(ContentHandler contentHandler,
233: ErrorHandler errorHandler) throws SAXException {
234: _mark.writeTo(contentHandler);
235: }
236:
237: /**
238: * Creates an EPR without copying infoset.
239: *
240: * This is the most common implementation on which {@link Header#readAsEPR(AddressingVersion)}
241: * is invoked on.
242: */
243: @Override
244: @NotNull
245: public WSEndpointReference readAsEPR(AddressingVersion expected)
246: throws XMLStreamException {
247: return new WSEndpointReference(_mark, expected);
248: }
249:
250: protected abstract FinalArrayList<Attribute> processHeaderAttributes(
251: XMLStreamReader reader);
252:
253: /**
254: * Convert null to "".
255: */
256: private static String fixNull(String s) {
257: if (s == null)
258: return "";
259: else
260: return s;
261: }
262: }
|