src/share/jaxws_classes/com/sun/xml/internal/ws/api/BindingID.java

Tue, 06 Mar 2012 16:09:35 -0800

author
ohair
date
Tue, 06 Mar 2012 16:09:35 -0800
changeset 286
f50545b5e2f1
child 368
0989ad8c0860
permissions
-rw-r--r--

7150322: Stop using drop source bundles in jaxws
Reviewed-by: darcy, ohrstrom

     1 /*
     2  * Copyright (c) 1997, 2011, 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  */
    26 package com.sun.xml.internal.ws.api;
    28 import com.sun.istack.internal.NotNull;
    29 import com.sun.xml.internal.ws.api.message.Message;
    30 import com.sun.xml.internal.ws.api.pipe.Codec;
    31 import com.sun.xml.internal.ws.api.pipe.Tube;
    32 import com.sun.xml.internal.ws.binding.BindingImpl;
    33 import com.sun.xml.internal.ws.binding.SOAPBindingImpl;
    34 import com.sun.xml.internal.ws.binding.WebServiceFeatureList;
    35 import com.sun.xml.internal.ws.encoding.SOAPBindingCodec;
    36 import com.sun.xml.internal.ws.encoding.XMLHTTPBindingCodec;
    37 import com.sun.xml.internal.ws.encoding.soap.streaming.SOAPNamespaceConstants;
    38 import com.sun.xml.internal.ws.encoding.soap.streaming.SOAP12NamespaceConstants;
    39 import com.sun.xml.internal.ws.util.ServiceFinder;
    40 import com.sun.xml.internal.ws.developer.JAXWSProperties;
    41 import static com.sun.xml.internal.ws.binding.WebServiceFeatureList.toFeatureArray;
    43 import javax.xml.ws.BindingType;
    44 import javax.xml.ws.WebServiceException;
    45 import javax.xml.ws.WebServiceFeature;
    46 import javax.xml.ws.handler.Handler;
    47 import javax.xml.ws.http.HTTPBinding;
    48 import javax.xml.ws.soap.MTOMFeature;
    49 import javax.xml.ws.soap.SOAPBinding;
    51 import java.io.UnsupportedEncodingException;
    52 import java.net.URL;
    53 import java.net.URLDecoder;
    54 import java.util.HashMap;
    55 import java.util.Map;
    57 /**
    58  * Parsed binding ID string.
    59  *
    60  * <p>
    61  * {@link BindingID} is an immutable object that represents a binding ID,
    62  * much like how {@link URL} is a representation of an URL.
    63  * Like {@link URL}, this class offers a bunch of methods that let you
    64  * query various traits/properties of a binding ID.
    65  *
    66  * <p>
    67  * {@link BindingID} is extensible; one can plug in a parser from
    68  * {@link String} to {@link BindingID} to interpret binding IDs that
    69  * the JAX-WS RI does no a-priori knowledge of.
    70  * Technologies such as Tango uses this to make the JAX-WS RI understand
    71  * binding IDs defined in their world.
    72  *
    73  * Such technologies are free to extend this class and expose more characterstics.
    74  *
    75  * <p>
    76  * Even though this class defines a few well known constants, {@link BindingID}
    77  * instances do not necessarily have singleton semantics. Use {@link #equals(Object)}
    78  * for the comparison.
    79  *
    80  * <h3>{@link BindingID} and {@link WSBinding}</h3>
    81  * <p>
    82  * {@link WSBinding} is mutable and represents a particular "use" of a {@link BindingID}.
    83  * As such, it has state like a list of {@link Handler}s, which are inherently local
    84  * to a particular usage. For example, if you have two proxies, you need two instances.
    85  *
    86  * {@link BindingID}, OTOH, is immutable and thus the single instance
    87  * that represents "SOAP1.2/HTTP" can be shared and reused by all proxies in the same VM.
    88  *
    89  * @author Kohsuke Kawaguchi
    90  */
    91 public abstract class BindingID {
    93     /**
    94      * Creates an instance of {@link WSBinding} (which is conceptually an "use"
    95      * of {@link BindingID}) from a {@link BindingID}.
    96      *
    97      * @return
    98      *      Always a new instance.
    99      */
   100     public final @NotNull WSBinding createBinding() {
   101         return BindingImpl.create(this);
   102     }
   104     /**
   105      * Returns wsdl:binding@transport attribute. Sub classes
   106      * are expected to override this method to provide their transport
   107      * attribute.
   108      *
   109      * @return wsdl:binding@transport attribute
   110      * @since JAX-WS RI 2.1.6
   111      */
   112     public @NotNull String getTransport() {
   113         return SOAPNamespaceConstants.TRANSPORT_HTTP;
   114     }
   116     public final @NotNull WSBinding createBinding(WebServiceFeature... features) {
   117         return BindingImpl.create(this, features);
   118     }
   120     public final @NotNull WSBinding createBinding(WSFeatureList features) {
   121         return createBinding(features.toArray());
   122     }
   124     /**
   125      * Gets the SOAP version of this binding.
   126      *
   127      * TODO: clarify what to do with XML/HTTP binding
   128      *
   129      * @return
   130      *      If the binding is using SOAP, this method returns
   131      *      a {@link SOAPVersion} constant.
   132      *
   133      *      If the binding is not based on SOAP, this method
   134      *      returns null. See {@link Message} for how a non-SOAP
   135      *      binding shall be handled by {@link Tube}s.
   136      */
   137     public abstract SOAPVersion getSOAPVersion();
   139     /**
   140      * Creates a new {@link Codec} for this binding.
   141      *
   142      * @param binding
   143      *      Ocassionally some aspects of binding can be overridden by
   144      *      {@link WSBinding} at runtime by users, so some {@link Codec}s
   145      *      need to have access to {@link WSBinding} that it's working for.
   146      */
   147     public abstract @NotNull Codec createEncoder(@NotNull WSBinding binding);
   149     /**
   150      * Gets the binding ID, which uniquely identifies the binding.
   151      *
   152      * <p>
   153      * The relevant specs define the binding IDs and what they mean.
   154      * The ID is used in many places to identify the kind of binding
   155      * (such as SOAP1.1, SOAP1.2, REST, ...)
   156      *
   157      * @return
   158      *      Always non-null same value.
   159      */
   160     public abstract String toString();
   162     /**
   163      * Returna a new {@link WebServiceFeatureList} instance
   164      * that represents the features that are built into this binding ID.
   165      *
   166      * <p>
   167      * For example, {@link BindingID} for
   168      * <tt>"{@value SOAPBinding#SOAP11HTTP_MTOM_BINDING}"</tt>
   169      * would always return a list that has {@link MTOMFeature} enabled.
   170      */
   171     public WebServiceFeatureList createBuiltinFeatureList() {
   172         return new WebServiceFeatureList();
   173     }
   175     /**
   176      * Returns true if this binding can generate WSDL.
   177      *
   178      * <p>
   179      * For e.g.: SOAP 1.1 and "XSOAP 1.2" is supposed to return true
   180      * from this method. For SOAP1.2, there is no standard WSDL, so the
   181      * runtime is not generating one and it expects the WSDL is packaged.
   182      *
   183      */
   184     public boolean canGenerateWSDL() {
   185         return false;
   186     }
   188     /**
   189      * Returns a parameter of this binding ID.
   190      *
   191      * <p>
   192      * Some binding ID, such as those for SOAP/HTTP, uses the URL
   193      * query syntax (like <tt>?mtom=true</tt>) to control
   194      * the optional part of the binding. This method obtains
   195      * the value for such optional parts.
   196      *
   197      * <p>
   198      * For implementors of the derived classes, if your binding ID
   199      * does not define such optional parts (such as the XML/HTTP binding ID),
   200      * then you should simply return the specified default value
   201      * (which is what this implementation does.)
   202      *
   203      * @param parameterName
   204      *      The parameter name, such as "mtom" in the above example.
   205      * @param defaultValue
   206      *      If this binding ID doesn't have the specified parameter explicitly,
   207      *      this value will be returned.
   208      *
   209      * @return
   210      *      the value of the parameter, if it's present (such as "true"
   211      *      in the above example.) If not present, this method returns
   212      *      the {@code defaultValue}.
   213      */
   214     public String getParameter(String parameterName, String defaultValue) {
   215         return defaultValue;
   216     }
   218     /**
   219      * Compares the equality based on {@link #toString()}.
   220      */
   221     public boolean equals(Object obj) {
   222         if(!(obj instanceof BindingID))
   223             return false;
   224         return toString().equals(obj.toString());
   225     }
   227     public int hashCode() {
   228         return toString().hashCode();
   229     }
   231     /**
   232      * Parses a binding ID string into a {@link BindingID} object.
   233      *
   234      * <p>
   235      * This method first checks for a few known values and then delegate
   236      * the parsing to {@link BindingIDFactory}.
   237      *
   238      * <p>
   239      * If parsing succeeds this method returns a value. Otherwise
   240      * throws {@link WebServiceException}.
   241      *
   242      * @throws WebServiceException
   243      *      If the binding ID is not understood.
   244      */
   245     public static @NotNull BindingID parse(String lexical) {
   246         if(lexical.equals(XML_HTTP.toString()))
   247             return XML_HTTP;
   248         if(lexical.equals(REST_HTTP.toString()))
   249             return REST_HTTP;
   250         if(belongsTo(lexical,SOAP11_HTTP.toString()))
   251             return customize(lexical,SOAP11_HTTP);
   252         if(belongsTo(lexical,SOAP12_HTTP.toString()))
   253             return customize(lexical,SOAP12_HTTP);
   254         if(belongsTo(lexical,SOAPBindingImpl.X_SOAP12HTTP_BINDING))
   255             return customize(lexical,X_SOAP12_HTTP);
   257         // OK, it's none of the values JAX-WS understands.
   258         for( BindingIDFactory f : ServiceFinder.find(BindingIDFactory.class) ) {
   259             BindingID r = f.parse(lexical);
   260             if(r!=null)
   261                 return r;
   262         }
   264         // nobody understood this value
   265         throw new WebServiceException("Wrong binding ID: "+lexical);
   266     }
   268     private static boolean belongsTo(String lexical, String id) {
   269         return lexical.equals(id) || lexical.startsWith(id+'?');
   270     }
   272     /**
   273      * Parses parameter portion and returns appropriately populated {@link SOAPHTTPImpl}
   274      */
   275     private static SOAPHTTPImpl customize(String lexical, SOAPHTTPImpl base) {
   276         if(lexical.equals(base.toString()))
   277             return base;
   279         // otherwise we must have query parameter
   280         // we assume the spec won't define any tricky parameters that require
   281         // complicated handling (such as %HH or non-ASCII char), so this parser
   282         // is quite simple-minded.
   283         SOAPHTTPImpl r = new SOAPHTTPImpl(base.getSOAPVersion(), lexical, base.canGenerateWSDL());
   284         try {
   285             // With X_SOAP12_HTTP, base != lexical and lexical does n't have any query string
   286             if(lexical.indexOf('?') == -1) {
   287                 return r;
   288             }
   289             String query = URLDecoder.decode(lexical.substring(lexical.indexOf('?')+1),"UTF-8");
   290             for( String token : query.split("&") ) {
   291                 int idx = token.indexOf('=');
   292                 if(idx<0)
   293                     throw new WebServiceException("Malformed binding ID (no '=' in "+token+")");
   294                 r.parameters.put(token.substring(0,idx),token.substring(idx+1));
   295             }
   296         } catch (UnsupportedEncodingException e) {
   297             throw new AssertionError(e);    // UTF-8 is supported everywhere
   298         }
   300         return r;
   301     }
   304     /**
   305      * Figures out the binding from {@link BindingType} annotation.
   306      *
   307      * @return
   308      *      default to {@link BindingID#SOAP11_HTTP}, if no such annotation is present.
   309      * @see #parse(String)
   310      */
   311     public static @NotNull BindingID parse(Class<?> implClass) {
   312         BindingType bindingType = implClass.getAnnotation(BindingType.class);
   313         if (bindingType != null) {
   314             String bindingId = bindingType.value();
   315             if (bindingId.length() > 0) {
   316                 return BindingID.parse(bindingId);
   317             }
   318         }
   319         return SOAP11_HTTP;
   320     }
   322     /**
   323      * Constant that represents implementation specific SOAP1.2/HTTP which is
   324      * used to generate non-standard WSDLs
   325      */
   326     public static final SOAPHTTPImpl X_SOAP12_HTTP = new SOAPHTTPImpl(
   327         SOAPVersion.SOAP_12, SOAPBindingImpl.X_SOAP12HTTP_BINDING, true);
   329     /**
   330      * Constant that represents SOAP1.2/HTTP.
   331      */
   332     public static final SOAPHTTPImpl SOAP12_HTTP = new SOAPHTTPImpl(
   333         SOAPVersion.SOAP_12, SOAPBinding.SOAP12HTTP_BINDING, true);
   334     /**
   335      * Constant that represents SOAP1.1/HTTP.
   336      */
   337     public static final SOAPHTTPImpl SOAP11_HTTP = new SOAPHTTPImpl(
   338         SOAPVersion.SOAP_11, SOAPBinding.SOAP11HTTP_BINDING, true);
   340     /**
   341      * Constant that represents SOAP1.2/HTTP.
   342      */
   343     public static final SOAPHTTPImpl SOAP12_HTTP_MTOM = new SOAPHTTPImpl(
   344         SOAPVersion.SOAP_12, SOAPBinding.SOAP12HTTP_MTOM_BINDING, true, true);
   345     /**
   346      * Constant that represents SOAP1.1/HTTP.
   347      */
   348     public static final SOAPHTTPImpl SOAP11_HTTP_MTOM = new SOAPHTTPImpl(
   349         SOAPVersion.SOAP_11, SOAPBinding.SOAP11HTTP_MTOM_BINDING, true, true);
   352     /**
   353      * Constant that represents REST.
   354      */
   355     public static final BindingID XML_HTTP = new Impl(SOAPVersion.SOAP_11, HTTPBinding.HTTP_BINDING,false) {
   356         public Codec createEncoder(WSBinding binding) {
   357             return new XMLHTTPBindingCodec(binding.getFeatures());
   358         }
   359     };
   361     /**
   362      * Constant that represents REST.
   363      */
   364     private static final BindingID REST_HTTP = new Impl(SOAPVersion.SOAP_11, JAXWSProperties.REST_BINDING,true) {
   365         public Codec createEncoder(WSBinding binding) {
   366             return new XMLHTTPBindingCodec(binding.getFeatures());
   367         }
   368     };
   370     private static abstract class Impl extends BindingID {
   371         final SOAPVersion version;
   372         private final String lexical;
   373         private final boolean canGenerateWSDL;
   375         public Impl(SOAPVersion version, String lexical, boolean canGenerateWSDL) {
   376             this.version = version;
   377             this.lexical = lexical;
   378             this.canGenerateWSDL = canGenerateWSDL;
   379         }
   381         public SOAPVersion getSOAPVersion() {
   382             return version;
   383         }
   385         public String toString() {
   386             return lexical;
   387         }
   389         @Deprecated
   390         public boolean canGenerateWSDL() {
   391             return canGenerateWSDL;
   392         }
   393     }
   395     /**
   396      * Internal implementation for SOAP/HTTP.
   397      */
   398     private static final class SOAPHTTPImpl extends Impl implements Cloneable {
   399         /*final*/ Map<String,String> parameters = new HashMap<String,String>();
   401         static final String MTOM_PARAM = "mtom";
   402         Boolean mtomSetting = null;
   404         public SOAPHTTPImpl(SOAPVersion version, String lexical, boolean canGenerateWSDL) {
   405             super(version, lexical, canGenerateWSDL);
   406         }
   408         public SOAPHTTPImpl(SOAPVersion version, String lexical, boolean canGenerateWSDL,
   409                            boolean mtomEnabled) {
   410             this(version, lexical, canGenerateWSDL);
   411             String mtomStr = mtomEnabled ? "true" : "false";
   412             parameters.put(MTOM_PARAM, mtomStr);
   413             mtomSetting = mtomEnabled;
   414         }
   416         public @NotNull Codec createEncoder(WSBinding binding) {
   417             return new SOAPBindingCodec(binding.getFeatures());
   418         }
   420         private Boolean isMTOMEnabled() {
   421             String mtom = parameters.get(MTOM_PARAM);
   422             return mtom==null?null:Boolean.valueOf(mtom);
   423         }
   425         public WebServiceFeatureList createBuiltinFeatureList() {
   426             WebServiceFeatureList r=super.createBuiltinFeatureList();
   427             Boolean mtom = isMTOMEnabled();
   428             if(mtom != null)
   429                 r.add(new MTOMFeature(mtom));
   430             return r;
   431         }
   433         public String getParameter(String parameterName, String defaultValue) {
   434             if (parameters.get(parameterName) == null)
   435                 return super.getParameter(parameterName, defaultValue);
   436             return parameters.get(parameterName);
   437         }
   438     }
   439 }

mercurial