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.incoming;
024:
025: import com.sun.xml.stream.buffer.XMLStreamBuffer;
026: import com.sun.xml.stream.buffer.XMLStreamBufferException;
027: import com.sun.xml.stream.buffer.XMLStreamBufferMark;
028: import com.sun.xml.stream.buffer.XMLStreamBufferSource;
029: import com.sun.xml.stream.buffer.stax.StreamReaderBufferCreator;
030: import com.sun.xml.ws.api.SOAPVersion;
031: import com.sun.xml.ws.message.AbstractHeaderImpl;
032: import com.sun.xml.ws.security.opt.api.NamespaceContextInfo;
033: import com.sun.xml.ws.security.opt.impl.util.StreamUtil;
034: import com.sun.xml.ws.security.opt.impl.util.XMLStreamReaderFactory;
035: import com.sun.istack.FinalArrayList;
036: import com.sun.xml.ws.message.Util;
037: import com.sun.xml.ws.security.opt.api.SecuredHeader;
038: import com.sun.xml.wss.impl.MessageConstants;
039:
040: import java.util.ArrayList;
041: import java.util.HashMap;
042: import java.util.List;
043: import java.util.Set;
044: import java.util.Vector;
045: import javax.xml.bind.Unmarshaller;
046:
047: import javax.xml.soap.SOAPConstants;
048: import javax.xml.soap.SOAPException;
049: import javax.xml.soap.SOAPHeader;
050: import javax.xml.soap.SOAPMessage;
051: import javax.xml.stream.XMLStreamException;
052: import javax.xml.stream.XMLStreamReader;
053: import javax.xml.stream.XMLStreamWriter;
054: import javax.xml.transform.Transformer;
055: import javax.xml.transform.TransformerFactory;
056: import javax.xml.transform.dom.DOMResult;
057: import org.w3c.dom.Node;
058: import org.xml.sax.ContentHandler;
059: import org.xml.sax.ErrorHandler;
060: import org.xml.sax.SAXException;
061: import javax.xml.stream.StreamFilter;
062: import javax.xml.stream.XMLInputFactory;
063: import javax.xml.bind.JAXBException;
064:
065: /**
066: *
067: * @author K.Venugopal@sun.com
068: */
069:
070: public class GenericSecuredHeader extends AbstractHeaderImpl implements
071: SecuredHeader, NamespaceContextInfo {
072:
073: private static final String SOAP_1_1_MUST_UNDERSTAND = "mustUnderstand";
074: private static final String SOAP_1_2_MUST_UNDERSTAND = SOAP_1_1_MUST_UNDERSTAND;
075: private static final String SOAP_1_1_ROLE = "actor";
076: private static final String SOAP_1_2_ROLE = "role";
077: private static final String SOAP_1_2_RELAY = "relay";
078: private XMLStreamBuffer completeHeader;
079: //private XMLStreamBuffer headerContent;
080: private boolean isMustUnderstand;
081: private SOAPVersion soapVersion = null;
082: //private boolean hasId = true;
083: private Vector idValues = new Vector(2);
084: private HashMap<String, String> shNSDecls = new HashMap<String, String>();
085: private HashMap<String, String> nsDecls = null;
086: //private QName headerName = null;
087: // never null. role or actor value
088: private String role;
089: private boolean isRelay;
090: private String localName;
091: private String namespaceURI = "";
092: private String id = "";
093: private final FinalArrayList<Attribute> attributes;
094:
095: private boolean hasED = false;
096:
097: public GenericSecuredHeader(XMLStreamReader reader,
098: SOAPVersion soapVersion, StreamReaderBufferCreator creator,
099: HashMap nsDecl, XMLInputFactory staxIF,
100: boolean encHeaderContent) throws XMLStreamBufferException,
101: XMLStreamException {
102:
103: this .shNSDecls = nsDecl;
104: this .soapVersion = soapVersion;
105: namespaceURI = reader.getNamespaceURI();
106: localName = reader.getLocalName();
107: attributes = processHeaderAttributes(reader);
108: completeHeader = new XMLStreamBufferMark(this .nsDecls, creator);
109: creator.createElementFragment(XMLStreamReaderFactory
110: .createFilteredXMLStreamReader(reader,
111: new IDProcessor()), true);
112: nsDecls.putAll(shNSDecls);
113: if (this .id.length() > 0) {
114: idValues.add(id);
115: }
116:
117: if (encHeaderContent) {
118: checkEncryptedData();
119: }
120: }
121:
122: public boolean hasEncData() {
123: return hasED;
124: }
125:
126: private void checkEncryptedData() throws XMLStreamException {
127: XMLStreamReader reader = readHeader();
128: while (StreamUtil.moveToNextElement(reader)) {
129: if (reader.getLocalName() == MessageConstants.ENCRYPTED_DATA_LNAME
130: && reader.getNamespaceURI() == MessageConstants.XENC_NS) {
131: hasED = true;
132: String encId = reader.getAttributeValue(null, "Id");
133: if (encId != null && encId.length() > 0) {
134: idValues.add(encId);
135: }
136: break;
137: }
138: }
139: }
140:
141: private com.sun.istack.FinalArrayList<Attribute> processHeaderAttributes(
142: XMLStreamReader reader) {
143: if (soapVersion == soapVersion.SOAP_11) {
144: return process11Header(reader);
145: } else {
146: return process12Header(reader);
147: }
148: }
149:
150: private com.sun.istack.FinalArrayList<Attribute> process12Header(
151: XMLStreamReader reader) {
152: FinalArrayList<Attribute> atts = null;
153: role = soapVersion.implicitRole;
154: nsDecls = new HashMap<String, String>();
155: //headerName = reader.getName();
156: nsDecls = new HashMap<String, String>();
157: if (reader.getNamespaceCount() > 0) {
158: for (int i = 0; i < reader.getNamespaceCount(); i++) {
159: nsDecls.put(reader.getNamespacePrefix(i), reader
160: .getNamespaceURI(i));
161: }
162: }
163:
164: for (int i = 0; i < reader.getAttributeCount(); i++) {
165: final String localName = reader.getAttributeLocalName(i);
166: final String namespaceURI = reader.getAttributeNamespace(i);
167: final String value = reader.getAttributeValue(i);
168: if (namespaceURI == MessageConstants.WSU_NS
169: && localName == "Id".intern()) {
170: //hasId = true;
171: id = value;
172:
173: } else if (namespaceURI == null
174: && localName == "Id".intern()) {
175: //hasId = true;
176: id = value;
177: }
178: //handle other Id's eg SAML
179: if (namespaceURI == SOAPConstants.URI_NS_SOAP_1_1_ENVELOPE) {
180: if (localName == SOAP_1_1_MUST_UNDERSTAND) {
181: isMustUnderstand = Util.parseBool(value);
182: } else if (localName == SOAP_1_1_ROLE) {
183: if (value != null && value.length() > 0) {
184: role = value;
185: }
186: }
187: }
188:
189: if (atts == null) {
190: atts = new FinalArrayList<Attribute>();
191: }
192: atts.add(new Attribute(namespaceURI, localName, value));
193: }
194: return atts;
195: }
196:
197: private final FinalArrayList<Attribute> process11Header(
198: XMLStreamReader reader) {
199: FinalArrayList<Attribute> atts = null;
200:
201: role = soapVersion.implicitRole;
202: //headerName = reader.getName();
203: nsDecls = new HashMap<String, String>();
204: if (reader.getNamespaceCount() > 0) {
205:
206: for (int j = 0; j < reader.getNamespaceCount(); j++) {
207: nsDecls.put(reader.getNamespacePrefix(j), reader
208: .getNamespaceURI(j));
209: }
210: }
211:
212: for (int i = 0; i < reader.getAttributeCount(); i++) {
213: final String localName = reader.getAttributeLocalName(i);
214: final String namespaceURI = reader.getAttributeNamespace(i);
215: final String value = reader.getAttributeValue(i);
216:
217: if (namespaceURI == MessageConstants.WSU_NS
218: && localName == "Id".intern()) {
219: //hasId = true;
220: id = value;
221: } else if (namespaceURI == null
222: && localName == "Id".intern()) {
223: //hasId = true;
224: id = value;
225: }
226:
227: if (namespaceURI == SOAPConstants.URI_NS_SOAP_1_2_ENVELOPE) {
228: if (localName == SOAP_1_2_MUST_UNDERSTAND) {
229: isMustUnderstand = Util.parseBool(value);
230: } else if (localName == SOAP_1_2_ROLE) {
231: if (value != null && value.length() > 0) {
232: role = value;
233: }
234: } else if (localName == SOAP_1_2_RELAY) {
235: isRelay = Util.parseBool(value);
236: }
237: }
238:
239: if (atts == null) {
240: atts = new FinalArrayList<Attribute>();
241: }
242: atts.add(new Attribute(namespaceURI, localName, value));
243: }
244:
245: return atts;
246: }
247:
248: public boolean hasID(String id) {
249: return idValues.contains(id);
250: }
251:
252: public final boolean isIgnorable(SOAPVersion soapVersion,
253: Set<String> roles) {
254: // check mustUnderstand
255: if (!isMustUnderstand)
256: return true;
257:
258: // now role
259: return !roles.contains(role);
260: }
261:
262: public String getRole(SOAPVersion soapVersion) {
263: assert role != null;
264: return role;
265: }
266:
267: public boolean isRelay() {
268: return isRelay;
269: }
270:
271: public String getNamespaceURI() {
272: return namespaceURI;
273: }
274:
275: public String getLocalPart() {
276: return localName;
277: }
278:
279: public String getAttribute(String nsUri, String localName) {
280: if (attributes != null) {
281: for (int i = attributes.size() - 1; i >= 0; i--) {
282: Attribute a = attributes.get(i);
283: if (a.localName.equals(localName)
284: && a.nsUri.equals(nsUri))
285: return a.value;
286: }
287: }
288: return null;
289: }
290:
291: /**
292: * Reads the header as a {@link XMLStreamReader}
293: */
294: public XMLStreamReader readHeader() throws XMLStreamException {
295: return completeHeader.readAsXMLStreamReader();
296: }
297:
298: public void writeTo(XMLStreamWriter w) throws XMLStreamException {
299: try {
300: // TODO what about in-scope namespaces
301: completeHeader.writeToXMLStreamWriter(w);
302: } catch (Exception e) {
303: throw new XMLStreamException(e);
304: }
305: }
306:
307: public void writeTo(SOAPMessage saaj) throws SOAPException {
308: try {
309: // TODO what about in-scope namespaces
310: // Not very efficient consider implementing a stream buffer
311: // processor that produces a DOM node from the buffer.
312: TransformerFactory tf = TransformerFactory.newInstance();
313: Transformer t = tf.newTransformer();
314: XMLStreamBufferSource source = new XMLStreamBufferSource(
315: completeHeader);
316: DOMResult result = new DOMResult();
317: t.transform(source, result);
318: Node d = result.getNode();
319: if (d.getNodeType() == Node.DOCUMENT_NODE)
320: d = d.getFirstChild();
321: SOAPHeader header = saaj.getSOAPHeader();
322: Node node = header.getOwnerDocument().importNode(d, true);
323: header.appendChild(node);
324: } catch (Exception e) {
325: throw new SOAPException(e);
326: }
327: }
328:
329: public void writeTo(ContentHandler contentHandler,
330: ErrorHandler errorHandler) throws SAXException {
331: completeHeader.writeTo(contentHandler);
332: }
333:
334: public String getStringContent() {
335: try {
336: XMLStreamReader xsr = readHeader();
337: xsr.nextTag();
338: return xsr.getElementText();
339: } catch (XMLStreamException e) {
340: return null;
341: }
342: }
343:
344: private static String fixNull(String s) {
345: if (s == null)
346: return "";
347: else
348: return s;
349: }
350:
351: public <T> T readAsJAXB(Unmarshaller um)
352: throws javax.xml.bind.JAXBException {
353: try {
354: return (T) um.unmarshal(completeHeader
355: .readAsXMLStreamReader());
356: } catch (XMLStreamException e) {
357: throw new JAXBException(e);
358: } catch (Exception e) {
359: throw new JAXBException(e);
360: }
361: }
362:
363: public <T> T readAsJAXB(com.sun.xml.bind.api.Bridge<T> bridge)
364: throws javax.xml.bind.JAXBException {
365: try {
366: return bridge.unmarshal(completeHeader
367: .readAsXMLStreamReader());
368: } catch (XMLStreamException e) {
369: throw new JAXBException(e);
370: } catch (Exception e) {
371: throw new JAXBException(e);
372: }
373: }
374:
375: public HashMap<String, String> getInscopeNSContext() {
376: return nsDecls;
377: }
378:
379: protected static final class Attribute {
380: /**
381: * Can be empty but never null.
382: */
383: final String nsUri;
384: final String localName;
385: final String value;
386:
387: public Attribute(String nsUri, String localName, String value) {
388: this .nsUri = fixNull(nsUri);
389: this .localName = localName;
390: this .value = value;
391: }
392: }
393:
394: class IDProcessor implements StreamFilter {
395: boolean elementRead = false;
396:
397: public boolean accept(XMLStreamReader reader) {
398: if (reader.getEventType() == XMLStreamReader.END_ELEMENT) {
399: if (reader.getLocalName() == localName
400: && reader.getNamespaceURI() == namespaceURI) {
401: elementRead = true;
402: }
403: }
404: if (!elementRead
405: && reader.getEventType() == XMLStreamReader.START_ELEMENT) {
406: String id = reader.getAttributeValue(
407: MessageConstants.WSU_NS, "Id");
408: if (id != null && id.length() > 0) {
409: idValues.add(id);
410: }
411: }
412:
413: return true;
414: }
415: }
416: }
|