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