1 /*
   2  * Copyright (c) 2005, 2012, Oracle and/or its affiliates. All rights reserved.
   3  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
   4  *
   5  * This code is free software; you can redistribute it and/or modify it
   6  * under the terms of the GNU General Public License version 2 only, as
   7  * published by the Free Software Foundation.  Oracle designates this
   8  * particular file as subject to the "Classpath" exception as provided
   9  * by Oracle in the LICENSE file that accompanied this code.
  10  *
  11  * This code is distributed in the hope that it will be useful, but WITHOUT
  12  * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
  13  * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
  14  * version 2 for more details (a copy is included in the LICENSE file that
  15  * accompanied this code).
  16  *
  17  * You should have received a copy of the GNU General Public License version
  18  * 2 along with this work; if not, write to the Free Software Foundation,
  19  * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
  20  *
  21  * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
  22  * or visit www.oracle.com if you need additional information or have any
  23  * questions.
  24  */
  25 
  26 package javax.xml.ws.wsaddressing;
  27 
  28 
  29 import org.w3c.dom.Element;
  30 
  31 import java.util.ArrayList;
  32 import java.util.List;
  33 import java.util.Map;
  34 import java.util.HashMap;
  35 import javax.xml.namespace.QName;
  36 import javax.xml.ws.WebServiceException;
  37 import javax.xml.ws.spi.Provider;
  38 
  39 
  40 /**
  41  * This class is used to build <code>W3CEndpointReference</code>
  42  * instances. The intended use of this clsss is for
  43  * an application component, for example a factory component,
  44  * to create an <code>W3CEndpointReference</code> for a
  45  * web service endpoint published by the same
  46  * Java EE application. It can also be used to create
  47  * <code>W3CEndpointReferences</code> for an Java SE based
  48  * endpoint by providing the <code>address</code> property.
  49  * <p>
  50  * When creating a <code>W3CEndpointReference</code> for an
  51  * endpoint that is not published by the same Java EE application,
  52  * the <code>address</code> property MUST be specified.
  53  * <p>
  54  * When creating a <code>W3CEndpointReference</code> for an endpoint
  55  * published by the same Java EE application, the <code>address</code>
  56  * property MAY be <code>null</code> but then the <code>serviceName</code>
  57  * and <code>endpointName</code> MUST specify an endpoint published by
  58  * the same Java EE application.
  59  * <p>
  60  * When the <code>wsdlDocumentLocation</code> is specified it MUST refer
  61  * to a valid WSDL document and the <code>serviceName</code> and
  62  * <code>endpointName</code> (if specified) MUST match a service and port
  63  * in the WSDL document.
  64  *
  65  * @since JAX-WS 2.1
  66  */
  67 public final class W3CEndpointReferenceBuilder {
  68     /**
  69      * Creates a new <code>W3CEndpointReferenceBuilder</code> instance.
  70      */
  71     public W3CEndpointReferenceBuilder() {
  72         referenceParameters = new ArrayList<Element>();
  73         metadata = new ArrayList<Element>();
  74         attributes = new HashMap<QName, String>();
  75         elements = new ArrayList<Element>();
  76     }
  77 
  78     /**
  79      * Sets the <code>address</code> to the
  80      * <code>W3CEndpointReference</code> instance's
  81      * <code>wsa:Address</code>.
  82      * <p>
  83      * The <code>address</code> MUST be set to a non-<code>null</code>
  84      * value when building a <code>W3CEndpointReference</code> for a
  85      * web service endpoint that is not published by the same
  86      * Java EE application or when running on Java SE.
  87      *
  88      * @param address The address of the endpoint to be targeted
  89      *      by the returned <code>W3CEndpointReference</code>.
  90      *
  91      * @return A <code>W3CEndpointReferenceBuilder</code> instance with
  92      *   the <code>address</code> set to the <code>wsa:Address</code>.
  93      */
  94     public W3CEndpointReferenceBuilder address(String address) {
  95         this.address = address;
  96         return this;
  97     }
  98 
  99     /**
 100      * Sets the <code>interfaceName</code> as the
 101      * <code>wsam:InterfaceName</code> element in the
 102      * <code>wsa:Metadata</code> element.
 103      *
 104      * See <a href="http://www.w3.org/TR/2007/REC-ws-addr-metadata-20070904/#refmetadatfromepr">
 105      * 2.1 Referencing WSDL Metadata from an EPR</a> for more details.
 106      *
 107      * @param interfaceName The port type name of the endpoint to be targeted
 108      *      by the returned <code>W3CEndpointReference</code>.
 109      *
 110      * @return A <code>W3CEndpointReferenceBuilder</code> instance with
 111      *   the <code>interfaceName</code> as <code>wsam:InterfaceName</code>
 112      *   element added to the <code>wsa:Metadata</code> element
 113      */
 114     public W3CEndpointReferenceBuilder interfaceName(QName interfaceName) {
 115         this.interfaceName = interfaceName;
 116         return this;
 117     }
 118 
 119     /**
 120      * Sets the <code>serviceName</code> as the
 121      * <code>wsam:ServiceName</code> element in the
 122      * <code>wsa:Metadata</code> element.
 123      *
 124      * See <a href="http://www.w3.org/TR/2007/REC-ws-addr-metadata-20070904/#refmetadatfromepr">
 125      * 2.1 Referencing WSDL Metadata from an EPR</a> for more details.
 126      *
 127      * @param serviceName The service name of the endpoint to be targeted
 128      *      by the returned <code>W3CEndpointReference</code>.  This property
 129      *      may also be used with the <code>endpointName</code> (portName)
 130      *      property to lookup the <code>address</code> of a web service
 131      *      endpoint that is published by the same Java EE application.
 132      *
 133      * @return A <code>W3CEndpointReferenceBuilder</code> instance with
 134      *   the <code>serviceName</code> as <code>wsam:ServiceName</code>
 135      *   element added to the <code>wsa:Metadata</code> element
 136      *
 137      */
 138     public W3CEndpointReferenceBuilder serviceName(QName serviceName) {
 139         this.serviceName = serviceName;
 140         return this;
 141     }
 142 
 143     /**
 144      * Sets the <code>endpointName</code> as
 145      * <code>wsam:ServiceName/@EndpointName</code> in the
 146      * <code>wsa:Metadata</code> element. This method can only be called
 147      * after the {@link #serviceName} method has been called.
 148      * <p>
 149      * See <a href="http://www.w3.org/TR/2007/REC-ws-addr-metadata-20070904/#refmetadatfromepr">
 150      * 2.1 Referencing WSDL Metadata from an EPR</a> for more details.
 151      *
 152      * @param endpointName The name of the endpoint to be targeted
 153      *      by the returned <code>W3CEndpointReference</code>. The
 154      *      <code>endpointName</code> (portName) property may also be
 155      *      used with the <code>serviceName</code> property to lookup
 156      *      the <code>address</code> of a web service
 157      *      endpoint published by the same Java EE application.
 158      *
 159      * @return A <code>W3CEndpointReferenceBuilder</code> instance with
 160      *   the <code>endpointName</code> as
 161      * <code>wsam:ServiceName/@EndpointName</code> in the
 162      * <code>wsa:Metadata</code> element.
 163      *
 164      * @throws IllegalStateException, if the <code>serviceName</code>
 165      * has not been set.
 166      * @throws IllegalArgumentException, if the <code>endpointName</code>'s
 167      * Namespace URI doesn't match <code>serviceName</code>'s Namespace URI
 168      *
 169      */
 170     public W3CEndpointReferenceBuilder endpointName(QName endpointName) {
 171         if (serviceName == null) {
 172             throw new IllegalStateException("The W3CEndpointReferenceBuilder's serviceName must be set before setting the endpointName: "+endpointName);
 173         }
 174 
 175         this.endpointName = endpointName;
 176         return this;
 177     }
 178 
 179     /**
 180      * Sets the <code>wsdlDocumentLocation</code> that will be referenced
 181      * as <code>wsa:Metadata/@wsdli:wsdlLocation</code>. The namespace name
 182      * for the wsdli:wsdlLocation's value can be taken from the WSDL itself.
 183      *
 184      * <p>
 185      * See <a href="http://www.w3.org/TR/2007/REC-ws-addr-metadata-20070904/#refmetadatfromepr">
 186      * 2.1 Referencing WSDL Metadata from an EPR</a> for more details.
 187      *
 188      * @param wsdlDocumentLocation The location of the WSDL document to
 189      *      be referenced in the <code>wsa:Metadata</code> of the
 190      *     <code>W3CEndpointReference</code>.
 191      * @return A <code>W3CEndpointReferenceBuilder</code> instance with
 192      *   the <code>wsdlDocumentLocation</code> that is to be referenced.
 193      */
 194     public W3CEndpointReferenceBuilder wsdlDocumentLocation(String wsdlDocumentLocation) {
 195         this.wsdlDocumentLocation = wsdlDocumentLocation;
 196         return this;
 197     }
 198 
 199     /**
 200      * Adds the <code>referenceParameter</code> to the
 201      * <code>W3CEndpointReference</code> instance
 202      * <code>wsa:ReferenceParameters</code> element.
 203      *
 204      * @param referenceParameter The element to be added to the
 205      *      <code>wsa:ReferenceParameters</code> element.
 206      *
 207      * @return A <code>W3CEndpointReferenceBuilder</code> instance with
 208      *   the <code>referenceParameter</code> added to the
 209      *   <code>wsa:ReferenceParameters</code> element.
 210      *
 211      * @throws java.lang.IllegalArgumentException if <code>referenceParameter</code>
 212      * is <code>null</code>.
 213      */
 214     public W3CEndpointReferenceBuilder referenceParameter(Element referenceParameter) {
 215         if (referenceParameter == null)
 216             throw new java.lang.IllegalArgumentException("The referenceParameter cannot be null.");
 217         referenceParameters.add(referenceParameter);
 218         return this;
 219     }
 220 
 221     /**
 222      * Adds the <code>metadataElement</code> to the
 223      * <code>W3CEndpointReference</code> instance's
 224      * <code>wsa:Metadata</code> element.
 225      *
 226      * @param metadataElement The element to be added to the
 227      *      <code>wsa:Metadata</code> element.
 228      *
 229      * @return A <code>W3CEndpointReferenceBuilder</code> instance with
 230      *   the <code>metadataElement</code> added to the
 231      *    <code>wsa:Metadata</code> element.
 232      *
 233      * @throws java.lang.IllegalArgumentException if <code>metadataElement</code>
 234      * is <code>null</code>.
 235      */
 236     public W3CEndpointReferenceBuilder metadata(Element metadataElement) {
 237         if (metadataElement == null)
 238             throw new java.lang.IllegalArgumentException("The metadataElement cannot be null.");
 239         metadata.add(metadataElement);
 240         return this;
 241     }
 242 
 243     /**
 244      * Adds an extension element to the
 245      * <code>W3CEndpointReference</code> instance's
 246      * <code>wsa:EndpointReference</code> element.
 247      *
 248      * @param element The extension element to be added to the
 249      *   <code>W3CEndpointReference</code>
 250      * @return A <code>W3CEndpointReferenceBuilder</code> instance with
 251      *   the extension <code>element</code> added to the
 252      *    <code>W3CEndpointReference</code> instance.
 253      * @throws java.lang.IllegalArgumentException if <code>element</code>
 254      * is <code>null</code>.
 255      *
 256      * @since JAX-WS 2.2
 257      */
 258     public W3CEndpointReferenceBuilder element(Element element) {
 259         if (element == null) {
 260             throw new IllegalArgumentException("The extension element cannot be null.");
 261         }
 262         elements.add(element);
 263         return this;
 264     }
 265 
 266     /**
 267      * Adds an extension attribute to the
 268      * <code>W3CEndpointReference</code> instance's
 269      * <code>wsa:EndpointReference</code> element.
 270      *
 271      * @param name The name of the extension attribute to be added to the
 272      *   <code>W3CEndpointReference</code>
 273      * @param value extension attribute value
 274      * @return A <code>W3CEndpointReferenceBuilder</code> instance with
 275      *   the extension attribute added to the <code>W3CEndpointReference</code>
 276      *   instance.
 277      * @throws java.lang.IllegalArgumentException if <code>name</code>
 278      *   or <code>value</code> is <code>null</code>.
 279      *
 280      * @since JAX-WS 2.2
 281      */
 282     public W3CEndpointReferenceBuilder attribute(QName name, String value) {
 283         if (name == null || value == null) {
 284             throw new IllegalArgumentException("The extension attribute name or value cannot be null.");
 285         }
 286         attributes.put(name, value);
 287         return this;
 288     }
 289 
 290     /**
 291      * Builds a <code>W3CEndpointReference</code> from the accumulated
 292      * properties set on this <code>W3CEndpointReferenceBuilder</code>
 293      * instance.
 294      * <p>
 295      * This method can be used to create a <code>W3CEndpointReference</code>
 296      * for any endpoint by specifying the <code>address</code> property along
 297      * with any other desired properties.  This method
 298      * can also be used to create a <code>W3CEndpointReference</code> for
 299      * an endpoint that is published by the same Java EE application.
 300      * This method can automatically determine the <code>address</code> of
 301      * an endpoint published by the same Java EE application that is identified by the
 302      * <code>serviceName</code> and
 303      * <code>endpointName</code> properties.  If the <code>address</code> is
 304      * <code>null</code> and the <code>serviceName</code> and
 305      * <code>endpointName</code>
 306      * do not identify an endpoint published by the same Java EE application, a
 307      * <code>java.lang.IllegalStateException</code> MUST be thrown.
 308      *
 309      *
 310      * @return <code>W3CEndpointReference</code> from the accumulated
 311      * properties set on this <code>W3CEndpointReferenceBuilder</code>
 312      * instance. This method never returns <code>null</code>.
 313      *
 314      * @throws IllegalStateException
 315      *     <ul>
 316      *        <li>If the <code>address</code>, <code>serviceName</code> and
 317      *            <code>endpointName</code> are all <code>null</code>.
 318      *        <li>If the <code>serviceName</code> service is <code>null</code> and the
 319      *            <code>endpointName</code> is NOT <code>null</code>.
 320      *        <li>If the <code>address</code> property is <code>null</code> and
 321      *            the <code>serviceName</code> and <code>endpointName</code> do not
 322      *            specify a valid endpoint published by the same Java EE
 323      *            application.
 324      *        <li>If the <code>serviceName</code> is NOT <code>null</code>
 325      *             and is not present in the specified WSDL.
 326      *        <li>If the <code>endpointName</code> port is not <code>null</code> and it
 327      *             is not present in <code>serviceName</code> service in the WSDL.
 328      *        <li>If the <code>wsdlDocumentLocation</code> is NOT <code>null</code>
 329      *            and does not represent a valid WSDL.
 330      *     </ul>
 331      * @throws WebServiceException If an error occurs while creating the
 332      *                             <code>W3CEndpointReference</code>.
 333      *
 334      */
 335     public W3CEndpointReference build() {
 336         if (elements.isEmpty() && attributes.isEmpty() && interfaceName == null) {
 337             // 2.1 API
 338             return Provider.provider().createW3CEndpointReference(address,
 339                 serviceName, endpointName, metadata, wsdlDocumentLocation,
 340                 referenceParameters);
 341         }
 342         return Provider.provider().createW3CEndpointReference(address,
 343                 interfaceName, serviceName, endpointName, metadata, wsdlDocumentLocation,
 344                 referenceParameters, elements, attributes);
 345     }
 346 
 347     private String address;
 348     private List<Element> referenceParameters;
 349     private List<Element> metadata;
 350     private QName interfaceName;
 351     private QName serviceName;
 352     private QName endpointName;
 353     private String wsdlDocumentLocation;
 354     private Map<QName,String> attributes;
 355     private List<Element> elements;
 356 }