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