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

Thu, 31 Aug 2017 15:18:52 +0800

author
aoqi
date
Thu, 31 Aug 2017 15:18:52 +0800
changeset 637
9c07ef4934dd
parent 368
0989ad8c0860
parent 0
373ffda63c9a
permissions
-rw-r--r--

merge

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

mercurial