Tue, 06 Mar 2012 16:09:35 -0800
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.server; |
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.api.BindingID; |
ohair@286 | 31 | import com.sun.xml.internal.ws.api.WSBinding; |
ohair@286 | 32 | import com.sun.xml.internal.ws.api.policy.PolicyResolverFactory; |
ohair@286 | 33 | import com.sun.xml.internal.ws.api.policy.PolicyResolver; |
ohair@286 | 34 | import com.sun.xml.internal.ws.api.databinding.WSDLGenInfo; |
ohair@286 | 35 | import com.sun.xml.internal.ws.api.databinding.DatabindingFactory; |
ohair@286 | 36 | import com.sun.xml.internal.ws.api.databinding.DatabindingConfig; |
ohair@286 | 37 | import com.sun.xml.internal.ws.api.model.SEIModel; |
ohair@286 | 38 | import com.sun.xml.internal.ws.api.model.wsdl.WSDLPort; |
ohair@286 | 39 | import com.sun.xml.internal.ws.api.pipe.Tube; |
ohair@286 | 40 | import com.sun.xml.internal.ws.api.server.*; |
ohair@286 | 41 | import com.sun.xml.internal.ws.api.wsdl.parser.WSDLParserExtension; |
ohair@286 | 42 | import com.sun.xml.internal.ws.api.wsdl.parser.XMLEntityResolver; |
ohair@286 | 43 | import com.sun.xml.internal.ws.api.wsdl.parser.XMLEntityResolver.Parser; |
ohair@286 | 44 | import com.sun.xml.internal.ws.api.wsdl.writer.WSDLGeneratorExtension; |
ohair@286 | 45 | import com.sun.xml.internal.ws.binding.BindingImpl; |
ohair@286 | 46 | import com.sun.xml.internal.ws.binding.SOAPBindingImpl; |
ohair@286 | 47 | import com.sun.xml.internal.ws.binding.WebServiceFeatureList; |
ohair@286 | 48 | import com.sun.xml.internal.ws.model.AbstractSEIModelImpl; |
ohair@286 | 49 | import com.sun.xml.internal.ws.model.RuntimeModeler; |
ohair@286 | 50 | import com.sun.xml.internal.ws.model.SOAPSEIModel; |
ohair@286 | 51 | import com.sun.xml.internal.ws.model.wsdl.WSDLModelImpl; |
ohair@286 | 52 | import com.sun.xml.internal.ws.model.wsdl.WSDLPortImpl; |
ohair@286 | 53 | import com.sun.xml.internal.ws.model.wsdl.WSDLServiceImpl; |
ohair@286 | 54 | import com.sun.xml.internal.ws.resources.ServerMessages; |
ohair@286 | 55 | import com.sun.xml.internal.ws.server.provider.ProviderInvokerTube; |
ohair@286 | 56 | import com.sun.xml.internal.ws.server.sei.SEIInvokerTube; |
ohair@286 | 57 | import com.sun.xml.internal.ws.util.HandlerAnnotationInfo; |
ohair@286 | 58 | import com.sun.xml.internal.ws.util.HandlerAnnotationProcessor; |
ohair@286 | 59 | import com.sun.xml.internal.ws.util.ServiceConfigurationError; |
ohair@286 | 60 | import com.sun.xml.internal.ws.util.ServiceFinder; |
ohair@286 | 61 | import com.sun.xml.internal.ws.wsdl.parser.RuntimeWSDLParser; |
ohair@286 | 62 | import com.sun.xml.internal.ws.wsdl.writer.WSDLGenerator; |
ohair@286 | 63 | import com.sun.xml.internal.ws.policy.PolicyMap; |
ohair@286 | 64 | import com.sun.xml.internal.ws.policy.jaxws.PolicyUtil; |
ohair@286 | 65 | import org.xml.sax.EntityResolver; |
ohair@286 | 66 | import org.xml.sax.SAXException; |
ohair@286 | 67 | |
ohair@286 | 68 | import javax.jws.WebService; |
ohair@286 | 69 | import javax.xml.namespace.QName; |
ohair@286 | 70 | import javax.xml.stream.XMLStreamException; |
ohair@286 | 71 | import javax.xml.ws.Provider; |
ohair@286 | 72 | import javax.xml.ws.WebServiceException; |
ohair@286 | 73 | import javax.xml.ws.WebServiceProvider; |
ohair@286 | 74 | import javax.xml.ws.WebServiceFeature; |
ohair@286 | 75 | import javax.xml.ws.soap.SOAPBinding; |
ohair@286 | 76 | import java.io.IOException; |
ohair@286 | 77 | import java.net.URL; |
ohair@286 | 78 | import java.util.ArrayList; |
ohair@286 | 79 | import java.util.Collection; |
ohair@286 | 80 | import java.util.HashMap; |
ohair@286 | 81 | import java.util.List; |
ohair@286 | 82 | import java.util.Map; |
ohair@286 | 83 | import java.util.logging.Logger; |
ohair@286 | 84 | |
ohair@286 | 85 | /** |
ohair@286 | 86 | * Entry point to the JAX-WS RI server-side runtime. |
ohair@286 | 87 | * |
ohair@286 | 88 | * @author Kohsuke Kawaguchi |
ohair@286 | 89 | * @author Jitendra Kotamraju |
ohair@286 | 90 | */ |
ohair@286 | 91 | public class EndpointFactory { |
ohair@286 | 92 | private static final EndpointFactory instance = new EndpointFactory(); |
ohair@286 | 93 | |
ohair@286 | 94 | public static EndpointFactory getInstance() { |
ohair@286 | 95 | return instance; |
ohair@286 | 96 | } |
ohair@286 | 97 | |
ohair@286 | 98 | /** |
ohair@286 | 99 | * Implements {@link WSEndpoint#create}. |
ohair@286 | 100 | * |
ohair@286 | 101 | * No need to take WebServiceContext implementation. When InvokerPipe is |
ohair@286 | 102 | * instantiated, it calls InstanceResolver to set up a WebServiceContext. |
ohair@286 | 103 | * We shall only take delegate to getUserPrincipal and isUserInRole from adapter. |
ohair@286 | 104 | * |
ohair@286 | 105 | * <p> |
ohair@286 | 106 | * Nobody else should be calling this method. |
ohair@286 | 107 | */ |
ohair@286 | 108 | public static <T> WSEndpoint<T> createEndpoint( |
ohair@286 | 109 | Class<T> implType, boolean processHandlerAnnotation, @Nullable Invoker invoker, |
ohair@286 | 110 | @Nullable QName serviceName, @Nullable QName portName, |
ohair@286 | 111 | @Nullable Container container, @Nullable WSBinding binding, |
ohair@286 | 112 | @Nullable SDDocumentSource primaryWsdl, |
ohair@286 | 113 | @Nullable Collection<? extends SDDocumentSource> metadata, |
ohair@286 | 114 | EntityResolver resolver, boolean isTransportSynchronous) { |
ohair@286 | 115 | return createEndpoint(implType, processHandlerAnnotation, invoker, serviceName, |
ohair@286 | 116 | portName, container, binding, primaryWsdl, metadata, resolver, isTransportSynchronous, true); |
ohair@286 | 117 | } |
ohair@286 | 118 | |
ohair@286 | 119 | public static <T> WSEndpoint<T> createEndpoint( |
ohair@286 | 120 | Class<T> implType, boolean processHandlerAnnotation, @Nullable Invoker invoker, |
ohair@286 | 121 | @Nullable QName serviceName, @Nullable QName portName, |
ohair@286 | 122 | @Nullable Container container, @Nullable WSBinding binding, |
ohair@286 | 123 | @Nullable SDDocumentSource primaryWsdl, |
ohair@286 | 124 | @Nullable Collection<? extends SDDocumentSource> metadata, |
ohair@286 | 125 | EntityResolver resolver, boolean isTransportSynchronous, boolean isStandard) { |
ohair@286 | 126 | EndpointFactory factory = container != null ? container.getSPI(EndpointFactory.class) : null; |
ohair@286 | 127 | if (factory == null) |
ohair@286 | 128 | factory = EndpointFactory.getInstance(); |
ohair@286 | 129 | |
ohair@286 | 130 | return factory.create( |
ohair@286 | 131 | implType,processHandlerAnnotation, invoker,serviceName,portName,container,binding,primaryWsdl,metadata,resolver,isTransportSynchronous,isStandard); |
ohair@286 | 132 | } |
ohair@286 | 133 | |
ohair@286 | 134 | /** |
ohair@286 | 135 | * Implements {@link WSEndpoint#create}. |
ohair@286 | 136 | * |
ohair@286 | 137 | * No need to take WebServiceContext implementation. When InvokerPipe is |
ohair@286 | 138 | * instantiated, it calls InstanceResolver to set up a WebServiceContext. |
ohair@286 | 139 | * We shall only take delegate to getUserPrincipal and isUserInRole from adapter. |
ohair@286 | 140 | * |
ohair@286 | 141 | * <p> |
ohair@286 | 142 | * Nobody else should be calling this method. |
ohair@286 | 143 | */ |
ohair@286 | 144 | public <T> WSEndpoint<T> create( |
ohair@286 | 145 | Class<T> implType, boolean processHandlerAnnotation, @Nullable Invoker invoker, |
ohair@286 | 146 | @Nullable QName serviceName, @Nullable QName portName, |
ohair@286 | 147 | @Nullable Container container, @Nullable WSBinding binding, |
ohair@286 | 148 | @Nullable SDDocumentSource primaryWsdl, |
ohair@286 | 149 | @Nullable Collection<? extends SDDocumentSource> metadata, |
ohair@286 | 150 | EntityResolver resolver, boolean isTransportSynchronous) { |
ohair@286 | 151 | return create(implType, processHandlerAnnotation, invoker, serviceName, |
ohair@286 | 152 | portName, container, binding, primaryWsdl, metadata, resolver, isTransportSynchronous, |
ohair@286 | 153 | true); |
ohair@286 | 154 | |
ohair@286 | 155 | } |
ohair@286 | 156 | |
ohair@286 | 157 | public <T> WSEndpoint<T> create( |
ohair@286 | 158 | Class<T> implType, boolean processHandlerAnnotation, @Nullable Invoker invoker, |
ohair@286 | 159 | @Nullable QName serviceName, @Nullable QName portName, |
ohair@286 | 160 | @Nullable Container container, @Nullable WSBinding binding, |
ohair@286 | 161 | @Nullable SDDocumentSource primaryWsdl, |
ohair@286 | 162 | @Nullable Collection<? extends SDDocumentSource> metadata, |
ohair@286 | 163 | EntityResolver resolver, boolean isTransportSynchronous, boolean isStandard) { |
ohair@286 | 164 | |
ohair@286 | 165 | if(implType ==null) |
ohair@286 | 166 | throw new IllegalArgumentException(); |
ohair@286 | 167 | |
ohair@286 | 168 | if (isStandard) { |
ohair@286 | 169 | verifyImplementorClass(implType); |
ohair@286 | 170 | } |
ohair@286 | 171 | |
ohair@286 | 172 | if (invoker == null) { |
ohair@286 | 173 | invoker = InstanceResolver.createDefault(implType).createInvoker(); |
ohair@286 | 174 | } |
ohair@286 | 175 | |
ohair@286 | 176 | List<SDDocumentSource> md = new ArrayList<SDDocumentSource>(); |
ohair@286 | 177 | if(metadata!=null) |
ohair@286 | 178 | md.addAll(metadata); |
ohair@286 | 179 | |
ohair@286 | 180 | if(primaryWsdl!=null && !md.contains(primaryWsdl)) |
ohair@286 | 181 | md.add(primaryWsdl); |
ohair@286 | 182 | |
ohair@286 | 183 | if(container==null) |
ohair@286 | 184 | container = ContainerResolver.getInstance().getContainer(); |
ohair@286 | 185 | |
ohair@286 | 186 | if(serviceName==null) |
ohair@286 | 187 | serviceName = getDefaultServiceName(implType); |
ohair@286 | 188 | |
ohair@286 | 189 | if(portName==null) |
ohair@286 | 190 | portName = getDefaultPortName(serviceName,implType); |
ohair@286 | 191 | |
ohair@286 | 192 | {// error check |
ohair@286 | 193 | String serviceNS = serviceName.getNamespaceURI(); |
ohair@286 | 194 | String portNS = portName.getNamespaceURI(); |
ohair@286 | 195 | if (!serviceNS.equals(portNS)) { |
ohair@286 | 196 | throw new ServerRtException("wrong.tns.for.port",portNS, serviceNS); |
ohair@286 | 197 | } |
ohair@286 | 198 | } |
ohair@286 | 199 | |
ohair@286 | 200 | // setting a default binding |
ohair@286 | 201 | if (binding == null) |
ohair@286 | 202 | binding = BindingImpl.create(BindingID.parse(implType)); |
ohair@286 | 203 | |
ohair@286 | 204 | if ( isStandard && primaryWsdl != null) { |
ohair@286 | 205 | verifyPrimaryWSDL(primaryWsdl, serviceName); |
ohair@286 | 206 | } |
ohair@286 | 207 | |
ohair@286 | 208 | QName portTypeName = null; |
ohair@286 | 209 | if (isStandard && implType.getAnnotation(WebServiceProvider.class)==null) { |
ohair@286 | 210 | portTypeName = RuntimeModeler.getPortTypeName(implType); |
ohair@286 | 211 | } |
ohair@286 | 212 | |
ohair@286 | 213 | // Categorises the documents as WSDL, Schema etc |
ohair@286 | 214 | List<SDDocumentImpl> docList = categoriseMetadata(md, serviceName, portTypeName); |
ohair@286 | 215 | // Finds the primary WSDL and makes sure that metadata doesn't have |
ohair@286 | 216 | // two concrete or abstract WSDLs |
ohair@286 | 217 | SDDocumentImpl primaryDoc = findPrimary(docList); |
ohair@286 | 218 | |
ohair@286 | 219 | EndpointAwareTube terminal; |
ohair@286 | 220 | WSDLPortImpl wsdlPort = null; |
ohair@286 | 221 | AbstractSEIModelImpl seiModel = null; |
ohair@286 | 222 | // create WSDL model |
ohair@286 | 223 | if (primaryDoc != null) { |
ohair@286 | 224 | wsdlPort = getWSDLPort(primaryDoc, docList, serviceName, portName, container); |
ohair@286 | 225 | } |
ohair@286 | 226 | |
ohair@286 | 227 | WebServiceFeatureList features=((BindingImpl)binding).getFeatures(); |
ohair@286 | 228 | if (isStandard) { |
ohair@286 | 229 | features.parseAnnotations(implType); |
ohair@286 | 230 | } |
ohair@286 | 231 | PolicyMap policyMap = null; |
ohair@286 | 232 | // create terminal pipe that invokes the application |
ohair@286 | 233 | if (isUseProviderTube(implType, isStandard)) { |
ohair@286 | 234 | //TODO incase of Provider, provide a way to User for complete control of the message processing by giving |
ohair@286 | 235 | // ability to turn off the WSDL/Policy based features and its associated tubes. |
ohair@286 | 236 | |
ohair@286 | 237 | //Even in case of Provider, merge all features configured via WSDL/Policy or deployment configuration |
ohair@286 | 238 | Iterable<WebServiceFeature> configFtrs; |
ohair@286 | 239 | if(wsdlPort != null) { |
ohair@286 | 240 | policyMap = wsdlPort.getOwner().getParent().getPolicyMap(); |
ohair@286 | 241 | //Merge features from WSDL and other policy configuration |
ohair@286 | 242 | configFtrs = wsdlPort.getFeatures(); |
ohair@286 | 243 | } else { |
ohair@286 | 244 | //No WSDL, so try to merge features from Policy configuration |
ohair@286 | 245 | policyMap = PolicyResolverFactory.create().resolve( |
ohair@286 | 246 | new PolicyResolver.ServerContext(null, container, implType, false)); |
ohair@286 | 247 | configFtrs = PolicyUtil.getPortScopedFeatures(policyMap,serviceName,portName); |
ohair@286 | 248 | } |
ohair@286 | 249 | features.mergeFeatures(configFtrs, true); |
ohair@286 | 250 | terminal = createProviderInvokerTube(implType,binding,invoker); |
ohair@286 | 251 | } else { |
ohair@286 | 252 | // Create runtime model for non Provider endpoints |
ohair@286 | 253 | seiModel = createSEIModel(wsdlPort, implType, serviceName, portName, binding); |
ohair@286 | 254 | if(binding instanceof SOAPBindingImpl){ |
ohair@286 | 255 | //set portKnownHeaders on Binding, so that they can be used for MU processing |
ohair@286 | 256 | ((SOAPBindingImpl)binding).setPortKnownHeaders( |
ohair@286 | 257 | ((SOAPSEIModel)seiModel).getKnownHeaders()); |
ohair@286 | 258 | } |
ohair@286 | 259 | // Generate WSDL for SEI endpoints(not for Provider endpoints) |
ohair@286 | 260 | if (primaryDoc == null) { |
ohair@286 | 261 | primaryDoc = generateWSDL(binding, seiModel, docList, container, implType); |
ohair@286 | 262 | // create WSDL model |
ohair@286 | 263 | wsdlPort = getWSDLPort(primaryDoc, docList, serviceName, portName, container); |
ohair@286 | 264 | seiModel.freeze(wsdlPort); |
ohair@286 | 265 | } |
ohair@286 | 266 | policyMap = wsdlPort.getOwner().getParent().getPolicyMap(); |
ohair@286 | 267 | // New Features might have been added in WSDL through Policy. |
ohair@286 | 268 | //Merge features from WSDL and other policy configuration |
ohair@286 | 269 | // This sets only the wsdl features that are not already set(enabled/disabled) |
ohair@286 | 270 | features.mergeFeatures(wsdlPort.getFeatures(), true); |
ohair@286 | 271 | terminal = createSEIInvokerTube(seiModel,invoker,binding); |
ohair@286 | 272 | } |
ohair@286 | 273 | |
ohair@286 | 274 | // Process @HandlerChain, if handler-chain is not set via Deployment Descriptor |
ohair@286 | 275 | if (processHandlerAnnotation) { |
ohair@286 | 276 | processHandlerAnnotation(binding, implType, serviceName, portName); |
ohair@286 | 277 | } |
ohair@286 | 278 | // Selects only required metadata for this endpoint from the passed-in metadata |
ohair@286 | 279 | if (primaryDoc != null) { |
ohair@286 | 280 | docList = findMetadataClosure(primaryDoc, docList); |
ohair@286 | 281 | } |
ohair@286 | 282 | ServiceDefinitionImpl serviceDefiniton = (primaryDoc != null) ? new ServiceDefinitionImpl(docList, primaryDoc) : null; |
ohair@286 | 283 | |
ohair@286 | 284 | return create(serviceName, portName, binding, container, seiModel, wsdlPort, implType, serviceDefiniton, |
ohair@286 | 285 | terminal, isTransportSynchronous, policyMap); |
ohair@286 | 286 | } |
ohair@286 | 287 | |
ohair@286 | 288 | protected <T> WSEndpoint<T> create(QName serviceName, QName portName, WSBinding binding, Container container, SEIModel seiModel, WSDLPort wsdlPort, Class<T> implType, ServiceDefinitionImpl serviceDefinition, EndpointAwareTube terminal, boolean isTransportSynchronous, PolicyMap policyMap) { |
ohair@286 | 289 | return new WSEndpointImpl<T>(serviceName, portName, binding, container, seiModel, |
ohair@286 | 290 | wsdlPort, implType, serviceDefinition, terminal, isTransportSynchronous, policyMap); |
ohair@286 | 291 | } |
ohair@286 | 292 | |
ohair@286 | 293 | protected boolean isUseProviderTube(Class<?> implType, boolean isStandard) { |
ohair@286 | 294 | return !isStandard || implType.getAnnotation(WebServiceProvider.class)!=null; |
ohair@286 | 295 | } |
ohair@286 | 296 | |
ohair@286 | 297 | protected EndpointAwareTube createSEIInvokerTube(AbstractSEIModelImpl seiModel, Invoker invoker, WSBinding binding) { |
ohair@286 | 298 | return new SEIInvokerTube(seiModel,invoker,binding); |
ohair@286 | 299 | } |
ohair@286 | 300 | |
ohair@286 | 301 | protected <T> EndpointAwareTube createProviderInvokerTube(Class<T> implType, WSBinding binding, Invoker invoker) { |
ohair@286 | 302 | return ProviderInvokerTube.create(implType, binding, invoker); |
ohair@286 | 303 | } |
ohair@286 | 304 | |
ohair@286 | 305 | /** |
ohair@286 | 306 | * Goes through the original metadata documents and collects the required ones. |
ohair@286 | 307 | * This done traversing from primary WSDL and its imports until it builds a |
ohair@286 | 308 | * complete set of documents(transitive closure) for the endpoint. |
ohair@286 | 309 | * |
ohair@286 | 310 | * @param primaryDoc primary WSDL doc |
ohair@286 | 311 | * @param docList complete metadata |
ohair@286 | 312 | * @return new metadata that doesn't contain extraneous documnets. |
ohair@286 | 313 | */ |
ohair@286 | 314 | private static List<SDDocumentImpl> findMetadataClosure(SDDocumentImpl primaryDoc, List<SDDocumentImpl> docList) { |
ohair@286 | 315 | // create a map for old metadata |
ohair@286 | 316 | Map<String, SDDocumentImpl> oldMap = new HashMap<String, SDDocumentImpl>(); |
ohair@286 | 317 | for(SDDocumentImpl doc : docList) { |
ohair@286 | 318 | oldMap.put(doc.getSystemId().toString(), doc); |
ohair@286 | 319 | } |
ohair@286 | 320 | // create a map for new metadata |
ohair@286 | 321 | Map<String, SDDocumentImpl> newMap = new HashMap<String, SDDocumentImpl>(); |
ohair@286 | 322 | newMap.put(primaryDoc.getSystemId().toString(), primaryDoc); |
ohair@286 | 323 | |
ohair@286 | 324 | List<String> remaining = new ArrayList<String>(); |
ohair@286 | 325 | remaining.addAll(primaryDoc.getImports()); |
ohair@286 | 326 | while(!remaining.isEmpty()) { |
ohair@286 | 327 | String url = remaining.remove(0); |
ohair@286 | 328 | SDDocumentImpl doc = oldMap.get(url); |
ohair@286 | 329 | if (doc == null) { |
ohair@286 | 330 | // old metadata doesn't have this imported doc, may be external |
ohair@286 | 331 | continue; |
ohair@286 | 332 | } |
ohair@286 | 333 | // Check if new metadata already contains this doc |
ohair@286 | 334 | if (!newMap.containsKey(url)) { |
ohair@286 | 335 | newMap.put(url, doc); |
ohair@286 | 336 | remaining.addAll(doc.getImports()); |
ohair@286 | 337 | } |
ohair@286 | 338 | } |
ohair@286 | 339 | List<SDDocumentImpl> newMetadata = new ArrayList<SDDocumentImpl>(); |
ohair@286 | 340 | newMetadata.addAll(newMap.values()); |
ohair@286 | 341 | return newMetadata; |
ohair@286 | 342 | } |
ohair@286 | 343 | |
ohair@286 | 344 | private static <T> void processHandlerAnnotation(WSBinding binding, Class<T> implType, QName serviceName, QName portName) { |
ohair@286 | 345 | HandlerAnnotationInfo chainInfo = |
ohair@286 | 346 | HandlerAnnotationProcessor.buildHandlerInfo( |
ohair@286 | 347 | implType, serviceName, portName, binding); |
ohair@286 | 348 | if (chainInfo != null) { |
ohair@286 | 349 | binding.setHandlerChain(chainInfo.getHandlers()); |
ohair@286 | 350 | if (binding instanceof SOAPBinding) { |
ohair@286 | 351 | ((SOAPBinding) binding).setRoles(chainInfo.getRoles()); |
ohair@286 | 352 | } |
ohair@286 | 353 | } |
ohair@286 | 354 | |
ohair@286 | 355 | } |
ohair@286 | 356 | |
ohair@286 | 357 | /** |
ohair@286 | 358 | * Verifies if the endpoint implementor class has @WebService or @WebServiceProvider |
ohair@286 | 359 | * annotation |
ohair@286 | 360 | * |
ohair@286 | 361 | * @return |
ohair@286 | 362 | * true if it is a Provider or AsyncProvider endpoint |
ohair@286 | 363 | * false otherwise |
ohair@286 | 364 | * @throws java.lang.IllegalArgumentException |
ohair@286 | 365 | * If it doesn't have any one of @WebService or @WebServiceProvider |
ohair@286 | 366 | * If it has both @WebService and @WebServiceProvider annotations |
ohair@286 | 367 | */ |
ohair@286 | 368 | public static boolean verifyImplementorClass(Class<?> clz) { |
ohair@286 | 369 | WebServiceProvider wsProvider = clz.getAnnotation(WebServiceProvider.class); |
ohair@286 | 370 | WebService ws = clz.getAnnotation(WebService.class); |
ohair@286 | 371 | if (wsProvider == null && ws == null) { |
ohair@286 | 372 | throw new IllegalArgumentException(clz +" has neither @WebService nor @WebServiceProvider annotation"); |
ohair@286 | 373 | } |
ohair@286 | 374 | if (wsProvider != null && ws != null) { |
ohair@286 | 375 | throw new IllegalArgumentException(clz +" has both @WebService and @WebServiceProvider annotations"); |
ohair@286 | 376 | } |
ohair@286 | 377 | if (wsProvider != null) { |
ohair@286 | 378 | if (Provider.class.isAssignableFrom(clz) || AsyncProvider.class.isAssignableFrom(clz)) { |
ohair@286 | 379 | return true; |
ohair@286 | 380 | } |
ohair@286 | 381 | throw new IllegalArgumentException(clz +" doesn't implement Provider or AsyncProvider interface"); |
ohair@286 | 382 | } |
ohair@286 | 383 | return false; |
ohair@286 | 384 | } |
ohair@286 | 385 | |
ohair@286 | 386 | |
ohair@286 | 387 | private static AbstractSEIModelImpl createSEIModel(WSDLPort wsdlPort, |
ohair@286 | 388 | Class<?> implType, @NotNull QName serviceName, @NotNull QName portName, WSBinding binding) { |
ohair@286 | 389 | // RuntimeModeler rap; |
ohair@286 | 390 | // // Create runtime model for non Provider endpoints |
ohair@286 | 391 | // |
ohair@286 | 392 | // // wsdlPort will be null, means we will generate WSDL. Hence no need to apply |
ohair@286 | 393 | // // bindings or need to look in the WSDL |
ohair@286 | 394 | // if(wsdlPort == null){ |
ohair@286 | 395 | // rap = new RuntimeModeler(implType,serviceName, binding.getBindingId(), binding.getFeatures().toArray()); |
ohair@286 | 396 | // } else { |
ohair@286 | 397 | // /* |
ohair@286 | 398 | // This not needed anymore as wsdlFeatures are merged later anyway |
ohair@286 | 399 | // and so is the MTOMFeature. |
ohair@286 | 400 | // applyEffectiveMtomSetting(wsdlPort.getBinding(), binding); |
ohair@286 | 401 | // */ |
ohair@286 | 402 | // //now we got the Binding so lets build the model |
ohair@286 | 403 | // rap = new RuntimeModeler(implType, serviceName, (WSDLPortImpl)wsdlPort, binding.getFeatures().toArray()); |
ohair@286 | 404 | // } |
ohair@286 | 405 | // rap.setClassLoader(implType.getClassLoader()); |
ohair@286 | 406 | // rap.setPortName(portName); |
ohair@286 | 407 | // return rap.buildRuntimeModel(); |
ohair@286 | 408 | DatabindingFactory fac = DatabindingFactory.newInstance(); |
ohair@286 | 409 | DatabindingConfig config = new DatabindingConfig(); |
ohair@286 | 410 | config.setEndpointClass(implType); |
ohair@286 | 411 | config.getMappingInfo().setServiceName(serviceName); |
ohair@286 | 412 | config.setWsdlPort(wsdlPort); |
ohair@286 | 413 | config.setWSBinding(binding); |
ohair@286 | 414 | // config.setFeatures(binding.getFeatures().toArray()); |
ohair@286 | 415 | // config.getMappingInfo().setBindingID(binding.getBindingId()); |
ohair@286 | 416 | config.setClassLoader(implType.getClassLoader()); |
ohair@286 | 417 | config.getMappingInfo().setPortName(portName); |
ohair@286 | 418 | com.sun.xml.internal.ws.db.DatabindingImpl rt = (com.sun.xml.internal.ws.db.DatabindingImpl)fac.createRuntime(config); |
ohair@286 | 419 | return (AbstractSEIModelImpl) rt.getModel(); |
ohair@286 | 420 | } |
ohair@286 | 421 | |
ohair@286 | 422 | /** |
ohair@286 | 423 | *Set the mtom enable setting from wsdl model (mtom policy assertion) on to @link WSBinding} if DD has |
ohair@286 | 424 | * not already set it on BindingID. Also check conflicts. |
ohair@286 | 425 | */ |
ohair@286 | 426 | /* |
ohair@286 | 427 | private static void applyEffectiveMtomSetting(WSDLBoundPortType wsdlBinding, WSBinding binding){ |
ohair@286 | 428 | if(wsdlBinding.isMTOMEnabled()){ |
ohair@286 | 429 | BindingID bindingId = binding.getBindingId(); |
ohair@286 | 430 | if(bindingId.isMTOMEnabled() == null){ |
ohair@286 | 431 | binding.setMTOMEnabled(true); |
ohair@286 | 432 | }else if (bindingId.isMTOMEnabled() != null && bindingId.isMTOMEnabled() == Boolean.FALSE){ |
ohair@286 | 433 | //TODO: i18N |
ohair@286 | 434 | throw new ServerRtException("Deployment failed! Mtom policy assertion in WSDL is enabled whereas the deplyment descriptor setting wants to disable it!"); |
ohair@286 | 435 | } |
ohair@286 | 436 | } |
ohair@286 | 437 | } |
ohair@286 | 438 | */ |
ohair@286 | 439 | /** |
ohair@286 | 440 | * If service name is not already set via DD or programmatically, it uses |
ohair@286 | 441 | * annotations {@link WebServiceProvider}, {@link WebService} on implementorClass to get PortName. |
ohair@286 | 442 | * |
ohair@286 | 443 | * @return non-null service name |
ohair@286 | 444 | */ |
ohair@286 | 445 | public static @NotNull QName getDefaultServiceName(Class<?> implType) { |
ohair@286 | 446 | return getDefaultServiceName(implType, true); |
ohair@286 | 447 | } |
ohair@286 | 448 | |
ohair@286 | 449 | public static @NotNull QName getDefaultServiceName(Class<?> implType, boolean isStandard) { |
ohair@286 | 450 | QName serviceName; |
ohair@286 | 451 | WebServiceProvider wsProvider = implType.getAnnotation(WebServiceProvider.class); |
ohair@286 | 452 | if (wsProvider!=null) { |
ohair@286 | 453 | String tns = wsProvider.targetNamespace(); |
ohair@286 | 454 | String local = wsProvider.serviceName(); |
ohair@286 | 455 | serviceName = new QName(tns, local); |
ohair@286 | 456 | } else { |
ohair@286 | 457 | serviceName = RuntimeModeler.getServiceName(implType, isStandard); |
ohair@286 | 458 | } |
ohair@286 | 459 | assert serviceName != null; |
ohair@286 | 460 | return serviceName; |
ohair@286 | 461 | } |
ohair@286 | 462 | |
ohair@286 | 463 | /** |
ohair@286 | 464 | * If portName is not already set via DD or programmatically, it uses |
ohair@286 | 465 | * annotations on implementorClass to get PortName. |
ohair@286 | 466 | * |
ohair@286 | 467 | * @return non-null port name |
ohair@286 | 468 | */ |
ohair@286 | 469 | public static @NotNull QName getDefaultPortName(QName serviceName, Class<?> implType) { |
ohair@286 | 470 | return getDefaultPortName(serviceName, implType, true); |
ohair@286 | 471 | } |
ohair@286 | 472 | |
ohair@286 | 473 | public static @NotNull QName getDefaultPortName(QName serviceName, Class<?> implType, boolean isStandard) { |
ohair@286 | 474 | QName portName; |
ohair@286 | 475 | WebServiceProvider wsProvider = implType.getAnnotation(WebServiceProvider.class); |
ohair@286 | 476 | if (wsProvider!=null) { |
ohair@286 | 477 | String tns = wsProvider.targetNamespace(); |
ohair@286 | 478 | String local = wsProvider.portName(); |
ohair@286 | 479 | portName = new QName(tns, local); |
ohair@286 | 480 | } else { |
ohair@286 | 481 | portName = RuntimeModeler.getPortName(implType, serviceName.getNamespaceURI(), isStandard); |
ohair@286 | 482 | } |
ohair@286 | 483 | assert portName != null; |
ohair@286 | 484 | return portName; |
ohair@286 | 485 | } |
ohair@286 | 486 | |
ohair@286 | 487 | /** |
ohair@286 | 488 | * Returns the wsdl from @WebService, or @WebServiceProvider annotation using |
ohair@286 | 489 | * wsdlLocation element. |
ohair@286 | 490 | * |
ohair@286 | 491 | * @param implType |
ohair@286 | 492 | * endpoint implementation class |
ohair@286 | 493 | * make sure that you called {@link #verifyImplementorClass} on it. |
ohair@286 | 494 | * @return wsdl if there is wsdlLocation, else null |
ohair@286 | 495 | */ |
ohair@286 | 496 | public static @Nullable String getWsdlLocation(Class<?> implType) { |
ohair@286 | 497 | String wsdl; |
ohair@286 | 498 | WebService ws = implType.getAnnotation(WebService.class); |
ohair@286 | 499 | if (ws != null) { |
ohair@286 | 500 | wsdl = ws.wsdlLocation(); |
ohair@286 | 501 | } else { |
ohair@286 | 502 | WebServiceProvider wsProvider = implType.getAnnotation(WebServiceProvider.class); |
ohair@286 | 503 | assert wsProvider != null; |
ohair@286 | 504 | wsdl = wsProvider.wsdlLocation(); |
ohair@286 | 505 | } |
ohair@286 | 506 | if (wsdl.length() < 1) { |
ohair@286 | 507 | wsdl = null; |
ohair@286 | 508 | } |
ohair@286 | 509 | return wsdl; |
ohair@286 | 510 | } |
ohair@286 | 511 | |
ohair@286 | 512 | /** |
ohair@286 | 513 | * Generates the WSDL and XML Schema for the endpoint if necessary |
ohair@286 | 514 | * It generates WSDL only for SOAP1.1, and for XSOAP1.2 bindings |
ohair@286 | 515 | */ |
ohair@286 | 516 | private static SDDocumentImpl generateWSDL(WSBinding binding, AbstractSEIModelImpl seiModel, List<SDDocumentImpl> docs, |
ohair@286 | 517 | Container container, Class implType) { |
ohair@286 | 518 | BindingID bindingId = binding.getBindingId(); |
ohair@286 | 519 | if (!bindingId.canGenerateWSDL()) { |
ohair@286 | 520 | throw new ServerRtException("can.not.generate.wsdl", bindingId); |
ohair@286 | 521 | } |
ohair@286 | 522 | |
ohair@286 | 523 | if (bindingId.toString().equals(SOAPBindingImpl.X_SOAP12HTTP_BINDING)) { |
ohair@286 | 524 | String msg = ServerMessages.GENERATE_NON_STANDARD_WSDL(); |
ohair@286 | 525 | logger.warning(msg); |
ohair@286 | 526 | } |
ohair@286 | 527 | |
ohair@286 | 528 | // Generate WSDL and schema documents using runtime model |
ohair@286 | 529 | WSDLGenResolver wsdlResolver = new WSDLGenResolver(docs,seiModel.getServiceQName(),seiModel.getPortTypeName()); |
ohair@286 | 530 | WSDLGenInfo wsdlGenInfo = new WSDLGenInfo(); |
ohair@286 | 531 | wsdlGenInfo.setWsdlResolver(wsdlResolver); |
ohair@286 | 532 | wsdlGenInfo.setContainer(container); |
ohair@286 | 533 | wsdlGenInfo.setExtensions(ServiceFinder.find(WSDLGeneratorExtension.class).toArray()); |
ohair@286 | 534 | wsdlGenInfo.setInlineSchemas(false); |
ohair@286 | 535 | seiModel.getDatabinding().generateWSDL(wsdlGenInfo); |
ohair@286 | 536 | // WSDLGenerator wsdlGen = new WSDLGenerator(seiModel, wsdlResolver, binding, container, implType, false, |
ohair@286 | 537 | // ServiceFinder.find(WSDLGeneratorExtension.class).toArray()); |
ohair@286 | 538 | // wsdlGen.doGeneration(); |
ohair@286 | 539 | return wsdlResolver.updateDocs(); |
ohair@286 | 540 | } |
ohair@286 | 541 | |
ohair@286 | 542 | /** |
ohair@286 | 543 | * Builds {@link SDDocumentImpl} from {@link SDDocumentSource}. |
ohair@286 | 544 | */ |
ohair@286 | 545 | private static List<SDDocumentImpl> categoriseMetadata( |
ohair@286 | 546 | List<SDDocumentSource> src, QName serviceName, QName portTypeName) { |
ohair@286 | 547 | |
ohair@286 | 548 | List<SDDocumentImpl> r = new ArrayList<SDDocumentImpl>(src.size()); |
ohair@286 | 549 | for (SDDocumentSource doc : src) { |
ohair@286 | 550 | r.add(SDDocumentImpl.create(doc,serviceName,portTypeName)); |
ohair@286 | 551 | } |
ohair@286 | 552 | return r; |
ohair@286 | 553 | } |
ohair@286 | 554 | |
ohair@286 | 555 | /** |
ohair@286 | 556 | * Verifies whether the given primaryWsdl contains the given serviceName. |
ohair@286 | 557 | * If the WSDL doesn't have the service, it throws an WebServiceException. |
ohair@286 | 558 | */ |
ohair@286 | 559 | private static void verifyPrimaryWSDL(@NotNull SDDocumentSource primaryWsdl, @NotNull QName serviceName) { |
ohair@286 | 560 | SDDocumentImpl primaryDoc = SDDocumentImpl.create(primaryWsdl,serviceName,null); |
ohair@286 | 561 | if (!(primaryDoc instanceof SDDocument.WSDL)) { |
ohair@286 | 562 | throw new WebServiceException(primaryWsdl.getSystemId()+ |
ohair@286 | 563 | " is not a WSDL. But it is passed as a primary WSDL"); |
ohair@286 | 564 | } |
ohair@286 | 565 | SDDocument.WSDL wsdlDoc = (SDDocument.WSDL)primaryDoc; |
ohair@286 | 566 | if (!wsdlDoc.hasService()) { |
ohair@286 | 567 | if(wsdlDoc.getAllServices().isEmpty()) |
ohair@286 | 568 | throw new WebServiceException("Not a primary WSDL="+primaryWsdl.getSystemId()+ |
ohair@286 | 569 | " since it doesn't have Service "+serviceName); |
ohair@286 | 570 | else |
ohair@286 | 571 | throw new WebServiceException("WSDL "+primaryDoc.getSystemId() |
ohair@286 | 572 | +" has the following services "+wsdlDoc.getAllServices() |
ohair@286 | 573 | +" but not "+serviceName+". Maybe you forgot to specify a serviceName and/or targetNamespace in @WebService/@WebServiceProvider?"); |
ohair@286 | 574 | } |
ohair@286 | 575 | } |
ohair@286 | 576 | |
ohair@286 | 577 | /** |
ohair@286 | 578 | * Finds the primary WSDL document from the list of metadata documents. If |
ohair@286 | 579 | * there are two metadata documents that qualify for primary, it throws an |
ohair@286 | 580 | * exception. If there are two metadata documents that qualify for porttype, |
ohair@286 | 581 | * it throws an exception. |
ohair@286 | 582 | * |
ohair@286 | 583 | * @return primay wsdl document, null if is not there in the docList |
ohair@286 | 584 | * |
ohair@286 | 585 | */ |
ohair@286 | 586 | private static @Nullable SDDocumentImpl findPrimary(@NotNull List<SDDocumentImpl> docList) { |
ohair@286 | 587 | SDDocumentImpl primaryDoc = null; |
ohair@286 | 588 | boolean foundConcrete = false; |
ohair@286 | 589 | boolean foundAbstract = false; |
ohair@286 | 590 | for(SDDocumentImpl doc : docList) { |
ohair@286 | 591 | if (doc instanceof SDDocument.WSDL) { |
ohair@286 | 592 | SDDocument.WSDL wsdlDoc = (SDDocument.WSDL)doc; |
ohair@286 | 593 | if (wsdlDoc.hasService()) { |
ohair@286 | 594 | primaryDoc = doc; |
ohair@286 | 595 | if (foundConcrete) { |
ohair@286 | 596 | throw new ServerRtException("duplicate.primary.wsdl", doc.getSystemId() ); |
ohair@286 | 597 | } |
ohair@286 | 598 | foundConcrete = true; |
ohair@286 | 599 | } |
ohair@286 | 600 | if (wsdlDoc.hasPortType()) { |
ohair@286 | 601 | if (foundAbstract) { |
ohair@286 | 602 | throw new ServerRtException("duplicate.abstract.wsdl", doc.getSystemId()); |
ohair@286 | 603 | } |
ohair@286 | 604 | foundAbstract = true; |
ohair@286 | 605 | } |
ohair@286 | 606 | } |
ohair@286 | 607 | } |
ohair@286 | 608 | return primaryDoc; |
ohair@286 | 609 | } |
ohair@286 | 610 | |
ohair@286 | 611 | /** |
ohair@286 | 612 | * Parses the primary WSDL and returns the {@link WSDLPort} for the given service and port names |
ohair@286 | 613 | * |
ohair@286 | 614 | * @param primaryWsdl Primary WSDL |
ohair@286 | 615 | * @param metadata it may contain imported WSDL and schema documents |
ohair@286 | 616 | * @param serviceName service name in wsdl |
ohair@286 | 617 | * @param portName port name in WSDL |
ohair@286 | 618 | * @param container container in which this service is running |
ohair@286 | 619 | * @return non-null wsdl port object |
ohair@286 | 620 | */ |
ohair@286 | 621 | private static @NotNull WSDLPortImpl getWSDLPort(SDDocumentSource primaryWsdl, List<? extends SDDocumentSource> metadata, |
ohair@286 | 622 | @NotNull QName serviceName, @NotNull QName portName, Container container) { |
ohair@286 | 623 | URL wsdlUrl = primaryWsdl.getSystemId(); |
ohair@286 | 624 | try { |
ohair@286 | 625 | // TODO: delegate to another entity resolver |
ohair@286 | 626 | WSDLModelImpl wsdlDoc = RuntimeWSDLParser.parse( |
ohair@286 | 627 | new Parser(primaryWsdl), new EntityResolverImpl(metadata), |
ohair@286 | 628 | false, container, ServiceFinder.find(WSDLParserExtension.class).toArray()); |
ohair@286 | 629 | if(wsdlDoc.getServices().size() == 0) { |
ohair@286 | 630 | throw new ServerRtException(ServerMessages.localizableRUNTIME_PARSER_WSDL_NOSERVICE_IN_WSDLMODEL(wsdlUrl)); |
ohair@286 | 631 | } |
ohair@286 | 632 | WSDLServiceImpl wsdlService = wsdlDoc.getService(serviceName); |
ohair@286 | 633 | if (wsdlService == null) { |
ohair@286 | 634 | throw new ServerRtException(ServerMessages.localizableRUNTIME_PARSER_WSDL_INCORRECTSERVICE(serviceName,wsdlUrl)); |
ohair@286 | 635 | } |
ohair@286 | 636 | WSDLPortImpl wsdlPort = wsdlService.get(portName); |
ohair@286 | 637 | if (wsdlPort == null) { |
ohair@286 | 638 | throw new ServerRtException(ServerMessages.localizableRUNTIME_PARSER_WSDL_INCORRECTSERVICEPORT(serviceName, portName, wsdlUrl)); |
ohair@286 | 639 | } |
ohair@286 | 640 | return wsdlPort; |
ohair@286 | 641 | } catch (IOException e) { |
ohair@286 | 642 | throw new ServerRtException("runtime.parser.wsdl", wsdlUrl,e); |
ohair@286 | 643 | } catch (XMLStreamException e) { |
ohair@286 | 644 | throw new ServerRtException("runtime.saxparser.exception", e.getMessage(), e.getLocation(), e); |
ohair@286 | 645 | } catch (SAXException e) { |
ohair@286 | 646 | throw new ServerRtException("runtime.parser.wsdl", wsdlUrl,e); |
ohair@286 | 647 | } catch (ServiceConfigurationError e) { |
ohair@286 | 648 | throw new ServerRtException("runtime.parser.wsdl", wsdlUrl,e); |
ohair@286 | 649 | } |
ohair@286 | 650 | } |
ohair@286 | 651 | |
ohair@286 | 652 | /** |
ohair@286 | 653 | * {@link XMLEntityResolver} that can resolve to {@link SDDocumentSource}s. |
ohair@286 | 654 | */ |
ohair@286 | 655 | private static final class EntityResolverImpl implements XMLEntityResolver { |
ohair@286 | 656 | private Map<String,SDDocumentSource> metadata = new HashMap<String,SDDocumentSource>(); |
ohair@286 | 657 | |
ohair@286 | 658 | public EntityResolverImpl(List<? extends SDDocumentSource> metadata) { |
ohair@286 | 659 | for (SDDocumentSource doc : metadata) { |
ohair@286 | 660 | this.metadata.put(doc.getSystemId().toExternalForm(),doc); |
ohair@286 | 661 | } |
ohair@286 | 662 | } |
ohair@286 | 663 | |
ohair@286 | 664 | public Parser resolveEntity (String publicId, String systemId) throws IOException, XMLStreamException { |
ohair@286 | 665 | if (systemId != null) { |
ohair@286 | 666 | SDDocumentSource doc = metadata.get(systemId); |
ohair@286 | 667 | if (doc != null) |
ohair@286 | 668 | return new Parser(doc); |
ohair@286 | 669 | } |
ohair@286 | 670 | return null; |
ohair@286 | 671 | } |
ohair@286 | 672 | |
ohair@286 | 673 | } |
ohair@286 | 674 | |
ohair@286 | 675 | private static final Logger logger = Logger.getLogger( |
ohair@286 | 676 | com.sun.xml.internal.ws.util.Constants.LoggingDomain + ".server.endpoint"); |
ohair@286 | 677 | } |