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