src/share/jaxws_classes/com/sun/xml/internal/ws/client/Stub.java

Thu, 31 Aug 2017 15:18:52 +0800

author
aoqi
date
Thu, 31 Aug 2017 15:18:52 +0800
changeset 637
9c07ef4934dd
parent 408
b0610cd08440
parent 0
373ffda63c9a
permissions
-rw-r--r--

merge

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

mercurial