1 /*
   2  * Copyright (c) 1997, 2013, 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.pipe;
  27 
  28 import com.sun.istack.internal.Nullable;
  29 import com.sun.xml.internal.ws.api.WSBinding;
  30 import com.sun.xml.internal.ws.api.WSService;
  31 import com.sun.xml.internal.ws.api.client.WSPortInfo;
  32 import com.sun.xml.internal.ws.api.addressing.WSEndpointReference;
  33 import com.sun.xml.internal.ws.api.message.Message;
  34 import com.sun.xml.internal.ws.api.message.Packet;
  35 import com.sun.xml.internal.ws.api.model.SEIModel;
  36 import com.sun.xml.internal.ws.binding.BindingImpl;
  37 import com.sun.xml.internal.ws.client.WSServiceDelegate;
  38 import com.sun.xml.internal.ws.client.dispatch.DataSourceDispatch;
  39 import com.sun.xml.internal.ws.client.dispatch.DispatchImpl;
  40 import com.sun.xml.internal.ws.client.dispatch.JAXBDispatch;
  41 import com.sun.xml.internal.ws.client.dispatch.MessageDispatch;
  42 import com.sun.xml.internal.ws.client.dispatch.PacketDispatch;
  43 import com.sun.xml.internal.ws.client.sei.SEIStub;
  44 import com.sun.xml.internal.ws.developer.WSBindingProvider;
  45 import com.sun.xml.internal.ws.model.SOAPSEIModel;
  46 
  47 import javax.activation.DataSource;
  48 import javax.xml.bind.JAXBContext;
  49 import javax.xml.namespace.QName;
  50 import javax.xml.soap.SOAPMessage;
  51 import javax.xml.transform.Source;
  52 import javax.xml.ws.BindingProvider;
  53 import javax.xml.ws.Dispatch;
  54 import javax.xml.ws.Service;
  55 import javax.xml.ws.Service.Mode;
  56 import javax.xml.ws.WebServiceException;
  57 import java.lang.reflect.Proxy;
  58 
  59 /**
  60  * Factory methods of various stubs.
  61  *
  62  * <p>
  63  * This class provides various methods to create "stub"s,
  64  * which are the component that turns a method invocation
  65  * into a {@link Message} and back into a return value.
  66  *
  67  * <p>
  68  * This class is meant to serve as the API from JAX-WS to
  69  * Tango, so that they don't have hard-code dependency on
  70  * our implementation classes.
  71  *
  72  * <a name="param"></a>
  73  * <h2>Common Parameters and Their Meanings</h2>
  74  *
  75  * <h3>Pipe next</h3>
  76  * <p>
  77  * Stubs turn a method invocation into a {@link Pipe#process(com.sun.xml.internal.ws.api.message.Packet)} invocation,
  78  * and this pipe passed in as the {@code next} parameter will receive a {@link Message}
  79  * from newly created stub. All the methods taking Tube <<next>> parameter are deprecated. JAX-WS Runtime takes care of
  80  * creating the tubeline when the {@code next} parameter is not passed. This gives flexibility for the JAX-WS Runtime
  81  * to pass extra information during the tube line creation via {@link ClientTubeAssemblerContext}.
  82  *
  83  * <h3>WSPortInfo portInfo</h3>
  84  * <p> Gives information about the port for which the "stub" being created. Such information includes Port QName,
  85  * target endpoint address, and bindingId etc.
  86  *
  87  * <h3>BindingImpl binding</h3>
  88  * <p>
  89  * Stubs implement {@link BindingProvider}, and its {@link BindingProvider#getBinding()}
  90  * will return this {@code binding} object. Stubs often also use this information
  91  * to decide which SOAP version a {@link Message} should be created in.
  92  *
  93  * <h3>{@link WSService} service</h3>
  94  * <p>
  95  * This object represents a {@link Service} that owns the newly created stub.
  96  * For example, asynchronous method invocation will use {@link Service#getExecutor()}.
  97  *
  98  * <h3>{@link WSEndpointReference} epr</h3>
  99  * <p>
 100  * If you want the created {@link Dispatch} to talk to the given EPR, specify the parameter.
 101  * Otherwise leave it {@code null}. Note that the addressing needs to be enabled separately
 102  * for this to take effect.
 103  *
 104  * @author Kohsuke Kawaguchi
 105  * @author Kathy Walsh
 106  */
 107 public abstract class Stubs {
 108     private Stubs() {}   // no instanciation please
 109 
 110     /**
 111      * Creates a new {@link Dispatch} stub for {@link SOAPMessage}.
 112      *
 113      * This is short-cut of calling
 114      * <pre>
 115      * createDispatch(port,owner,binding,SOAPMessage.class,mode,next);
 116      * </pre>
 117      */
 118     @Deprecated
 119     public static Dispatch<SOAPMessage> createSAAJDispatch(QName portName, WSService owner, WSBinding binding, Service.Mode mode, Tube next, @Nullable WSEndpointReference epr) {
 120         DispatchImpl.checkValidSOAPMessageDispatch(binding, mode);
 121         return new com.sun.xml.internal.ws.client.dispatch.SOAPMessageDispatch(portName, mode, (WSServiceDelegate)owner, next, (BindingImpl)binding, epr);
 122     }
 123 
 124     /**
 125      * Creates a new {@link Dispatch} stub for {@link SOAPMessage}.
 126      *
 127      * This is short-cut of calling
 128      * <pre>
 129      * createDispatch(port,owner,binding,SOAPMessage.class,mode,next);
 130      * </pre>
 131      */
 132     public static Dispatch<SOAPMessage> createSAAJDispatch(WSPortInfo portInfo, WSBinding binding, Service.Mode mode, @Nullable WSEndpointReference epr) {
 133         DispatchImpl.checkValidSOAPMessageDispatch(binding, mode);
 134         return new com.sun.xml.internal.ws.client.dispatch.SOAPMessageDispatch(portInfo, mode, (BindingImpl)binding, epr);
 135     }
 136 
 137     /**
 138      * Creates a new {@link Dispatch} stub for {@link DataSource}.
 139      *
 140      * This is short-cut of calling
 141      * <pre>
 142      * createDispatch(port,owner,binding,DataSource.class,mode,next);
 143      * </pre>
 144      */
 145     @Deprecated
 146     public static Dispatch<DataSource> createDataSourceDispatch(QName portName, WSService owner, WSBinding binding, Service.Mode mode, Tube next, @Nullable WSEndpointReference epr) {
 147         DispatchImpl.checkValidDataSourceDispatch(binding, mode);
 148         return new DataSourceDispatch(portName, mode, (WSServiceDelegate)owner, next, (BindingImpl)binding, epr);
 149     }
 150 
 151     /**
 152      * Creates a new {@link Dispatch} stub for {@link DataSource}.
 153      *
 154      * This is short-cut of calling
 155      * <pre>
 156      * createDispatch(port,owner,binding,DataSource.class,mode,next);
 157      * </pre>
 158      */
 159     public static Dispatch<DataSource> createDataSourceDispatch(WSPortInfo portInfo, WSBinding binding, Service.Mode mode,@Nullable WSEndpointReference epr) {
 160         DispatchImpl.checkValidDataSourceDispatch(binding, mode);
 161         return new DataSourceDispatch(portInfo, mode, (BindingImpl)binding, epr);
 162     }
 163 
 164     /**
 165      * Creates a new {@link Dispatch} stub for {@link Source}.
 166      *
 167      * This is short-cut of calling
 168      * <pre>
 169      * createDispatch(port,owner,binding,Source.class,mode,next);
 170      * </pre>
 171      */
 172     @Deprecated
 173     public static Dispatch<Source> createSourceDispatch(QName portName, WSService owner, WSBinding binding, Service.Mode mode, Tube next, @Nullable WSEndpointReference epr) {
 174         return DispatchImpl.createSourceDispatch(portName, mode, (WSServiceDelegate)owner, next, (BindingImpl)binding, epr);
 175     }
 176 
 177     /**
 178      * Creates a new {@link Dispatch} stub for {@link Source}.
 179      *
 180      * This is short-cut of calling
 181      * <pre>
 182      * createDispatch(port,owner,binding,Source.class,mode,next);
 183      * </pre>
 184      */
 185     public static Dispatch<Source> createSourceDispatch(WSPortInfo portInfo, WSBinding binding, Service.Mode mode, @Nullable WSEndpointReference epr) {
 186         return DispatchImpl.createSourceDispatch(portInfo, mode, (BindingImpl)binding, epr);
 187     }
 188 
 189     /**
 190      * Creates a new {@link Dispatch} stub that connects to the given pipe.
 191      *
 192      * @param portName
 193      *      see {@link Service#createDispatch(QName, Class, Service.Mode)}.
 194      * @param owner
 195      *      see <a href="#param">common parameters</a>
 196      * @param binding
 197      *      see <a href="#param">common parameters</a>
 198      * @param clazz
 199      *      Type of the {@link Dispatch} to be created.
 200      *      See {@link Service#createDispatch(QName, Class, Service.Mode)}.
 201      * @param mode
 202      *      The mode of the dispatch.
 203      *      See {@link Service#createDispatch(QName, Class, Service.Mode)}.
 204      * @param next
 205      *      see <a href="#param">common parameters</a>
 206      * @param epr
 207      *      see <a href="#param">common parameters</a>
 208      * TODO: are these parameters making sense?
 209      */
 210     @SuppressWarnings("unchecked")
 211         public static <T> Dispatch<T> createDispatch(QName portName,
 212                                                  WSService owner,
 213                                                  WSBinding binding,
 214                                                  Class<T> clazz, Service.Mode mode, Tube next,
 215                                                  @Nullable WSEndpointReference epr) {
 216         if (clazz == SOAPMessage.class) {
 217             return (Dispatch<T>) createSAAJDispatch(portName, owner, binding, mode, next, epr);
 218         } else if (clazz == Source.class) {
 219             return (Dispatch<T>) createSourceDispatch(portName, owner, binding, mode, next, epr);
 220         } else if (clazz == DataSource.class) {
 221             return (Dispatch<T>) createDataSourceDispatch(portName, owner, binding, mode, next, epr);
 222         } else if (clazz == Message.class) {
 223             if(mode==Mode.MESSAGE)
 224                 return (Dispatch<T>) createMessageDispatch(portName, owner, binding, next, epr);
 225             else
 226                 throw new WebServiceException(mode+" not supported with Dispatch<Message>");
 227         } else if (clazz == Packet.class) {
 228             return (Dispatch<T>) createPacketDispatch(portName, owner, binding, next, epr);
 229         } else
 230             throw new WebServiceException("Unknown class type " + clazz.getName());
 231     }
 232 
 233     /**
 234      * Creates a new {@link Dispatch} stub that connects to the given pipe.
 235      *
 236      * @param portInfo
 237      *      see <a href="#param">common parameters</a>
 238      * @param owner
 239      *      see <a href="#param">common parameters</a>
 240      * @param binding
 241      *      see <a href="#param">common parameters</a>
 242      * @param clazz
 243      *      Type of the {@link Dispatch} to be created.
 244      *      See {@link Service#createDispatch(QName, Class, Service.Mode)}.
 245      * @param mode
 246      *      The mode of the dispatch.
 247      *      See {@link Service#createDispatch(QName, Class, Service.Mode)}.
 248      * @param epr
 249      *      see <a href="#param">common parameters</a>
 250      * TODO: are these parameters making sense?
 251      */
 252     public static <T> Dispatch<T> createDispatch(WSPortInfo portInfo,
 253                                                  WSService owner,
 254                                                  WSBinding binding,
 255                                                  Class<T> clazz, Service.Mode mode,
 256                                                  @Nullable WSEndpointReference epr) {
 257         if (clazz == SOAPMessage.class) {
 258             return (Dispatch<T>) createSAAJDispatch(portInfo, binding, mode, epr);
 259         } else if (clazz == Source.class) {
 260             return (Dispatch<T>) createSourceDispatch(portInfo, binding, mode, epr);
 261         } else if (clazz == DataSource.class) {
 262             return (Dispatch<T>) createDataSourceDispatch(portInfo, binding, mode, epr);
 263         } else if (clazz == Message.class) {
 264             if(mode==Mode.MESSAGE)
 265                 return (Dispatch<T>) createMessageDispatch(portInfo, binding, epr);
 266             else
 267                 throw new WebServiceException(mode+" not supported with Dispatch<Message>");
 268         } else if (clazz == Packet.class) {
 269             if(mode==Mode.MESSAGE)
 270                 return (Dispatch<T>) createPacketDispatch(portInfo, binding, epr);
 271             else
 272                 throw new WebServiceException(mode+" not supported with Dispatch<Packet>");
 273         } else
 274             throw new WebServiceException("Unknown class type " + clazz.getName());
 275     }
 276 
 277     /**
 278      * Creates a new JAXB-based {@link Dispatch} stub that connects to the given pipe.
 279      *
 280      * @param portName
 281      *      see {@link Service#createDispatch(QName, Class, Service.Mode)}.
 282      * @param owner
 283      *      see <a href="#param">common parameters</a>
 284      * @param binding
 285      *      see <a href="#param">common parameters</a>
 286      * @param jaxbContext
 287      *      {@link JAXBContext} used to convert between objects and XML.
 288      * @param mode
 289      *      The mode of the dispatch.
 290      *      See {@link Service#createDispatch(QName, Class, Service.Mode)}.
 291      * @param next
 292      *      see <a href="#param">common parameters</a>
 293      * @param epr
 294      *      see <a href="#param">common parameters</a>
 295      */
 296     @Deprecated
 297     public static Dispatch<Object> createJAXBDispatch(
 298                                            QName portName, WSService owner, WSBinding binding,
 299                                            JAXBContext jaxbContext, Service.Mode mode, Tube next,
 300                                            @Nullable WSEndpointReference epr) {
 301         return new JAXBDispatch(portName, jaxbContext, mode, (WSServiceDelegate)owner, next, (BindingImpl)binding, epr);
 302     }
 303 
 304     /**
 305      * Creates a new JAXB-based {@link Dispatch} stub that connects to the given pipe.
 306      *
 307      * @param portInfo    see <a href="#param">common parameters</a>
 308      * @param binding     see <a href="#param">common parameters</a>
 309      * @param jaxbContext {@link JAXBContext} used to convert between objects and XML.
 310      * @param mode        The mode of the dispatch.
 311      *                    See {@link Service#createDispatch(QName, Class, Service.Mode)}.
 312      * @param epr         see <a href="#param">common parameters</a>
 313      */
 314     public static Dispatch<Object> createJAXBDispatch(
 315             WSPortInfo portInfo, WSBinding binding,
 316             JAXBContext jaxbContext, Service.Mode mode,
 317             @Nullable WSEndpointReference epr) {
 318         return new JAXBDispatch(portInfo, jaxbContext, mode, (BindingImpl) binding, epr);
 319     }
 320 
 321 
 322     /**
 323      * Creates a new {@link Message}-based {@link Dispatch} stub that connects to the given pipe.
 324      * The returned dispatch is always {@link Mode#MESSAGE}.
 325      *
 326      * @param portName
 327      *      see {@link Service#createDispatch(QName, Class, Service.Mode)}.
 328      * @param owner
 329      *      see <a href="#param">common parameters</a>
 330      * @param binding
 331      *      see <a href="#param">common parameters</a>
 332      * @param next
 333      *      see <a href="#param">common parameters</a>
 334      * @param epr
 335      *      see <a href="#param">common parameters</a>
 336      */
 337     @Deprecated
 338     public static Dispatch<Message> createMessageDispatch(
 339                                            QName portName, WSService owner, WSBinding binding,
 340                                            Tube next, @Nullable WSEndpointReference epr) {
 341         return new MessageDispatch(portName, (WSServiceDelegate)owner, next, (BindingImpl)binding, epr);
 342     }
 343 
 344 
 345     /**
 346      * Creates a new {@link Message}-based {@link Dispatch} stub that connects to the given pipe.
 347      * The returned dispatch is always {@link Mode#MESSAGE}.
 348      *
 349      * @param portInfo
 350      *      see <a href="#param">common parameters</a>
 351      * @param binding
 352      *      see <a href="#param">common parameters</a>
 353      * @param epr
 354      *      see <a href="#param">common parameters</a>
 355      */
 356     public static Dispatch<Message> createMessageDispatch(
 357                                            WSPortInfo portInfo, WSBinding binding,
 358                                            @Nullable WSEndpointReference epr) {
 359         return new MessageDispatch(portInfo, (BindingImpl)binding, epr);
 360     }
 361 
 362     /**
 363      * Creates a new {@link Packet}-based {@link Dispatch} stub that connects to the given pipe.
 364      *
 365      * @param portName
 366      *      see {@link Service#createDispatch(QName, Class, Service.Mode)}.
 367      * @param owner
 368      *      see <a href="#param">common parameters</a>
 369      * @param binding
 370      *      see <a href="#param">common parameters</a>
 371      * @param next
 372      *      see <a href="#param">common parameters</a>
 373      * @param epr
 374      *      see <a href="#param">common parameters</a>
 375      */
 376     public static Dispatch<Packet> createPacketDispatch(
 377                                            QName portName, WSService owner, WSBinding binding,
 378                                            Tube next, @Nullable WSEndpointReference epr) {
 379         return new PacketDispatch(portName, (WSServiceDelegate)owner, next, (BindingImpl)binding, epr);
 380     }
 381 
 382     /**
 383      * Creates a new {@link Message}-based {@link Dispatch} stub that connects to the given pipe.
 384      * The returned dispatch is always {@link Mode#MESSAGE}.
 385      *
 386      * @param portInfo
 387      *      see <a href="#param">common parameters</a>
 388      * @param binding
 389      *      see <a href="#param">common parameters</a>
 390      * @param epr
 391      *      see <a href="#param">common parameters</a>
 392      */
 393     public static Dispatch<Packet> createPacketDispatch(
 394                                            WSPortInfo portInfo, WSBinding binding,
 395                                            @Nullable WSEndpointReference epr) {
 396         return new PacketDispatch(portInfo, (BindingImpl)binding, epr);
 397     }
 398 
 399     /**
 400      * Creates a new strongly-typed proxy object that implements a given port interface.
 401      *
 402      * @param service
 403      *      see <a href="#param">common parameters</a>
 404      * @param binding
 405      *      see <a href="#param">common parameters</a>
 406      * @param model
 407      *      This model shall represent a port interface.
 408      *      TODO: can model be constructed from portInterface and binding?
 409      *      Find out and update.
 410      * @param portInterface
 411      *      The port interface that has operations as Java methods.
 412      * @param next
 413      *      see <a href="#param">common parameters</a>
 414      * @param epr
 415      *      see <a href="#param">common parameters</a>
 416      */
 417     public <T> T createPortProxy( WSService service, WSBinding binding, SEIModel model,
 418                                   Class<T> portInterface, Tube next, @Nullable WSEndpointReference epr ) {
 419 
 420         SEIStub ps = new SEIStub((WSServiceDelegate)service,(BindingImpl)binding, (SOAPSEIModel)model, next, epr);
 421         return portInterface.cast(
 422             Proxy.newProxyInstance( portInterface.getClassLoader(),
 423                 new Class[]{portInterface, WSBindingProvider.class}, ps ));
 424     }
 425 
 426      /**
 427      * Creates a new strongly-typed proxy object that implements a given port interface.
 428      *
 429      * @param portInfo
 430      *      see <a href="#param">common parameters</a>
 431      * @param binding
 432      *      see <a href="#param">common parameters</a>
 433      * @param model
 434      *      This model shall represent a port interface.
 435      *      TODO: can model be constructed from portInterface and binding?
 436      *      Find out and update.
 437      * @param portInterface
 438      *      The port interface that has operations as Java methods.
 439      * @param epr
 440      *      see <a href="#param">common parameters</a>
 441      */
 442     public <T> T createPortProxy( WSPortInfo portInfo, WSBinding binding, SEIModel model,
 443                                   Class<T> portInterface, @Nullable WSEndpointReference epr ) {
 444 
 445         SEIStub ps = new SEIStub(portInfo, (BindingImpl)binding, (SOAPSEIModel)model, epr);
 446         return portInterface.cast(
 447             Proxy.newProxyInstance( portInterface.getClassLoader(),
 448                 new Class[]{portInterface, WSBindingProvider.class}, ps ));
 449     }
 450 }