View Javadoc

1   /*
2    * Copyright  1999-2004 The Apache Software Foundation.
3    *
4    *  Licensed under the Apache License, Version 2.0 (the "License");
5    *  you may not use this file except in compliance with the License.
6    *  You may obtain a copy of the License at
7    *
8    *      http://www.apache.org/licenses/LICENSE-2.0
9    *
10   *  Unless required by applicable law or agreed to in writing, software
11   *  distributed under the License is distributed on an "AS IS" BASIS,
12   *  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13   *  See the License for the specific language governing permissions and
14   *  limitations under the License.
15   *
16   */
17  package org.apache.axis.message.addressing;
18  
19  import org.apache.axis.message.addressing.util.AddressingUtils;
20  
21  import org.apache.axis.message.MessageElement;
22  import org.apache.axis.types.URI;
23  import org.w3c.dom.Element;
24  
25  import javax.xml.namespace.QName;
26  import javax.xml.parsers.ParserConfigurationException;
27  import javax.xml.soap.SOAPEnvelope;
28  import javax.xml.soap.SOAPHeaderElement;
29  import javax.xml.soap.SOAPHeader;
30  import javax.xml.soap.Name;
31  
32  import java.util.ArrayList;
33  import java.util.Iterator;
34  import java.util.List;
35  
36  /***
37   * Represents a set of message addressing headers as defined by the WS-Addressing spec.
38   * 
39   * @author Davanum Srinivas (dims@yahoo.com)
40   */
41  public class AddressingHeaders {
42  
43      /***
44       * Field action
45       */
46      private Action action = null;
47  
48      /***
49       * Field replyTo
50       */
51      private ReplyTo replyTo = null;
52  
53      /***
54       * Field to
55       */
56      private To to = null;
57  
58      /***
59       * Field faultTo
60       */
61      private FaultTo faultTo = null;
62  
63      /***
64       * Field from
65       */
66      private From from = null;
67  
68      /***
69       * Field recipient
70       */
71      private Recipient recipient = null;
72  
73      /***
74       * Field messageID
75       */
76      private MessageID messageID = null;
77  
78      /***
79       * Field relatesTo
80       */
81      private ArrayList relatesTo = new ArrayList();
82      
83      /***
84       * Field ReferenceProperties
85       */
86      private ReferencePropertiesType referenceProperties = 
87          new ReferencePropertiesType();
88  
89      /***
90       * Option to set mustUnderstand="true" on the headers or not
91       */
92      private boolean setMustUnderstand = false;
93  
94      private String nsURI = Constants.NS_URI_ADDRESSING_DEFAULT;
95  
96      /***
97       * Constructor AddressingHeaders
98       */
99      public AddressingHeaders() {
100     }
101 
102     public AddressingHeaders(EndpointReference epr) {
103         this.to = new To(epr.getAddress());
104         this.referenceProperties = epr.getProperties();
105     }
106 
107     /***
108      * Constructor AddressingHeaders
109      * 
110      * @param env 
111      * @throws Exception 
112      */
113     public AddressingHeaders(SOAPEnvelope env) throws Exception {
114         this(env, null, true, false, true, new ArrayList(0));
115     }
116 
117     /***
118      * Constructor AddressingHeaders
119      * 
120      * @param env     
121      * @param process 
122      * @param remove
123      * @throws Exception 
124      */
125     public AddressingHeaders(SOAPEnvelope env, 
126                              boolean process, 
127                              boolean remove)
128             throws Exception {
129         this(env, null, process, remove, true,  new ArrayList(0));
130         }
131 
132     /***
133      * Constructor AddressingHeaders
134      * 
135      * @param env     
136      * @param actorURI
137      * @param process 
138      * @throws Exception 
139      */
140     public AddressingHeaders(SOAPEnvelope env, 
141                              String actorURI,
142                              boolean process, 
143                              boolean remove)
144         throws Exception {
145         this(env, actorURI, process, remove, true, new ArrayList(0));
146     }
147 
148     /***
149      * Constructor AddressingHeaders.
150      * 
151      * @param env       The SOAP Envelope 
152      * @param actorURI  The SOAP Actor URI
153      * @param process   Should the headers be marked as processed
154      * @param remove    Should the headers be removed after processing
155      * @param setMustUnderstand whether or not to set mustUnderstand="true" on the headers
156      * @param refPropsQNames A list of QNames for reference properties. If null
157      *                       all non-WSA headers will be added as reference
158      *                       properties. If an empty list is passed
159      *                       than no headers will be added reference properties
160      *                       (default). If non empty list of qnames is passed
161      *                       then only headers matching the qname in the list
162      *                       will be added as reference properties.
163      * 
164      * @throws Exception 
165      */
166     public AddressingHeaders(SOAPEnvelope env, 
167                              String actorURI,
168                              boolean process, 
169                              boolean remove,
170                              boolean setMustUnderstand,
171                              List refPropsQNames)
172         throws Exception {
173 
174         this.setMustUnderstand = setMustUnderstand;
175 
176         SOAPHeader header = env.getHeader();
177         if (header == null) {
178             return;
179         }
180 
181         Iterator iter = header.examineHeaderElements(actorURI);
182 
183         while(iter.hasNext()) {
184             SOAPHeaderElement headerElement =
185                 (SOAPHeaderElement)iter.next();
186 
187             Name name = headerElement.getElementName();
188             if (AddressingUtils.isAddressingNamespaceURI(name.getURI())) {
189                 // it's a WSA header
190                 String localName = name.getLocalName();
191 
192                 if (localName.equals(Constants.MESSAGE_ID)) {
193                     messageID = new MessageID(headerElement);
194                 } else if (localName.equals(Constants.TO)) {
195                     to = new To(headerElement);
196                     nsURI = headerElement.getNamespaceURI();
197                 } else if (localName.equals(Constants.ACTION)) {
198                     action = new Action(headerElement);
199                 } else if (localName.equals(Constants.FROM)) {
200                     from = new From(headerElement);
201                 } else if (localName.equals(Constants.REPLY_TO)) {
202                     replyTo = new ReplyTo(headerElement);
203                 } else if (localName.equals(Constants.FAULT_TO)) {
204                     faultTo = new FaultTo(headerElement);
205                 } else if (localName.equals(Constants.RECIPIENT)) {
206                     recipient = new Recipient(headerElement);
207                 } else if (localName.equals(Constants.RELATES_TO)) {
208                     relatesTo.add(new RelatesTo(headerElement));
209                 } else {
210                     throw new Exception("Unsupported addressing header: " +
211                                         localName);
212                 }
213             } else {
214                 // its a reference property - check if it was added to refProps
215                 if (!processReferenceProperty(headerElement,
216                                               refPropsQNames)) {
217                     continue;
218                 }
219             }
220 
221             // !!! We shouldn't be removing these headers here.  The only
222             // reason to remove them is for use as an intermediary, and
223             // that should work via the infrastructure, NOT by removing
224             // headers here.  Removing them here just means other handlers
225             // which run after this one don't see the whole message, which
226             // is bad.  Change awaiting discussion on fx-dev.  --Glen
227 
228             // must have found one
229             if (remove) {
230                 headerElement.detachNode();
231             }
232 
233             // axis specific call
234             if (process && headerElement instanceof org.apache.axis.message.SOAPHeaderElement) {
235                 ((org.apache.axis.message.SOAPHeaderElement)headerElement).setProcessed(true);
236             }
237         }
238 
239     }
240 
241     /***
242      * Returns the WSA namespace URI used in this set of headers.
243      *
244      * @return the WSA namespace URI used in this set of headers
245      */
246     public String getNamespaceURI() {
247         return nsURI;
248     }
249 
250     /***
251      * Method getAction
252      * 
253      * @return 
254      */
255     public Action getAction() {
256         return action;
257     }
258 
259     /***
260      * Method setAction
261      * 
262      * @param action 
263      */
264     public void setAction(Action action) {
265         this.action = action;
266     }
267 
268     public void setAction(String uri) throws Exception {
269         this.action = new Action(new URI(uri));
270     }
271 
272     /***
273      * Method getTo
274      * 
275      * @return 
276      */
277     public To getTo() {
278         return to;
279     }
280 
281     /***
282      * Method setTo
283      * 
284      * @param to 
285      */
286     public void setTo(To to) {
287         this.to = to;
288     }
289 
290     /***
291      * Method setMessageID
292      * 
293      * @param messageID 
294      */
295     public void setMessageID(MessageID messageID) {
296         this.messageID = messageID;
297     }
298     
299     /***
300      * Method setReferenceProperties
301      * 
302      * @param refProps
303      */
304     public void setReferenceProperties(ReferencePropertiesType refProps) {
305         this.referenceProperties = refProps;
306     }
307     
308     /***
309      * Method getReferenceProperties
310      * 
311      * @return referenceProperties
312      */
313     public ReferencePropertiesType getReferenceProperties() {
314         return referenceProperties;
315     }
316     
317     /***
318      * Method addReferenceProperty : Adds an XML element
319      * to the referencePropeties collection
320      * 
321      * @param refProp
322      */
323     public void addReferenceProperty(Element refProp) {
324         referenceProperties.add(refProp);
325     }
326         
327     public void addReferenceProperty(MessageElement refProp) {
328         referenceProperties.add(refProp);
329     }
330 
331     /***
332      * Adds these addressing headers to the specified SOAP envelope.
333      * 
334      * @param env 
335      * @throws Exception
336      */
337     public void toEnvelope(SOAPEnvelope env)
338         throws Exception {
339         toEnvelope(env, null);
340     }
341 
342 
343     /***
344      * Adds these addressing headers to the specified SOAP envelope.
345      * 
346      * @param env 
347      * @throws javax.xml.soap.SOAPException
348      * @throws ParserConfigurationException 
349      */
350     public void toEnvelope(SOAPEnvelope env, String actorURI)
351         throws Exception {
352 
353         if (env.getNamespaceURI(Constants.NS_PREFIX_ADDRESSING) == null) {
354             env.addNamespaceDeclaration(Constants.NS_PREFIX_ADDRESSING, 
355                                         getNamespaceURI());
356         }
357 
358         AddressingUtils.removeHeaders(env.getHeader(), actorURI);
359 
360         SOAPHeaderElement header = null;
361         
362         if (messageID != null) {
363             header = messageID.toSOAPHeaderElement(env, actorURI);
364             header.setMustUnderstand(setMustUnderstand);
365         }
366 
367         if (to != null) {
368             header = to.toSOAPHeaderElement(env, actorURI);
369             header.setMustUnderstand(setMustUnderstand);
370         }
371 
372         if (action != null) {
373             header = action.toSOAPHeaderElement(env, actorURI);
374             header.setMustUnderstand(setMustUnderstand);
375         }
376 
377         if (from != null) {
378             header = from.toSOAPHeaderElement(env, actorURI);
379             header.setMustUnderstand(setMustUnderstand);
380         }
381 
382         if (replyTo != null) {
383             header = replyTo.toSOAPHeaderElement(env, actorURI);
384             header.setMustUnderstand(setMustUnderstand);
385         }
386 
387         if (faultTo != null) {
388             header = faultTo.toSOAPHeaderElement(env, actorURI);
389             header.setMustUnderstand(setMustUnderstand);
390         }
391 
392         if (recipient != null) {
393             header = recipient.toSOAPHeaderElement(env, actorURI);
394             header.setMustUnderstand(setMustUnderstand);
395         }
396 
397         if (relatesTo != null) {
398             for (int i = 0; i < relatesTo.size(); i++) {
399                 RelatesTo rtp = (RelatesTo) relatesTo.get(i);
400                 header = rtp.toSOAPHeaderElement(env, actorURI);
401                 header.setMustUnderstand(setMustUnderstand);
402             }
403         }
404         
405         serializeReferenceProperties(env, actorURI);
406     }
407     
408 
409     /***
410      * Method getMessageID
411      * 
412      * @return 
413      */
414     public MessageID getMessageID() {
415         return messageID;
416     }
417 
418     /***
419      * Method getRelatesTo
420      * 
421      * @return 
422      */
423     public List getRelatesTo() {
424         return relatesTo;
425     }
426 
427     /***
428      * Set the collection of RelatesToProperties. Not additive,
429      * this replaces the current collection.
430      * 
431      * @param v Vector of RelatesToProperties
432      */
433     public void setRelatesTo(List v) {
434         relatesTo.clear();
435         relatesTo.addAll(v);
436     }
437 
438     /***
439      * Method addRelatesTo
440      * 
441      * @param uri  
442      * @param type 
443      * @throws URI.MalformedURIException 
444      */
445     public void addRelatesTo(String uri, QName type)
446             throws URI.MalformedURIException {
447         relatesTo.add(new RelatesTo(uri, type));
448     }
449 
450     /***
451      * Method setTo
452      * 
453      * @param uri
454      */
455     public void setTo(AttributedURI uri) {
456         to = new To(uri);
457     }
458 
459     /***
460      * Method getFrom
461      * 
462      * @return 
463      */
464     public EndpointReference getFrom() {
465         return from;
466     }
467 
468     /***
469      * Method setFrom
470      * 
471      * @param ref 
472      */
473     public void setFrom(EndpointReference ref) {
474         from = new From(ref);
475     }
476 
477     /***
478      * Method getReplyTo
479      * 
480      * @return 
481      */
482     public EndpointReference getReplyTo() {
483         return replyTo;
484     }
485 
486     /***
487      * Method setReplyTo
488      * 
489      * @param ref 
490      */
491     public void setReplyTo(EndpointReference ref) {
492         replyTo = new ReplyTo(ref);
493     }
494 
495     /***
496      * Method getFaultTo
497      * 
498      * @return 
499      */
500     public EndpointReference getFaultTo() {
501         return faultTo;
502     }
503 
504     /***
505      * Method setFaultTo
506      * 
507      * @param epr 
508      */
509     public void setFaultTo(EndpointReference epr) {
510         this.faultTo = new FaultTo(epr);
511     }
512     
513     /***
514      * Add the reference property to the reference properties collection
515      * 
516      * @param headerElement
517      * @throws Exception
518      */
519     private boolean processReferenceProperty(SOAPHeaderElement headerElement, 
520                                              List refPropQNames) 
521         throws Exception {
522         Name name = headerElement.getElementName();
523         QName elementName = new QName(name.getURI(), name.getLocalName());
524         
525         // if we got to this point, the user wants deserialization of ref props.
526         // if refPropQNames was a null, it is treated as a '*' or process all headers
527         // otherwise we check to see if the element name was specified by the user
528         if ((refPropQNames == null) || (refPropQNames.contains(elementName))) {
529             referenceProperties.add(headerElement);
530             return true;
531         } else {
532             return false;
533         }
534     }
535         
536     /***
537      * Serialize the reference properties in the SOAP Header
538      * 
539      * @param env
540      * @param actorURI
541      */
542     private void serializeReferenceProperties(SOAPEnvelope env,
543                                               String actorURI) 
544         throws Exception {
545         // If no referenceProps are available, we are done
546         if (referenceProperties == null) return;
547         
548         SOAPHeaderElement element = null;
549         // Add each ref property to SOAP Header
550         for (int i = 0; i < referenceProperties.size(); i++) {
551             Object refProp = referenceProperties.get(i);
552             
553             if (refProp instanceof SOAPHeaderElement) {
554                 // already a SOAPHeaderElement
555                 element = (SOAPHeaderElement)refProp;
556             } else if (refProp instanceof org.apache.axis.message.MessageElement) {
557                 // conversion from MessageElement to SOAPHeaderElement
558                 org.apache.axis.message.MessageElement msgElement = 
559                     (org.apache.axis.message.MessageElement)refProp;
560                 element = new org.apache.axis.message.SOAPHeaderElement(msgElement.getAsDOM());
561             } else if (refProp instanceof Element) {
562                 Element refPropElement = (Element) refProp;
563                 // conversion from DOM Element
564                 element = new org.apache.axis.message.SOAPHeaderElement(refPropElement);
565             } else {
566                 throw new Exception(refProp.getClass().getName());
567             }
568             
569             SOAPHeader header = env.getHeader();
570             if (header == null) {
571                 header = env.addHeader();
572             }
573             element.setActor(actorURI);
574             header.addChildElement(element);
575         }
576     }
577 
578     public boolean isSetMustUnderstand() {
579         return setMustUnderstand;
580     }
581 
582     public void setSetMustUnderstand(boolean setMustUnderstand) {
583         this.setMustUnderstand = setMustUnderstand;
584     }
585 }