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

Fri, 04 Oct 2013 16:21:34 +0100

author
mkos
date
Fri, 04 Oct 2013 16:21:34 +0100
changeset 408
b0610cd08440
parent 368
0989ad8c0860
child 637
9c07ef4934dd
permissions
-rw-r--r--

8025054: Update JAX-WS RI integration to 2.2.9-b130926.1035
Reviewed-by: chegar

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

mercurial