diff -r 000000000000 -r 373ffda63c9a src/share/jaxws_classes/com/sun/xml/internal/ws/client/Stub.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/src/share/jaxws_classes/com/sun/xml/internal/ws/client/Stub.java Wed Apr 27 01:27:09 2016 +0800 @@ -0,0 +1,753 @@ +/* + * Copyright (c) 1997, 2013, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. Oracle designates this + * particular file as subject to the "Classpath" exception as provided + * by Oracle in the LICENSE file that accompanied this code. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ + +package com.sun.xml.internal.ws.client; + +import com.sun.istack.internal.NotNull; +import com.sun.istack.internal.Nullable; +import com.sun.xml.internal.stream.buffer.XMLStreamBuffer; +import com.sun.xml.internal.ws.addressing.WSEPRExtension; +import com.sun.xml.internal.ws.api.BindingID; +import com.sun.xml.internal.ws.api.Component; +import com.sun.xml.internal.ws.api.ComponentFeature; +import com.sun.xml.internal.ws.api.ComponentFeature.Target; +import com.sun.xml.internal.ws.api.ComponentRegistry; +import com.sun.xml.internal.ws.api.ComponentsFeature; +import com.sun.xml.internal.ws.api.EndpointAddress; +import com.sun.xml.internal.ws.api.WSBinding; +import com.sun.xml.internal.ws.api.WSService; +import com.sun.xml.internal.ws.api.addressing.AddressingVersion; +import com.sun.xml.internal.ws.api.addressing.WSEndpointReference; +import com.sun.xml.internal.ws.api.client.WSPortInfo; +import com.sun.xml.internal.ws.api.message.AddressingUtils; +import com.sun.xml.internal.ws.api.message.Header; +import com.sun.xml.internal.ws.api.message.HeaderList; +import com.sun.xml.internal.ws.api.message.MessageHeaders; +import com.sun.xml.internal.ws.api.message.Packet; +import com.sun.xml.internal.ws.api.model.SEIModel; +import com.sun.xml.internal.ws.api.model.wsdl.WSDLPort; +import com.sun.xml.internal.ws.api.pipe.ClientTubeAssemblerContext; +import com.sun.xml.internal.ws.api.pipe.Engine; +import com.sun.xml.internal.ws.api.pipe.Fiber; +import com.sun.xml.internal.ws.api.pipe.FiberContextSwitchInterceptorFactory; +import com.sun.xml.internal.ws.api.pipe.SyncStartForAsyncFeature; +import com.sun.xml.internal.ws.api.pipe.Tube; +import com.sun.xml.internal.ws.api.pipe.TubelineAssembler; +import com.sun.xml.internal.ws.api.pipe.TubelineAssemblerFactory; +import com.sun.xml.internal.ws.api.server.Container; +import com.sun.xml.internal.ws.api.server.ContainerResolver; +import com.sun.xml.internal.ws.binding.BindingImpl; +import com.sun.xml.internal.ws.developer.JAXWSProperties; +import com.sun.xml.internal.ws.developer.WSBindingProvider; +import com.sun.xml.internal.ws.model.wsdl.WSDLDirectProperties; +import com.sun.xml.internal.ws.model.wsdl.WSDLPortProperties; +import com.sun.xml.internal.ws.model.wsdl.WSDLProperties; +import com.sun.xml.internal.ws.resources.ClientMessages; +import com.sun.xml.internal.ws.util.Pool; +import com.sun.xml.internal.ws.util.Pool.TubePool; +import com.sun.xml.internal.ws.util.RuntimeVersion; +import com.sun.xml.internal.ws.wsdl.OperationDispatcher; +import com.sun.org.glassfish.gmbal.ManagedObjectManager; + +import javax.xml.namespace.QName; +import javax.xml.stream.XMLStreamException; +import javax.xml.ws.BindingProvider; +import javax.xml.ws.EndpointReference; +import javax.xml.ws.RespectBindingFeature; +import javax.xml.ws.Response; +import javax.xml.ws.WebServiceException; +import javax.xml.ws.http.HTTPBinding; +import javax.xml.ws.wsaddressing.W3CEndpointReference; +import java.util.ArrayList; +import java.util.Collections; +import java.util.List; +import java.util.Map; +import java.util.Set; +import java.util.concurrent.CopyOnWriteArraySet; +import java.util.concurrent.Executor; +import java.util.logging.Level; +import java.util.logging.Logger; +import javax.management.ObjectName; + +/** + * Base class for stubs, which accept method invocations from + * client applications and pass the message to a {@link Tube} + * for processing. + * + *

+ * This class implements the management of pipe instances, + * and most of the {@link BindingProvider} methods. + * + * @author Kohsuke Kawaguchi + */ +public abstract class Stub implements WSBindingProvider, ResponseContextReceiver, ComponentRegistry { + /** + * Internal flag indicating async dispatch should be used even when the + * SyncStartForAsyncInvokeFeature is present on the binding associated + * with a stub. There is no type associated with this property on the + * request context. Its presence is what triggers the 'prevent' behavior. + */ + public static final String PREVENT_SYNC_START_FOR_ASYNC_INVOKE = "com.sun.xml.internal.ws.client.StubRequestSyncStartForAsyncInvoke"; + + /** + * Reuse pipelines as it's expensive to create. + *

+ * Set to null when {@link #close() closed}. + */ + private Pool tubes; + + private final Engine engine; + + /** + * The {@link WSServiceDelegate} object that owns us. + */ + protected final WSServiceDelegate owner; + + /** + * Non-null if this stub is configured to talk to an EPR. + *

+ * When this field is non-null, its reference parameters are sent as out-bound headers. + * This field can be null even when addressing is enabled, but if the addressing is + * not enabled, this field must be null. + *

+ * Unlike endpoint address, we are not letting users to change the EPR, + * as it contains references to services and so on that we don't want to change. + */ + protected + @Nullable + WSEndpointReference endpointReference; + + protected final BindingImpl binding; + + protected final WSPortInfo portInfo; + + /** + * represents AddressingVersion on binding if enabled, otherwise null; + */ + protected AddressingVersion addrVersion; + + public RequestContext requestContext = new RequestContext(); + + private final RequestContext cleanRequestContext; + + /** + * {@link ResponseContext} from the last synchronous operation. + */ + private ResponseContext responseContext; + @Nullable + protected final WSDLPort wsdlPort; + + protected QName portname; + + /** + * {@link Header}s to be added to outbound {@link Packet}. + * The contents is determined by the user. + */ + @Nullable + private volatile Header[] userOutboundHeaders; + + private final + @NotNull + WSDLProperties wsdlProperties; + protected OperationDispatcher operationDispatcher = null; + private final + @NotNull + ManagedObjectManager managedObjectManager; + private boolean managedObjectManagerClosed = false; + + private final Set components = new CopyOnWriteArraySet(); + + /** + * @param master The created stub will send messages to this pipe. + * @param binding As a {@link BindingProvider}, this object will + * return this binding from {@link BindingProvider#getBinding()}. + * @param defaultEndPointAddress The destination of the message. The actual destination + * could be overridden by {@link RequestContext}. + * @param epr To create a stub that sends out reference parameters + * of a specific EPR, give that instance. Otherwise null. + * Its address field will not be used, and that should be given + * separately as the defaultEndPointAddress. + */ + @Deprecated + protected Stub(WSServiceDelegate owner, Tube master, BindingImpl binding, WSDLPort wsdlPort, EndpointAddress defaultEndPointAddress, @Nullable WSEndpointReference epr) { + this(owner, master, null, null, binding, wsdlPort, defaultEndPointAddress, epr); + } + + /** + * @param portname The name of this port + * @param master The created stub will send messages to this pipe. + * @param binding As a {@link BindingProvider}, this object will + * return this binding from {@link BindingProvider#getBinding()}. + * @param defaultEndPointAddress The destination of the message. The actual destination + * could be overridden by {@link RequestContext}. + * @param epr To create a stub that sends out reference parameters + * of a specific EPR, give that instance. Otherwise null. + * Its address field will not be used, and that should be given + * separately as the defaultEndPointAddress. + */ + @Deprecated + protected Stub(QName portname, WSServiceDelegate owner, Tube master, BindingImpl binding, WSDLPort wsdlPort, EndpointAddress defaultEndPointAddress, @Nullable WSEndpointReference epr) { + this(owner, master, null, portname, binding, wsdlPort, defaultEndPointAddress, epr); + } + + /** + * @param portInfo PortInfo for this stub + * @param binding As a {@link BindingProvider}, this object will + * return this binding from {@link BindingProvider#getBinding()}. + * @param master The created stub will send messages to this pipe. + * @param defaultEndPointAddress The destination of the message. The actual destination + * could be overridden by {@link RequestContext}. + * @param epr To create a stub that sends out reference parameters + * of a specific EPR, give that instance. Otherwise null. + * Its address field will not be used, and that should be given + * separately as the defaultEndPointAddress. + */ + protected Stub(WSPortInfo portInfo, BindingImpl binding, Tube master,EndpointAddress defaultEndPointAddress, @Nullable WSEndpointReference epr) { + this((WSServiceDelegate) portInfo.getOwner(), master, portInfo, null, binding,portInfo.getPort(), defaultEndPointAddress, epr); + } + + /** + * @param portInfo PortInfo for this stub + * @param binding As a {@link BindingProvider}, this object will + * return this binding from {@link BindingProvider#getBinding()}. + * @param defaultEndPointAddress The destination of the message. The actual destination + * could be overridden by {@link RequestContext}. + * @param epr To create a stub that sends out reference parameters + * of a specific EPR, give that instance. Otherwise null. + * Its address field will not be used, and that should be given + * separately as the defaultEndPointAddress. + */ + protected Stub(WSPortInfo portInfo, BindingImpl binding, EndpointAddress defaultEndPointAddress, @Nullable WSEndpointReference epr) { + this(portInfo,binding,null, defaultEndPointAddress,epr); + + } + + private Stub(WSServiceDelegate owner, @Nullable Tube master, @Nullable WSPortInfo portInfo, QName portname, BindingImpl binding, @Nullable WSDLPort wsdlPort, EndpointAddress defaultEndPointAddress, @Nullable WSEndpointReference epr) { + Container old = ContainerResolver.getDefault().enterContainer(owner.getContainer()); + try { + this.owner = owner; + this.portInfo = portInfo; + this.wsdlPort = wsdlPort != null ? wsdlPort : (portInfo != null ? portInfo.getPort() : null); + this.portname = portname; + if (portname == null) { + if (portInfo != null) { + this.portname = portInfo.getPortName(); + } else if (wsdlPort != null) { + this.portname = wsdlPort.getName(); + } + } + this.binding = binding; + + ComponentFeature cf = binding.getFeature(ComponentFeature.class); + if (cf != null && Target.STUB.equals(cf.getTarget())) { + components.add(cf.getComponent()); + } + ComponentsFeature csf = binding.getFeature(ComponentsFeature.class); + if (csf != null) { + for (ComponentFeature cfi : csf.getComponentFeatures()) { + if (Target.STUB.equals(cfi.getTarget())) + components.add(cfi.getComponent()); + } + } + + // if there is an EPR, EPR's address should be used for invocation instead of default address + if (epr != null) { + this.requestContext.setEndPointAddressString(epr.getAddress()); + } else { + this.requestContext.setEndpointAddress(defaultEndPointAddress); + } + this.engine = new Engine(getStringId(), owner.getContainer(), owner.getExecutor()); + this.endpointReference = epr; + wsdlProperties = (wsdlPort == null) ? new WSDLDirectProperties(owner.getServiceName(), portname) : new WSDLPortProperties(wsdlPort); + + this.cleanRequestContext = this.requestContext.copy(); + + // ManagedObjectManager MUST be created before the pipeline + // is constructed. + + managedObjectManager = new MonitorRootClient(this).createManagedObjectManager(this); + + if (master != null) { + this.tubes = new TubePool(master); + } else { + this.tubes = new TubePool(createPipeline(portInfo, binding)); + } + + addrVersion = binding.getAddressingVersion(); + + // This needs to happen after createPipeline. + // TBD: Check if it needs to happen outside the Stub constructor. + managedObjectManager.resumeJMXRegistration(); + } finally { + ContainerResolver.getDefault().exitContainer(old); + } + } + + /** + * Creates a new pipeline for the given port name. + */ + private Tube createPipeline(WSPortInfo portInfo, WSBinding binding) { + //Check all required WSDL extensions are understood + checkAllWSDLExtensionsUnderstood(portInfo, binding); + SEIModel seiModel = null; + Class sei = null; + if (portInfo instanceof SEIPortInfo) { + SEIPortInfo sp = (SEIPortInfo) portInfo; + seiModel = sp.model; + sei = sp.sei; + } + BindingID bindingId = portInfo.getBindingId(); + + TubelineAssembler assembler = TubelineAssemblerFactory.create( + Thread.currentThread().getContextClassLoader(), bindingId, owner.getContainer()); + if (assembler == null) { + throw new WebServiceException("Unable to process bindingID=" + bindingId); // TODO: i18n + } + return assembler.createClient( + new ClientTubeAssemblerContext( + portInfo.getEndpointAddress(), + portInfo.getPort(), + this, binding, owner.getContainer(), ((BindingImpl) binding).createCodec(), seiModel, sei)); + } + + public WSDLPort getWSDLPort() { + return wsdlPort; + } + + public WSService getService() { + return owner; + } + + public Pool getTubes() { + return tubes; + } + + /** + * Checks only if RespectBindingFeature is enabled + * checks if all required wsdl extensions in the + * corresponding wsdl:Port are understood when RespectBindingFeature is enabled. + * @throws WebServiceException + * when any wsdl extension that has wsdl:required=true is not understood + */ + private static void checkAllWSDLExtensionsUnderstood(WSPortInfo port, WSBinding binding) { + if (port.getPort() != null && binding.isFeatureEnabled(RespectBindingFeature.class)) { + port.getPort().areRequiredExtensionsUnderstood(); + } + } + + @Override + public WSPortInfo getPortInfo() { + return portInfo; + } + + /** + * Nullable when there is no associated WSDL Model + * @return + */ + public + @Nullable + OperationDispatcher getOperationDispatcher() { + if (operationDispatcher == null && wsdlPort != null) { + operationDispatcher = new OperationDispatcher(wsdlPort, binding, null); + } + return operationDispatcher; + } + + /** + * Gets the port name that this stub is configured to talk to. + *

+ * When {@link #wsdlPort} is non-null, the port name is always + * the same as {@link WSDLPort#getName()}, but this method + * returns a port name even if no WSDL is available for this stub. + */ + protected abstract + @NotNull + QName getPortName(); + + /** + * Gets the service name that this stub is configured to talk to. + *

+ * When {@link #wsdlPort} is non-null, the service name is always + * the same as the one that's inferred from {@link WSDLPort#getOwner()}, + * but this method returns a port name even if no WSDL is available for + * this stub. + */ + protected final + @NotNull + QName getServiceName() { + return owner.getServiceName(); + } + + /** + * Gets the {@link Executor} to be used for asynchronous method invocations. + *

+ * Note that the value this method returns may different from invocations + * to invocations. The caller must not cache. + * + * @return always non-null. + */ + public final Executor getExecutor() { + return owner.getExecutor(); + } + + /** + * Passes a message to a pipe for processing. + *

+ * Unlike {@link Tube} instances, + * this method is thread-safe and can be invoked from + * multiple threads concurrently. + * + * @param packet The message to be sent to the server + * @param requestContext The {@link RequestContext} when this invocation is originally scheduled. + * This must be the same object as {@link #requestContext} for synchronous + * invocations, but for asynchronous invocations, it needs to be a snapshot + * captured at the point of invocation, to correctly satisfy the spec requirement. + * @param receiver Receives the {@link ResponseContext}. Since the spec requires + * that the asynchronous invocations must not update response context, + * depending on the mode of invocation they have to go to different places. + * So we take a setter that abstracts that away. + */ + protected final Packet process(Packet packet, RequestContext requestContext, ResponseContextReceiver receiver) { + packet.isSynchronousMEP = true; + packet.component = this; + configureRequestPacket(packet, requestContext); + Pool pool = tubes; + if (pool == null) { + throw new WebServiceException("close method has already been invoked"); // TODO: i18n + } + + Fiber fiber = engine.createFiber(); + configureFiber(fiber); + + // then send it away! + Tube tube = pool.take(); + + try { + return fiber.runSync(tube, packet); + } finally { + // this allows us to capture the packet even when the call failed with an exception. + // when the call fails with an exception it's no longer a 'reply' but it may provide some information + // about what went wrong. + + // note that Packet can still be updated after + // ResponseContext is created. + Packet reply = (fiber.getPacket() == null) ? packet : fiber.getPacket(); + receiver.setResponseContext(new ResponseContext(reply)); + + pool.recycle(tube); + } + } + + private void configureRequestPacket(Packet packet, RequestContext requestContext) { + // fill in Packet + packet.proxy = this; + packet.handlerConfig = binding.getHandlerConfig(); + + // to make it multi-thread safe we need to first get a stable snapshot + Header[] hl = userOutboundHeaders; + if (hl != null) { + MessageHeaders mh = packet.getMessage().getHeaders(); + for (Header h : hl) { + mh.add(h); + } + } + + requestContext.fill(packet, (binding.getAddressingVersion() != null)); + packet.addSatellite(wsdlProperties); + + if (addrVersion != null) { + // populate request WS-Addressing headers + MessageHeaders headerList = packet.getMessage().getHeaders(); + AddressingUtils.fillRequestAddressingHeaders(headerList, wsdlPort, binding, packet); + + + // Spec is not clear on if ReferenceParameters are to be added when addressing is not enabled, + // but the EPR has ReferenceParameters. + // Current approach: Add ReferenceParameters only if addressing enabled. + if (endpointReference != null) { + endpointReference.addReferenceParametersToList(packet.getMessage().getHeaders()); + } + } + } + + /** + * Passes a message through a {@link Tube}line for processing. The processing happens + * asynchronously and when the response is available, Fiber.CompletionCallback is + * called. The processing could happen on multiple threads. + * + *

+ * Unlike {@link Tube} instances, + * this method is thread-safe and can be invoked from + * multiple threads concurrently. + * + * @param receiver The {@link Response} implementation + * @param request The message to be sent to the server + * @param requestContext The {@link RequestContext} when this invocation is originally scheduled. + * This must be the same object as {@link #requestContext} for synchronous + * invocations, but for asynchronous invocations, it needs to be a snapshot + * captured at the point of invocation, to correctly satisfy the spec requirement. + * @param completionCallback Once the processing is done, the callback is invoked. + */ + protected final void processAsync(AsyncResponseImpl receiver, Packet request, RequestContext requestContext, final Fiber.CompletionCallback completionCallback) { + // fill in Packet + request.component = this; + configureRequestPacket(request, requestContext); + + final Pool pool = tubes; + if (pool == null) { + throw new WebServiceException("close method has already been invoked"); // TODO: i18n + } + + final Fiber fiber = engine.createFiber(); + configureFiber(fiber); + + receiver.setCancelable(fiber); + + // check race condition on cancel + if (receiver.isCancelled()) { + return; + } + + FiberContextSwitchInterceptorFactory fcsif = owner.getSPI(FiberContextSwitchInterceptorFactory.class); + if (fcsif != null) { + fiber.addInterceptor(fcsif.create()); + } + + // then send it away! + final Tube tube = pool.take(); + + Fiber.CompletionCallback fiberCallback = new Fiber.CompletionCallback() { + @Override + public void onCompletion(@NotNull Packet response) { + pool.recycle(tube); + completionCallback.onCompletion(response); + } + + @Override + public void onCompletion(@NotNull Throwable error) { + // let's not reuse tubes as they might be in a wrong state, so not + // calling pool.recycle() + completionCallback.onCompletion(error); + } + }; + + // Check for SyncStartForAsyncInvokeFeature + + fiber.start(tube, request, fiberCallback, + getBinding().isFeatureEnabled(SyncStartForAsyncFeature.class) && + !requestContext.containsKey(PREVENT_SYNC_START_FOR_ASYNC_INVOKE)); + } + + protected void configureFiber(Fiber fiber) { + // no-op in the base class, but can be used by derived classes to configure the Fiber prior + // to invocation + } + + private static final Logger monitoringLogger = Logger.getLogger(com.sun.xml.internal.ws.util.Constants.LoggingDomain + ".monitoring"); + + @Override + public void close() { + TubePool tp = (TubePool) tubes; + if (tp != null) { + // multi-thread safety of 'close' needs to be considered more carefully. + // some calls might be pending while this method is invoked. Should we + // block until they are complete, or should we abort them (but how?) + Tube p = tp.takeMaster(); + p.preDestroy(); + tubes = null; + } + if (!managedObjectManagerClosed) { + try { + final ObjectName name = managedObjectManager.getObjectName(managedObjectManager.getRoot()); + // The name is null when the MOM is a NOOP. + if (name != null) { + monitoringLogger.log(Level.INFO, "Closing Metro monitoring root: {0}", name); + } + managedObjectManager.close(); + } catch (java.io.IOException e) { + monitoringLogger.log(Level.WARNING, "Ignoring error when closing Managed Object Manager", e); + } + managedObjectManagerClosed = true; + } + } + + @Override + public final WSBinding getBinding() { + return binding; + } + + @Override + public final Map getRequestContext() { + return requestContext.asMap(); + } + + public void resetRequestContext() { + requestContext = cleanRequestContext.copy(); + } + + @Override + public final ResponseContext getResponseContext() { + return responseContext; + } + + @Override + public void setResponseContext(ResponseContext rc) { + this.responseContext = rc; + } + + private String getStringId() { + return RuntimeVersion.VERSION + ": Stub for " + getRequestContext().get(BindingProvider.ENDPOINT_ADDRESS_PROPERTY); + } + + @Override + public String toString() { + return getStringId(); + } + + @Override + public final WSEndpointReference getWSEndpointReference() { + if (binding.getBindingID().equals(HTTPBinding.HTTP_BINDING)) { + throw new java.lang.UnsupportedOperationException( + ClientMessages.UNSUPPORTED_OPERATION("BindingProvider.getEndpointReference(Class class)", "XML/HTTP Binding", "SOAP11 or SOAP12 Binding") + ); + } + + if (endpointReference != null) { + return endpointReference; + } + + String eprAddress = requestContext.getEndpointAddress().toString(); + QName portTypeName = null; + String wsdlAddress = null; + List wsdlEPRExtensions = new ArrayList(); + if (wsdlPort != null) { + portTypeName = wsdlPort.getBinding().getPortTypeName(); + wsdlAddress = eprAddress + "?wsdl"; + + //gather EPRExtensions specified in WSDL. + try { + WSEndpointReference wsdlEpr = wsdlPort.getEPR(); + if (wsdlEpr != null) { + for (WSEndpointReference.EPRExtension extnEl : wsdlEpr.getEPRExtensions()) { + wsdlEPRExtensions.add(new WSEPRExtension( + XMLStreamBuffer.createNewBufferFromXMLStreamReader(extnEl.readAsXMLStreamReader()), extnEl.getQName())); + } + } + + } catch (XMLStreamException ex) { + throw new WebServiceException(ex); + } + } + AddressingVersion av = AddressingVersion.W3C; + this.endpointReference = new WSEndpointReference( + av, eprAddress, getServiceName(), getPortName(), portTypeName, null, wsdlAddress, null, wsdlEPRExtensions, null); + + return this.endpointReference; + } + + + @Override + public final W3CEndpointReference getEndpointReference() { + if (binding.getBindingID().equals(HTTPBinding.HTTP_BINDING)) { + throw new java.lang.UnsupportedOperationException( + ClientMessages.UNSUPPORTED_OPERATION("BindingProvider.getEndpointReference()", "XML/HTTP Binding", "SOAP11 or SOAP12 Binding")); + } + return getEndpointReference(W3CEndpointReference.class); + } + + @Override + public final T getEndpointReference(Class clazz) { + return getWSEndpointReference().toSpec(clazz); + } + + public + @NotNull + @Override + ManagedObjectManager getManagedObjectManager() { + return managedObjectManager; + } + + // +// +// WSBindingProvider methods +// +// + @Override + public final void setOutboundHeaders(List

headers) { + if (headers == null) { + this.userOutboundHeaders = null; + } else { + for (Header h : headers) { + if (h == null) { + throw new IllegalArgumentException(); + } + } + userOutboundHeaders = headers.toArray(new Header[headers.size()]); + } + } + + @Override + public final void setOutboundHeaders(Header... headers) { + if (headers == null) { + this.userOutboundHeaders = null; + } else { + for (Header h : headers) { + if (h == null) { + throw new IllegalArgumentException(); + } + } + Header[] hl = new Header[headers.length]; + System.arraycopy(headers, 0, hl, 0, headers.length); + userOutboundHeaders = hl; + } + } + + @Override + public final List
getInboundHeaders() { + return Collections.unmodifiableList(((MessageHeaders) + responseContext.get(JAXWSProperties.INBOUND_HEADER_LIST_PROPERTY)).asList()); + } + + @Override + public final void setAddress(String address) { + requestContext.put(BindingProvider.ENDPOINT_ADDRESS_PROPERTY, address); + } + + @Override + public S getSPI(Class spiType) { + for (Component c : components) { + S s = c.getSPI(spiType); + if (s != null) { + return s; + } + } + return owner.getSPI(spiType); + } + + @Override + public Set getComponents() { + return components; + } +}