001: /*
002: * The contents of this file are subject to the terms
003: * of the Common Development and Distribution License
004: * (the License). You may not use this file except in
005: * compliance with the License.
006: *
007: * You can obtain a copy of the license at
008: * https://glassfish.dev.java.net/public/CDDLv1.0.html.
009: * See the License for the specific language governing
010: * permissions and limitations under the License.
011: *
012: * When distributing Covered Code, include this CDDL
013: * Header Notice in each file and include the License file
014: * at https://glassfish.dev.java.net/public/CDDLv1.0.html.
015: * If applicable, add the following below the CDDL Header,
016: * with the fields enclosed by brackets [] replaced by
017: * you own identifying information:
018: * "Portions Copyrighted [year] [name of copyright owner]"
019: *
020: * Copyright 2006 Sun Microsystems Inc. All Rights Reserved
021: */
022:
023: package com.sun.xml.ws.security.opt.impl.message;
024:
025: import com.sun.xml.ws.api.addressing.AddressingVersion;
026: import com.sun.xml.ws.api.addressing.WSEndpointReference;
027: import com.sun.xml.ws.security.opt.api.SecurityElement;
028: import com.sun.xml.ws.security.opt.api.SecurityElementWriter;
029: import com.sun.xml.ws.security.opt.impl.outgoing.SecurityHeader;
030: import com.sun.istack.NotNull;
031: import com.sun.xml.bind.api.Bridge;
032: import com.sun.xml.bind.api.BridgeContext;
033: import com.sun.xml.ws.api.SOAPVersion;
034: import com.sun.xml.ws.security.opt.impl.dsig.SignedMessageHeader;
035: import org.xml.sax.ContentHandler;
036: import org.xml.sax.ErrorHandler;
037: import org.xml.sax.SAXException;
038: import javax.xml.bind.JAXBException;
039: import javax.xml.bind.Unmarshaller;
040: import javax.xml.namespace.QName;
041: import javax.xml.soap.SOAPException;
042: import javax.xml.soap.SOAPMessage;
043: import javax.xml.stream.XMLStreamException;
044: import javax.xml.stream.XMLStreamReader;
045: import javax.xml.stream.XMLStreamWriter;
046: import java.util.Set;
047:
048: /**
049: *
050: * @author K.Venugopal@sun.com
051: */
052: public class HeaderWrapper implements com.sun.xml.ws.api.message.Header {
053:
054: private SecurityHeader sh;
055: private SecurityElement se;
056: private com.sun.xml.ws.api.message.Header header = null;
057:
058: /** Creates a new instance of HeaderWrapper */
059: public HeaderWrapper(SecurityHeader sh) {
060: this .sh = sh;
061: }
062:
063: public HeaderWrapper(SecurityElement se) {
064: this .se = se;
065: if (this .se instanceof SignedMessageHeader) {
066: header = ((SignedMessageHeader) se).getSignedHeader();
067: }
068: }
069:
070: /**
071: * Checks if this header is ignorable for us (IOW, make sure
072: * that this header has a problematic "mustUnderstand" header value
073: * that we have to reject.)
074: *
075: * <p>
076: * This method is used as a part of the
077: * <a href="HeaderList.html#MU">mustUnderstanx processing</a>.
078: * At the end of the processing, the JAX-WS identifies a list of {@link Header}s
079: * that were not understood. This method is invoked on those {@link Header}s,
080: * to verify that we don't need to report an error for it.
081: *
082: * <p>
083: * specifically, this method has to perform the following tasks:
084: *
085: * <ul>
086: * <li>If this header does not have <tt>mustUnderstand</tt> as "1" nor "true",
087: * then this method must return true.
088: * <li>Otherwise, check the role attribute (for SOAP 1.2) or the actor attribute (for SOAP 1.1).
089: * When those attributes are absent, the default values have to be assumed.
090: * See {@link #getRole(SOAPVersion)} for how the values are defaulted.
091: * Now, see if the {@code roles} set contains the value.
092: * If so, this method must return false (indicating that an error is in order.)
093: * <li>Otherwise return true (since we don't play the role this header is intended for.)
094: * </ul>
095: *
096: * @param soapVersion
097: * The caller specifies the SOAP version that the pipeline is working against.
098: * Often each {@link Header} implementation already knows the SOAP version
099: * anyway, but this allows some {@link Header}s to avoid keeping it.
100: * That's why this redundant parameter is passed in.
101: * @param roles
102: * The set of role values that the current JAX-WS pipeline is assuming.
103: * Note that SOAP 1.1 and SOAP 1.2 use different strings for the same role,
104: * and the caller is responsible for supplying a proper value depending on the
105: * active SOAP version in use.
106: *
107: * @return
108: * true if no error needs to be reported. False if an error needs to be raised.
109: * See the method javadoc for more discussion.
110: */
111: public boolean isIgnorable(SOAPVersion soapVersion,
112: Set<String> roles) {
113: if (header != null) {
114: return header.isIgnorable(soapVersion, roles);
115: }
116: throw new UnsupportedOperationException();
117: }
118:
119: /**
120: * Gets the value of the soap:role attribute (or soap:actor for SOAP 1.1).
121: *
122: * <p>
123: * If the attribute is omitted, the value defaults to {@link SOAPVersion#implicitRole}.
124: *
125: * @param soapVersion
126: * The caller specifies the SOAP version that the pipeline is working against.
127: * Often each {@link Header} implementation already knows the SOAP version
128: * anyway, but this allows some {@link Header}s to avoid keeping it.
129: * That's why this redundant parameter is passed in.
130: * @return
131: * never null. This string need not be interned.
132: */
133: public String getRole(SOAPVersion soapVersion) {
134: if (header != null) {
135: return header.getRole(soapVersion);
136: }
137: throw new UnsupportedOperationException();
138: }
139:
140: /**
141: * True if this header is to be relayed if not processed.
142: * For SOAP 1.1 messages, this method always return false.
143: *
144: * <p>
145: * IOW, this method returns true if there's @soap:relay='true'
146: * is present.
147: *
148: * <h3>Implementation Note</h3>
149: * <p>
150: * The implementation needs to check for both "true" and "1",
151: * but because attribute values are normalized, it doesn't have
152: * to consider " true", " 1 ", and so on.
153: *
154: * @return
155: * false.
156: */
157: public boolean isRelay() {
158: if (header != null) {
159: return header.isRelay();
160: }
161: throw new UnsupportedOperationException();
162: }
163:
164: /**
165: * Gets the namespace URI of this header element.
166: *
167: * @return
168: * this string must be interned.
169: */
170: public String getNamespaceURI() {
171: return se.getNamespaceURI();
172: }
173:
174: /**
175: * Gets the local name of this header element.
176: *
177: * @return
178: * this string must be interned.
179: */
180: public String getLocalPart() {
181: return se.getLocalPart();
182: }
183:
184: /**
185: * Gets the attribute value on the header element.
186: *
187: * @param nsUri
188: * The namespace URI of the attribute. Can be empty.
189: * @param localName
190: * The local name of the attribute.
191: *
192: * @return
193: * if the attribute is found, return the whitespace normalized value.
194: * (meaning no leading/trailing space, no consequtive whitespaces in-between.)
195: * Otherwise null. Note that the XML parsers are responsible for
196: * whitespace-normalizing attributes, so {@link Header} implementation
197: * doesn't have to do anything.
198: */
199: public String getAttribute(String nsUri, String localName) {
200: if (header != null) {
201: return header.getAttribute(nsUri, localName);
202: }
203: throw new UnsupportedOperationException();
204: }
205:
206: /**
207: * Gets the attribute value on the header element.
208: *
209: * <p>
210: * This is a convenience method that calls into {@link #getAttribute(String, String)}
211: *
212: * @param name
213: * Never null.
214: *
215: * @see #getAttribute(String, String)
216: */
217: public String getAttribute(QName name) {
218: if (header != null) {
219: return header.getAttribute(name);
220: }
221: throw new UnsupportedOperationException();
222: }
223:
224: /**
225: * Reads the header as a {@link XMLStreamReader}.
226: *
227: * <p>
228: * The returned parser points at the start element of this header.
229: * (IOW, {@link XMLStreamReader#getEventType()} would return
230: * {@link XMLStreamReader#START_ELEMENT}.
231: *
232: * <h3>Performance Expectation</h3>
233: * <p>
234: * For some {@link Header} implementations, this operation
235: * is a non-trivial operation. Therefore, use of this method
236: * is discouraged unless the caller is interested in reading
237: * the whole header.
238: *
239: * <p>
240: * Similarly, if the caller wants to use this method only to do
241: * the API conversion (such as simply firing SAX events from
242: * {@link XMLStreamReader}), then the JAX-WS team requests
243: * that you talk to us.
244: *
245: * <p>
246: * {@link Message}s that come from tranport usually provides
247: * a reasonably efficient implementation of this method.
248: *
249: * @return
250: * must not null.
251: */
252: public XMLStreamReader readHeader() throws XMLStreamException {
253: if (header != null) {
254: return header.readHeader();
255: }
256: throw new UnsupportedOperationException();
257: //We should avoid such operations for Security operated headers.
258:
259: }
260:
261: /**
262: * Reads the header as a JAXB object by using the given unmarshaller.
263: */
264: public <T> T readAsJAXB(Unmarshaller unmarshaller)
265: throws JAXBException {
266: if (header != null) {
267: return (T) header.readAsJAXB(unmarshaller);
268: }
269: throw new UnsupportedOperationException();
270: }
271:
272: /**
273: * Reads the header as a JAXB object by using the given unmarshaller.
274: */
275: public <T> T readAsJAXB(Bridge<T> bridge) throws JAXBException {
276: if (header != null) {
277: return header.readAsJAXB(bridge);
278: }
279: throw new UnsupportedOperationException();
280: }
281:
282: /**
283: * Writes out the header.
284: *
285: * @throws XMLStreamException
286: * if the operation fails for some reason. This leaves the
287: * writer to an undefined state.
288: */
289: public void writeTo(XMLStreamWriter w) throws XMLStreamException {
290: ((SecurityElementWriter) se).writeTo(w);
291: }
292:
293: /**
294: * Writes out the header to the given SOAPMessage.
295: *
296: * <p>
297: * Sometimes a {@link Message} needs to produce itself
298: * as {@link SOAPMessage}, in which case each header needs
299: * to turn itself into a header.
300: *
301: * @throws SOAPException
302: * if the operation fails for some reason. This leaves the
303: * writer to an undefined state.
304: */
305: public void writeTo(SOAPMessage saaj) throws SOAPException {
306: throw new UnsupportedOperationException(
307: "use writeTo(XMLStreamWriter w) ");
308: }
309:
310: /**
311: * Writes out the header as SAX events.
312: *
313: * <p>
314: * Sometimes a {@link Message} needs to produce SAX events,
315: * and this method is necessary for headers to participate to it.
316: *
317: * <p>
318: * A header is responsible for producing the SAX events for its part,
319: * including <tt>startPrefixMapping</tt> and <tt>endPrefixMapping</tt>,
320: * but not startDocument/endDocument.
321: *
322: * <p>
323: * Note that SAX contract requires that any error that does NOT originate
324: * from {@link ContentHandler} (meaning any parsing error and etc) must
325: * be first reported to {@link ErrorHandler}. If the SAX event production
326: * cannot be continued and the processing needs to abort, the code may
327: * then throw the same {@link SAXParseException} reported to {@link ErrorHandler}.
328: *
329: * @param contentHandler
330: * The {@link ContentHandler} that receives SAX events.
331: *
332: * @param errorHandler
333: * The {@link ErrorHandler} that receives parsing errors.
334: */
335: public void writeTo(ContentHandler contentHandler,
336: ErrorHandler errorHandler) throws SAXException {
337: throw new UnsupportedOperationException(
338: "use writeTo(XMLStreamWriter w) ");
339: }
340:
341: public String getStringContent() {
342: if (header != null) {
343: return header.getStringContent();
344: }
345: throw new UnsupportedOperationException();
346: }
347:
348: public @NotNull
349: WSEndpointReference readAsEPR(AddressingVersion expected)
350: throws XMLStreamException {
351: if (header != null) {
352: return header.readAsEPR(expected);
353: }
354: throw new UnsupportedOperationException();
355: }
356:
357: }
|