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

Tue, 06 Mar 2012 16:09:35 -0800

author
ohair
date
Tue, 06 Mar 2012 16:09:35 -0800
changeset 286
f50545b5e2f1
child 368
0989ad8c0860
permissions
-rw-r--r--

7150322: Stop using drop source bundles in jaxws
Reviewed-by: darcy, ohrstrom

     1 /*
     2  * Copyright (c) 1997, 2010, Oracle and/or its affiliates. All rights reserved.
     3  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
     4  *
     5  * This code is free software; you can redistribute it and/or modify it
     6  * under the terms of the GNU General Public License version 2 only, as
     7  * published by the Free Software Foundation.  Oracle designates this
     8  * particular file as subject to the "Classpath" exception as provided
     9  * by Oracle in the LICENSE file that accompanied this code.
    10  *
    11  * This code is distributed in the hope that it will be useful, but WITHOUT
    12  * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
    13  * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
    14  * version 2 for more details (a copy is included in the LICENSE file that
    15  * accompanied this code).
    16  *
    17  * You should have received a copy of the GNU General Public License version
    18  * 2 along with this work; if not, write to the Free Software Foundation,
    19  * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
    20  *
    21  * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
    22  * or visit www.oracle.com if you need additional information or have any
    23  * questions.
    24  */
    26 package com.sun.xml.internal.ws.client;
    28 import com.sun.istack.internal.NotNull;
    29 import com.sun.istack.internal.Nullable;
    30 import com.sun.xml.internal.ws.Closeable;
    31 import com.sun.xml.internal.ws.api.BindingID;
    32 import com.sun.xml.internal.ws.api.ComponentFeature;
    33 import com.sun.xml.internal.ws.api.ComponentFeature.Target;
    34 import com.sun.xml.internal.ws.api.EndpointAddress;
    35 import com.sun.xml.internal.ws.api.WSService;
    36 import com.sun.xml.internal.ws.api.addressing.WSEndpointReference;
    37 import com.sun.xml.internal.ws.api.client.ServiceInterceptor;
    38 import com.sun.xml.internal.ws.api.client.ServiceInterceptorFactory;
    39 import com.sun.xml.internal.ws.api.databinding.DatabindingFactory;
    40 import com.sun.xml.internal.ws.api.databinding.DatabindingConfig;
    41 import com.sun.xml.internal.ws.api.model.SEIModel;
    42 import com.sun.xml.internal.ws.api.model.wsdl.WSDLPort;
    43 import com.sun.xml.internal.ws.api.model.wsdl.WSDLService;
    44 import com.sun.xml.internal.ws.api.pipe.*;
    45 import com.sun.xml.internal.ws.api.server.Container;
    46 import com.sun.xml.internal.ws.api.server.ContainerResolver;
    47 import com.sun.xml.internal.ws.api.wsdl.parser.WSDLParserExtension;
    48 import com.sun.xml.internal.ws.binding.BindingImpl;
    49 import com.sun.xml.internal.ws.binding.WebServiceFeatureList;
    50 import com.sun.xml.internal.ws.client.HandlerConfigurator.AnnotationConfigurator;
    51 import com.sun.xml.internal.ws.client.HandlerConfigurator.HandlerResolverImpl;
    52 import com.sun.xml.internal.ws.client.sei.SEIStub;
    53 import com.sun.xml.internal.ws.developer.MemberSubmissionAddressingFeature;
    54 import com.sun.xml.internal.ws.developer.WSBindingProvider;
    55 import com.sun.xml.internal.ws.developer.UsesJAXBContextFeature;
    56 import com.sun.xml.internal.ws.model.RuntimeModeler;
    57 import com.sun.xml.internal.ws.model.SOAPSEIModel;
    58 import com.sun.xml.internal.ws.model.wsdl.WSDLModelImpl;
    59 import com.sun.xml.internal.ws.model.wsdl.WSDLPortImpl;
    60 import com.sun.xml.internal.ws.model.wsdl.WSDLServiceImpl;
    61 import com.sun.xml.internal.ws.resources.ClientMessages;
    62 import com.sun.xml.internal.ws.resources.DispatchMessages;
    63 import com.sun.xml.internal.ws.resources.ProviderApiMessages;
    64 import com.sun.xml.internal.ws.util.JAXWSUtils;
    65 import com.sun.xml.internal.ws.util.ServiceConfigurationError;
    66 import com.sun.xml.internal.ws.util.ServiceFinder;
    67 import static com.sun.xml.internal.ws.util.xml.XmlUtil.createDefaultCatalogResolver;
    68 import com.sun.xml.internal.ws.wsdl.parser.RuntimeWSDLParser;
    70 import org.xml.sax.EntityResolver;
    71 import org.xml.sax.SAXException;
    73 import javax.jws.HandlerChain;
    74 import javax.jws.WebService;
    75 import javax.xml.bind.JAXBContext;
    76 import javax.xml.namespace.QName;
    77 import javax.xml.stream.XMLStreamException;
    78 import javax.xml.transform.Source;
    79 import javax.xml.transform.stream.StreamSource;
    80 import javax.xml.ws.*;
    81 import javax.xml.ws.handler.HandlerResolver;
    82 import javax.xml.ws.soap.AddressingFeature;
    83 import java.io.IOException;
    84 import java.lang.reflect.InvocationHandler;
    85 import java.lang.reflect.Proxy;
    86 import java.net.MalformedURLException;
    87 import java.net.URL;
    88 import java.security.AccessController;
    89 import java.security.PrivilegedAction;
    90 import java.util.*;
    91 import java.util.concurrent.Executor;
    92 import java.util.concurrent.ThreadFactory;
    94 /**
    95  * <code>Service</code> objects provide the client view of a Web service.
    96  *
    97  * <p><code>Service</code> acts as a factory of the following:
    98  * <ul>
    99  * <li>Proxies for a target service endpoint.
   100  * <li>Instances of <code>javax.xml.ws.Dispatch</code> for
   101  * dynamic message-oriented invocation of a remote
   102  * operation.
   103  * </li>
   104  *
   105  * <p>The ports available on a service can be enumerated using the
   106  * <code>getPorts</code> method. Alternatively, you can pass a
   107  * service endpoint interface to the unary <code>getPort</code> method
   108  * and let the runtime select a compatible port.
   109  *
   110  * <p>Handler chains for all the objects created by a <code>Service</code>
   111  * can be set by means of the provided <code>HandlerRegistry</code>.
   112  *
   113  * <p>An <code>Executor</code> may be set on the service in order
   114  * to gain better control over the threads used to dispatch asynchronous
   115  * callbacks. For instance, thread pooling with certain parameters
   116  * can be enabled by creating a <code>ThreadPoolExecutor</code> and
   117  * registering it with the service.
   118  *
   119  * @author WS Development Team
   120  * @see Executor
   121  * @since JAX-WS 2.0
   122  */
   123 public class WSServiceDelegate extends WSService {
   124     /**
   125      * All ports.
   126      * <p>
   127      * This includes ports statically known to WSDL, as well as
   128      * ones that are dynamically added
   129      * through {@link #addPort(QName, String, String)}.
   130      * <p>
   131      * For statically known ports we'll have {@link SEIPortInfo}.
   132      * For dynamically added ones we'll have {@link PortInfo}.
   133      */
   134     private final Map<QName, PortInfo> ports = new HashMap<QName, PortInfo>();
   135     // For monitoring
   136     protected Map<QName, PortInfo> getQNameToPortInfoMap() { return ports; }
   138     /**
   139      * Whenever we create {@link BindingProvider}, we use this to configure handlers.
   140      */
   141     private @NotNull HandlerConfigurator handlerConfigurator = new HandlerResolverImpl(null);
   143     private final Class<? extends Service> serviceClass;
   145     private final WebServiceFeatureList features;
   147     /**
   148      * Name of the service for which this {@link WSServiceDelegate} is created for.
   149      */
   150     private final @NotNull QName serviceName;
   152     /**
   153      * Information about SEI, keyed by their interface type.
   154      */
   155    // private final Map<Class,SEIPortInfo> seiContext = new HashMap<Class,SEIPortInfo>();
   156    private final Map<QName,SEIPortInfo> seiContext = new HashMap<QName,SEIPortInfo>();
   158     // This executor is used for all the async invocations for all proxies
   159     // created from this service. But once the proxy is created, then changing
   160     // this executor doesn't affect the already created proxies.
   161     private volatile Executor executor;
   163     /**
   164      * The WSDL service that this {@link Service} object represents.
   165      * <p>
   166      * This field is null iff no WSDL is given to {@link Service}.
   167      * This fiels can be be null if the service is created without wsdl but later
   168      * the epr supplies a wsdl that can be parsed.
   169      */
   170     private  @Nullable WSDLServiceImpl wsdlService;
   172     private final Container container;
   173     /**
   174      * Multiple {@link ServiceInterceptor}s are aggregated into one.
   175      */
   176     /*package*/ final @NotNull ServiceInterceptor serviceInterceptor;
   179     public WSServiceDelegate(URL wsdlDocumentLocation, QName serviceName, Class<? extends Service> serviceClass, WebServiceFeature... features) {
   180         this(
   181             wsdlDocumentLocation==null ? null : new StreamSource(wsdlDocumentLocation.toExternalForm()),
   182             serviceName,serviceClass, features);
   183     }
   185     /**
   186      * @param serviceClass
   187      *      Either {@link Service}.class or other generated service-derived classes.
   188      */
   189     public WSServiceDelegate(@Nullable Source wsdl, @NotNull QName serviceName, @NotNull final Class<? extends Service> serviceClass, WebServiceFeature... features) {
   190         this(wsdl, null, serviceName, serviceClass, features);
   191     }
   193     /**
   194      * @param serviceClass
   195      *      Either {@link Service}.class or other generated service-derived classes.
   196      */
   197     public WSServiceDelegate(@Nullable Source wsdl, @Nullable WSDLServiceImpl service, @NotNull QName serviceName, @NotNull final Class<? extends Service> serviceClass, WebServiceFeature... features) {
   198         //we cant create a Service without serviceName
   199         if (serviceName == null)
   200             throw new WebServiceException(ClientMessages.INVALID_SERVICE_NAME_NULL(serviceName));
   202         this.features = new WebServiceFeatureList(features);
   204         InitParams initParams = INIT_PARAMS.get();
   205         INIT_PARAMS.set(null);  // mark it as consumed
   206         if(initParams==null)    initParams = EMPTY_PARAMS;
   208         this.serviceName = serviceName;
   209         this.serviceClass = serviceClass;
   210         Container tContainer = initParams.getContainer()!=null ? initParams.getContainer() : ContainerResolver.getInstance().getContainer();
   211         if (tContainer == Container.NONE) {
   212             tContainer = new ClientContainer();
   213         }
   214         this.container = tContainer;
   216         ComponentFeature cf = this.features.get(ComponentFeature.class);
   217         if (cf != null) {
   218             switch(cf.getTarget()) {
   219                 case SERVICE:
   220                     getComponents().add(cf.getComponent());
   221                     break;
   222                 case CONTAINER:
   223                     this.container.getComponents().add(cf.getComponent());
   224                 default:
   225                     throw new IllegalArgumentException();
   226             }
   227         }
   229         // load interceptor
   230         ServiceInterceptor interceptor = ServiceInterceptorFactory.load(this, Thread.currentThread().getContextClassLoader());
   231         ServiceInterceptor si = container.getSPI(ServiceInterceptor.class);
   232         if (si != null) {
   233             interceptor = ServiceInterceptor.aggregate(interceptor, si);
   234         }
   235         this.serviceInterceptor = interceptor;
   237         if (service == null) {
   238                 //if wsdl is null, try and get it from the WebServiceClient.wsdlLocation
   239                 if(wsdl == null){
   240                     if(serviceClass != Service.class){
   241                         WebServiceClient wsClient = AccessController.doPrivileged(new PrivilegedAction<WebServiceClient>() {
   242                                 public WebServiceClient run() {
   243                                     return serviceClass.getAnnotation(WebServiceClient.class);
   244                                 }
   245                             });
   246                         String wsdlLocation = wsClient.wsdlLocation();
   247                         wsdlLocation = JAXWSUtils.absolutize(JAXWSUtils.getFileOrURLName(wsdlLocation));
   248                         wsdl = new StreamSource(wsdlLocation);
   249                     }
   250                 }
   251                 if (wsdl != null) {
   252                     try {
   253                         URL url = wsdl.getSystemId()==null ? null : JAXWSUtils.getEncodedURL(wsdl.getSystemId());
   254                         WSDLModelImpl model = parseWSDL(url, wsdl, serviceClass);
   255                         service = model.getService(this.serviceName);
   256                         if (service == null)
   257                             throw new WebServiceException(
   258                                 ClientMessages.INVALID_SERVICE_NAME(this.serviceName,
   259                                     buildNameList(model.getServices().keySet())));
   260                         // fill in statically known ports
   261                         for (WSDLPort port : service.getPorts())
   262                             ports.put(port.getName(), new PortInfo(this, port));
   263                     } catch (MalformedURLException e) {
   264                         throw new WebServiceException(ClientMessages.INVALID_WSDL_URL(wsdl.getSystemId()));
   265                     }
   266                 }
   267         }
   268         this.wsdlService = service;
   270         if (serviceClass != Service.class) {
   271             //if @HandlerChain present, set HandlerResolver on service context
   272             HandlerChain handlerChain =
   273                     AccessController.doPrivileged(new PrivilegedAction<HandlerChain>() {
   274                         public HandlerChain run() {
   275                             return serviceClass.getAnnotation(HandlerChain.class);
   276                         }
   277                     });
   278             if (handlerChain != null)
   279                 handlerConfigurator = new AnnotationConfigurator(this);
   280         }
   282     }
   284     /**
   285      * Parses the WSDL and builds {@link com.sun.xml.internal.ws.api.model.wsdl.WSDLModel}.
   286      * @param wsdlDocumentLocation
   287      *      Either this or <tt>wsdl</tt> parameter must be given.
   288      *      Null location means the system won't be able to resolve relative references in the WSDL,
   289      */
   290     private WSDLModelImpl parseWSDL(URL wsdlDocumentLocation, Source wsdlSource, Class serviceClass) {
   291         try {
   292             return RuntimeWSDLParser.parse(wsdlDocumentLocation, wsdlSource, createCatalogResolver(),
   293                 true, getContainer(), serviceClass, ServiceFinder.find(WSDLParserExtension.class).toArray());
   294         } catch (IOException e) {
   295             throw new WebServiceException(e);
   296         } catch (XMLStreamException e) {
   297             throw new WebServiceException(e);
   298         } catch (SAXException e) {
   299             throw new WebServiceException(e);
   300         } catch (ServiceConfigurationError e) {
   301             throw new WebServiceException(e);
   302         }
   303     }
   305     protected EntityResolver createCatalogResolver() {
   306         return createDefaultCatalogResolver();
   307     }
   309     public Executor getExecutor() {
   310         return executor;
   311     }
   313     public void setExecutor(Executor executor) {
   314         this.executor = executor;
   315     }
   317     public HandlerResolver getHandlerResolver() {
   318         return handlerConfigurator.getResolver();
   319     }
   321     /*package*/ final HandlerConfigurator getHandlerConfigurator() {
   322         return handlerConfigurator;
   323     }
   325     public void setHandlerResolver(HandlerResolver resolver) {
   326         handlerConfigurator = new HandlerResolverImpl(resolver);
   327     }
   329     public <T> T getPort(QName portName, Class<T> portInterface) throws WebServiceException {
   330         return getPort(portName, portInterface, EMPTY_FEATURES);
   331     }
   333     public <T> T getPort(QName portName, Class<T> portInterface, WebServiceFeature... features) {
   334         if (portName == null || portInterface == null)
   335             throw new IllegalArgumentException();
   336         WSDLServiceImpl tWsdlService = this.wsdlService;
   337         if (tWsdlService == null) {
   338             // assigning it to local variable and not setting it back to this.wsdlService intentionally
   339             // as we don't want to include the service instance with information gathered from sei
   340             tWsdlService = getWSDLModelfromSEI(portInterface);
   341             //still null? throw error need wsdl metadata to create a proxy
   342             if (tWsdlService == null) {
   343                 throw new WebServiceException(ProviderApiMessages.NO_WSDL_NO_PORT(portInterface.getName()));
   344             }
   346         }
   347         WSDLPortImpl portModel = getPortModel(tWsdlService, portName);
   348         return getPort(portModel.getEPR(), portName, portInterface, new WebServiceFeatureList(features));
   349     }
   351     public <T> T getPort(EndpointReference epr, Class<T> portInterface, WebServiceFeature... features) {
   352         return getPort(WSEndpointReference.create(epr),portInterface,features);
   353     }
   355     public <T> T getPort(WSEndpointReference wsepr, Class<T> portInterface, WebServiceFeature... features) {
   356         //get the portType from SEI, so that it can be used if EPR does n't have endpointName
   357         QName portTypeName = RuntimeModeler.getPortTypeName(portInterface);
   358         //if port name is not specified in EPR, it will use portTypeName to get it from the WSDL model.
   359         QName portName = getPortNameFromEPR(wsepr, portTypeName);
   360         return getPort(wsepr,portName,portInterface,new WebServiceFeatureList(features));
   361     }
   363     protected <T> T getPort(WSEndpointReference wsepr, QName portName, Class<T> portInterface,
   364                           WebServiceFeatureList features) {
   365         ComponentFeature cf = features.get(ComponentFeature.class);
   366         if (cf != null && !Target.STUB.equals(cf.getTarget())) {
   367             throw new IllegalArgumentException();
   368         }
   369         features.addAll(this.features);
   371         SEIPortInfo spi = addSEI(portName, portInterface, features);
   372         return createEndpointIFBaseProxy(wsepr,portName,portInterface,features, spi);
   373     }
   375     public <T> T getPort(Class<T> portInterface, WebServiceFeature... features) {
   376         //get the portType from SEI
   377         QName portTypeName = RuntimeModeler.getPortTypeName(portInterface);
   378         WSDLServiceImpl wsdlService = this.wsdlService;
   379         if(wsdlService == null) {
   380             // assigning it to local variable and not setting it back to this.wsdlService intentionally
   381             // as we don't want to include the service instance with information gathered from sei
   382             wsdlService = getWSDLModelfromSEI(portInterface);
   383             //still null? throw error need wsdl metadata to create a proxy
   384             if(wsdlService == null) {
   385                 throw new WebServiceException(ProviderApiMessages.NO_WSDL_NO_PORT(portInterface.getName()));
   386             }
   387         }
   388         //get the first port corresponding to the SEI
   389         WSDLPortImpl port = wsdlService.getMatchingPort(portTypeName);
   390         if (port == null)
   391                 throw new WebServiceException(ClientMessages.UNDEFINED_PORT_TYPE(portTypeName));
   392         QName portName = port.getName();
   393         return getPort(portName, portInterface,features);
   394     }
   396     public <T> T getPort(Class<T> portInterface) throws WebServiceException {
   397         return getPort(portInterface, EMPTY_FEATURES);
   398     }
   400     public void addPort(QName portName, String bindingId, String endpointAddress) throws WebServiceException {
   401         if (!ports.containsKey(portName)) {
   402             BindingID bid = (bindingId == null) ? BindingID.SOAP11_HTTP : BindingID.parse(bindingId);
   403             ports.put(portName,
   404                     new PortInfo(this, (endpointAddress == null) ? null :
   405                             EndpointAddress.create(endpointAddress), portName, bid));
   406         } else
   407             throw new WebServiceException(DispatchMessages.DUPLICATE_PORT(portName.toString()));
   408     }
   411     public <T> Dispatch<T> createDispatch(QName portName, Class<T>  aClass, Service.Mode mode) throws WebServiceException {
   412         return createDispatch(portName, aClass, mode, EMPTY_FEATURES);
   413     }
   415     @Override
   416     public <T> Dispatch<T> createDispatch(QName portName, WSEndpointReference wsepr, Class<T> aClass, Service.Mode mode, WebServiceFeature... features) {
   417         return createDispatch(portName, wsepr, aClass, mode, new WebServiceFeatureList(features));
   418     }
   420     public <T> Dispatch<T> createDispatch(QName portName, WSEndpointReference wsepr, Class<T> aClass, Service.Mode mode, WebServiceFeatureList features) {
   421         PortInfo port = safeGetPort(portName);
   423         ComponentFeature cf = features.get(ComponentFeature.class);
   424         if (cf != null && !Target.STUB.equals(cf.getTarget())) {
   425             throw new IllegalArgumentException();
   426         }
   427         features.addAll(this.features);
   429         BindingImpl binding = port.createBinding(features, null, null);
   430         binding.setMode(mode);
   431         Dispatch<T> dispatch = Stubs.createDispatch(port, this, binding, aClass, mode, wsepr);
   432         serviceInterceptor.postCreateDispatch((WSBindingProvider) dispatch);
   433         return dispatch;
   434     }
   436     public <T> Dispatch<T> createDispatch(QName portName, Class<T> aClass, Service.Mode mode, WebServiceFeature... features) {
   437         return createDispatch(portName, aClass, mode, new WebServiceFeatureList(features));
   438     }
   440     public <T> Dispatch<T> createDispatch(QName portName, Class<T> aClass, Service.Mode mode, WebServiceFeatureList features) {
   441         WSEndpointReference wsepr = null;
   442         boolean isAddressingEnabled = false;
   443         AddressingFeature af = features.get(AddressingFeature.class);
   444         if (af == null) {
   445             af = this.features.get(AddressingFeature.class);
   446         }
   447         if (af != null && af.isEnabled())
   448             isAddressingEnabled = true;
   449         MemberSubmissionAddressingFeature msa = features.get(MemberSubmissionAddressingFeature.class);
   450         if (msa == null) {
   451             msa = this.features.get(MemberSubmissionAddressingFeature.class);
   452         }
   453         if (msa != null && msa.isEnabled())
   454             isAddressingEnabled = true;
   455         if(isAddressingEnabled && wsdlService != null && wsdlService.get(portName) != null) {
   456             wsepr = wsdlService.get(portName).getEPR();
   457         }
   458         return createDispatch(portName, wsepr, aClass, mode, features);
   459     }
   461     public <T> Dispatch<T> createDispatch(EndpointReference endpointReference, Class<T> type, Service.Mode mode, WebServiceFeature... features) {
   462         WSEndpointReference wsepr = new WSEndpointReference(endpointReference);
   463         QName portName = addPortEpr(wsepr);
   464         return createDispatch(portName, wsepr, type, mode, features);
   465     }
   467     /**
   468      * Obtains {@link PortInfo} for the given name, with error check.
   469      */
   470     public
   471     @NotNull
   472     PortInfo safeGetPort(QName portName) {
   473         PortInfo port = ports.get(portName);
   474         if (port == null) {
   475             throw new WebServiceException(ClientMessages.INVALID_PORT_NAME(portName, buildNameList(ports.keySet())));
   476         }
   477         return port;
   478     }
   480     private StringBuilder buildNameList(Collection<QName> names) {
   481         StringBuilder sb = new StringBuilder();
   482         for (QName qn : names) {
   483             if (sb.length() > 0) sb.append(',');
   484             sb.append(qn);
   485         }
   486         return sb;
   487     }
   489     public EndpointAddress getEndpointAddress(QName qName) {
   490         PortInfo p = ports.get(qName);
   491         return p != null ? p.targetEndpoint : null;
   492     }
   494     public Dispatch<Object> createDispatch(QName portName, JAXBContext jaxbContext, Service.Mode mode) throws WebServiceException {
   495         return createDispatch(portName, jaxbContext, mode, EMPTY_FEATURES);
   496     }
   498     @Override
   499     public Dispatch<Object> createDispatch(QName portName, WSEndpointReference wsepr, JAXBContext jaxbContext, Service.Mode mode, WebServiceFeature... features) {
   500         return createDispatch(portName, wsepr, jaxbContext, mode, new WebServiceFeatureList(features));
   501     }
   503     protected Dispatch<Object> createDispatch(QName portName, WSEndpointReference wsepr, JAXBContext jaxbContext, Service.Mode mode, WebServiceFeatureList features) {
   504         PortInfo port = safeGetPort(portName);
   506         ComponentFeature cf = features.get(ComponentFeature.class);
   507         if (cf != null && !Target.STUB.equals(cf.getTarget())) {
   508             throw new IllegalArgumentException();
   509         }
   510         features.addAll(this.features);
   512         BindingImpl binding = port.createBinding(features, null, null);
   513         binding.setMode(mode);
   514         Dispatch<Object> dispatch = Stubs.createJAXBDispatch(
   515                 port, binding, jaxbContext, mode,wsepr);
   516          serviceInterceptor.postCreateDispatch((WSBindingProvider)dispatch);
   517          return dispatch;
   518     }
   520     @Override
   521     public @NotNull Container getContainer() {
   522         return container;
   523     }
   525     public Dispatch<Object> createDispatch(QName portName, JAXBContext jaxbContext, Service.Mode mode, WebServiceFeature... webServiceFeatures) {
   526         return createDispatch(portName, jaxbContext, mode, new WebServiceFeatureList(webServiceFeatures));
   527     }
   529     protected Dispatch<Object> createDispatch(QName portName, JAXBContext jaxbContext, Service.Mode mode, WebServiceFeatureList features) {
   530         WSEndpointReference wsepr = null;
   531         boolean isAddressingEnabled = false;
   532         AddressingFeature af = features.get(AddressingFeature.class);
   533         if (af == null) {
   534             af = this.features.get(AddressingFeature.class);
   535         }
   536         if (af != null && af.isEnabled())
   537             isAddressingEnabled = true;
   538         MemberSubmissionAddressingFeature msa = features.get(MemberSubmissionAddressingFeature.class);
   539         if (msa == null) {
   540             msa = this.features.get(MemberSubmissionAddressingFeature.class);
   541         }
   542         if (msa != null && msa.isEnabled())
   543             isAddressingEnabled = true;
   544         if(isAddressingEnabled && wsdlService != null && wsdlService.get(portName) != null) {
   545             wsepr = wsdlService.get(portName).getEPR();
   546         }
   547         return createDispatch(portName, wsepr, jaxbContext, mode, features);
   548     }
   550     public Dispatch<Object> createDispatch(EndpointReference endpointReference, JAXBContext context, Service.Mode mode, WebServiceFeature... features) {
   551         WSEndpointReference wsepr = new WSEndpointReference(endpointReference);
   552         QName portName = addPortEpr(wsepr);
   553         return createDispatch(portName, wsepr, context, mode, features);
   554     }
   556     private QName addPortEpr(WSEndpointReference wsepr) {
   557         if (wsepr == null)
   558             throw new WebServiceException(ProviderApiMessages.NULL_EPR());
   559         QName eprPortName = getPortNameFromEPR(wsepr, null);
   560         //add Port, if it does n't exist;
   561         // TODO: what if it has different epr address?
   562         {
   563             PortInfo portInfo = new PortInfo(this, (wsepr.getAddress() == null) ? null : EndpointAddress.create(wsepr.getAddress()), eprPortName,
   564                     getPortModel(wsdlService, eprPortName).getBinding().getBindingId());
   565             if (!ports.containsKey(eprPortName)) {
   566                 ports.put(eprPortName, portInfo);
   567             }
   568         }
   569         return eprPortName;
   570     }
   572     /**
   573      *
   574      * @param wsepr EndpointReference from which portName will be extracted.
   575      *      If EndpointName ( port name) is null in EPR, then it will try to get if from WSDLModel using portType QName
   576      * @param portTypeName
   577      *          should be null in dispatch case
   578      *          should be non null in SEI case
   579      * @return
   580      *      port name from EPR after validating various metadat elements.
   581      *      Also if service instance does n't have wsdl,
   582      *      then it gets the WSDL metadata from EPR and builds wsdl model.
   583      */
   584     private QName getPortNameFromEPR(@NotNull WSEndpointReference wsepr, @Nullable QName portTypeName) {
   585         QName portName;
   586         WSEndpointReference.Metadata metadata = wsepr.getMetaData();
   587         QName eprServiceName = metadata.getServiceName();
   588         QName eprPortName = metadata.getPortName();
   589         if ((eprServiceName != null ) && !eprServiceName.equals(serviceName)) {
   590             throw new WebServiceException("EndpointReference WSDL ServiceName differs from Service Instance WSDL Service QName.\n"
   591                     + " The two Service QNames must match");
   592         }
   593         if (wsdlService == null) {
   594             Source eprWsdlSource = metadata.getWsdlSource();
   595             if (eprWsdlSource == null) {
   596                 throw new WebServiceException(ProviderApiMessages.NULL_WSDL());
   597             }
   598             try {
   599                 WSDLModelImpl eprWsdlMdl = parseWSDL(new URL(wsepr.getAddress()), eprWsdlSource, null);
   600                 wsdlService = eprWsdlMdl.getService(serviceName);
   601                 if (wsdlService == null)
   602                     throw new WebServiceException(ClientMessages.INVALID_SERVICE_NAME(serviceName,
   603                             buildNameList(eprWsdlMdl.getServices().keySet())));
   604             } catch (MalformedURLException e) {
   605                 throw new WebServiceException(ClientMessages.INVALID_ADDRESS(wsepr.getAddress()));
   606             }
   607         }
   608         portName = eprPortName;
   610         if (portName == null && portTypeName != null) {
   611             //get the first port corresponding to the SEI
   612             WSDLPortImpl port = wsdlService.getMatchingPort(portTypeName);
   613             if (port == null)
   614                 throw new WebServiceException(ClientMessages.UNDEFINED_PORT_TYPE(portTypeName));
   615             portName = port.getName();
   616         }
   617         if (portName == null)
   618             throw new WebServiceException(ProviderApiMessages.NULL_PORTNAME());
   619         if (wsdlService.get(portName) == null)
   620             throw new WebServiceException(ClientMessages.INVALID_EPR_PORT_NAME(portName, buildWsdlPortNames()));
   622         return portName;
   624     }
   626     private WSDLServiceImpl getWSDLModelfromSEI(final Class sei) {
   627         WebService ws = AccessController.doPrivileged(new PrivilegedAction<WebService>() {
   628             public WebService run() {
   629                 return (WebService) sei.getAnnotation(WebService.class);
   630             }
   631         });
   632         if (ws == null || ws.wsdlLocation().equals(""))
   633             return null;
   634         String wsdlLocation = ws.wsdlLocation();
   635         wsdlLocation = JAXWSUtils.absolutize(JAXWSUtils.getFileOrURLName(wsdlLocation));
   636         Source wsdl = new StreamSource(wsdlLocation);
   637         WSDLServiceImpl service = null;
   639         try {
   640             URL url = wsdl.getSystemId() == null ? null : new URL(wsdl.getSystemId());
   641             WSDLModelImpl model = parseWSDL(url, wsdl, sei);
   642             service = model.getService(this.serviceName);
   643             if (service == null)
   644                 throw new WebServiceException(
   645                         ClientMessages.INVALID_SERVICE_NAME(this.serviceName,
   646                                 buildNameList(model.getServices().keySet())));
   647         } catch (MalformedURLException e) {
   648             throw new WebServiceException(ClientMessages.INVALID_WSDL_URL(wsdl.getSystemId()));
   649         }
   650         return service;
   651     }
   653     public QName getServiceName() {
   654         return serviceName;
   655     }
   657     public Class getServiceClass() {
   658         return serviceClass;
   659     }
   661     public Iterator<QName> getPorts() throws WebServiceException {
   662         // KK: the spec seems to be ambigous about whether
   663         // this returns ports that are dynamically added or not.
   664         return ports.keySet().iterator();
   665     }
   667     public URL getWSDLDocumentLocation() {
   668         if(wsdlService==null)   return null;
   669         try {
   670             return new URL(wsdlService.getParent().getLocation().getSystemId());
   671         } catch (MalformedURLException e) {
   672             throw new AssertionError(e); // impossible
   673         }
   674     }
   676     private <T> T createEndpointIFBaseProxy(@Nullable WSEndpointReference epr,QName portName, Class<T> portInterface,
   677                                             WebServiceFeatureList webServiceFeatures, SEIPortInfo eif) {
   678         //fail if service doesnt have WSDL
   679         if (wsdlService == null)
   680             throw new WebServiceException(ClientMessages.INVALID_SERVICE_NO_WSDL(serviceName));
   682         if (wsdlService.get(portName)==null) {
   683             throw new WebServiceException(
   684                 ClientMessages.INVALID_PORT_NAME(portName,buildWsdlPortNames()));
   685         }
   687         BindingImpl binding = eif.createBinding(webServiceFeatures,portInterface);
   688         InvocationHandler pis = getStubHandler(binding, eif, epr);
   690         // When creating the proxy, use a ClassLoader that can load classes
   691         // from both the interface class and also from this classes
   692         // classloader. This is necessary when this code is used in systems
   693         // such as OSGi where the class loader for the interface class may
   694         // not be able to load internal JAX-WS classes like
   695         // "WSBindingProvider", but the class loader for this class may not
   696         // be able to load the interface class.
   697         ClassLoader loader =
   698             getDelegatingLoader(portInterface.getClassLoader(),
   699                                WSServiceDelegate.class.getClassLoader());
   700         T proxy = portInterface.cast(Proxy.newProxyInstance(loader,
   701                 new Class[]{portInterface, WSBindingProvider.class, Closeable.class}, pis));
   702         if (serviceInterceptor != null) {
   703             serviceInterceptor.postCreateProxy((WSBindingProvider)proxy, portInterface);
   704         }
   705         return proxy;
   706     }
   708     protected InvocationHandler getStubHandler(BindingImpl binding, SEIPortInfo eif, @Nullable WSEndpointReference epr) {
   709         SEIPortInfo spi = (SEIPortInfo) eif;
   710         return new SEIStub(eif, binding, eif.model, epr);
   711     }
   713     /**
   714      * Lists up the port names in WSDL. For error diagnostics.
   715      */
   716     private StringBuilder buildWsdlPortNames() {
   717         Set<QName> wsdlPortNames = new HashSet<QName>();
   718         for (WSDLPortImpl port : wsdlService.getPorts())
   719             wsdlPortNames.add(port.getName());
   720         return buildNameList(wsdlPortNames);
   721     }
   723     /**
   724      * Obtains a {@link WSDLPortImpl} with error check.
   725      *
   726      * @return guaranteed to be non-null.
   727      */
   728     public @NotNull WSDLPortImpl getPortModel(WSDLServiceImpl wsdlService, QName portName) {
   729         WSDLPortImpl port = wsdlService.get(portName);
   730         if (port == null)
   731             throw new WebServiceException(
   732                 ClientMessages.INVALID_PORT_NAME(portName,buildWsdlPortNames()));
   733         return port;
   734     }
   736     /**
   737      * Contributes to the construction of {@link WSServiceDelegate} by filling in
   738      * {@link SEIPortInfo} about a given SEI (linked from the {@link Service}-derived class.)
   739      */
   740     //todo: valid port in wsdl
   741     private SEIPortInfo addSEI(QName portName, Class portInterface, WebServiceFeatureList features) throws WebServiceException {
   742         boolean ownModel = useOwnSEIModel(features);
   743         if (ownModel) {
   744             // Create a new model and do not cache it
   745             return createSEIPortInfo(portName, portInterface, features);
   746         }
   748         SEIPortInfo spi = seiContext.get(portName);
   749         if (spi == null) {
   750             spi = createSEIPortInfo(portName, portInterface, features);
   751             seiContext.put(spi.portName, spi);
   752             ports.put(spi.portName, spi);
   753         }
   754         return spi;
   755     }
   757     public SEIModel buildRuntimeModel(QName serviceName, QName portName, Class portInterface, WSDLPort wsdlPort, WebServiceFeatureList features) {
   758                 DatabindingFactory fac = DatabindingFactory.newInstance();
   759                 DatabindingConfig config = new DatabindingConfig();
   760                 config.setContractClass(portInterface);
   761                 config.getMappingInfo().setServiceName(serviceName);
   762                 config.setWsdlPort(wsdlPort);
   763                 config.setFeatures(features);
   764                 config.setClassLoader(portInterface.getClassLoader());
   765                 config.getMappingInfo().setPortName(portName);
   767                 com.sun.xml.internal.ws.db.DatabindingImpl rt = (com.sun.xml.internal.ws.db.DatabindingImpl)fac.createRuntime(config);
   769                 return rt.getModel();
   770     }
   772     private SEIPortInfo createSEIPortInfo(QName portName, Class portInterface, WebServiceFeatureList features) {
   773         WSDLPortImpl wsdlPort = getPortModel(wsdlService, portName);
   774         SEIModel model = buildRuntimeModel(serviceName, portName, portInterface, wsdlPort, features);
   776         return new SEIPortInfo(this, portInterface, (SOAPSEIModel) model, wsdlPort);
   777     }
   779     private boolean useOwnSEIModel(WebServiceFeatureList features) {
   780         return features.contains(UsesJAXBContextFeature.class);
   781     }
   783     public WSDLServiceImpl getWsdlService() {
   784         return wsdlService;
   785     }
   787      class DaemonThreadFactory implements ThreadFactory {
   788         public Thread newThread(Runnable r) {
   789             Thread daemonThread = new Thread(r);
   790             daemonThread.setDaemon(Boolean.TRUE);
   791             return daemonThread;
   792         }
   793     }
   795     protected static final WebServiceFeature[] EMPTY_FEATURES = new WebServiceFeature[0];
   797     private static ClassLoader getDelegatingLoader(ClassLoader loader1, ClassLoader loader2) {
   798         if (loader1 == null) return loader2;
   799         if (loader2 == null) return loader1;
   800         return new DelegatingLoader(loader1, loader2);
   801     }
   803     private static final class DelegatingLoader
   804       extends ClassLoader
   805     {
   806       private final ClassLoader loader;
   808       DelegatingLoader(ClassLoader loader1, ClassLoader loader2)
   809       {
   810         super(loader2);
   811         this.loader = loader1;
   812       }
   814       protected Class findClass(String name)
   815         throws ClassNotFoundException
   816       {
   817         return loader.loadClass(name);
   818       }
   820       protected URL findResource(String name)
   821       {
   822         return loader.getResource(name);
   823       }
   824     }
   825 }

mercurial