View Javadoc

1   /*
2    *  Copyright (c) 2008 Rodrigo Ruiz
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  package org.apache.axis.message.addressing;
17  
18  import java.util.Iterator;
19  
20  import javax.xml.parsers.ParserConfigurationException;
21  import javax.xml.soap.SOAPElement;
22  import javax.xml.soap.SOAPEnvelope;
23  import javax.xml.soap.SOAPException;
24  import javax.xml.soap.SOAPHeader;
25  import javax.xml.soap.SOAPHeaderElement;
26  
27  import org.apache.axis.message.MessageElement;
28  import org.apache.axis.message.addressing.util.AddressingUtils;
29  import org.apache.axis.types.URI;
30  import org.apache.axis.types.URI.MalformedURIException;
31  import org.apache.axis.utils.XMLUtils;
32  import org.apache.commons.logging.Log;
33  import org.apache.commons.logging.LogFactory;
34  import org.w3c.dom.Document;
35  import org.w3c.dom.Element;
36  import org.w3c.dom.Node;
37  import org.w3c.dom.NodeList;
38  
39  /**
40   * Java content class for EndpointReference element declaration.
41   * <p>
42   * The following schema fragment specifies the expected content contained within
43   * this java content object. (defined at
44   * http://schemas.xmlsoap.org/ws/2004/08/addressing line 45)
45   *
46   * <pre>
47   * &lt;element
48   *   xmlns:wsa=&quot;http://schemas.xmlsoap.org/ws/2004/08/addressing&quot;
49   *   name=&quot;EndpointReference&quot;
50   *   type=&quot;wsa:EndpointReferenceType&quot;/&gt;
51   * </pre>
52   *
53   * @author Davanum Srinivas
54   * @author Rodrigo Ruiz
55   * @version $Revision: 13 $
56   */
57  public class EndpointReference extends EndpointReferenceType
58    implements AddressingHeaderItem {
59  
60    /**
61     * <code>serialVersionUID</code> attribute.
62     */
63    private static final long serialVersionUID = -1650335889022891672L;
64  
65    /**
66     * Class logger.
67     */
68    private static final Log LOG = LogFactory.getLog(EndpointReference.class);
69  
70    /**
71     * Creates a new EndpointReference instance.
72     *
73     * @param address Remote address
74     */
75    public EndpointReference(Address address) {
76      this.setAddress(address);
77    }
78  
79    /**
80     * Constructor EndpointReference.
81     *
82     * @param element Source element
83     * @throws MalformedURIException If an error occurs
84     */
85    public EndpointReference(Element element) throws MalformedURIException {
86      NodeList children = element.getChildNodes();
87      for (int i = 0; i < children.getLength(); i++) {
88        Node node = children.item(i);
89        if (node instanceof Element) {
90          Element child = (Element) node;
91  
92          String ns = child.getNamespaceURI();
93          if (AddressingUtils.getAddressingVersion(ns) == null) {
94            // skip for now - does not currently handle
95            // extensibility elements
96            continue;
97          }
98  
99          String localName = child.getLocalName();
100         if (Constants.ADDRESS.equals(localName)) {
101           this.setAddress(Address.fromElement(child));
102         } else if (Constants.PORT_TYPE.equals(localName)) {
103           this.setPortType(PortType.fromElement(child));
104         } else if (Constants.SERVICE_NAME.equals(localName)) {
105           this.setServiceName(ServiceNameType.fromElement(child));
106         } else if (Constants.REFERENCE_PROPERTIES.equals(localName)) {
107           this.setProperties(ReferencePropertiesType.fromElement(child));
108         } else if (Constants.REFERENCE_PARAMETERS.equals(localName)) {
109           this.setParameters(ReferenceParametersType.fromElement(child));
110         } else if (Constants.METADATA.equals(localName)) {
111           this.setMetadata(MetaDataType.fromElement(child));
112         }
113       }
114     }
115     if (this.getAddress() == null) {
116       throw new IllegalArgumentException("Specified element does not contain the"
117         + " required 'wsa:Address' child element.");
118     }
119   }
120 
121   /**
122    * Creates a new EndpointReference instance.
123    *
124    * @param endpoint Remote end-point
125    */
126   public EndpointReference(EndpointReferenceType endpoint) {
127     super(endpoint);
128   }
129 
130   /**
131    * Creates a new EndpointReference instance.
132    *
133    * @param element SOAP element node
134    * @throws MalformedURIException If an error occurs
135    */
136   public EndpointReference(SOAPElement element) throws MalformedURIException {
137     Iterator<?> iter = element.getChildElements();
138     while (iter.hasNext()) {
139       Object node = iter.next();
140 
141       if (node instanceof SOAPElement) {
142         SOAPElement child = (SOAPElement) node;
143 
144         String ns = child.getNamespaceURI();
145         if (AddressingUtils.getAddressingVersion(ns) == null) {
146           // skip for now - does not currently handle extensibility elements
147           continue;
148         }
149 
150         String localName = child.getLocalName();
151         if (Constants.ADDRESS.equals(localName)) {
152           this.setAddress(Address.fromSOAPElement(child));
153         } else if (Constants.PORT_TYPE.equals(localName)) {
154           this.setPortType(PortType.fromSOAPElement(child));
155         } else if (Constants.SERVICE_NAME.equals(localName)) {
156           this.setServiceName(ServiceNameType.fromSOAPElement(child));
157         } else if (Constants.REFERENCE_PROPERTIES.equals(localName)) {
158           this.setProperties(ReferencePropertiesType.fromSOAPElement(child));
159         } else if (Constants.REFERENCE_PARAMETERS.equals(localName)) {
160           this.setParameters(ReferenceParametersType.fromSOAPElement(child));
161         } else if (Constants.METADATA.equals(localName)) {
162           this.setMetadata(MetaDataType.fromSOAPElement(child));
163         }
164       }
165     }
166     if (this.getAddress() == null) {
167       throw new IllegalArgumentException("Specified element does not contain the"
168         + " required 'wsa:Address' child element.");
169     }
170   }
171 
172   /**
173    * Creates a new EndpointReference instance.
174    *
175    * @param endpoint Target end-point
176    * @throws URI.MalformedURIException If the specified URI is not valid
177    */
178   public EndpointReference(String endpoint) throws URI.MalformedURIException {
179     this.setAddress(new Address(endpoint));
180   }
181 
182   /**
183    * Creates a new EndpointReference instance.
184    *
185    * @param uri Remote address URI
186    */
187   public EndpointReference(URI uri) {
188     if (uri != null) {
189       this.setAddress(new Address(uri));
190     }
191   }
192 
193   /**
194    * Insert a new metadata item.
195    *
196    * @param data XML rep. of metadata (MessageElement)
197    */
198   public void addMetadata(MessageElement data) {
199     if (this.metaData == null) {
200       this.metaData = new MetaDataType();
201     }
202     this.metaData.add(data);
203   }
204 
205   /**
206    * Insert a new reference parameter.
207    *
208    * @param param XML rep of referenceParameter (MessageElement)
209    */
210   public void addReferenceParameter(MessageElement param) {
211     this.getParameters().add(param);
212   }
213 
214   /**
215    * Insert a new reference property.
216    *
217    * @param prop XML rep of referenceParameter (MessageElement)
218    */
219   public void addReferenceProperty(MessageElement prop) {
220     this.getProperties().add(prop);
221   }
222 
223   /**
224    * Method toDOM.
225    *
226    * @param doc Document to use for Node creation
227    * @return DOM Element
228    */
229   public Element toDOM(Document doc) {
230     return this.toDOM(doc, Constants.ENDPOINT_REFERENCE);
231   }
232 
233   /**
234    * Method toDOM. This will create a DOM element in the supplied document
235    * containing the XML-ized EPR. A namespace declaration for WSA will be added
236    * to this element, using either the default namespace (if the passed
237    * elementName isn't prefixed) or a prefixed namespace (if it is of the form
238    * "foo:bar").
239    *
240    * @param doc Document to use as Node factory
241    * @param elementName Element name
242    * @return DOM element
243    */
244   public Element toDOM(Document doc, String elementName) {
245     if (doc == null) {
246       try {
247         doc = XMLUtils.newDocument();
248       } catch (ParserConfigurationException pce) {
249         LOG.error("Error creating XML document", pce);
250         return null;
251       }
252     }
253 
254     Element elem = toDOMInternal(doc, elementName);
255 
256     // !!! Shouldn't we let the user decide where to put it?? --gdaniels
257     if (doc.getDocumentElement() == null) {
258       doc.appendChild(elem);
259     } else {
260       doc.getDocumentElement().appendChild(elem);
261     }
262     return elem;
263   }
264 
265   /**
266    * This will create a DOM element containing the XML-ized EPR.
267    * <p>
268    * A namespace declaration for WSA will be added
269    * to this element, using either the default namespace (if the passed
270    * elementName isn't prefixed) or a prefixed namespace (if it is of the form
271    * "foo:bar").
272    *
273    * @param doc         DOM node factory
274    * @param elementName Name of the root element to create
275    * @return Created element
276    */
277   private Element toDOMInternal(Document doc, String elementName) {
278     int ix = elementName.indexOf(":");
279     String prefix = "";
280     if (ix != -1) {
281       prefix = elementName.substring(0, ix);
282     }
283 
284     AddressingVersion version = AddressingUtils.getAddressingVersion();
285     String ns = version.getNamespace();
286     Element parent = doc.createElementNS(ns, elementName);
287 
288     // Add namespace declaration
289     if (prefix.equals("")) {
290       parent.setAttributeNS(org.apache.axis.Constants.NS_URI_XMLNS, "xmlns", ns);
291     } else {
292       parent
293         .setAttributeNS(org.apache.axis.Constants.NS_URI_XMLNS, "xmlns:" + prefix, ns);
294       prefix = prefix + ":"; // Now we just use this to make QNames...
295     }
296 
297     append(this.getAddress(), version, parent, prefix + Constants.ADDRESS);
298     append(this.getPortType(), version, parent, prefix + Constants.PORT_TYPE);
299     append(this.getServiceName(), version, parent, prefix + Constants.SERVICE_NAME);
300     if (version.supportsProperties()) {
301       append(this.getProperties(), version, parent,
302              prefix + Constants.REFERENCE_PROPERTIES);
303     }
304     if (version.supportsParameters()) {
305       append(this.getParameters(), version, parent,
306              prefix + Constants.REFERENCE_PARAMETERS);
307     }
308     if (version.supportsMetadata()) {
309       append(this.getMetadata(), version, parent, prefix + Constants.METADATA);
310     }
311 
312     MessageElement[] any = this.get_any();
313     if (any != null && any.length > 0) {
314       for (MessageElement element : any) {
315         try {
316           parent.appendChild(doc.importNode(element.getAsDOM(), true));
317         } catch (Exception e) {
318           LOG.debug("", e);
319         }
320       }
321     }
322 
323     return parent;
324   }
325 
326   /**
327    * Appends the specified instance to the parent DOM node, taking care
328    * of null values.
329    *
330    * @param appendable   Instance to be appended
331    * @param version      WS-Addressing version to use
332    * @param parent       DOM Element to append to
333    * @param elementName  Name of the element to create as root node of appendable
334    */
335   private void append(DOMAppendable appendable, AddressingVersion version,
336     Element parent, String elementName) {
337     if (appendable != null) {
338       appendable.append(version, parent, elementName);
339     }
340   }
341 
342   /**
343    * {@inheritDoc}
344    */
345   public SOAPHeaderElement toSOAPHeaderElement(AddressingVersion version,
346     SOAPEnvelope env, String actorURI) throws SOAPException {
347     return this.toSOAPHeaderElement(version, env, actorURI, Constants.ENDPOINT_REFERENCE);
348   }
349 
350 
351   /**
352    * {@inheritDoc}
353    */
354   public SOAPHeaderElement toSOAPHeaderElement(SOAPEnvelope env, String actorURI)
355     throws SOAPException {
356     AddressingVersion version = AddressingUtils.getAddressingVersion();
357     return this.toSOAPHeaderElement(version, env, actorURI);
358   }
359 
360   /**
361    * Translates this instance into a SOAPHeaderElement.
362    *
363    * @param version   WS-Addressing version to use
364    * @param env       SOAP Envelope to put the element into
365    * @param actorURI  Actor URI
366    * @param name      Element name
367    * @return Created element
368    * @throws SOAPException If an error occurs
369    */
370   protected SOAPHeaderElement toSOAPHeaderElement(AddressingVersion version,
371     SOAPEnvelope env, String actorURI, String name) throws SOAPException {
372 
373     if (name == null) {
374       throw new IllegalArgumentException("Name parameter must be non-null.");
375     }
376     if (env == null) {
377       throw new IllegalArgumentException("Env parameter must be non-null.");
378     }
379     if (env instanceof org.apache.axis.message.SOAPEnvelope) {
380 
381       SOAPHeader header = env.getHeader();
382       if (header == null) {
383         env.addHeader();
384       }
385 
386       try {
387         Document doc = XMLUtils.newDocument();
388 
389         org.apache.axis.message.SOAPHeaderElement headerElem
390           = new org.apache.axis.message.SOAPHeaderElement(this.toDOM(doc, name));
391         headerElem.setActor(actorURI);
392         ((org.apache.axis.message.SOAPEnvelope) env).addHeader(headerElem);
393 
394         return headerElem;
395       } catch (Exception e) {
396         throw new SOAPException("Could not create XML document", e);
397       }
398     } else {
399       throw new SOAPException("SOAPEnvelope implementation not supported: "
400         + env.getClass().getName());
401     }
402   }
403 
404 }