/*
 * Copyright (c) 1997, 2015, 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.ws.Closeable;
import com.sun.xml.internal.ws.api.BindingID;
import com.sun.xml.internal.ws.api.ComponentFeature;
import com.sun.xml.internal.ws.api.ComponentsFeature;
import com.sun.xml.internal.ws.api.ComponentFeature.Target;
import com.sun.xml.internal.ws.api.EndpointAddress;
import com.sun.xml.internal.ws.api.WSService;
import com.sun.xml.internal.ws.api.addressing.WSEndpointReference;
import com.sun.xml.internal.ws.api.client.ServiceInterceptor;
import com.sun.xml.internal.ws.api.client.ServiceInterceptorFactory;
import com.sun.xml.internal.ws.api.databinding.DatabindingConfig;
import com.sun.xml.internal.ws.api.databinding.DatabindingFactory;
import com.sun.xml.internal.ws.api.databinding.MetadataReader;
import com.sun.xml.internal.ws.api.model.SEIModel;
import com.sun.xml.internal.ws.api.model.wsdl.WSDLModel;
import com.sun.xml.internal.ws.api.model.wsdl.WSDLPort;
import com.sun.xml.internal.ws.api.model.wsdl.WSDLService;
import com.sun.xml.internal.ws.api.pipe.Stubs;
import com.sun.xml.internal.ws.api.server.Container;
import com.sun.xml.internal.ws.api.server.ContainerResolver;
import com.sun.xml.internal.ws.api.wsdl.parser.WSDLParserExtension;
import com.sun.xml.internal.ws.binding.BindingImpl;
import com.sun.xml.internal.ws.binding.WebServiceFeatureList;
import com.sun.xml.internal.ws.client.HandlerConfigurator.AnnotationConfigurator;
import com.sun.xml.internal.ws.client.HandlerConfigurator.HandlerResolverImpl;
import com.sun.xml.internal.ws.client.sei.SEIStub;
import com.sun.xml.internal.ws.developer.MemberSubmissionAddressingFeature;
import com.sun.xml.internal.ws.developer.UsesJAXBContextFeature;
import com.sun.xml.internal.ws.developer.WSBindingProvider;
import com.sun.xml.internal.ws.model.RuntimeModeler;
import com.sun.xml.internal.ws.model.SOAPSEIModel;
import com.sun.xml.internal.ws.resources.ClientMessages;
import com.sun.xml.internal.ws.resources.DispatchMessages;
import com.sun.xml.internal.ws.resources.ProviderApiMessages;
import com.sun.xml.internal.ws.util.JAXWSUtils;
import com.sun.xml.internal.ws.util.ServiceConfigurationError;
import com.sun.xml.internal.ws.util.ServiceFinder;
import com.sun.xml.internal.ws.wsdl.parser.RuntimeWSDLParser;

import org.xml.sax.EntityResolver;
import org.xml.sax.SAXException;

import javax.jws.HandlerChain;
import javax.jws.WebService;
import javax.xml.bind.JAXBContext;
import javax.xml.namespace.QName;
import javax.xml.stream.XMLStreamException;
import javax.xml.transform.Source;
import javax.xml.transform.stream.StreamSource;
import javax.xml.ws.BindingProvider;
import javax.xml.ws.Dispatch;
import javax.xml.ws.EndpointReference;
import javax.xml.ws.Service;
import javax.xml.ws.WebServiceClient;
import javax.xml.ws.WebServiceException;
import javax.xml.ws.WebServiceFeature;
import javax.xml.ws.handler.HandlerResolver;
import javax.xml.ws.soap.AddressingFeature;

import java.io.IOException;
import java.lang.reflect.InvocationHandler;
import java.lang.reflect.Proxy;
import java.net.MalformedURLException;
import java.net.URL;
import java.security.AccessController;
import java.security.PrivilegedAction;
import java.util.Collection;
import java.util.HashMap;
import java.util.HashSet;
import java.util.Iterator;
import java.util.Map;
import java.util.Set;
import java.util.concurrent.Executor;
import java.util.concurrent.ThreadFactory;

import static com.sun.xml.internal.ws.util.xml.XmlUtil.createDefaultCatalogResolver;

Service objects provide the client view of a Web service.

Service acts as a factory of the following:

  • Proxies for a target service endpoint.
  • Instances of javax.xml.ws.Dispatch for dynamic message-oriented invocation of a remote operation.
  • The ports available on a service can be enumerated using the getPorts method. Alternatively, you can pass a service endpoint interface to the unary getPort method and let the runtime select a compatible port.

    Handler chains for all the objects created by a Service can be set by means of the provided HandlerRegistry.

    An Executor may be set on the service in order to gain better control over the threads used to dispatch asynchronous callbacks. For instance, thread pooling with certain parameters can be enabled by creating a ThreadPoolExecutor and registering it with the service.

Author:WS Development Team
See Also:
Since:JAX-WS 2.0
/** * <code>Service</code> objects provide the client view of a Web service. * * <p><code>Service</code> acts as a factory of the following: * <ul> * <li>Proxies for a target service endpoint. * <li>Instances of <code>javax.xml.ws.Dispatch</code> for * dynamic message-oriented invocation of a remote * operation. * </li> * * <p>The ports available on a service can be enumerated using the * <code>getPorts</code> method. Alternatively, you can pass a * service endpoint interface to the unary <code>getPort</code> method * and let the runtime select a compatible port. * * <p>Handler chains for all the objects created by a <code>Service</code> * can be set by means of the provided <code>HandlerRegistry</code>. * * <p>An <code>Executor</code> may be set on the service in order * to gain better control over the threads used to dispatch asynchronous * callbacks. For instance, thread pooling with certain parameters * can be enabled by creating a <code>ThreadPoolExecutor</code> and * registering it with the service. * * @author WS Development Team * @see Executor * @since JAX-WS 2.0 */
public class WSServiceDelegate extends WSService {
All ports.

This includes ports statically known to WSDL, as well as ones that are dynamically added through addPort(QName, String, String).

For statically known ports we'll have SEIPortInfo. For dynamically added ones we'll have PortInfo.

/** * All ports. * <p> * This includes ports statically known to WSDL, as well as * ones that are dynamically added * through {@link #addPort(QName, String, String)}. * <p> * For statically known ports we'll have {@link SEIPortInfo}. * For dynamically added ones we'll have {@link PortInfo}. */
private final Map<QName, PortInfo> ports = new HashMap<QName, PortInfo>(); // For monitoring protected Map<QName, PortInfo> getQNameToPortInfoMap() { return ports; }
Whenever we create BindingProvider, we use this to configure handlers.
/** * Whenever we create {@link BindingProvider}, we use this to configure handlers. */
private @NotNull HandlerConfigurator handlerConfigurator = new HandlerResolverImpl(null); private final Class<? extends Service> serviceClass; private final WebServiceFeatureList features;
Name of the service for which this WSServiceDelegate is created for.
/** * Name of the service for which this {@link WSServiceDelegate} is created for. */
private final @NotNull QName serviceName;
Information about SEI, keyed by their interface type.
/** * Information about SEI, keyed by their interface type. */
// private final Map<Class,SEIPortInfo> seiContext = new HashMap<Class,SEIPortInfo>(); private final Map<QName,SEIPortInfo> seiContext = new HashMap<QName,SEIPortInfo>(); // This executor is used for all the async invocations for all proxies // created from this service. But once the proxy is created, then changing // this executor doesn't affect the already created proxies. private volatile Executor executor;
The WSDL service that this Service object represents.

This field is null iff no WSDL is given to Service. This fiels can be be null if the service is created without wsdl but later the epr supplies a wsdl that can be parsed.

/** * The WSDL service that this {@link Service} object represents. * <p> * This field is null iff no WSDL is given to {@link Service}. * This fiels can be be null if the service is created without wsdl but later * the epr supplies a wsdl that can be parsed. */
private @Nullable WSDLService wsdlService; private final Container container;
Multiple ServiceInterceptors are aggregated into one.
/** * Multiple {@link ServiceInterceptor}s are aggregated into one. */
/*package*/ final @NotNull ServiceInterceptor serviceInterceptor; private URL wsdlURL; public WSServiceDelegate(URL wsdlDocumentLocation, QName serviceName, Class<? extends Service> serviceClass, WebServiceFeature... features) { this(wsdlDocumentLocation, serviceName, serviceClass, new WebServiceFeatureList(features)); } protected WSServiceDelegate(URL wsdlDocumentLocation, QName serviceName, Class<? extends Service> serviceClass, WebServiceFeatureList features) { this( wsdlDocumentLocation==null ? null : new StreamSource(wsdlDocumentLocation.toExternalForm()), serviceName,serviceClass, features); wsdlURL = wsdlDocumentLocation; }
Params:
  • serviceClass – Either Service.class or other generated service-derived classes.
/** * @param serviceClass * Either {@link Service}.class or other generated service-derived classes. */
public WSServiceDelegate(@Nullable Source wsdl, @NotNull QName serviceName, @NotNull final Class<? extends Service> serviceClass, WebServiceFeature... features) { this(wsdl, serviceName, serviceClass, new WebServiceFeatureList(features)); }
Params:
  • serviceClass – Either Service.class or other generated service-derived classes.
/** * @param serviceClass * Either {@link Service}.class or other generated service-derived classes. */
protected WSServiceDelegate(@Nullable Source wsdl, @NotNull QName serviceName, @NotNull final Class<? extends Service> serviceClass, WebServiceFeatureList features) { this(wsdl, null, serviceName, serviceClass, features); }
Params:
  • serviceClass – Either Service.class or other generated service-derived classes.
/** * @param serviceClass * Either {@link Service}.class or other generated service-derived classes. */
public WSServiceDelegate(@Nullable Source wsdl, @Nullable WSDLService service, @NotNull QName serviceName, @NotNull final Class<? extends Service> serviceClass, WebServiceFeature... features) { this(wsdl, service, serviceName, serviceClass, new WebServiceFeatureList(features)); }
Params:
  • serviceClass – Either Service.class or other generated service-derived classes.
/** * @param serviceClass * Either {@link Service}.class or other generated service-derived classes. */
public WSServiceDelegate(@Nullable Source wsdl, @Nullable WSDLService service, @NotNull QName serviceName, @NotNull final Class<? extends Service> serviceClass, WebServiceFeatureList features) { //we cant create a Service without serviceName if (serviceName == null) { throw new WebServiceException(ClientMessages.INVALID_SERVICE_NAME_NULL(null)); } this.features = features; InitParams initParams = INIT_PARAMS.get(); INIT_PARAMS.set(null); // mark it as consumed if(initParams==null) { initParams = EMPTY_PARAMS; } this.serviceName = serviceName; this.serviceClass = serviceClass; Container tContainer = initParams.getContainer()!=null ? initParams.getContainer() : ContainerResolver.getInstance().getContainer(); if (tContainer == Container.NONE) { tContainer = new ClientContainer(); } this.container = tContainer; ComponentFeature cf = this.features.get(ComponentFeature.class); if (cf != null) { switch(cf.getTarget()) { case SERVICE: getComponents().add(cf.getComponent()); break; case CONTAINER: this.container.getComponents().add(cf.getComponent()); break; default: throw new IllegalArgumentException(); } } ComponentsFeature csf = this.features.get(ComponentsFeature.class); if (csf != null) { for (ComponentFeature cfi : csf.getComponentFeatures()) { switch(cfi.getTarget()) { case SERVICE: getComponents().add(cfi.getComponent()); break; case CONTAINER: this.container.getComponents().add(cfi.getComponent()); break; default: throw new IllegalArgumentException(); } } } // load interceptor ServiceInterceptor interceptor = ServiceInterceptorFactory.load(this, Thread.currentThread().getContextClassLoader()); ServiceInterceptor si = container.getSPI(ServiceInterceptor.class); if (si != null) { interceptor = ServiceInterceptor.aggregate(interceptor, si); } this.serviceInterceptor = interceptor; if (service == null) { //if wsdl is null, try and get it from the WebServiceClient.wsdlLocation if(wsdl == null){ if(serviceClass != Service.class){ WebServiceClient wsClient = AccessController.doPrivileged(new PrivilegedAction<WebServiceClient>() { public WebServiceClient run() { return serviceClass.getAnnotation(WebServiceClient.class); } }); String wsdlLocation = wsClient.wsdlLocation(); wsdlLocation = JAXWSUtils.absolutize(JAXWSUtils.getFileOrURLName(wsdlLocation)); wsdl = new StreamSource(wsdlLocation); } } if (wsdl != null) { try { URL url = wsdl.getSystemId()==null ? null : JAXWSUtils.getEncodedURL(wsdl.getSystemId()); WSDLModel model = parseWSDL(url, wsdl, serviceClass); service = model.getService(this.serviceName); if (service == null) throw new WebServiceException( ClientMessages.INVALID_SERVICE_NAME(this.serviceName, buildNameList(model.getServices().keySet()))); // fill in statically known ports for (WSDLPort port : service.getPorts()) ports.put(port.getName(), new PortInfo(this, port)); } catch (MalformedURLException e) { throw new WebServiceException(ClientMessages.INVALID_WSDL_URL(wsdl.getSystemId())); } } } else { // fill in statically known ports for (WSDLPort port : service.getPorts()) ports.put(port.getName(), new PortInfo(this, port)); } this.wsdlService = service; if (serviceClass != Service.class) { //if @HandlerChain present, set HandlerResolver on service context HandlerChain handlerChain = AccessController.doPrivileged(new PrivilegedAction<HandlerChain>() { public HandlerChain run() { return serviceClass.getAnnotation(HandlerChain.class); } }); if (handlerChain != null) handlerConfigurator = new AnnotationConfigurator(this); } }
Parses the WSDL and builds WSDLModel.
Params:
  • wsdlDocumentLocation – Either this or wsdl parameter must be given. Null location means the system won't be able to resolve relative references in the WSDL.
/** * Parses the WSDL and builds {@link com.sun.xml.internal.ws.api.model.wsdl.WSDLModel}. * @param wsdlDocumentLocation * Either this or {@code wsdl} parameter must be given. * Null location means the system won't be able to resolve relative references in the WSDL. */
private WSDLModel parseWSDL(URL wsdlDocumentLocation, Source wsdlSource, Class serviceClass) { try { return RuntimeWSDLParser.parse(wsdlDocumentLocation, wsdlSource, createCatalogResolver(), true, getContainer(), serviceClass, ServiceFinder.find(WSDLParserExtension.class).toArray()); } catch (IOException e) { throw new WebServiceException(e); } catch (XMLStreamException e) { throw new WebServiceException(e); } catch (SAXException e) { throw new WebServiceException(e); } catch (ServiceConfigurationError e) { throw new WebServiceException(e); } } protected EntityResolver createCatalogResolver() { return createDefaultCatalogResolver(); } public Executor getExecutor() { return executor; } public void setExecutor(Executor executor) { this.executor = executor; } public HandlerResolver getHandlerResolver() { return handlerConfigurator.getResolver(); } /*package*/ final HandlerConfigurator getHandlerConfigurator() { return handlerConfigurator; } public void setHandlerResolver(HandlerResolver resolver) { handlerConfigurator = new HandlerResolverImpl(resolver); } public <T> T getPort(QName portName, Class<T> portInterface) throws WebServiceException { return getPort(portName, portInterface, EMPTY_FEATURES); } public <T> T getPort(QName portName, Class<T> portInterface, WebServiceFeature... features) { if (portName == null || portInterface == null) throw new IllegalArgumentException(); WSDLService tWsdlService = this.wsdlService; if (tWsdlService == null) { // assigning it to local variable and not setting it back to this.wsdlService intentionally // as we don't want to include the service instance with information gathered from sei tWsdlService = getWSDLModelfromSEI(portInterface); //still null? throw error need wsdl metadata to create a proxy if (tWsdlService == null) { throw new WebServiceException(ProviderApiMessages.NO_WSDL_NO_PORT(portInterface.getName())); } } WSDLPort portModel = getPortModel(tWsdlService, portName); return getPort(portModel.getEPR(), portName, portInterface, new WebServiceFeatureList(features)); } public <T> T getPort(EndpointReference epr, Class<T> portInterface, WebServiceFeature... features) { return getPort(WSEndpointReference.create(epr),portInterface,features); } public <T> T getPort(WSEndpointReference wsepr, Class<T> portInterface, WebServiceFeature... features) { //get the portType from SEI, so that it can be used if EPR does n't have endpointName WebServiceFeatureList featureList = new WebServiceFeatureList(features); QName portTypeName = RuntimeModeler.getPortTypeName(portInterface, getMetadadaReader(featureList, portInterface.getClassLoader())); //if port name is not specified in EPR, it will use portTypeName to get it from the WSDL model. QName portName = getPortNameFromEPR(wsepr, portTypeName); return getPort(wsepr,portName,portInterface, featureList); } protected <T> T getPort(WSEndpointReference wsepr, QName portName, Class<T> portInterface, WebServiceFeatureList features) { ComponentFeature cf = features.get(ComponentFeature.class); if (cf != null && !Target.STUB.equals(cf.getTarget())) { throw new IllegalArgumentException(); } ComponentsFeature csf = features.get(ComponentsFeature.class); if (csf != null) { for (ComponentFeature cfi : csf.getComponentFeatures()) { if (!Target.STUB.equals(cfi.getTarget())) throw new IllegalArgumentException(); } } features.addAll(this.features); SEIPortInfo spi = addSEI(portName, portInterface, features); return createEndpointIFBaseProxy(wsepr,portName,portInterface,features, spi); } @Override public <T> T getPort(Class<T> portInterface, WebServiceFeature... features) { //get the portType from SEI QName portTypeName = RuntimeModeler.getPortTypeName(portInterface, getMetadadaReader(new WebServiceFeatureList(features), portInterface.getClassLoader())); WSDLService tmpWsdlService = this.wsdlService; if (tmpWsdlService == null) { // assigning it to local variable and not setting it back to this.wsdlService intentionally // as we don't want to include the service instance with information gathered from sei tmpWsdlService = getWSDLModelfromSEI(portInterface); //still null? throw error need wsdl metadata to create a proxy if(tmpWsdlService == null) { throw new WebServiceException(ProviderApiMessages.NO_WSDL_NO_PORT(portInterface.getName())); } } //get the first port corresponding to the SEI WSDLPort port = tmpWsdlService.getMatchingPort(portTypeName); if (port == null) { throw new WebServiceException(ClientMessages.UNDEFINED_PORT_TYPE(portTypeName)); } QName portName = port.getName(); return getPort(portName, portInterface,features); } public <T> T getPort(Class<T> portInterface) throws WebServiceException { return getPort(portInterface, EMPTY_FEATURES); } public void addPort(QName portName, String bindingId, String endpointAddress) throws WebServiceException { if (!ports.containsKey(portName)) { BindingID bid = (bindingId == null) ? BindingID.SOAP11_HTTP : BindingID.parse(bindingId); ports.put(portName, new PortInfo(this, (endpointAddress == null) ? null : EndpointAddress.create(endpointAddress), portName, bid)); } else throw new WebServiceException(DispatchMessages.DUPLICATE_PORT(portName.toString())); } public <T> Dispatch<T> createDispatch(QName portName, Class<T> aClass, Service.Mode mode) throws WebServiceException { return createDispatch(portName, aClass, mode, EMPTY_FEATURES); } @Override public <T> Dispatch<T> createDispatch(QName portName, WSEndpointReference wsepr, Class<T> aClass, Service.Mode mode, WebServiceFeature... features) { return createDispatch(portName, wsepr, aClass, mode, new WebServiceFeatureList(features)); } public <T> Dispatch<T> createDispatch(QName portName, WSEndpointReference wsepr, Class<T> aClass, Service.Mode mode, WebServiceFeatureList features) { PortInfo port = safeGetPort(portName); ComponentFeature cf = features.get(ComponentFeature.class); if (cf != null && !Target.STUB.equals(cf.getTarget())) { throw new IllegalArgumentException(); } ComponentsFeature csf = features.get(ComponentsFeature.class); if (csf != null) { for (ComponentFeature cfi : csf.getComponentFeatures()) { if (!Target.STUB.equals(cfi.getTarget())) throw new IllegalArgumentException(); } } features.addAll(this.features); BindingImpl binding = port.createBinding(features, null, null); binding.setMode(mode); Dispatch<T> dispatch = Stubs.createDispatch(port, this, binding, aClass, mode, wsepr); serviceInterceptor.postCreateDispatch((WSBindingProvider) dispatch); return dispatch; } public <T> Dispatch<T> createDispatch(QName portName, Class<T> aClass, Service.Mode mode, WebServiceFeature... features) { return createDispatch(portName, aClass, mode, new WebServiceFeatureList(features)); } public <T> Dispatch<T> createDispatch(QName portName, Class<T> aClass, Service.Mode mode, WebServiceFeatureList features) { WSEndpointReference wsepr = null; boolean isAddressingEnabled = false; AddressingFeature af = features.get(AddressingFeature.class); if (af == null) { af = this.features.get(AddressingFeature.class); } if (af != null && af.isEnabled()) isAddressingEnabled = true; MemberSubmissionAddressingFeature msa = features.get(MemberSubmissionAddressingFeature.class); if (msa == null) { msa = this.features.get(MemberSubmissionAddressingFeature.class); } if (msa != null && msa.isEnabled()) isAddressingEnabled = true; if(isAddressingEnabled && wsdlService != null && wsdlService.get(portName) != null) { wsepr = wsdlService.get(portName).getEPR(); } return createDispatch(portName, wsepr, aClass, mode, features); } public <T> Dispatch<T> createDispatch(EndpointReference endpointReference, Class<T> type, Service.Mode mode, WebServiceFeature... features) { WSEndpointReference wsepr = new WSEndpointReference(endpointReference); QName portName = addPortEpr(wsepr); return createDispatch(portName, wsepr, type, mode, features); }
Obtains PortInfo for the given name, with error check.
/** * Obtains {@link PortInfo} for the given name, with error check. */
public @NotNull PortInfo safeGetPort(QName portName) { PortInfo port = ports.get(portName); if (port == null) { throw new WebServiceException(ClientMessages.INVALID_PORT_NAME(portName, buildNameList(ports.keySet()))); } return port; } private StringBuilder buildNameList(Collection<QName> names) { StringBuilder sb = new StringBuilder(); for (QName qn : names) { if (sb.length() > 0) sb.append(','); sb.append(qn); } return sb; } public EndpointAddress getEndpointAddress(QName qName) { PortInfo p = ports.get(qName); return p != null ? p.targetEndpoint : null; } public Dispatch<Object> createDispatch(QName portName, JAXBContext jaxbContext, Service.Mode mode) throws WebServiceException { return createDispatch(portName, jaxbContext, mode, EMPTY_FEATURES); } @Override public Dispatch<Object> createDispatch(QName portName, WSEndpointReference wsepr, JAXBContext jaxbContext, Service.Mode mode, WebServiceFeature... features) { return createDispatch(portName, wsepr, jaxbContext, mode, new WebServiceFeatureList(features)); } protected Dispatch<Object> createDispatch(QName portName, WSEndpointReference wsepr, JAXBContext jaxbContext, Service.Mode mode, WebServiceFeatureList features) { PortInfo port = safeGetPort(portName); ComponentFeature cf = features.get(ComponentFeature.class); if (cf != null && !Target.STUB.equals(cf.getTarget())) { throw new IllegalArgumentException(); } ComponentsFeature csf = features.get(ComponentsFeature.class); if (csf != null) { for (ComponentFeature cfi : csf.getComponentFeatures()) { if (!Target.STUB.equals(cfi.getTarget())) throw new IllegalArgumentException(); } } features.addAll(this.features); BindingImpl binding = port.createBinding(features, null, null); binding.setMode(mode); Dispatch<Object> dispatch = Stubs.createJAXBDispatch( port, binding, jaxbContext, mode,wsepr); serviceInterceptor.postCreateDispatch((WSBindingProvider)dispatch); return dispatch; } @Override public @NotNull Container getContainer() { return container; } public Dispatch<Object> createDispatch(QName portName, JAXBContext jaxbContext, Service.Mode mode, WebServiceFeature... webServiceFeatures) { return createDispatch(portName, jaxbContext, mode, new WebServiceFeatureList(webServiceFeatures)); } protected Dispatch<Object> createDispatch(QName portName, JAXBContext jaxbContext, Service.Mode mode, WebServiceFeatureList features) { WSEndpointReference wsepr = null; boolean isAddressingEnabled = false; AddressingFeature af = features.get(AddressingFeature.class); if (af == null) { af = this.features.get(AddressingFeature.class); } if (af != null && af.isEnabled()) isAddressingEnabled = true; MemberSubmissionAddressingFeature msa = features.get(MemberSubmissionAddressingFeature.class); if (msa == null) { msa = this.features.get(MemberSubmissionAddressingFeature.class); } if (msa != null && msa.isEnabled()) isAddressingEnabled = true; if(isAddressingEnabled && wsdlService != null && wsdlService.get(portName) != null) { wsepr = wsdlService.get(portName).getEPR(); } return createDispatch(portName, wsepr, jaxbContext, mode, features); } public Dispatch<Object> createDispatch(EndpointReference endpointReference, JAXBContext context, Service.Mode mode, WebServiceFeature... features) { WSEndpointReference wsepr = new WSEndpointReference(endpointReference); QName portName = addPortEpr(wsepr); return createDispatch(portName, wsepr, context, mode, features); } private QName addPortEpr(WSEndpointReference wsepr) { if (wsepr == null) throw new WebServiceException(ProviderApiMessages.NULL_EPR()); QName eprPortName = getPortNameFromEPR(wsepr, null); //add Port, if it does n't exist; // TODO: what if it has different epr address? { PortInfo portInfo = new PortInfo(this, (wsepr.getAddress() == null) ? null : EndpointAddress.create(wsepr.getAddress()), eprPortName, getPortModel(wsdlService, eprPortName).getBinding().getBindingId()); if (!ports.containsKey(eprPortName)) { ports.put(eprPortName, portInfo); } } return eprPortName; }
Params:
  • wsepr – EndpointReference from which portName will be extracted. If EndpointName ( port name) is null in EPR, then it will try to get if from WSDLModel using portType QName
  • portTypeName – should be null in dispatch case should be non null in SEI case
Returns: port name from EPR after validating various metadat elements. Also if service instance does n't have wsdl, then it gets the WSDL metadata from EPR and builds wsdl model.
/** * * @param wsepr EndpointReference from which portName will be extracted. * If EndpointName ( port name) is null in EPR, then it will try to get if from WSDLModel using portType QName * @param portTypeName * should be null in dispatch case * should be non null in SEI case * @return * port name from EPR after validating various metadat elements. * Also if service instance does n't have wsdl, * then it gets the WSDL metadata from EPR and builds wsdl model. */
private QName getPortNameFromEPR(@NotNull WSEndpointReference wsepr, @Nullable QName portTypeName) { QName portName; WSEndpointReference.Metadata metadata = wsepr.getMetaData(); QName eprServiceName = metadata.getServiceName(); QName eprPortName = metadata.getPortName(); if ((eprServiceName != null ) && !eprServiceName.equals(serviceName)) { throw new WebServiceException("EndpointReference WSDL ServiceName differs from Service Instance WSDL Service QName.\n" + " The two Service QNames must match"); } if (wsdlService == null) { Source eprWsdlSource = metadata.getWsdlSource(); if (eprWsdlSource == null) { throw new WebServiceException(ProviderApiMessages.NULL_WSDL()); } try { WSDLModel eprWsdlMdl = parseWSDL(new URL(wsepr.getAddress()), eprWsdlSource, null); wsdlService = eprWsdlMdl.getService(serviceName); if (wsdlService == null) throw new WebServiceException(ClientMessages.INVALID_SERVICE_NAME(serviceName, buildNameList(eprWsdlMdl.getServices().keySet()))); } catch (MalformedURLException e) { throw new WebServiceException(ClientMessages.INVALID_ADDRESS(wsepr.getAddress())); } } portName = eprPortName; if (portName == null && portTypeName != null) { //get the first port corresponding to the SEI WSDLPort port = wsdlService.getMatchingPort(portTypeName); if (port == null) throw new WebServiceException(ClientMessages.UNDEFINED_PORT_TYPE(portTypeName)); portName = port.getName(); } if (portName == null) throw new WebServiceException(ProviderApiMessages.NULL_PORTNAME()); if (wsdlService.get(portName) == null) throw new WebServiceException(ClientMessages.INVALID_EPR_PORT_NAME(portName, buildWsdlPortNames())); return portName; } private <T> T createProxy(final Class<T> portInterface, final InvocationHandler pis) { // When creating the proxy, use a ClassLoader that can load classes // from both the interface class and also from this classes // classloader. This is necessary when this code is used in systems // such as OSGi where the class loader for the interface class may // not be able to load internal JAX-WS classes like // "WSBindingProvider", but the class loader for this class may not // be able to load the interface class. final ClassLoader loader = getDelegatingLoader(portInterface.getClassLoader(), WSServiceDelegate.class.getClassLoader()); return AccessController.doPrivileged( new PrivilegedAction<T>() { @Override public T run() { Object proxy = Proxy.newProxyInstance(loader, new Class[]{portInterface, WSBindingProvider.class, Closeable.class}, pis); return portInterface.cast(proxy); } }); } private WSDLService getWSDLModelfromSEI(final Class sei) { WebService ws = AccessController.doPrivileged(new PrivilegedAction<WebService>() { public WebService run() { return (WebService) sei.getAnnotation(WebService.class); } }); if (ws == null || ws.wsdlLocation().equals("")) return null; String wsdlLocation = ws.wsdlLocation(); wsdlLocation = JAXWSUtils.absolutize(JAXWSUtils.getFileOrURLName(wsdlLocation)); Source wsdl = new StreamSource(wsdlLocation); WSDLService service = null; try { URL url = wsdl.getSystemId() == null ? null : new URL(wsdl.getSystemId()); WSDLModel model = parseWSDL(url, wsdl, sei); service = model.getService(this.serviceName); if (service == null) throw new WebServiceException( ClientMessages.INVALID_SERVICE_NAME(this.serviceName, buildNameList(model.getServices().keySet()))); } catch (MalformedURLException e) { throw new WebServiceException(ClientMessages.INVALID_WSDL_URL(wsdl.getSystemId())); } return service; } public QName getServiceName() { return serviceName; } public Class getServiceClass() { return serviceClass; } public Iterator<QName> getPorts() throws WebServiceException { // KK: the spec seems to be ambigous about whether // this returns ports that are dynamically added or not. return ports.keySet().iterator(); } @Override public URL getWSDLDocumentLocation() { if(wsdlService==null) return null; try { return new URL(wsdlService.getParent().getLocation().getSystemId()); } catch (MalformedURLException e) { throw new AssertionError(e); // impossible } } private <T> T createEndpointIFBaseProxy(@Nullable WSEndpointReference epr, QName portName, Class<T> portInterface, WebServiceFeatureList webServiceFeatures, SEIPortInfo eif) { //fail if service doesnt have WSDL if (wsdlService == null) { throw new WebServiceException(ClientMessages.INVALID_SERVICE_NO_WSDL(serviceName)); } if (wsdlService.get(portName)==null) { throw new WebServiceException( ClientMessages.INVALID_PORT_NAME(portName,buildWsdlPortNames())); } BindingImpl binding = eif.createBinding(webServiceFeatures, portInterface); InvocationHandler pis = getStubHandler(binding, eif, epr); T proxy = createProxy(portInterface, pis); if (serviceInterceptor != null) { serviceInterceptor.postCreateProxy((WSBindingProvider)proxy, portInterface); } return proxy; } protected InvocationHandler getStubHandler(BindingImpl binding, SEIPortInfo eif, @Nullable WSEndpointReference epr) { return new SEIStub(eif, binding, eif.model, epr); }
Lists up the port names in WSDL. For error diagnostics.
/** * Lists up the port names in WSDL. For error diagnostics. */
private StringBuilder buildWsdlPortNames() { Set<QName> wsdlPortNames = new HashSet<QName>(); for (WSDLPort port : wsdlService.getPorts()) { wsdlPortNames.add(port.getName()); } return buildNameList(wsdlPortNames); }
Obtains a WSDLPortImpl with error check.
Returns:guaranteed to be non-null.
/** * Obtains a {@link WSDLPortImpl} with error check. * * @return guaranteed to be non-null. */
public @NotNull WSDLPort getPortModel(WSDLService wsdlService, QName portName) { WSDLPort port = wsdlService.get(portName); if (port == null) throw new WebServiceException( ClientMessages.INVALID_PORT_NAME(portName,buildWsdlPortNames())); return port; }
Contributes to the construction of WSServiceDelegate by filling in SEIPortInfo about a given SEI (linked from the Service-derived class.)
/** * Contributes to the construction of {@link WSServiceDelegate} by filling in * {@link SEIPortInfo} about a given SEI (linked from the {@link Service}-derived class.) */
//todo: valid port in wsdl private SEIPortInfo addSEI(QName portName, Class portInterface, WebServiceFeatureList features) throws WebServiceException { boolean ownModel = useOwnSEIModel(features); if (ownModel) { // Create a new model and do not cache it return createSEIPortInfo(portName, portInterface, features); } SEIPortInfo spi = seiContext.get(portName); if (spi == null) { spi = createSEIPortInfo(portName, portInterface, features); seiContext.put(spi.portName, spi); ports.put(spi.portName, spi); } return spi; } public SEIModel buildRuntimeModel(QName serviceName, QName portName, Class portInterface, WSDLPort wsdlPort, WebServiceFeatureList features) { DatabindingFactory fac = DatabindingFactory.newInstance(); DatabindingConfig config = new DatabindingConfig(); config.setContractClass(portInterface); config.getMappingInfo().setServiceName(serviceName); config.setWsdlPort(wsdlPort); config.setFeatures(features); config.setClassLoader(portInterface.getClassLoader()); config.getMappingInfo().setPortName(portName); config.setWsdlURL(wsdlURL); // if ExternalMetadataFeature present, ExternalMetadataReader will be created ... config.setMetadataReader(getMetadadaReader(features, portInterface.getClassLoader())); com.sun.xml.internal.ws.db.DatabindingImpl rt = (com.sun.xml.internal.ws.db.DatabindingImpl)fac.createRuntime(config); return rt.getModel(); } private MetadataReader getMetadadaReader(WebServiceFeatureList features, ClassLoader classLoader) { if (features == null) return null; com.oracle.webservices.internal.api.databinding.ExternalMetadataFeature ef = features.get(com.oracle.webservices.internal.api.databinding.ExternalMetadataFeature.class); // TODO-Miran: would it be necessary to disable secure xml processing? if (ef != null) return ef.getMetadataReader(classLoader, false); return null; } private SEIPortInfo createSEIPortInfo(QName portName, Class portInterface, WebServiceFeatureList features) { WSDLPort wsdlPort = getPortModel(wsdlService, portName); SEIModel model = buildRuntimeModel(serviceName, portName, portInterface, wsdlPort, features); return new SEIPortInfo(this, portInterface, (SOAPSEIModel) model, wsdlPort); } private boolean useOwnSEIModel(WebServiceFeatureList features) { return features.contains(UsesJAXBContextFeature.class); } public WSDLService getWsdlService() { return wsdlService; } protected static final WebServiceFeature[] EMPTY_FEATURES = new WebServiceFeature[0]; private static ClassLoader getDelegatingLoader(ClassLoader loader1, ClassLoader loader2) { if (loader1 == null) return loader2; if (loader2 == null) return loader1; return new DelegatingLoader(loader1, loader2); } private static final class DelegatingLoader extends ClassLoader { private final ClassLoader loader; @Override public int hashCode() { final int prime = 31; int result = 1; result = prime * result + ((loader == null) ? 0 : loader.hashCode()); result = prime * result + ((getParent() == null) ? 0 : getParent().hashCode()); return result; } @Override public boolean equals(Object obj) { if (this == obj) return true; if (obj == null) return false; if (getClass() != obj.getClass()) return false; DelegatingLoader other = (DelegatingLoader) obj; if (loader == null) { if (other.loader != null) return false; } else if (!loader.equals(other.loader)) return false; if (getParent() == null) { if (other.getParent() != null) return false; } else if (!getParent().equals(other.getParent())) return false; return true; } DelegatingLoader(ClassLoader loader1, ClassLoader loader2) { super(loader2); this.loader = loader1; } protected Class findClass(String name) throws ClassNotFoundException { return loader.loadClass(name); } protected URL findResource(String name) { return loader.getResource(name); } } }