1 /*
   2  * Copyright (c) 2005, 2015, 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}
  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} for a
  45  * web service endpoint published by the same
  46  * Java EE application. It can also be used to create
  47  * {@code W3CEndpointReferences} for an Java SE based
  48  * endpoint by providing the {@code address} property.
  49  * <p>
  50  * When creating a {@code W3CEndpointReference} for an
  51  * endpoint that is not published by the same Java EE application,
  52  * the {@code address} property MUST be specified.
  53  * <p>
  54  * When creating a {@code W3CEndpointReference} for an endpoint
  55  * published by the same Java EE application, the {@code address}
  56  * property MAY be {@code null} but then the {@code serviceName}
  57  * and {@code endpointName} MUST specify an endpoint published by
  58  * the same Java EE application.
  59  * <p>
  60  * When the {@code wsdlDocumentLocation} is specified it MUST refer
  61  * to a valid WSDL document and the {@code serviceName} and
  62  * {@code endpointName} (if specified) MUST match a service and port
  63  * in the WSDL document.
  64  *
  65  * @since 1.6, JAX-WS 2.1
  66  */
  67 public final class W3CEndpointReferenceBuilder {
  68     /**
  69      * Creates a new {@code W3CEndpointReferenceBuilder} 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} to the
  80      * {@code W3CEndpointReference} instance's
  81      * {@code wsa:Address}.
  82      * <p>
  83      * The {@code address} MUST be set to a non-{@code null}
  84      * value when building a {@code W3CEndpointReference} 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}.
  90      *
  91      * @return A {@code W3CEndpointReferenceBuilder} instance with
  92      *   the {@code address} set to the {@code wsa:Address}.
  93      */
  94     public W3CEndpointReferenceBuilder address(String address) {
  95         this.address = address;
  96         return this;
  97     }
  98 
  99     /**
 100      * Sets the {@code interfaceName} as the
 101      * {@code wsam:InterfaceName} element in the
 102      * {@code wsa:Metadata} 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}.
 109      *
 110      * @return A {@code W3CEndpointReferenceBuilder} instance with
 111      *   the {@code interfaceName} as {@code wsam:InterfaceName}
 112      *   element added to the {@code wsa:Metadata} element
 113      * @since 1.7
 114      */
 115     public W3CEndpointReferenceBuilder interfaceName(QName interfaceName) {
 116         this.interfaceName = interfaceName;
 117         return this;
 118     }
 119 
 120     /**
 121      * Sets the {@code serviceName} as the
 122      * {@code wsam:ServiceName} element in the
 123      * {@code wsa:Metadata} element.
 124      *
 125      * See <a href="http://www.w3.org/TR/2007/REC-ws-addr-metadata-20070904/#refmetadatfromepr">
 126      * 2.1 Referencing WSDL Metadata from an EPR</a> for more details.
 127      *
 128      * @param serviceName The service name of the endpoint to be targeted
 129      *      by the returned {@code W3CEndpointReference}.  This property
 130      *      may also be used with the {@code endpointName} (portName)
 131      *      property to lookup the {@code address} of a web service
 132      *      endpoint that is published by the same Java EE application.
 133      *
 134      * @return A {@code W3CEndpointReferenceBuilder} instance with
 135      *   the {@code serviceName} as {@code wsam:ServiceName}
 136      *   element added to the {@code wsa:Metadata} element
 137      *
 138      */
 139     public W3CEndpointReferenceBuilder serviceName(QName serviceName) {
 140         this.serviceName = serviceName;
 141         return this;
 142     }
 143 
 144     /**
 145      * Sets the {@code endpointName} as
 146      * {@code wsam:ServiceName/@EndpointName} in the
 147      * {@code wsa:Metadata} element. This method can only be called
 148      * after the {@link #serviceName} method has been called.
 149      * <p>
 150      * See <a href="http://www.w3.org/TR/2007/REC-ws-addr-metadata-20070904/#refmetadatfromepr">
 151      * 2.1 Referencing WSDL Metadata from an EPR</a> for more details.
 152      *
 153      * @param endpointName The name of the endpoint to be targeted
 154      *      by the returned {@code W3CEndpointReference}. The
 155      *      {@code endpointName} (portName) property may also be
 156      *      used with the {@code serviceName} property to lookup
 157      *      the {@code address} of a web service
 158      *      endpoint published by the same Java EE application.
 159      *
 160      * @return A {@code W3CEndpointReferenceBuilder} instance with
 161      *   the {@code endpointName} as
 162      *   {@code wsam:ServiceName/@EndpointName} in the
 163      *   {@code wsa:Metadata} element.
 164      *
 165      * @throws java.lang.IllegalStateException if the {@code serviceName}
 166      *   has not been set
 167      *
 168      * @throws java.lang.IllegalArgumentException if the {@code endpointName}'s
 169      *   Namespace URI doesn't match {@code serviceName}'s Namespace URI
 170      *
 171      */
 172     public W3CEndpointReferenceBuilder endpointName(QName endpointName) {
 173         if (serviceName == null) {
 174             throw new IllegalStateException("The W3CEndpointReferenceBuilder's serviceName must be set before setting the endpointName: "+endpointName);
 175         }
 176 
 177         this.endpointName = endpointName;
 178         return this;
 179     }
 180 
 181     /**
 182      * Sets the {@code wsdlDocumentLocation} that will be referenced
 183      * as {@code wsa:Metadata/@wsdli:wsdlLocation}. The namespace name
 184      * for the wsdli:wsdlLocation's value can be taken from the WSDL itself.
 185      *
 186      * <p>
 187      * See <a href="http://www.w3.org/TR/2007/REC-ws-addr-metadata-20070904/#refmetadatfromepr">
 188      * 2.1 Referencing WSDL Metadata from an EPR</a> for more details.
 189      *
 190      * @param wsdlDocumentLocation The location of the WSDL document to
 191      *      be referenced in the {@code wsa:Metadata} of the
 192      *     {@code W3CEndpointReference}.
 193      * @return A {@code W3CEndpointReferenceBuilder} instance with
 194      *   the {@code wsdlDocumentLocation} that is to be referenced.
 195      */
 196     public W3CEndpointReferenceBuilder wsdlDocumentLocation(String wsdlDocumentLocation) {
 197         this.wsdlDocumentLocation = wsdlDocumentLocation;
 198         return this;
 199     }
 200 
 201     /**
 202      * Adds the {@code referenceParameter} to the
 203      * {@code W3CEndpointReference} instance
 204      * {@code wsa:ReferenceParameters} element.
 205      *
 206      * @param referenceParameter The element to be added to the
 207      *      {@code wsa:ReferenceParameters} element.
 208      *
 209      * @return A {@code W3CEndpointReferenceBuilder} instance with
 210      *   the {@code referenceParameter} added to the
 211      *   {@code wsa:ReferenceParameters} element.
 212      *
 213      * @throws java.lang.IllegalArgumentException if {@code referenceParameter}
 214      * is {@code null}.
 215      */
 216     public W3CEndpointReferenceBuilder referenceParameter(Element referenceParameter) {
 217         if (referenceParameter == null)
 218             throw new java.lang.IllegalArgumentException("The referenceParameter cannot be null.");
 219         referenceParameters.add(referenceParameter);
 220         return this;
 221     }
 222 
 223     /**
 224      * Adds the {@code metadataElement} to the
 225      * {@code W3CEndpointReference} instance's
 226      * {@code wsa:Metadata} element.
 227      *
 228      * @param metadataElement The element to be added to the
 229      *      {@code wsa:Metadata} element.
 230      *
 231      * @return A {@code W3CEndpointReferenceBuilder} instance with
 232      *   the {@code metadataElement} added to the
 233      *    {@code wsa:Metadata} element.
 234      *
 235      * @throws java.lang.IllegalArgumentException if {@code metadataElement}
 236      * is {@code null}.
 237      */
 238     public W3CEndpointReferenceBuilder metadata(Element metadataElement) {
 239         if (metadataElement == null)
 240             throw new java.lang.IllegalArgumentException("The metadataElement cannot be null.");
 241         metadata.add(metadataElement);
 242         return this;
 243     }
 244 
 245     /**
 246      * Adds an extension element to the
 247      * {@code W3CEndpointReference} instance's
 248      * {@code wsa:EndpointReference} element.
 249      *
 250      * @param element The extension element to be added to the
 251      *   {@code W3CEndpointReference}
 252      * @return A {@code W3CEndpointReferenceBuilder} instance with
 253      *   the extension {@code element} added to the
 254      *    {@code W3CEndpointReference} instance.
 255      * @throws java.lang.IllegalArgumentException if {@code element}
 256      * is {@code null}.
 257      *
 258      * @since 1.7, JAX-WS 2.2
 259      */
 260     public W3CEndpointReferenceBuilder element(Element element) {
 261         if (element == null) {
 262             throw new IllegalArgumentException("The extension element cannot be null.");
 263         }
 264         elements.add(element);
 265         return this;
 266     }
 267 
 268     /**
 269      * Adds an extension attribute to the
 270      * {@code W3CEndpointReference} instance's
 271      * {@code wsa:EndpointReference} element.
 272      *
 273      * @param name The name of the extension attribute to be added to the
 274      *   {@code W3CEndpointReference}
 275      * @param value extension attribute value
 276      * @return A {@code W3CEndpointReferenceBuilder} instance with
 277      *   the extension attribute added to the {@code W3CEndpointReference}
 278      *   instance.
 279      * @throws java.lang.IllegalArgumentException if {@code name}
 280      *   or {@code value} is {@code null}.
 281      *
 282      * @since 1.7, JAX-WS 2.2
 283      */
 284     public W3CEndpointReferenceBuilder attribute(QName name, String value) {
 285         if (name == null || value == null) {
 286             throw new IllegalArgumentException("The extension attribute name or value cannot be null.");
 287         }
 288         attributes.put(name, value);
 289         return this;
 290     }
 291 
 292     /**
 293      * Builds a {@code W3CEndpointReference} from the accumulated
 294      * properties set on this {@code W3CEndpointReferenceBuilder}
 295      * instance.
 296      * <p>
 297      * This method can be used to create a {@code W3CEndpointReference}
 298      * for any endpoint by specifying the {@code address} property along
 299      * with any other desired properties.  This method
 300      * can also be used to create a {@code W3CEndpointReference} for
 301      * an endpoint that is published by the same Java EE application.
 302      * This method can automatically determine the {@code address} of
 303      * an endpoint published by the same Java EE application that is identified by the
 304      * {@code serviceName} and
 305      * {@code endpointName} properties.  If the {@code address} is
 306      * {@code null} and the {@code serviceName} and
 307      * {@code endpointName}
 308      * do not identify an endpoint published by the same Java EE application, a
 309      * {@code java.lang.IllegalStateException} MUST be thrown.
 310      *
 311      *
 312      * @return {@code W3CEndpointReference} from the accumulated
 313      * properties set on this {@code W3CEndpointReferenceBuilder}
 314      * instance. This method never returns {@code null}.
 315      *
 316      * @throws IllegalStateException
 317      *     <ul>
 318      *        <li>If the {@code address}, {@code serviceName} and
 319      *            {@code endpointName} are all {@code null}.
 320      *        <li>If the {@code serviceName} service is {@code null} and the
 321      *            {@code endpointName} is NOT {@code null}.
 322      *        <li>If the {@code address} property is {@code null} and
 323      *            the {@code serviceName} and {@code endpointName} do not
 324      *            specify a valid endpoint published by the same Java EE
 325      *            application.
 326      *        <li>If the {@code serviceName} is NOT {@code null}
 327      *             and is not present in the specified WSDL.
 328      *        <li>If the {@code endpointName} port is not {@code null} and it
 329      *             is not present in {@code serviceName} service in the WSDL.
 330      *        <li>If the {@code wsdlDocumentLocation} is NOT {@code null}
 331      *            and does not represent a valid WSDL.
 332      *     </ul>
 333      * @throws WebServiceException If an error occurs while creating the
 334      *                             {@code W3CEndpointReference}.
 335      *
 336      */
 337     public W3CEndpointReference build() {
 338         if (elements.isEmpty() && attributes.isEmpty() && interfaceName == null) {
 339             // 2.1 API
 340             return Provider.provider().createW3CEndpointReference(address,
 341                 serviceName, endpointName, metadata, wsdlDocumentLocation,
 342                 referenceParameters);
 343         }
 344         return Provider.provider().createW3CEndpointReference(address,
 345                 interfaceName, serviceName, endpointName, metadata, wsdlDocumentLocation,
 346                 referenceParameters, elements, attributes);
 347     }
 348 
 349     private String address;
 350     private List<Element> referenceParameters;
 351     private List<Element> metadata;
 352     private QName interfaceName;
 353     private QName serviceName;
 354     private QName endpointName;
 355     private String wsdlDocumentLocation;
 356     private Map<QName,String> attributes;
 357     private List<Element> elements;
 358 }