|
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.client; |
|
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.WSEPRExtension; |
|
32 import com.sun.xml.internal.ws.api.BindingID; |
|
33 import com.sun.xml.internal.ws.model.wsdl.WSDLDirectProperties; |
|
34 import com.sun.xml.internal.ws.model.wsdl.WSDLPortProperties; |
|
35 import com.sun.xml.internal.ws.model.wsdl.WSDLProperties; |
|
36 import com.sun.xml.internal.ws.model.wsdl.WSDLServiceImpl; |
|
37 import com.sun.xml.internal.ws.api.Component; |
|
38 import com.sun.xml.internal.ws.api.ComponentFeature; |
|
39 import com.sun.xml.internal.ws.api.ComponentFeature.Target; |
|
40 import com.sun.xml.internal.ws.api.ComponentRegistry; |
|
41 import com.sun.xml.internal.ws.api.EndpointAddress; |
|
42 import com.sun.xml.internal.ws.api.WSBinding; |
|
43 import com.sun.xml.internal.ws.api.WSService; |
|
44 import com.sun.xml.internal.ws.api.addressing.AddressingVersion; |
|
45 import com.sun.xml.internal.ws.api.addressing.WSEndpointReference; |
|
46 import com.sun.xml.internal.ws.api.client.WSPortInfo; |
|
47 import com.sun.xml.internal.ws.api.message.Header; |
|
48 import com.sun.xml.internal.ws.api.message.HeaderList; |
|
49 import com.sun.xml.internal.ws.api.message.Packet; |
|
50 import com.sun.xml.internal.ws.api.model.SEIModel; |
|
51 import com.sun.xml.internal.ws.api.model.wsdl.WSDLPort; |
|
52 import com.sun.xml.internal.ws.api.pipe.*; |
|
53 import com.sun.xml.internal.ws.binding.BindingImpl; |
|
54 import com.sun.xml.internal.ws.developer.JAXWSProperties; |
|
55 import com.sun.xml.internal.ws.developer.WSBindingProvider; |
|
56 import com.sun.xml.internal.ws.model.wsdl.WSDLPortImpl; |
|
57 import com.sun.xml.internal.ws.resources.ClientMessages; |
|
58 import com.sun.xml.internal.ws.util.Pool; |
|
59 import com.sun.xml.internal.ws.util.Pool.TubePool; |
|
60 import com.sun.xml.internal.ws.util.RuntimeVersion; |
|
61 import com.sun.xml.internal.ws.wsdl.OperationDispatcher; |
|
62 import com.sun.org.glassfish.gmbal.ManagedObjectManager; |
|
63 |
|
64 import javax.xml.namespace.QName; |
|
65 import javax.xml.stream.XMLStreamException; |
|
66 import javax.xml.ws.BindingProvider; |
|
67 import javax.xml.ws.EndpointReference; |
|
68 import javax.xml.ws.RespectBindingFeature; |
|
69 import javax.xml.ws.WebServiceException; |
|
70 import javax.xml.ws.http.HTTPBinding; |
|
71 import javax.xml.ws.wsaddressing.W3CEndpointReference; |
|
72 import java.util.ArrayList; |
|
73 import java.util.Collections; |
|
74 import java.util.List; |
|
75 import java.util.Map; |
|
76 import java.util.Set; |
|
77 import java.util.concurrent.CopyOnWriteArraySet; |
|
78 import java.util.concurrent.Executor; |
|
79 import org.xml.sax.InputSource; |
|
80 |
|
81 /** |
|
82 * Base class for stubs, which accept method invocations from |
|
83 * client applications and pass the message to a {@link Tube} |
|
84 * for processing. |
|
85 * |
|
86 * <p> |
|
87 * This class implements the management of pipe instances, |
|
88 * and most of the {@link BindingProvider} methods. |
|
89 * |
|
90 * @author Kohsuke Kawaguchi |
|
91 */ |
|
92 public abstract class Stub implements WSBindingProvider, ResponseContextReceiver, ComponentRegistry { |
|
93 /** |
|
94 * Internal flag indicating async dispatch should be used even when the |
|
95 * SyncStartForAsyncInvokeFeature is present on the binding associated |
|
96 * with a stub. There is no type associated with this property on the |
|
97 * request context. Its presence is what triggers the 'prevent' behavior. |
|
98 */ |
|
99 public static final String PREVENT_SYNC_START_FOR_ASYNC_INVOKE = "com.sun.xml.internal.ws.client.StubRequestSyncStartForAsyncInvoke"; |
|
100 |
|
101 /** |
|
102 * Reuse pipelines as it's expensive to create. |
|
103 * <p> |
|
104 * Set to null when {@link #close() closed}. |
|
105 */ |
|
106 private Pool<Tube> tubes; |
|
107 |
|
108 private final Engine engine; |
|
109 |
|
110 /** |
|
111 * The {@link WSServiceDelegate} object that owns us. |
|
112 */ |
|
113 protected final WSServiceDelegate owner; |
|
114 |
|
115 /** |
|
116 * Non-null if this stub is configured to talk to an EPR. |
|
117 * <p> |
|
118 * When this field is non-null, its reference parameters are sent as out-bound headers. |
|
119 * This field can be null even when addressing is enabled, but if the addressing is |
|
120 * not enabled, this field must be null. |
|
121 * <p> |
|
122 * Unlike endpoint address, we are not letting users to change the EPR, |
|
123 * as it contains references to services and so on that we don't want to change. |
|
124 */ |
|
125 protected |
|
126 @Nullable |
|
127 WSEndpointReference endpointReference; |
|
128 |
|
129 protected final BindingImpl binding; |
|
130 |
|
131 protected final WSPortInfo portInfo; |
|
132 |
|
133 /** |
|
134 * represents AddressingVersion on binding if enabled, otherwise null; |
|
135 */ |
|
136 protected AddressingVersion addrVersion; |
|
137 |
|
138 public RequestContext requestContext = new RequestContext(); |
|
139 |
|
140 private final RequestContext cleanRequestContext; |
|
141 |
|
142 /** |
|
143 * {@link ResponseContext} from the last synchronous operation. |
|
144 */ |
|
145 private ResponseContext responseContext; |
|
146 @Nullable |
|
147 protected final WSDLPort wsdlPort; |
|
148 |
|
149 protected QName portname; |
|
150 |
|
151 /** |
|
152 * {@link Header}s to be added to outbound {@link Packet}. |
|
153 * The contents is determined by the user. |
|
154 */ |
|
155 @Nullable |
|
156 private volatile Header[] userOutboundHeaders; |
|
157 |
|
158 private final |
|
159 @NotNull |
|
160 WSDLProperties wsdlProperties; |
|
161 protected OperationDispatcher operationDispatcher = null; |
|
162 private final |
|
163 @NotNull |
|
164 ManagedObjectManager managedObjectManager; |
|
165 private boolean managedObjectManagerClosed = false; |
|
166 |
|
167 private final Set<Component> components = new CopyOnWriteArraySet<Component>(); |
|
168 |
|
169 /** |
|
170 * @param master The created stub will send messages to this pipe. |
|
171 * @param binding As a {@link BindingProvider}, this object will |
|
172 * return this binding from {@link BindingProvider#getBinding()}. |
|
173 * @param defaultEndPointAddress The destination of the message. The actual destination |
|
174 * could be overridden by {@link RequestContext}. |
|
175 * @param epr To create a stub that sends out reference parameters |
|
176 * of a specific EPR, give that instance. Otherwise null. |
|
177 * Its address field will not be used, and that should be given |
|
178 * separately as the <tt>defaultEndPointAddress</tt>. |
|
179 */ |
|
180 @Deprecated |
|
181 protected Stub(WSServiceDelegate owner, Tube master, BindingImpl binding, WSDLPort wsdlPort, EndpointAddress defaultEndPointAddress, @Nullable WSEndpointReference epr) { |
|
182 this(owner, master, null, null, binding, wsdlPort, defaultEndPointAddress, epr); |
|
183 } |
|
184 |
|
185 /** |
|
186 * @param portname The name of this port |
|
187 * @param master The created stub will send messages to this pipe. |
|
188 * @param binding As a {@link BindingProvider}, this object will |
|
189 * return this binding from {@link BindingProvider#getBinding()}. |
|
190 * @param defaultEndPointAddress The destination of the message. The actual destination |
|
191 * could be overridden by {@link RequestContext}. |
|
192 * @param epr To create a stub that sends out reference parameters |
|
193 * of a specific EPR, give that instance. Otherwise null. |
|
194 * Its address field will not be used, and that should be given |
|
195 * separately as the <tt>defaultEndPointAddress</tt>. |
|
196 */ |
|
197 @Deprecated |
|
198 protected Stub(QName portname, WSServiceDelegate owner, Tube master, BindingImpl binding, WSDLPort wsdlPort, EndpointAddress defaultEndPointAddress, @Nullable WSEndpointReference epr) { |
|
199 this(owner, master, null, portname, binding, wsdlPort, defaultEndPointAddress, epr); |
|
200 } |
|
201 |
|
202 /** |
|
203 * @param portInfo PortInfo for this stub |
|
204 * @param binding As a {@link BindingProvider}, this object will |
|
205 * return this binding from {@link BindingProvider#getBinding()}. |
|
206 * @param master The created stub will send messages to this pipe. |
|
207 * @param defaultEndPointAddress The destination of the message. The actual destination |
|
208 * could be overridden by {@link RequestContext}. |
|
209 * @param epr To create a stub that sends out reference parameters |
|
210 * of a specific EPR, give that instance. Otherwise null. |
|
211 * Its address field will not be used, and that should be given |
|
212 * separately as the <tt>defaultEndPointAddress</tt>. |
|
213 */ |
|
214 protected Stub(WSPortInfo portInfo, BindingImpl binding, Tube master,EndpointAddress defaultEndPointAddress, @Nullable WSEndpointReference epr) { |
|
215 this((WSServiceDelegate) portInfo.getOwner(), master, portInfo, null, binding,portInfo.getPort(), defaultEndPointAddress, epr); |
|
216 } |
|
217 |
|
218 /** |
|
219 * @param portInfo PortInfo for this stub |
|
220 * @param binding As a {@link BindingProvider}, this object will |
|
221 * return this binding from {@link BindingProvider#getBinding()}. |
|
222 * @param defaultEndPointAddress The destination of the message. The actual destination |
|
223 * could be overridden by {@link RequestContext}. |
|
224 * @param epr To create a stub that sends out reference parameters |
|
225 * of a specific EPR, give that instance. Otherwise null. |
|
226 * Its address field will not be used, and that should be given |
|
227 * separately as the <tt>defaultEndPointAddress</tt>. |
|
228 */ |
|
229 protected Stub(WSPortInfo portInfo, BindingImpl binding, EndpointAddress defaultEndPointAddress, @Nullable WSEndpointReference epr) { |
|
230 this(portInfo,binding,null, defaultEndPointAddress,epr); |
|
231 |
|
232 } |
|
233 |
|
234 private Stub(WSServiceDelegate owner, @Nullable Tube master, @Nullable WSPortInfo portInfo, QName portname, BindingImpl binding, @Nullable WSDLPort wsdlPort, EndpointAddress defaultEndPointAddress, @Nullable WSEndpointReference epr) { |
|
235 this.owner = owner; |
|
236 this.portInfo = portInfo; |
|
237 this.wsdlPort = wsdlPort != null ? wsdlPort : (portInfo != null ? portInfo.getPort() : null); |
|
238 this.portname = portname; |
|
239 if (portname == null) { |
|
240 if (portInfo != null) |
|
241 this.portname = portInfo.getPortName(); |
|
242 else if (wsdlPort != null) |
|
243 this.portname = wsdlPort.getName(); |
|
244 } |
|
245 this.binding = binding; |
|
246 |
|
247 ComponentFeature cf = binding.getFeature(ComponentFeature.class); |
|
248 if (cf != null && Target.STUB.equals(cf.getTarget())) { |
|
249 components.add(cf.getComponent()); |
|
250 } |
|
251 |
|
252 // if there is an EPR, EPR's address should be used for invocation instead of default address |
|
253 if (epr != null) |
|
254 this.requestContext.setEndPointAddressString(epr.getAddress()); |
|
255 else |
|
256 this.requestContext.setEndpointAddress(defaultEndPointAddress); |
|
257 this.engine = new Engine(toString(), owner.getExecutor()); |
|
258 this.endpointReference = epr; |
|
259 wsdlProperties = (wsdlPort == null) ? new WSDLDirectProperties(owner.getServiceName(), portname) : new WSDLPortProperties(wsdlPort); |
|
260 |
|
261 this.cleanRequestContext = this.requestContext.copy(); |
|
262 |
|
263 // ManagedObjectManager MUST be created before the pipeline |
|
264 // is constructed. |
|
265 |
|
266 managedObjectManager = new MonitorRootClient(this).createManagedObjectManager(this); |
|
267 |
|
268 if (master != null) |
|
269 this.tubes = new TubePool(master); |
|
270 else |
|
271 this.tubes = new TubePool(createPipeline(portInfo, binding)); |
|
272 |
|
273 addrVersion = binding.getAddressingVersion(); |
|
274 |
|
275 // This needs to happen after createPipeline. |
|
276 // TBD: Check if it needs to happen outside the Stub constructor. |
|
277 managedObjectManager.resumeJMXRegistration(); |
|
278 } |
|
279 |
|
280 /** |
|
281 * Creates a new pipeline for the given port name. |
|
282 */ |
|
283 private Tube createPipeline(WSPortInfo portInfo, WSBinding binding) { |
|
284 //Check all required WSDL extensions are understood |
|
285 checkAllWSDLExtensionsUnderstood(portInfo, binding); |
|
286 SEIModel seiModel = null; |
|
287 Class sei = null; |
|
288 if (portInfo instanceof SEIPortInfo) { |
|
289 SEIPortInfo sp = (SEIPortInfo) portInfo; |
|
290 seiModel = sp.model; |
|
291 sei = sp.sei; |
|
292 } |
|
293 BindingID bindingId = portInfo.getBindingId(); |
|
294 |
|
295 TubelineAssembler assembler = TubelineAssemblerFactory.create( |
|
296 Thread.currentThread().getContextClassLoader(), bindingId); |
|
297 if (assembler == null) |
|
298 throw new WebServiceException("Unable to process bindingID=" + bindingId); // TODO: i18n |
|
299 return assembler.createClient( |
|
300 new ClientTubeAssemblerContext( |
|
301 portInfo.getEndpointAddress(), |
|
302 portInfo.getPort(), |
|
303 this, binding, owner.getContainer(), ((BindingImpl) binding).createCodec(), seiModel, sei)); |
|
304 } |
|
305 |
|
306 public WSDLPort getWSDLPort() { |
|
307 return wsdlPort; |
|
308 } |
|
309 |
|
310 public WSService getService() { |
|
311 return owner; |
|
312 } |
|
313 |
|
314 public Pool<Tube> getTubes() { |
|
315 return tubes; |
|
316 } |
|
317 |
|
318 /** |
|
319 * Checks only if RespectBindingFeature is enabled |
|
320 * checks if all required wsdl extensions in the |
|
321 * corresponding wsdl:Port are understood when RespectBindingFeature is enabled. |
|
322 * @throws WebServiceException |
|
323 * when any wsdl extension that has wsdl:required=true is not understood |
|
324 */ |
|
325 private static void checkAllWSDLExtensionsUnderstood(WSPortInfo port, WSBinding binding) { |
|
326 if (port.getPort() != null && binding.isFeatureEnabled(RespectBindingFeature.class)) { |
|
327 ((WSDLPortImpl) port.getPort()).areRequiredExtensionsUnderstood(); |
|
328 } |
|
329 } |
|
330 |
|
331 public WSPortInfo getPortInfo() { |
|
332 return portInfo; |
|
333 } |
|
334 |
|
335 /** |
|
336 * Nullable when there is no associated WSDL Model |
|
337 * @return |
|
338 */ |
|
339 public |
|
340 @Nullable |
|
341 OperationDispatcher getOperationDispatcher() { |
|
342 if (operationDispatcher == null && wsdlPort != null) |
|
343 operationDispatcher = new OperationDispatcher(wsdlPort, binding, null); |
|
344 return operationDispatcher; |
|
345 } |
|
346 |
|
347 /** |
|
348 * Gets the port name that this stub is configured to talk to. |
|
349 * <p> |
|
350 * When {@link #wsdlPort} is non-null, the port name is always |
|
351 * the same as {@link WSDLPort#getName()}, but this method |
|
352 * returns a port name even if no WSDL is available for this stub. |
|
353 */ |
|
354 protected abstract |
|
355 @NotNull |
|
356 QName getPortName(); |
|
357 |
|
358 /** |
|
359 * Gets the service name that this stub is configured to talk to. |
|
360 * <p> |
|
361 * When {@link #wsdlPort} is non-null, the service name is always |
|
362 * the same as the one that's inferred from {@link WSDLPort#getOwner()}, |
|
363 * but this method returns a port name even if no WSDL is available for |
|
364 * this stub. |
|
365 */ |
|
366 protected final |
|
367 @NotNull |
|
368 QName getServiceName() { |
|
369 return owner.getServiceName(); |
|
370 } |
|
371 |
|
372 /** |
|
373 * Gets the {@link Executor} to be used for asynchronous method invocations. |
|
374 * <p> |
|
375 * Note that the value this method returns may different from invocations |
|
376 * to invocations. The caller must not cache. |
|
377 * |
|
378 * @return always non-null. |
|
379 */ |
|
380 public final Executor getExecutor() { |
|
381 return owner.getExecutor(); |
|
382 } |
|
383 |
|
384 /** |
|
385 * Passes a message to a pipe for processing. |
|
386 * <p> |
|
387 * Unlike {@link Tube} instances, |
|
388 * this method is thread-safe and can be invoked from |
|
389 * multiple threads concurrently. |
|
390 * |
|
391 * @param packet The message to be sent to the server |
|
392 * @param requestContext The {@link RequestContext} when this invocation is originally scheduled. |
|
393 * This must be the same object as {@link #requestContext} for synchronous |
|
394 * invocations, but for asynchronous invocations, it needs to be a snapshot |
|
395 * captured at the point of invocation, to correctly satisfy the spec requirement. |
|
396 * @param receiver Receives the {@link ResponseContext}. Since the spec requires |
|
397 * that the asynchronous invocations must not update response context, |
|
398 * depending on the mode of invocation they have to go to different places. |
|
399 * So we take a setter that abstracts that away. |
|
400 */ |
|
401 protected final Packet process(Packet packet, RequestContext requestContext, ResponseContextReceiver receiver) { |
|
402 packet.isSynchronousMEP = true; |
|
403 packet.component = this; |
|
404 configureRequestPacket(packet, requestContext); |
|
405 Pool<Tube> pool = tubes; |
|
406 if (pool == null) |
|
407 throw new WebServiceException("close method has already been invoked"); // TODO: i18n |
|
408 |
|
409 Fiber fiber = engine.createFiber(); |
|
410 // then send it away! |
|
411 Tube tube = pool.take(); |
|
412 |
|
413 try { |
|
414 return fiber.runSync(tube, packet); |
|
415 } finally { |
|
416 // this allows us to capture the packet even when the call failed with an exception. |
|
417 // when the call fails with an exception it's no longer a 'reply' but it may provide some information |
|
418 // about what went wrong. |
|
419 |
|
420 // note that Packet can still be updated after |
|
421 // ResponseContext is created. |
|
422 Packet reply = (fiber.getPacket() == null) ? packet : fiber.getPacket(); |
|
423 receiver.setResponseContext(new ResponseContext(reply)); |
|
424 |
|
425 pool.recycle(tube); |
|
426 } |
|
427 } |
|
428 |
|
429 private void configureRequestPacket(Packet packet, RequestContext requestContext) { |
|
430 // fill in Packet |
|
431 packet.proxy = this; |
|
432 packet.handlerConfig = binding.getHandlerConfig(); |
|
433 |
|
434 // to make it multi-thread safe we need to first get a stable snapshot |
|
435 Header[] hl = userOutboundHeaders; |
|
436 if (hl != null) |
|
437 packet.getMessage().getHeaders().addAll(hl); |
|
438 |
|
439 requestContext.fill(packet, (binding.getAddressingVersion() != null)); |
|
440 packet.addSatellite(wsdlProperties); |
|
441 |
|
442 if (addrVersion != null) { |
|
443 // populate request WS-Addressing headers |
|
444 HeaderList headerList = packet.getMessage().getHeaders(); |
|
445 headerList.fillRequestAddressingHeaders(wsdlPort, binding, packet); |
|
446 |
|
447 |
|
448 // Spec is not clear on if ReferenceParameters are to be added when addressing is not enabled, |
|
449 // but the EPR has ReferenceParameters. |
|
450 // Current approach: Add ReferenceParameters only if addressing enabled. |
|
451 if (endpointReference != null) { |
|
452 endpointReference.addReferenceParametersToList(packet.getMessage().getHeaders()); |
|
453 } |
|
454 } |
|
455 } |
|
456 |
|
457 /** |
|
458 * Passes a message through a {@link Tube}line for processing. The processing happens |
|
459 * asynchronously and when the response is available, Fiber.CompletionCallback is |
|
460 * called. The processing could happen on multiple threads. |
|
461 * |
|
462 * <p> |
|
463 * Unlike {@link Tube} instances, |
|
464 * this method is thread-safe and can be invoked from |
|
465 * multiple threads concurrently. |
|
466 * |
|
467 * @param receiver The {@link Response} implementation |
|
468 * @param request The message to be sent to the server |
|
469 * @param requestContext The {@link RequestContext} when this invocation is originally scheduled. |
|
470 * This must be the same object as {@link #requestContext} for synchronous |
|
471 * invocations, but for asynchronous invocations, it needs to be a snapshot |
|
472 * captured at the point of invocation, to correctly satisfy the spec requirement. |
|
473 * @param completionCallback Once the processing is done, the callback is invoked. |
|
474 */ |
|
475 protected final void processAsync(AsyncResponseImpl<?> receiver, Packet request, RequestContext requestContext, final Fiber.CompletionCallback completionCallback) { |
|
476 // fill in Packet |
|
477 request.component = this; |
|
478 configureRequestPacket(request, requestContext); |
|
479 |
|
480 final Pool<Tube> pool = tubes; |
|
481 if (pool == null) |
|
482 throw new WebServiceException("close method has already been invoked"); // TODO: i18n |
|
483 |
|
484 final Fiber fiber = engine.createFiber(); |
|
485 |
|
486 receiver.setCancelable(fiber); |
|
487 |
|
488 // check race condition on cancel |
|
489 if (receiver.isCancelled()) |
|
490 return; |
|
491 |
|
492 FiberContextSwitchInterceptorFactory fcsif = owner.getSPI(FiberContextSwitchInterceptorFactory.class); |
|
493 if(fcsif != null) |
|
494 fiber.addInterceptor(fcsif.create()); |
|
495 |
|
496 // then send it away! |
|
497 final Tube tube = pool.take(); |
|
498 |
|
499 Fiber.CompletionCallback fiberCallback = new Fiber.CompletionCallback() { |
|
500 public void onCompletion(@NotNull Packet response) { |
|
501 pool.recycle(tube); |
|
502 completionCallback.onCompletion(response); |
|
503 } |
|
504 |
|
505 public void onCompletion(@NotNull Throwable error) { |
|
506 // let's not reuse tubes as they might be in a wrong state, so not |
|
507 // calling pool.recycle() |
|
508 completionCallback.onCompletion(error); |
|
509 } |
|
510 }; |
|
511 |
|
512 // Check for SyncStartForAsyncInvokeFeature |
|
513 |
|
514 fiber.start(tube, request, fiberCallback, |
|
515 getBinding().isFeatureEnabled(SyncStartForAsyncFeature.class) && |
|
516 !requestContext.containsKey(PREVENT_SYNC_START_FOR_ASYNC_INVOKE)); |
|
517 } |
|
518 |
|
519 public void close() { |
|
520 if (tubes != null) { |
|
521 // multi-thread safety of 'close' needs to be considered more carefully. |
|
522 // some calls might be pending while this method is invoked. Should we |
|
523 // block until they are complete, or should we abort them (but how?) |
|
524 Tube p = tubes.take(); |
|
525 tubes = null; |
|
526 p.preDestroy(); |
|
527 } |
|
528 if (managedObjectManagerClosed) { |
|
529 return; |
|
530 } else { |
|
531 com.sun.xml.internal.ws.server.MonitorBase.closeMOM(managedObjectManager); |
|
532 managedObjectManagerClosed = true; |
|
533 } |
|
534 |
|
535 } |
|
536 |
|
537 public final WSBinding getBinding() { |
|
538 return binding; |
|
539 } |
|
540 |
|
541 public final Map<String, Object> getRequestContext() { |
|
542 return requestContext.getMapView(); |
|
543 } |
|
544 |
|
545 public void resetRequestContext() { |
|
546 requestContext = cleanRequestContext.copy(); |
|
547 } |
|
548 |
|
549 public final ResponseContext getResponseContext() { |
|
550 return responseContext; |
|
551 } |
|
552 |
|
553 public void setResponseContext(ResponseContext rc) { |
|
554 this.responseContext = rc; |
|
555 } |
|
556 |
|
557 public String toString() { |
|
558 return RuntimeVersion.VERSION + ": Stub for " + getRequestContext().get(BindingProvider.ENDPOINT_ADDRESS_PROPERTY); |
|
559 } |
|
560 |
|
561 public final WSEndpointReference getWSEndpointReference() { |
|
562 if (binding.getBindingID().equals(HTTPBinding.HTTP_BINDING)) |
|
563 throw new java.lang.UnsupportedOperationException(ClientMessages.UNSUPPORTED_OPERATION("BindingProvider.getEndpointReference(Class<T> class)", "XML/HTTP Binding", "SOAP11 or SOAP12 Binding")); |
|
564 |
|
565 if (endpointReference != null) { |
|
566 return endpointReference; |
|
567 } |
|
568 |
|
569 String eprAddress = requestContext.getEndpointAddress().toString(); |
|
570 QName portTypeName = null; |
|
571 String wsdlAddress = null; |
|
572 List<WSEndpointReference.EPRExtension> wsdlEPRExtensions = new ArrayList<WSEndpointReference.EPRExtension>(); |
|
573 if (wsdlPort != null) { |
|
574 portTypeName = wsdlPort.getBinding().getPortTypeName(); |
|
575 wsdlAddress = eprAddress + "?wsdl"; |
|
576 |
|
577 //gather EPRExtensions specified in WSDL. |
|
578 try { |
|
579 WSEndpointReference wsdlEpr = ((WSDLPortImpl) wsdlPort).getEPR(); |
|
580 if (wsdlEpr != null) { |
|
581 for (WSEndpointReference.EPRExtension extnEl : wsdlEpr.getEPRExtensions()) { |
|
582 wsdlEPRExtensions.add(new WSEPRExtension( |
|
583 XMLStreamBuffer.createNewBufferFromXMLStreamReader(extnEl.readAsXMLStreamReader()), extnEl.getQName())); |
|
584 } |
|
585 } |
|
586 |
|
587 } catch (XMLStreamException ex) { |
|
588 throw new WebServiceException(ex); |
|
589 } |
|
590 } |
|
591 AddressingVersion av = AddressingVersion.W3C; |
|
592 this.endpointReference = new WSEndpointReference( |
|
593 av, eprAddress, getServiceName(), getPortName(), portTypeName, null, wsdlAddress, null, wsdlEPRExtensions, null); |
|
594 |
|
595 return this.endpointReference; |
|
596 } |
|
597 |
|
598 |
|
599 public final W3CEndpointReference getEndpointReference() { |
|
600 if (binding.getBindingID().equals(HTTPBinding.HTTP_BINDING)) |
|
601 throw new java.lang.UnsupportedOperationException(ClientMessages.UNSUPPORTED_OPERATION("BindingProvider.getEndpointReference()", "XML/HTTP Binding", "SOAP11 or SOAP12 Binding")); |
|
602 return getEndpointReference(W3CEndpointReference.class); |
|
603 } |
|
604 |
|
605 public final <T extends EndpointReference> T getEndpointReference(Class<T> clazz) { |
|
606 return getWSEndpointReference().toSpec(clazz); |
|
607 } |
|
608 |
|
609 public |
|
610 @NotNull |
|
611 ManagedObjectManager getManagedObjectManager() { |
|
612 return managedObjectManager; |
|
613 } |
|
614 |
|
615 // |
|
616 // |
|
617 // WSBindingProvider methods |
|
618 // |
|
619 // |
|
620 public final void setOutboundHeaders(List<Header> headers) { |
|
621 if (headers == null) { |
|
622 this.userOutboundHeaders = null; |
|
623 } else { |
|
624 for (Header h : headers) { |
|
625 if (h == null) |
|
626 throw new IllegalArgumentException(); |
|
627 } |
|
628 userOutboundHeaders = headers.toArray(new Header[headers.size()]); |
|
629 } |
|
630 } |
|
631 |
|
632 public final void setOutboundHeaders(Header... headers) { |
|
633 if (headers == null) { |
|
634 this.userOutboundHeaders = null; |
|
635 } else { |
|
636 for (Header h : headers) { |
|
637 if (h == null) |
|
638 throw new IllegalArgumentException(); |
|
639 } |
|
640 Header[] hl = new Header[headers.length]; |
|
641 System.arraycopy(headers, 0, hl, 0, headers.length); |
|
642 userOutboundHeaders = hl; |
|
643 } |
|
644 } |
|
645 |
|
646 public final List<Header> getInboundHeaders() { |
|
647 return Collections.unmodifiableList((HeaderList) |
|
648 responseContext.get(JAXWSProperties.INBOUND_HEADER_LIST_PROPERTY)); |
|
649 } |
|
650 |
|
651 public final void setAddress(String address) { |
|
652 requestContext.put(BindingProvider.ENDPOINT_ADDRESS_PROPERTY, address); |
|
653 } |
|
654 |
|
655 public <S> S getSPI(Class<S> spiType) { |
|
656 for (Component c : components) { |
|
657 S s = c.getSPI(spiType); |
|
658 if (s != null) |
|
659 return s; |
|
660 } |
|
661 return owner.getSPI(spiType); |
|
662 } |
|
663 |
|
664 public Set<Component> getComponents() { |
|
665 return components; |
|
666 } |
|
667 } |