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
26package com.sun.xml.internal.ws.api.pipe;
27
28import com.sun.istack.internal.Nullable;
29import com.sun.xml.internal.ws.api.WSBinding;
30import com.sun.xml.internal.ws.api.WSService;
31import com.sun.xml.internal.ws.api.client.WSPortInfo;
32import com.sun.xml.internal.ws.api.addressing.WSEndpointReference;
33import com.sun.xml.internal.ws.api.message.Message;
34import com.sun.xml.internal.ws.api.message.Packet;
35import com.sun.xml.internal.ws.api.model.SEIModel;
36import com.sun.xml.internal.ws.binding.BindingImpl;
37import com.sun.xml.internal.ws.client.WSServiceDelegate;
38import com.sun.xml.internal.ws.client.dispatch.DataSourceDispatch;
39import com.sun.xml.internal.ws.client.dispatch.DispatchImpl;
40import com.sun.xml.internal.ws.client.dispatch.JAXBDispatch;
41import com.sun.xml.internal.ws.client.dispatch.MessageDispatch;
42import com.sun.xml.internal.ws.client.dispatch.PacketDispatch;
43import com.sun.xml.internal.ws.client.sei.SEIStub;
44import com.sun.xml.internal.ws.developer.WSBindingProvider;
45import com.sun.xml.internal.ws.model.SOAPSEIModel;
46
47import javax.activation.DataSource;
48import javax.xml.bind.JAXBContext;
49import javax.xml.namespace.QName;
50import javax.xml.soap.SOAPMessage;
51import javax.xml.transform.Source;
52import javax.xml.ws.BindingProvider;
53import javax.xml.ws.Dispatch;
54import javax.xml.ws.Service;
55import javax.xml.ws.Service.Mode;
56import javax.xml.ws.WebServiceException;
57import 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 */
107public 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}
451