1 /*
   2  * Copyright (c) 1997, 2010, 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 com.sun.xml.internal.ws.api.addressing;
  27 
  28 import com.sun.istack.internal.NotNull;
  29 import com.sun.istack.internal.Nullable;
  30 import com.sun.xml.internal.stream.buffer.XMLStreamBuffer;
  31 import com.sun.xml.internal.ws.addressing.W3CAddressingConstants;
  32 import com.sun.xml.internal.ws.addressing.WsaTubeHelper;
  33 import com.sun.xml.internal.ws.addressing.v200408.MemberSubmissionAddressingConstants;
  34 import com.sun.xml.internal.ws.api.WSBinding;
  35 import com.sun.xml.internal.ws.api.message.Header;
  36 import com.sun.xml.internal.ws.api.model.wsdl.WSDLPort;
  37 import com.sun.xml.internal.ws.api.model.SEIModel;
  38 import com.sun.xml.internal.ws.developer.MemberSubmissionAddressingFeature;
  39 import com.sun.xml.internal.ws.developer.MemberSubmissionEndpointReference;
  40 import com.sun.xml.internal.ws.message.stream.OutboundStreamHeader;
  41 
  42 import javax.xml.namespace.QName;
  43 import javax.xml.stream.XMLStreamException;
  44 import javax.xml.ws.EndpointReference;
  45 import javax.xml.ws.WebServiceException;
  46 import javax.xml.ws.WebServiceFeature;
  47 import javax.xml.ws.soap.AddressingFeature;
  48 import javax.xml.ws.wsaddressing.W3CEndpointReference;
  49 import java.io.ByteArrayInputStream;
  50 import java.io.UnsupportedEncodingException;
  51 
  52 /**
  53  * 'Traits' object that absorbs differences of WS-Addressing versions.
  54  *
  55  * @author Arun Gupta
  56  */
  57 public enum AddressingVersion {
  58 
  59     W3C("http://www.w3.org/2005/08/addressing",
  60         "wsa",
  61         W3CAddressingConstants.ANONYMOUS_EPR,
  62         "http://www.w3.org/2006/05/addressing/wsdl",
  63         "http://www.w3.org/2006/05/addressing/wsdl",
  64         "http://www.w3.org/2005/08/addressing/anonymous",
  65         "http://www.w3.org/2005/08/addressing/none",
  66         new EPR(W3CEndpointReference.class,
  67                     "Address",
  68                     "ServiceName",
  69                     "EndpointName",
  70                     "InterfaceName",
  71                     new QName("http://www.w3.org/2005/08/addressing","Metadata","wsa"),
  72                     "ReferenceParameters",
  73                     null )) {
  74 
  75         /* package */  String getActionMismatchLocalName() {
  76             return "ActionMismatch";
  77         }
  78         @Override
  79         public boolean isReferenceParameter(String localName) {
  80             return localName.equals("ReferenceParameters");
  81         }
  82 
  83         @Override
  84         public WsaTubeHelper getWsaHelper(WSDLPort wsdlPort, SEIModel seiModel, WSBinding binding) {
  85             return new com.sun.xml.internal.ws.addressing.WsaTubeHelperImpl(wsdlPort, seiModel, binding);
  86         }
  87 
  88         @Override
  89         /* package */ String getMapRequiredLocalName() {
  90             return "MessageAddressingHeaderRequired";
  91         }
  92 
  93         @Override
  94         public String getMapRequiredText() {
  95             return "A required header representing a Message Addressing Property is not present";
  96         }
  97 
  98         /* package */ String getInvalidAddressLocalName() {
  99             return "InvalidAddress";
 100         }
 101 
 102         @Override
 103         /* package */ String getInvalidMapLocalName() {
 104             return "InvalidAddressingHeader";
 105         }
 106 
 107         @Override
 108         public String getInvalidMapText() {
 109             return "A header representing a Message Addressing Property is not valid and the message cannot be processed";
 110         }
 111 
 112         @Override
 113         /* package */ String getInvalidCardinalityLocalName() {
 114             return "InvalidCardinality";
 115         }
 116 
 117         /*package*/ Header createReferenceParameterHeader(XMLStreamBuffer mark, String nsUri, String localName) {
 118             return new OutboundReferenceParameterHeader(mark,nsUri,localName);
 119         }
 120 
 121         /*package*/ String getIsReferenceParameterLocalName() {
 122             return "IsReferenceParameter";
 123         }
 124 
 125         /* package */ String getWsdlAnonymousLocalName() {
 126             return "Anonymous";
 127         }
 128 
 129         public String getPrefix() {
 130             return "wsa";
 131         }
 132 
 133         public String getWsdlPrefix() {
 134             return "wsaw";
 135         }
 136 
 137         public Class<? extends WebServiceFeature> getFeatureClass() {
 138             return AddressingFeature.class;
 139         }
 140     },
 141     MEMBER("http://schemas.xmlsoap.org/ws/2004/08/addressing",
 142            "wsa",
 143            MemberSubmissionAddressingConstants.ANONYMOUS_EPR,
 144            "http://schemas.xmlsoap.org/ws/2004/08/addressing",
 145            "http://schemas.xmlsoap.org/ws/2004/08/addressing/policy",
 146            "http://schemas.xmlsoap.org/ws/2004/08/addressing/role/anonymous",
 147             "",
 148            new EPR(MemberSubmissionEndpointReference.class,
 149                     "Address",
 150                     "ServiceName",
 151                     "PortName",
 152                     "PortType",
 153                     MemberSubmissionAddressingConstants.MEX_METADATA,
 154                     "ReferenceParameters",
 155                     "ReferenceProperties")) {
 156         /* package */  String getActionMismatchLocalName() {
 157             return "InvalidMessageInformationHeader";
 158         }
 159         @Override
 160         public boolean isReferenceParameter(String localName) {
 161             return localName.equals("ReferenceParameters") || localName.equals("ReferenceProperties");
 162         }
 163 
 164         @Override
 165         public WsaTubeHelper getWsaHelper(WSDLPort wsdlPort, SEIModel seiModel, WSBinding binding) {
 166             return new com.sun.xml.internal.ws.addressing.v200408.WsaTubeHelperImpl(wsdlPort, seiModel, binding);
 167         }
 168 
 169         @Override
 170         /* package */ String getMapRequiredLocalName() {
 171             return "MessageInformationHeaderRequired";
 172         }
 173 
 174         @Override
 175         public String getMapRequiredText() {
 176             return "A required message information header, To, MessageID, or Action, is not present.";
 177         }
 178 
 179         /* package */ String getInvalidAddressLocalName() {
 180             return getInvalidMapLocalName();
 181         }
 182 
 183         @Override
 184         /* package */ String getInvalidMapLocalName() {
 185             return "InvalidMessageInformationHeader";
 186         }
 187 
 188         @Override
 189         public String getInvalidMapText() {
 190             return "A message information header is not valid and the message cannot be processed.";
 191         }
 192 
 193         @Override
 194         /* package */ String getInvalidCardinalityLocalName() {
 195             return getInvalidMapLocalName();
 196         }
 197 
 198         /*package*/ Header createReferenceParameterHeader(XMLStreamBuffer mark, String nsUri, String localName) {
 199             return new OutboundStreamHeader(mark,nsUri,localName);
 200         }
 201 
 202         /*package*/ String getIsReferenceParameterLocalName() {
 203             return "";
 204         }
 205 
 206         /* package */ String getWsdlAnonymousLocalName() {
 207             return "";
 208         }
 209 
 210         public String getPrefix() {
 211             return "wsa";
 212         }
 213 
 214         public String getWsdlPrefix() {
 215             return "wsaw";
 216         }
 217 
 218         public Class<? extends WebServiceFeature> getFeatureClass() {
 219             return MemberSubmissionAddressingFeature.class;
 220         }
 221     };
 222 
 223     /**
 224      * Namespace URI
 225      */
 226     public final String nsUri;
 227 
 228     /**
 229      * Namespace URI for the WSDL Binding
 230      */
 231     public final String wsdlNsUri;
 232 
 233     /**
 234      * Representing either {@link W3CEndpointReference} or
 235      * {@link MemberSubmissionEndpointReference}.
 236      */
 237     public final EPR eprType;
 238 
 239     /**
 240      * Namespace URI for the WSDL Binding
 241      */
 242     public final String policyNsUri;
 243 
 244     /**
 245      * Gets the anonymous URI value associated with this WS-Addressing version.
 246      */
 247     public final @NotNull String anonymousUri;
 248 
 249     /**
 250      * Gets the none URI value associated with this WS-Addressing version.
 251      */
 252     public final @NotNull String noneUri;
 253 
 254     /**
 255      * Represents the anonymous EPR.
 256      */
 257     public final WSEndpointReference anonymousEpr;
 258 
 259     /**
 260      * Represents the To QName in the SOAP message for a specific WS-Addressing Version.
 261      */
 262     public final QName toTag;
 263 
 264     /**
 265      * Represents the From QName in the SOAP message for a specific WS-Addressing Version.
 266      */
 267     public final QName fromTag;
 268 
 269     /**
 270      * Represents the ReplyTo QName in the SOAP message for a specific WS-Addressing Version.
 271      */
 272     public final QName replyToTag;
 273 
 274     /**
 275      * Represents the FaultTo QName for a specific WS-Addressing Version.
 276      */
 277     public final QName faultToTag;
 278 
 279     /**
 280      * Represents the Action QName in the SOAP message for a specific WS-Addressing Version.
 281      */
 282     public final QName actionTag;
 283 
 284     /**
 285      * Represents the MessageID QName in the SOAP message for a specific WS-Addressing Version.
 286      */
 287     public final QName messageIDTag;
 288 
 289     /**
 290      * Represents the RelatesTo QName in the SOAP message for a specific WS-Addressing Version.
 291      */
 292     public final QName relatesToTag;
 293 
 294     /**
 295      * Represents the QName of the fault code when a required header representing a
 296      * WS-Addressing Message Addressing Property is not present.
 297      */
 298     public final QName mapRequiredTag;
 299 
 300     /**
 301      * Represents the QName of the fault code when Action is not supported at this endpoint.
 302      */
 303     public final QName actionMismatchTag;
 304 
 305     /**
 306      * Represents the QName of the fault code when Action is not supported at this endpoint.
 307      */
 308     public final QName actionNotSupportedTag;
 309 
 310     /**
 311      * Represents the text of the fault when Action is not supported at this endpoint.
 312      */
 313     public final String actionNotSupportedText;
 314 
 315     /**
 316      * Represents the QName of the fault code when a header representing a
 317      * WS-Addressing Message Addressing Property is invalid and cannot be processed.
 318      */
 319     public final QName invalidMapTag;
 320 
 321     /**
 322      * Represents the QName of the fault code when a header representing a
 323      * WS-Addressing Message Addressing Property occurs greater than expected number.
 324      */
 325     public final QName invalidCardinalityTag;
 326 
 327     /**
 328      * Represents the QName of the fault code when a header representing an
 329      * address is not valid.
 330      */
 331     public final QName invalidAddressTag;
 332 
 333     /**
 334      * Represents the QName of the element that conveys additional information
 335      * on the pre-defined WS-Addressing faults.
 336      */
 337     public final QName problemHeaderQNameTag;
 338 
 339     /**
 340      * Represents the QName of the element that conveys additional information
 341      * if Action is not matching with that expected.
 342      */
 343     public final QName problemActionTag;
 344 
 345     /**
 346      * Represents the QName of the header element that is used to capture the fault detail
 347      * if there is a fault processing WS-Addressing Message Addressing Property. This is
 348      * only used for SOAP 1.1.
 349      */
 350     public final QName faultDetailTag;
 351 
 352     /**
 353      * Fault sub-sub-code that represents
 354      * "Specifies that the invalid header was expected to be an EPR but did not contain an [address]."
 355      */
 356     public final QName fault_missingAddressInEpr;
 357 
 358     /**
 359      * Represents the Action QName in the WSDL for a specific WS-Addressing Version.
 360      */
 361     public final QName wsdlActionTag;
 362 
 363     /**
 364      * Represents the WSDL extension QName for a specific WS-Addressing Version.
 365      */
 366     public final QName wsdlExtensionTag;
 367 
 368     /**
 369      * Represents the WSDL anonymous QName for a specific WS-Addressing Version.
 370      */
 371     public final QName wsdlAnonymousTag;
 372 
 373     /**
 374      * Represents the QName of the reference parameter in a SOAP message. This is
 375      * only valid for W3C WS-Addressing.
 376      */
 377     public final QName isReferenceParameterTag;
 378 
 379     private static final String EXTENDED_FAULT_NAMESPACE = "http://jax-ws.dev.java.net/addressing/fault";
 380     public static final String UNSET_OUTPUT_ACTION = "http://jax-ws.dev.java.net/addressing/output-action-not-set";
 381     public static final String UNSET_INPUT_ACTION = "http://jax-ws.dev.java.net/addressing/input-action-not-set";
 382 
 383     /**
 384      * Fault sub-sub-code that represents duplicate &lt;Address> element in EPR.
 385      * This is a fault code not defined in the spec.
 386      */
 387     public static final QName fault_duplicateAddressInEpr = new QName(
 388         EXTENDED_FAULT_NAMESPACE, "DuplicateAddressInEpr", "wsa"
 389     );
 390 
 391     private AddressingVersion(String nsUri, String prefix, String anonymousEprString, String wsdlNsUri, String policyNsUri,
 392                               String anonymousUri, String noneUri,
 393                               EPR eprType ) {
 394         this.nsUri = nsUri;
 395         this.wsdlNsUri = wsdlNsUri;
 396         this.policyNsUri = policyNsUri;
 397         this.anonymousUri = anonymousUri;
 398         this.noneUri = noneUri;
 399         toTag = new QName(nsUri,"To", prefix);
 400         fromTag = new QName(nsUri,"From", prefix);
 401         replyToTag = new QName(nsUri,"ReplyTo", prefix);
 402         faultToTag = new QName(nsUri,"FaultTo", prefix);
 403         actionTag = new QName(nsUri,"Action", prefix);
 404         messageIDTag = new QName(nsUri,"MessageID", prefix);
 405         relatesToTag = new QName(nsUri,"RelatesTo", prefix);
 406 
 407         mapRequiredTag = new QName(nsUri,getMapRequiredLocalName(), prefix);
 408         actionMismatchTag = new QName(nsUri,getActionMismatchLocalName(), prefix);
 409         actionNotSupportedTag = new QName(nsUri,"ActionNotSupported", prefix);
 410         actionNotSupportedText = "The \"%s\" cannot be processed at the receiver";
 411         invalidMapTag = new QName(nsUri,getInvalidMapLocalName(), prefix);
 412         invalidAddressTag = new QName(nsUri,getInvalidAddressLocalName(), prefix);
 413         invalidCardinalityTag = new QName(nsUri,getInvalidCardinalityLocalName(), prefix);
 414         faultDetailTag = new QName(nsUri,"FaultDetail", prefix);
 415 
 416         problemHeaderQNameTag = new QName(nsUri,"ProblemHeaderQName", prefix);
 417         problemActionTag = new QName(nsUri, "ProblemAction", prefix);
 418 
 419         fault_missingAddressInEpr = new QName(nsUri,"MissingAddressInEPR", prefix);
 420         isReferenceParameterTag = new QName(nsUri,getIsReferenceParameterLocalName(), prefix);
 421 
 422         wsdlActionTag = new QName(wsdlNsUri,"Action", prefix);
 423         wsdlExtensionTag = new QName(wsdlNsUri, "UsingAddressing", prefix);
 424         wsdlAnonymousTag = new QName(wsdlNsUri, getWsdlAnonymousLocalName(), prefix);
 425 
 426         // create stock anonymous EPR
 427         try {
 428             this.anonymousEpr = new WSEndpointReference(new ByteArrayInputStream(anonymousEprString.getBytes("UTF-8")),this);
 429         } catch (XMLStreamException e) {
 430             throw new Error(e); // bug in our code as EPR should parse.
 431         } catch (UnsupportedEncodingException e) {
 432             throw new Error(e);
 433         }
 434         this.eprType = eprType;
 435     }
 436 
 437     /**
 438      * Gets the local name of the fault when a header representing a WS-Addressing Action is not same as SOAPAction
 439      *
 440      * @return local name
 441      */
 442     /* package */ abstract String getActionMismatchLocalName();
 443 
 444     /**
 445      * Returns {@link AddressingVersion} whose {@link #nsUri} equals to
 446      * the given string.
 447      *
 448      * This method does not perform input string validation.
 449      *
 450      * @param nsUri
 451      *      must not be null.
 452      * @return always non-null.
 453      */
 454     public static AddressingVersion fromNsUri(String nsUri) {
 455         if (nsUri.equals(W3C.nsUri))
 456             return W3C;
 457 
 458         if (nsUri.equals(MEMBER.nsUri))
 459             return MEMBER;
 460 
 461         return null;
 462     }
 463 
 464     /**
 465      * Gets the {@link AddressingVersion} from a {@link WSBinding}
 466      *
 467      * @param binding WSDL binding
 468      * @return
 469      *     addresing version enabled, or null if none is enabled.
 470      */
 471     public static @Nullable
 472     AddressingVersion fromBinding(WSBinding binding) {
 473         // TODO: who is responsible for reporting an error if both versions
 474         // are on?
 475         if (binding.isFeatureEnabled(AddressingFeature.class))
 476             return W3C;
 477 
 478         if (binding.isFeatureEnabled(MemberSubmissionAddressingFeature.class))
 479             return MEMBER;
 480 
 481         return null;
 482     }
 483 
 484     /**
 485      * Gets the {@link AddressingVersion} from a {@link WSDLPort}
 486      *
 487      * @param port WSDL port
 488      * @return addresing version
 489      */
 490     public static AddressingVersion fromPort(WSDLPort port) {
 491         if (port == null)
 492             return null;
 493 
 494         WebServiceFeature wsf = port.getFeature(AddressingFeature.class);
 495         if (wsf == null) {
 496             wsf = port.getFeature(MemberSubmissionAddressingFeature.class);
 497         }
 498         if (wsf == null)
 499             return null;
 500 
 501         return fromFeature(wsf);
 502     }
 503 
 504     /**
 505      * Returns {@link #nsUri} associated with this {@link AddressingVersion}
 506      *
 507      * @return namespace URI
 508      * @deprecated
 509      *      Use {@link #nsUri}.
 510      */
 511     public String getNsUri() {
 512         return nsUri;
 513     }
 514 
 515     /**
 516      * Returns true if the given local name is considered as
 517      * a reference parameter in EPR.
 518      *
 519      * For W3C, this means "ReferenceParameters",
 520      * and for the member submission version, this means
 521      * either "ReferenceParameters" or "ReferenceProperties".
 522      */
 523     public abstract boolean isReferenceParameter(String localName);
 524 
 525     /**
 526      * Returns WsaTubeHelper for the WS-Addressing version identified by <code>binding</code>
 527      * {@link WSBinding} and for the {@link WSDLPort} port.
 528      *
 529      * @return WS-A version specific helper
 530      *
 531      * @deprecated
 532      *     TODO  why are we exposing implementation specificc class through api?
 533      *     TODO  Remove it if no one elase uses it.
 534      */
 535     public abstract WsaTubeHelper getWsaHelper(WSDLPort wsdlPort, SEIModel seiModel, WSBinding binding);
 536 
 537     /**
 538      * Gets the none URI value associated with this WS-Addressing version.
 539      *
 540      * @return none URI value
 541      * @deprecated
 542      *      Use {@link #noneUri}.
 543      */
 544     public final String getNoneUri() {
 545         return noneUri;
 546     }
 547 
 548     /**
 549      * Gets the anonymous URI value associated with this WS-Addressing version.
 550      *
 551      * @deprecated
 552      *      Use {@link #anonymousUri}
 553      */
 554     public final String getAnonymousUri() {
 555         return anonymousUri;
 556     }
 557 
 558     /**
 559      * Gets the default fault Action value associated with this WS-Addressing version.
 560      *
 561      * @return default fault Action value
 562      */
 563     public String getDefaultFaultAction() {
 564         return nsUri + "/fault";
 565     }
 566 
 567     /**
 568      * Gets the local name of the fault when a header representing a WS-Addressing Message
 569      * Addresing Property is absent.
 570      *
 571      * @return local name
 572      */
 573     /* package */ abstract String getMapRequiredLocalName();
 574 
 575     /**
 576      * Gets the description text when a required WS-Addressing header representing a
 577      * Message Addressing Property is absent.
 578      *
 579      * @return description text
 580      */
 581     public abstract String getMapRequiredText();
 582 
 583     /**
 584          * Gets the local name of the fault when a header representing anaddress is invalid.
 585          * @return local name
 586          */
 587     /* package */ abstract String getInvalidAddressLocalName();
 588 
 589 
 590     /**
 591      * Gets the local name of the fault when a header representing a WS-Addressing Message
 592      * Addresing Property is invalid and cannot be processed.
 593      *
 594      * @return local name
 595      */
 596     /* package */ abstract String getInvalidMapLocalName();
 597 
 598     /**
 599      * Gets the description text when a header representing a WS-Addressing
 600      * Message Addressing Property is invalid and cannot be processed.
 601      *
 602      * @return description text
 603      */
 604     public abstract String getInvalidMapText();
 605 
 606     /**
 607      * Gets the local name of the fault when a header representing a WS-Addressing Message
 608      * Addresing Property occurs greater than expected number.
 609      *
 610      * @return local name
 611      */
 612     /* package */ abstract String getInvalidCardinalityLocalName();
 613 
 614     /* package */ abstract String getWsdlAnonymousLocalName();
 615 
 616     public abstract String getPrefix();
 617 
 618     public abstract String getWsdlPrefix();
 619 
 620     public abstract Class<? extends WebServiceFeature> getFeatureClass();
 621     /**
 622      * Creates an outbound {@link Header} from a reference parameter.
 623      */
 624     /*package*/ abstract Header createReferenceParameterHeader(XMLStreamBuffer mark, String nsUri, String localName);
 625 
 626     /**
 627      * Gets the local name for wsa:IsReferenceParameter. This method will return a valid
 628      * value only valid for W3C WS-Addressing. For Member Submission WS-Addressing, this method
 629      * returns null.
 630      */
 631     /*package*/ abstract String getIsReferenceParameterLocalName();
 632 
 633     public static AddressingVersion fromFeature(WebServiceFeature af) {
 634         if (af.getID().equals(AddressingFeature.ID))
 635             return W3C;
 636         else if (af.getID().equals(MemberSubmissionAddressingFeature.ID))
 637             return MEMBER;
 638         else
 639             return null;
 640     }
 641 
 642     /**
 643      * Gets the {@link WebServiceFeature} corresponding to the namespace URI of
 644      * WS-Addressing policy assertion in the WSDL. <code>enabled</code> and
 645      * <code>required</code> are used to initialize the value of the feature.
 646      *
 647      * @param nsUri namespace URI of the WS-Addressing policy assertion in the WSDL
 648      * @param enabled true if feature is to be enabled, false otherwise
 649      * @param required true if feature is required, false otherwise. Corresponds
 650      *          to wsdl:required on the extension/assertion.
 651      * @return WebServiceFeature corresponding to the assertion namespace URI
 652      * @throws WebServiceException if an unsupported namespace URI is passed
 653      */
 654     public static @NotNull WebServiceFeature getFeature(String nsUri, boolean enabled, boolean required) {
 655         if (nsUri.equals(W3C.policyNsUri))
 656             return new AddressingFeature(enabled, required);
 657         else if (nsUri.equals(MEMBER.policyNsUri))
 658             return new MemberSubmissionAddressingFeature(enabled, required);
 659         else
 660             throw new WebServiceException("Unsupported namespace URI: " + nsUri);
 661     }
 662 
 663     /**
 664      * Gets the corresponding {@link AddressingVersion} instance from the
 665      * EPR class.
 666      */
 667     public static @NotNull AddressingVersion fromSpecClass(Class<? extends EndpointReference> eprClass) {
 668         if(eprClass==W3CEndpointReference.class)
 669             return W3C;
 670         if(eprClass==MemberSubmissionEndpointReference.class)
 671             return MEMBER;
 672         throw new WebServiceException("Unsupported EPR type: "+eprClass);
 673     }
 674 
 675     /**
 676      * Returns true if the WebServiceFeature is either a {@link AddressingFeature} or
 677      * {@link MemberSubmissionAddressingFeature} and is required.
 678      *
 679      * @param wsf The WebServiceFeature encaps
 680      * @throws WebServiceException if <code>wsf</code> does not contain either {@link AddressingFeature} or
 681      * {@link MemberSubmissionAddressingFeature}
 682      * @return true if <code>wsf</code> requires WS-Addressing
 683      */
 684     public static boolean isRequired(WebServiceFeature wsf) {
 685         if (wsf.getID().equals(AddressingFeature.ID)) {
 686             return ((AddressingFeature)wsf).isRequired();
 687         } else if (wsf.getID().equals(MemberSubmissionAddressingFeature.ID)) {
 688             return ((MemberSubmissionAddressingFeature)wsf).isRequired();
 689         } else
 690             throw new WebServiceException("WebServiceFeature not an Addressing feature: "+ wsf.getID());
 691     }
 692 
 693     /**
 694      * Returns true if <code>binding</code> contains either a {@link AddressingFeature} or
 695      * {@link MemberSubmissionAddressingFeature} and is required.
 696      *
 697      * @param binding The binding
 698      * @return true if <code>binding</code> requires WS-Addressing
 699      */
 700     public static boolean isRequired(WSBinding binding) {
 701         AddressingFeature af = binding.getFeature(AddressingFeature.class);
 702         if (af != null)
 703             return af.isRequired();
 704         MemberSubmissionAddressingFeature msaf = binding.getFeature(MemberSubmissionAddressingFeature.class);
 705         if(msaf != null)
 706             return msaf.isRequired();
 707 
 708         return false;
 709     }
 710 
 711     /**
 712      * Returns true if <code>binding</code> contains either a {@link AddressingFeature} or
 713      * {@link MemberSubmissionAddressingFeature} and is enabled.
 714      *
 715      * @param binding The binding
 716      * @return true if WS-Addressing is enabled for <code>binding</code>.
 717      */
 718     public static boolean isEnabled(WSBinding binding) {
 719         return binding.isFeatureEnabled(MemberSubmissionAddressingFeature.class) ||
 720                 binding.isFeatureEnabled(AddressingFeature.class);
 721     }
 722 
 723     public final static class EPR {
 724         public final Class<? extends EndpointReference> eprClass;
 725         public final String address;
 726         public final String serviceName;
 727         public final String portName;
 728         public final String portTypeName;
 729         public final String referenceParameters;
 730         /**
 731          * Element under which metadata is specified.
 732          * In W3C, it is wsa:Metadata
 733          * In Member, it is directly under mex:MetadataSection
 734          */
 735         public final QName wsdlMetadata;
 736         public final String referenceProperties;
 737 
 738         public EPR(Class<? extends EndpointReference> eprClass, String address, String serviceName, String portName,
 739                     String portTypeName, QName wsdlMetadata,
 740                     String referenceParameters, String referenceProperties) {
 741             this.eprClass = eprClass;
 742             this.address = address;
 743             this.serviceName = serviceName;
 744             this.portName = portName;
 745             this.portTypeName = portTypeName;
 746             this.referenceParameters = referenceParameters;
 747             this.referenceProperties = referenceProperties;
 748             this.wsdlMetadata = wsdlMetadata;
 749 
 750         }
 751     }
 752 
 753 }