ohair@286: /*
alanb@368: * Copyright (c) 1997, 2013, Oracle and/or its affiliates. All rights reserved.
ohair@286: * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
ohair@286: *
ohair@286: * This code is free software; you can redistribute it and/or modify it
ohair@286: * under the terms of the GNU General Public License version 2 only, as
ohair@286: * published by the Free Software Foundation. Oracle designates this
ohair@286: * particular file as subject to the "Classpath" exception as provided
ohair@286: * by Oracle in the LICENSE file that accompanied this code.
ohair@286: *
ohair@286: * This code is distributed in the hope that it will be useful, but WITHOUT
ohair@286: * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
ohair@286: * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
ohair@286: * version 2 for more details (a copy is included in the LICENSE file that
ohair@286: * accompanied this code).
ohair@286: *
ohair@286: * You should have received a copy of the GNU General Public License version
ohair@286: * 2 along with this work; if not, write to the Free Software Foundation,
ohair@286: * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
ohair@286: *
ohair@286: * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
ohair@286: * or visit www.oracle.com if you need additional information or have any
ohair@286: * questions.
ohair@286: */
ohair@286:
ohair@286: package com.sun.xml.internal.ws.client;
ohair@286:
ohair@286: import com.sun.istack.internal.NotNull;
ohair@286: import com.sun.istack.internal.Nullable;
ohair@286: import com.sun.xml.internal.ws.Closeable;
ohair@286: import com.sun.xml.internal.ws.api.BindingID;
ohair@286: import com.sun.xml.internal.ws.api.ComponentFeature;
alanb@368: import com.sun.xml.internal.ws.api.ComponentsFeature;
ohair@286: import com.sun.xml.internal.ws.api.ComponentFeature.Target;
ohair@286: import com.sun.xml.internal.ws.api.EndpointAddress;
ohair@286: import com.sun.xml.internal.ws.api.WSService;
ohair@286: import com.sun.xml.internal.ws.api.addressing.WSEndpointReference;
ohair@286: import com.sun.xml.internal.ws.api.client.ServiceInterceptor;
ohair@286: import com.sun.xml.internal.ws.api.client.ServiceInterceptorFactory;
alanb@368: import com.sun.xml.internal.ws.api.databinding.DatabindingConfig;
ohair@286: import com.sun.xml.internal.ws.api.databinding.DatabindingFactory;
alanb@368: import com.sun.xml.internal.ws.api.databinding.MetadataReader;
ohair@286: import com.sun.xml.internal.ws.api.model.SEIModel;
mkos@408: import com.sun.xml.internal.ws.api.model.wsdl.WSDLModel;
ohair@286: import com.sun.xml.internal.ws.api.model.wsdl.WSDLPort;
mkos@408: import com.sun.xml.internal.ws.api.model.wsdl.WSDLService;
alanb@368: import com.sun.xml.internal.ws.api.pipe.Stubs;
ohair@286: import com.sun.xml.internal.ws.api.server.Container;
ohair@286: import com.sun.xml.internal.ws.api.server.ContainerResolver;
ohair@286: import com.sun.xml.internal.ws.api.wsdl.parser.WSDLParserExtension;
ohair@286: import com.sun.xml.internal.ws.binding.BindingImpl;
ohair@286: import com.sun.xml.internal.ws.binding.WebServiceFeatureList;
ohair@286: import com.sun.xml.internal.ws.client.HandlerConfigurator.AnnotationConfigurator;
ohair@286: import com.sun.xml.internal.ws.client.HandlerConfigurator.HandlerResolverImpl;
ohair@286: import com.sun.xml.internal.ws.client.sei.SEIStub;
ohair@286: import com.sun.xml.internal.ws.developer.MemberSubmissionAddressingFeature;
alanb@368: import com.sun.xml.internal.ws.developer.UsesJAXBContextFeature;
ohair@286: import com.sun.xml.internal.ws.developer.WSBindingProvider;
ohair@286: import com.sun.xml.internal.ws.model.RuntimeModeler;
ohair@286: import com.sun.xml.internal.ws.model.SOAPSEIModel;
ohair@286: import com.sun.xml.internal.ws.resources.ClientMessages;
ohair@286: import com.sun.xml.internal.ws.resources.DispatchMessages;
ohair@286: import com.sun.xml.internal.ws.resources.ProviderApiMessages;
ohair@286: import com.sun.xml.internal.ws.util.JAXWSUtils;
ohair@286: import com.sun.xml.internal.ws.util.ServiceConfigurationError;
ohair@286: import com.sun.xml.internal.ws.util.ServiceFinder;
ohair@286: import com.sun.xml.internal.ws.wsdl.parser.RuntimeWSDLParser;
mkos@408:
ohair@286: import org.xml.sax.EntityResolver;
ohair@286: import org.xml.sax.SAXException;
ohair@286:
ohair@286: import javax.jws.HandlerChain;
ohair@286: import javax.jws.WebService;
ohair@286: import javax.xml.bind.JAXBContext;
ohair@286: import javax.xml.namespace.QName;
ohair@286: import javax.xml.stream.XMLStreamException;
ohair@286: import javax.xml.transform.Source;
ohair@286: import javax.xml.transform.stream.StreamSource;
alanb@368: import javax.xml.ws.BindingProvider;
alanb@368: import javax.xml.ws.Dispatch;
alanb@368: import javax.xml.ws.EndpointReference;
alanb@368: import javax.xml.ws.Service;
alanb@368: import javax.xml.ws.WebServiceClient;
alanb@368: import javax.xml.ws.WebServiceException;
alanb@368: import javax.xml.ws.WebServiceFeature;
ohair@286: import javax.xml.ws.handler.HandlerResolver;
ohair@286: import javax.xml.ws.soap.AddressingFeature;
mkos@408:
ohair@286: import java.io.IOException;
ohair@286: import java.lang.reflect.InvocationHandler;
ohair@286: import java.lang.reflect.Proxy;
ohair@286: import java.net.MalformedURLException;
ohair@286: import java.net.URL;
mkos@384: import java.security.*;
alanb@368: import java.util.Collection;
alanb@368: import java.util.HashMap;
alanb@368: import java.util.HashSet;
alanb@368: import java.util.Iterator;
alanb@368: import java.util.Map;
alanb@368: import java.util.Set;
ohair@286: import java.util.concurrent.Executor;
ohair@286: import java.util.concurrent.ThreadFactory;
ohair@286:
alanb@368: import static com.sun.xml.internal.ws.util.xml.XmlUtil.createDefaultCatalogResolver;
alanb@368:
ohair@286: /**
ohair@286: * Service objects provide the client view of a Web service.
ohair@286: *
ohair@286: *
Service acts as a factory of the following:
ohair@286: *
ohair@286: *
Proxies for a target service endpoint.
ohair@286: *
Instances of javax.xml.ws.Dispatch for
ohair@286: * dynamic message-oriented invocation of a remote
ohair@286: * operation.
ohair@286: *
ohair@286: *
ohair@286: *
The ports available on a service can be enumerated using the
ohair@286: * getPorts method. Alternatively, you can pass a
ohair@286: * service endpoint interface to the unary getPort method
ohair@286: * and let the runtime select a compatible port.
ohair@286: *
ohair@286: *
Handler chains for all the objects created by a Service
ohair@286: * can be set by means of the provided HandlerRegistry.
ohair@286: *
ohair@286: *
An Executor may be set on the service in order
ohair@286: * to gain better control over the threads used to dispatch asynchronous
ohair@286: * callbacks. For instance, thread pooling with certain parameters
ohair@286: * can be enabled by creating a ThreadPoolExecutor and
ohair@286: * registering it with the service.
ohair@286: *
ohair@286: * @author WS Development Team
ohair@286: * @see Executor
ohair@286: * @since JAX-WS 2.0
ohair@286: */
ohair@286: public class WSServiceDelegate extends WSService {
ohair@286: /**
ohair@286: * All ports.
ohair@286: *
ohair@286: * This includes ports statically known to WSDL, as well as
ohair@286: * ones that are dynamically added
ohair@286: * through {@link #addPort(QName, String, String)}.
ohair@286: *
ohair@286: * For statically known ports we'll have {@link SEIPortInfo}.
ohair@286: * For dynamically added ones we'll have {@link PortInfo}.
ohair@286: */
ohair@286: private final Map ports = new HashMap();
ohair@286: // For monitoring
ohair@286: protected Map getQNameToPortInfoMap() { return ports; }
ohair@286:
ohair@286: /**
ohair@286: * Whenever we create {@link BindingProvider}, we use this to configure handlers.
ohair@286: */
ohair@286: private @NotNull HandlerConfigurator handlerConfigurator = new HandlerResolverImpl(null);
ohair@286:
ohair@286: private final Class extends Service> serviceClass;
ohair@286:
ohair@286: private final WebServiceFeatureList features;
ohair@286:
ohair@286: /**
ohair@286: * Name of the service for which this {@link WSServiceDelegate} is created for.
ohair@286: */
ohair@286: private final @NotNull QName serviceName;
ohair@286:
ohair@286: /**
ohair@286: * Information about SEI, keyed by their interface type.
ohair@286: */
ohair@286: // private final Map seiContext = new HashMap();
ohair@286: private final Map seiContext = new HashMap();
ohair@286:
ohair@286: // This executor is used for all the async invocations for all proxies
ohair@286: // created from this service. But once the proxy is created, then changing
ohair@286: // this executor doesn't affect the already created proxies.
ohair@286: private volatile Executor executor;
ohair@286:
ohair@286: /**
ohair@286: * The WSDL service that this {@link Service} object represents.
ohair@286: *
ohair@286: * This field is null iff no WSDL is given to {@link Service}.
ohair@286: * This fiels can be be null if the service is created without wsdl but later
ohair@286: * the epr supplies a wsdl that can be parsed.
ohair@286: */
mkos@408: private @Nullable WSDLService wsdlService;
ohair@286:
ohair@286: private final Container container;
ohair@286: /**
ohair@286: * Multiple {@link ServiceInterceptor}s are aggregated into one.
ohair@286: */
ohair@286: /*package*/ final @NotNull ServiceInterceptor serviceInterceptor;
mkos@384: private URL wsdlURL;
ohair@286:
ohair@286: public WSServiceDelegate(URL wsdlDocumentLocation, QName serviceName, Class extends Service> serviceClass, WebServiceFeature... features) {
alanb@368: this(wsdlDocumentLocation, serviceName, serviceClass, new WebServiceFeatureList(features));
alanb@368: }
alanb@368:
alanb@368: protected WSServiceDelegate(URL wsdlDocumentLocation, QName serviceName, Class extends Service> serviceClass, WebServiceFeatureList features) {
ohair@286: this(
ohair@286: wsdlDocumentLocation==null ? null : new StreamSource(wsdlDocumentLocation.toExternalForm()),
ohair@286: serviceName,serviceClass, features);
mkos@384: wsdlURL = wsdlDocumentLocation;
ohair@286: }
ohair@286:
ohair@286: /**
ohair@286: * @param serviceClass
ohair@286: * Either {@link Service}.class or other generated service-derived classes.
ohair@286: */
ohair@286: public WSServiceDelegate(@Nullable Source wsdl, @NotNull QName serviceName, @NotNull final Class extends Service> serviceClass, WebServiceFeature... features) {
alanb@368: this(wsdl, serviceName, serviceClass, new WebServiceFeatureList(features));
alanb@368: }
alanb@368:
alanb@368: /**
alanb@368: * @param serviceClass
alanb@368: * Either {@link Service}.class or other generated service-derived classes.
alanb@368: */
alanb@368: protected WSServiceDelegate(@Nullable Source wsdl, @NotNull QName serviceName, @NotNull final Class extends Service> serviceClass, WebServiceFeatureList features) {
ohair@286: this(wsdl, null, serviceName, serviceClass, features);
ohair@286: }
ohair@286:
ohair@286: /**
ohair@286: * @param serviceClass
ohair@286: * Either {@link Service}.class or other generated service-derived classes.
ohair@286: */
mkos@408: public WSServiceDelegate(@Nullable Source wsdl, @Nullable WSDLService service, @NotNull QName serviceName, @NotNull final Class extends Service> serviceClass, WebServiceFeature... features) {
alanb@368: this(wsdl, service, serviceName, serviceClass, new WebServiceFeatureList(features));
alanb@368: }
alanb@368:
alanb@368: /**
alanb@368: * @param serviceClass
alanb@368: * Either {@link Service}.class or other generated service-derived classes.
alanb@368: */
mkos@408: public WSServiceDelegate(@Nullable Source wsdl, @Nullable WSDLService service, @NotNull QName serviceName, @NotNull final Class extends Service> serviceClass, WebServiceFeatureList features) {
ohair@286: //we cant create a Service without serviceName
alanb@368: if (serviceName == null) {
alanb@368: throw new WebServiceException(ClientMessages.INVALID_SERVICE_NAME_NULL(null));
alanb@368: }
ohair@286:
alanb@368: this.features = features;
ohair@286:
ohair@286: InitParams initParams = INIT_PARAMS.get();
ohair@286: INIT_PARAMS.set(null); // mark it as consumed
alanb@368: if(initParams==null) {
alanb@368: initParams = EMPTY_PARAMS;
alanb@368: }
ohair@286:
ohair@286: this.serviceName = serviceName;
ohair@286: this.serviceClass = serviceClass;
ohair@286: Container tContainer = initParams.getContainer()!=null ? initParams.getContainer() : ContainerResolver.getInstance().getContainer();
ohair@286: if (tContainer == Container.NONE) {
ohair@286: tContainer = new ClientContainer();
ohair@286: }
ohair@286: this.container = tContainer;
ohair@286:
ohair@286: ComponentFeature cf = this.features.get(ComponentFeature.class);
ohair@286: if (cf != null) {
ohair@286: switch(cf.getTarget()) {
ohair@286: case SERVICE:
ohair@286: getComponents().add(cf.getComponent());
ohair@286: break;
ohair@286: case CONTAINER:
ohair@286: this.container.getComponents().add(cf.getComponent());
alanb@368: break;
ohair@286: default:
ohair@286: throw new IllegalArgumentException();
ohair@286: }
ohair@286: }
alanb@368: ComponentsFeature csf = this.features.get(ComponentsFeature.class);
alanb@368: if (csf != null) {
alanb@368: for (ComponentFeature cfi : csf.getComponentFeatures()) {
alanb@368: switch(cfi.getTarget()) {
alanb@368: case SERVICE:
alanb@368: getComponents().add(cfi.getComponent());
alanb@368: break;
alanb@368: case CONTAINER:
alanb@368: this.container.getComponents().add(cfi.getComponent());
alanb@368: break;
alanb@368: default:
alanb@368: throw new IllegalArgumentException();
alanb@368: }
alanb@368: }
alanb@368: }
ohair@286:
ohair@286: // load interceptor
ohair@286: ServiceInterceptor interceptor = ServiceInterceptorFactory.load(this, Thread.currentThread().getContextClassLoader());
ohair@286: ServiceInterceptor si = container.getSPI(ServiceInterceptor.class);
ohair@286: if (si != null) {
ohair@286: interceptor = ServiceInterceptor.aggregate(interceptor, si);
ohair@286: }
ohair@286: this.serviceInterceptor = interceptor;
ohair@286:
ohair@286: if (service == null) {
ohair@286: //if wsdl is null, try and get it from the WebServiceClient.wsdlLocation
ohair@286: if(wsdl == null){
ohair@286: if(serviceClass != Service.class){
ohair@286: WebServiceClient wsClient = AccessController.doPrivileged(new PrivilegedAction() {
ohair@286: public WebServiceClient run() {
ohair@286: return serviceClass.getAnnotation(WebServiceClient.class);
ohair@286: }
ohair@286: });
ohair@286: String wsdlLocation = wsClient.wsdlLocation();
ohair@286: wsdlLocation = JAXWSUtils.absolutize(JAXWSUtils.getFileOrURLName(wsdlLocation));
ohair@286: wsdl = new StreamSource(wsdlLocation);
ohair@286: }
ohair@286: }
ohair@286: if (wsdl != null) {
ohair@286: try {
ohair@286: URL url = wsdl.getSystemId()==null ? null : JAXWSUtils.getEncodedURL(wsdl.getSystemId());
mkos@408: WSDLModel model = parseWSDL(url, wsdl, serviceClass);
ohair@286: service = model.getService(this.serviceName);
ohair@286: if (service == null)
ohair@286: throw new WebServiceException(
ohair@286: ClientMessages.INVALID_SERVICE_NAME(this.serviceName,
ohair@286: buildNameList(model.getServices().keySet())));
ohair@286: // fill in statically known ports
ohair@286: for (WSDLPort port : service.getPorts())
ohair@286: ports.put(port.getName(), new PortInfo(this, port));
ohair@286: } catch (MalformedURLException e) {
ohair@286: throw new WebServiceException(ClientMessages.INVALID_WSDL_URL(wsdl.getSystemId()));
ohair@286: }
ohair@286: }
mkos@408: } else {
mkos@408: // fill in statically known ports
mkos@408: for (WSDLPort port : service.getPorts())
mkos@408: ports.put(port.getName(), new PortInfo(this, port));
ohair@286: }
ohair@286: this.wsdlService = service;
ohair@286:
ohair@286: if (serviceClass != Service.class) {
ohair@286: //if @HandlerChain present, set HandlerResolver on service context
ohair@286: HandlerChain handlerChain =
ohair@286: AccessController.doPrivileged(new PrivilegedAction() {
ohair@286: public HandlerChain run() {
ohair@286: return serviceClass.getAnnotation(HandlerChain.class);
ohair@286: }
ohair@286: });
ohair@286: if (handlerChain != null)
ohair@286: handlerConfigurator = new AnnotationConfigurator(this);
ohair@286: }
ohair@286:
ohair@286: }
ohair@286:
ohair@286: /**
ohair@286: * Parses the WSDL and builds {@link com.sun.xml.internal.ws.api.model.wsdl.WSDLModel}.
ohair@286: * @param wsdlDocumentLocation
ohair@286: * Either this or wsdl parameter must be given.
ohair@286: * Null location means the system won't be able to resolve relative references in the WSDL,
ohair@286: */
mkos@408: private WSDLModel parseWSDL(URL wsdlDocumentLocation, Source wsdlSource, Class serviceClass) {
ohair@286: try {
ohair@286: return RuntimeWSDLParser.parse(wsdlDocumentLocation, wsdlSource, createCatalogResolver(),
ohair@286: true, getContainer(), serviceClass, ServiceFinder.find(WSDLParserExtension.class).toArray());
ohair@286: } catch (IOException e) {
ohair@286: throw new WebServiceException(e);
ohair@286: } catch (XMLStreamException e) {
ohair@286: throw new WebServiceException(e);
ohair@286: } catch (SAXException e) {
ohair@286: throw new WebServiceException(e);
ohair@286: } catch (ServiceConfigurationError e) {
ohair@286: throw new WebServiceException(e);
ohair@286: }
ohair@286: }
ohair@286:
ohair@286: protected EntityResolver createCatalogResolver() {
ohair@286: return createDefaultCatalogResolver();
ohair@286: }
ohair@286:
ohair@286: public Executor getExecutor() {
ohair@286: return executor;
ohair@286: }
ohair@286:
ohair@286: public void setExecutor(Executor executor) {
ohair@286: this.executor = executor;
ohair@286: }
ohair@286:
ohair@286: public HandlerResolver getHandlerResolver() {
ohair@286: return handlerConfigurator.getResolver();
ohair@286: }
ohair@286:
ohair@286: /*package*/ final HandlerConfigurator getHandlerConfigurator() {
ohair@286: return handlerConfigurator;
ohair@286: }
ohair@286:
ohair@286: public void setHandlerResolver(HandlerResolver resolver) {
ohair@286: handlerConfigurator = new HandlerResolverImpl(resolver);
ohair@286: }
ohair@286:
ohair@286: public T getPort(QName portName, Class portInterface) throws WebServiceException {
ohair@286: return getPort(portName, portInterface, EMPTY_FEATURES);
ohair@286: }
ohair@286:
ohair@286: public T getPort(QName portName, Class portInterface, WebServiceFeature... features) {
ohair@286: if (portName == null || portInterface == null)
ohair@286: throw new IllegalArgumentException();
mkos@408: WSDLService tWsdlService = this.wsdlService;
ohair@286: if (tWsdlService == null) {
ohair@286: // assigning it to local variable and not setting it back to this.wsdlService intentionally
ohair@286: // as we don't want to include the service instance with information gathered from sei
ohair@286: tWsdlService = getWSDLModelfromSEI(portInterface);
ohair@286: //still null? throw error need wsdl metadata to create a proxy
ohair@286: if (tWsdlService == null) {
ohair@286: throw new WebServiceException(ProviderApiMessages.NO_WSDL_NO_PORT(portInterface.getName()));
ohair@286: }
ohair@286:
ohair@286: }
mkos@408: WSDLPort portModel = getPortModel(tWsdlService, portName);
ohair@286: return getPort(portModel.getEPR(), portName, portInterface, new WebServiceFeatureList(features));
ohair@286: }
ohair@286:
ohair@286: public T getPort(EndpointReference epr, Class portInterface, WebServiceFeature... features) {
ohair@286: return getPort(WSEndpointReference.create(epr),portInterface,features);
ohair@286: }
ohair@286:
ohair@286: public T getPort(WSEndpointReference wsepr, Class portInterface, WebServiceFeature... features) {
ohair@286: //get the portType from SEI, so that it can be used if EPR does n't have endpointName
alanb@368: WebServiceFeatureList featureList = new WebServiceFeatureList(features);
alanb@368: QName portTypeName = RuntimeModeler.getPortTypeName(portInterface, getMetadadaReader(featureList, portInterface.getClassLoader()));
ohair@286: //if port name is not specified in EPR, it will use portTypeName to get it from the WSDL model.
ohair@286: QName portName = getPortNameFromEPR(wsepr, portTypeName);
alanb@368: return getPort(wsepr,portName,portInterface, featureList);
ohair@286: }
ohair@286:
ohair@286: protected T getPort(WSEndpointReference wsepr, QName portName, Class portInterface,
ohair@286: WebServiceFeatureList features) {
ohair@286: ComponentFeature cf = features.get(ComponentFeature.class);
ohair@286: if (cf != null && !Target.STUB.equals(cf.getTarget())) {
ohair@286: throw new IllegalArgumentException();
ohair@286: }
alanb@368: ComponentsFeature csf = features.get(ComponentsFeature.class);
alanb@368: if (csf != null) {
alanb@368: for (ComponentFeature cfi : csf.getComponentFeatures()) {
alanb@368: if (!Target.STUB.equals(cfi.getTarget()))
alanb@368: throw new IllegalArgumentException();
alanb@368: }
alanb@368: }
ohair@286: features.addAll(this.features);
ohair@286:
ohair@286: SEIPortInfo spi = addSEI(portName, portInterface, features);
ohair@286: return createEndpointIFBaseProxy(wsepr,portName,portInterface,features, spi);
ohair@286: }
ohair@286:
alanb@368: @Override
ohair@286: public T getPort(Class portInterface, WebServiceFeature... features) {
ohair@286: //get the portType from SEI
alanb@368: QName portTypeName = RuntimeModeler.getPortTypeName(portInterface, getMetadadaReader(new WebServiceFeatureList(features), portInterface.getClassLoader()));
mkos@408: WSDLService tmpWsdlService = this.wsdlService;
alanb@368: if (tmpWsdlService == null) {
ohair@286: // assigning it to local variable and not setting it back to this.wsdlService intentionally
ohair@286: // as we don't want to include the service instance with information gathered from sei
alanb@368: tmpWsdlService = getWSDLModelfromSEI(portInterface);
ohair@286: //still null? throw error need wsdl metadata to create a proxy
alanb@368: if(tmpWsdlService == null) {
ohair@286: throw new WebServiceException(ProviderApiMessages.NO_WSDL_NO_PORT(portInterface.getName()));
ohair@286: }
ohair@286: }
ohair@286: //get the first port corresponding to the SEI
mkos@408: WSDLPort port = tmpWsdlService.getMatchingPort(portTypeName);
alanb@368: if (port == null) {
alanb@368: throw new WebServiceException(ClientMessages.UNDEFINED_PORT_TYPE(portTypeName));
alanb@368: }
ohair@286: QName portName = port.getName();
ohair@286: return getPort(portName, portInterface,features);
ohair@286: }
ohair@286:
ohair@286: public T getPort(Class portInterface) throws WebServiceException {
ohair@286: return getPort(portInterface, EMPTY_FEATURES);
ohair@286: }
ohair@286:
ohair@286: public void addPort(QName portName, String bindingId, String endpointAddress) throws WebServiceException {
ohair@286: if (!ports.containsKey(portName)) {
ohair@286: BindingID bid = (bindingId == null) ? BindingID.SOAP11_HTTP : BindingID.parse(bindingId);
ohair@286: ports.put(portName,
ohair@286: new PortInfo(this, (endpointAddress == null) ? null :
ohair@286: EndpointAddress.create(endpointAddress), portName, bid));
ohair@286: } else
ohair@286: throw new WebServiceException(DispatchMessages.DUPLICATE_PORT(portName.toString()));
ohair@286: }
ohair@286:
ohair@286:
ohair@286: public Dispatch createDispatch(QName portName, Class aClass, Service.Mode mode) throws WebServiceException {
ohair@286: return createDispatch(portName, aClass, mode, EMPTY_FEATURES);
ohair@286: }
ohair@286:
ohair@286: @Override
ohair@286: public Dispatch createDispatch(QName portName, WSEndpointReference wsepr, Class aClass, Service.Mode mode, WebServiceFeature... features) {
ohair@286: return createDispatch(portName, wsepr, aClass, mode, new WebServiceFeatureList(features));
ohair@286: }
ohair@286:
ohair@286: public Dispatch createDispatch(QName portName, WSEndpointReference wsepr, Class aClass, Service.Mode mode, WebServiceFeatureList features) {
ohair@286: PortInfo port = safeGetPort(portName);
ohair@286:
ohair@286: ComponentFeature cf = features.get(ComponentFeature.class);
ohair@286: if (cf != null && !Target.STUB.equals(cf.getTarget())) {
ohair@286: throw new IllegalArgumentException();
ohair@286: }
alanb@368: ComponentsFeature csf = features.get(ComponentsFeature.class);
alanb@368: if (csf != null) {
alanb@368: for (ComponentFeature cfi : csf.getComponentFeatures()) {
alanb@368: if (!Target.STUB.equals(cfi.getTarget()))
alanb@368: throw new IllegalArgumentException();
alanb@368: }
alanb@368: }
ohair@286: features.addAll(this.features);
ohair@286:
ohair@286: BindingImpl binding = port.createBinding(features, null, null);
ohair@286: binding.setMode(mode);
ohair@286: Dispatch dispatch = Stubs.createDispatch(port, this, binding, aClass, mode, wsepr);
ohair@286: serviceInterceptor.postCreateDispatch((WSBindingProvider) dispatch);
ohair@286: return dispatch;
ohair@286: }
ohair@286:
ohair@286: public Dispatch createDispatch(QName portName, Class aClass, Service.Mode mode, WebServiceFeature... features) {
ohair@286: return createDispatch(portName, aClass, mode, new WebServiceFeatureList(features));
ohair@286: }
ohair@286:
ohair@286: public Dispatch createDispatch(QName portName, Class aClass, Service.Mode mode, WebServiceFeatureList features) {
ohair@286: WSEndpointReference wsepr = null;
ohair@286: boolean isAddressingEnabled = false;
ohair@286: AddressingFeature af = features.get(AddressingFeature.class);
ohair@286: if (af == null) {
ohair@286: af = this.features.get(AddressingFeature.class);
ohair@286: }
ohair@286: if (af != null && af.isEnabled())
ohair@286: isAddressingEnabled = true;
ohair@286: MemberSubmissionAddressingFeature msa = features.get(MemberSubmissionAddressingFeature.class);
ohair@286: if (msa == null) {
ohair@286: msa = this.features.get(MemberSubmissionAddressingFeature.class);
ohair@286: }
ohair@286: if (msa != null && msa.isEnabled())
ohair@286: isAddressingEnabled = true;
ohair@286: if(isAddressingEnabled && wsdlService != null && wsdlService.get(portName) != null) {
ohair@286: wsepr = wsdlService.get(portName).getEPR();
ohair@286: }
ohair@286: return createDispatch(portName, wsepr, aClass, mode, features);
ohair@286: }
ohair@286:
ohair@286: public Dispatch createDispatch(EndpointReference endpointReference, Class type, Service.Mode mode, WebServiceFeature... features) {
ohair@286: WSEndpointReference wsepr = new WSEndpointReference(endpointReference);
ohair@286: QName portName = addPortEpr(wsepr);
ohair@286: return createDispatch(portName, wsepr, type, mode, features);
ohair@286: }
ohair@286:
ohair@286: /**
ohair@286: * Obtains {@link PortInfo} for the given name, with error check.
ohair@286: */
ohair@286: public
ohair@286: @NotNull
ohair@286: PortInfo safeGetPort(QName portName) {
ohair@286: PortInfo port = ports.get(portName);
ohair@286: if (port == null) {
ohair@286: throw new WebServiceException(ClientMessages.INVALID_PORT_NAME(portName, buildNameList(ports.keySet())));
ohair@286: }
ohair@286: return port;
ohair@286: }
ohair@286:
ohair@286: private StringBuilder buildNameList(Collection names) {
ohair@286: StringBuilder sb = new StringBuilder();
ohair@286: for (QName qn : names) {
ohair@286: if (sb.length() > 0) sb.append(',');
ohair@286: sb.append(qn);
ohair@286: }
ohair@286: return sb;
ohair@286: }
ohair@286:
ohair@286: public EndpointAddress getEndpointAddress(QName qName) {
ohair@286: PortInfo p = ports.get(qName);
ohair@286: return p != null ? p.targetEndpoint : null;
ohair@286: }
ohair@286:
ohair@286: public Dispatch