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

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

mercurial