Thu, 31 Aug 2017 15:18:52 +0800
merge
aoqi@0 | 1 | /* |
aoqi@0 | 2 | * Copyright (c) 1997, 2013, Oracle and/or its affiliates. All rights reserved. |
aoqi@0 | 3 | * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. |
aoqi@0 | 4 | * |
aoqi@0 | 5 | * This code is free software; you can redistribute it and/or modify it |
aoqi@0 | 6 | * under the terms of the GNU General Public License version 2 only, as |
aoqi@0 | 7 | * published by the Free Software Foundation. Oracle designates this |
aoqi@0 | 8 | * particular file as subject to the "Classpath" exception as provided |
aoqi@0 | 9 | * by Oracle in the LICENSE file that accompanied this code. |
aoqi@0 | 10 | * |
aoqi@0 | 11 | * This code is distributed in the hope that it will be useful, but WITHOUT |
aoqi@0 | 12 | * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or |
aoqi@0 | 13 | * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License |
aoqi@0 | 14 | * version 2 for more details (a copy is included in the LICENSE file that |
aoqi@0 | 15 | * accompanied this code). |
aoqi@0 | 16 | * |
aoqi@0 | 17 | * You should have received a copy of the GNU General Public License version |
aoqi@0 | 18 | * 2 along with this work; if not, write to the Free Software Foundation, |
aoqi@0 | 19 | * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. |
aoqi@0 | 20 | * |
aoqi@0 | 21 | * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA |
aoqi@0 | 22 | * or visit www.oracle.com if you need additional information or have any |
aoqi@0 | 23 | * questions. |
aoqi@0 | 24 | */ |
aoqi@0 | 25 | |
aoqi@0 | 26 | package com.sun.xml.internal.ws.server; |
aoqi@0 | 27 | |
aoqi@0 | 28 | import com.sun.istack.internal.NotNull; |
aoqi@0 | 29 | import com.sun.istack.internal.Nullable; |
aoqi@0 | 30 | import com.sun.xml.internal.stream.buffer.MutableXMLStreamBuffer; |
aoqi@0 | 31 | import com.sun.xml.internal.ws.api.BindingID; |
aoqi@0 | 32 | import com.sun.xml.internal.ws.api.WSBinding; |
aoqi@0 | 33 | import com.sun.xml.internal.ws.api.WSFeatureList; |
aoqi@0 | 34 | import com.sun.xml.internal.ws.api.databinding.DatabindingConfig; |
aoqi@0 | 35 | import com.sun.xml.internal.ws.api.databinding.DatabindingFactory; |
aoqi@0 | 36 | import com.sun.xml.internal.ws.api.databinding.MetadataReader; |
aoqi@0 | 37 | import com.sun.xml.internal.ws.api.databinding.WSDLGenInfo; |
aoqi@0 | 38 | import com.sun.xml.internal.ws.api.model.SEIModel; |
aoqi@0 | 39 | import com.sun.xml.internal.ws.api.model.wsdl.WSDLModel; |
aoqi@0 | 40 | import com.sun.xml.internal.ws.api.model.wsdl.WSDLPort; |
aoqi@0 | 41 | import com.sun.xml.internal.ws.api.model.wsdl.WSDLService; |
aoqi@0 | 42 | import com.sun.xml.internal.ws.api.policy.PolicyResolver; |
aoqi@0 | 43 | import com.sun.xml.internal.ws.api.policy.PolicyResolverFactory; |
aoqi@0 | 44 | import com.sun.xml.internal.ws.api.server.AsyncProvider; |
aoqi@0 | 45 | import com.sun.xml.internal.ws.api.server.Container; |
aoqi@0 | 46 | import com.sun.xml.internal.ws.api.server.ContainerResolver; |
aoqi@0 | 47 | import com.sun.xml.internal.ws.api.server.InstanceResolver; |
aoqi@0 | 48 | import com.sun.xml.internal.ws.api.server.Invoker; |
aoqi@0 | 49 | import com.sun.xml.internal.ws.api.server.SDDocument; |
aoqi@0 | 50 | import com.sun.xml.internal.ws.api.server.SDDocumentSource; |
aoqi@0 | 51 | import com.sun.xml.internal.ws.api.server.WSEndpoint; |
aoqi@0 | 52 | import com.sun.xml.internal.ws.api.streaming.XMLStreamReaderFactory; |
aoqi@0 | 53 | import com.sun.xml.internal.ws.api.wsdl.parser.WSDLParserExtension; |
aoqi@0 | 54 | import com.sun.xml.internal.ws.api.wsdl.parser.XMLEntityResolver; |
aoqi@0 | 55 | import com.sun.xml.internal.ws.api.wsdl.parser.XMLEntityResolver.Parser; |
aoqi@0 | 56 | import com.sun.xml.internal.ws.api.wsdl.writer.WSDLGeneratorExtension; |
aoqi@0 | 57 | import com.sun.xml.internal.ws.binding.BindingImpl; |
aoqi@0 | 58 | import com.sun.xml.internal.ws.binding.SOAPBindingImpl; |
aoqi@0 | 59 | import com.sun.xml.internal.ws.binding.WebServiceFeatureList; |
aoqi@0 | 60 | import com.sun.xml.internal.ws.model.AbstractSEIModelImpl; |
aoqi@0 | 61 | import com.sun.xml.internal.ws.model.ReflectAnnotationReader; |
aoqi@0 | 62 | import com.sun.xml.internal.ws.model.RuntimeModeler; |
aoqi@0 | 63 | import com.sun.xml.internal.ws.model.SOAPSEIModel; |
aoqi@0 | 64 | import com.sun.xml.internal.ws.policy.PolicyMap; |
aoqi@0 | 65 | import com.sun.xml.internal.ws.policy.jaxws.PolicyUtil; |
aoqi@0 | 66 | import com.sun.xml.internal.ws.resources.ServerMessages; |
aoqi@0 | 67 | import com.sun.xml.internal.ws.server.provider.ProviderInvokerTube; |
aoqi@0 | 68 | import com.sun.xml.internal.ws.server.sei.SEIInvokerTube; |
aoqi@0 | 69 | import com.sun.xml.internal.ws.util.HandlerAnnotationInfo; |
aoqi@0 | 70 | import com.sun.xml.internal.ws.util.HandlerAnnotationProcessor; |
aoqi@0 | 71 | import com.sun.xml.internal.ws.util.ServiceConfigurationError; |
aoqi@0 | 72 | import com.sun.xml.internal.ws.util.ServiceFinder; |
aoqi@0 | 73 | import com.sun.xml.internal.ws.util.xml.XmlUtil; |
aoqi@0 | 74 | import com.sun.xml.internal.ws.wsdl.parser.RuntimeWSDLParser; |
aoqi@0 | 75 | |
aoqi@0 | 76 | import org.xml.sax.EntityResolver; |
aoqi@0 | 77 | import org.xml.sax.InputSource; |
aoqi@0 | 78 | import org.xml.sax.SAXException; |
aoqi@0 | 79 | |
aoqi@0 | 80 | import javax.jws.WebService; |
aoqi@0 | 81 | import javax.xml.namespace.QName; |
aoqi@0 | 82 | import javax.xml.stream.XMLStreamException; |
aoqi@0 | 83 | import javax.xml.stream.XMLStreamReader; |
aoqi@0 | 84 | import javax.xml.ws.Provider; |
aoqi@0 | 85 | import javax.xml.ws.WebServiceException; |
aoqi@0 | 86 | import javax.xml.ws.WebServiceFeature; |
aoqi@0 | 87 | import javax.xml.ws.WebServiceProvider; |
aoqi@0 | 88 | import javax.xml.ws.soap.SOAPBinding; |
aoqi@0 | 89 | |
aoqi@0 | 90 | import java.io.IOException; |
aoqi@0 | 91 | import java.net.URL; |
aoqi@0 | 92 | import java.util.ArrayList; |
aoqi@0 | 93 | import java.util.Collection; |
aoqi@0 | 94 | import java.util.HashMap; |
aoqi@0 | 95 | import java.util.List; |
aoqi@0 | 96 | import java.util.Map; |
aoqi@0 | 97 | import java.util.logging.Logger; |
aoqi@0 | 98 | |
aoqi@0 | 99 | /** |
aoqi@0 | 100 | * Entry point to the JAX-WS RI server-side runtime. |
aoqi@0 | 101 | * |
aoqi@0 | 102 | * @author Kohsuke Kawaguchi |
aoqi@0 | 103 | * @author Jitendra Kotamraju |
aoqi@0 | 104 | */ |
aoqi@0 | 105 | public class EndpointFactory { |
aoqi@0 | 106 | private static final EndpointFactory instance = new EndpointFactory(); |
aoqi@0 | 107 | |
aoqi@0 | 108 | public static EndpointFactory getInstance() { |
aoqi@0 | 109 | return instance; |
aoqi@0 | 110 | } |
aoqi@0 | 111 | |
aoqi@0 | 112 | /** |
aoqi@0 | 113 | * Implements {@link WSEndpoint#create}. |
aoqi@0 | 114 | * |
aoqi@0 | 115 | * No need to take WebServiceContext implementation. When InvokerPipe is |
aoqi@0 | 116 | * instantiated, it calls InstanceResolver to set up a WebServiceContext. |
aoqi@0 | 117 | * We shall only take delegate to getUserPrincipal and isUserInRole from adapter. |
aoqi@0 | 118 | * |
aoqi@0 | 119 | * <p> |
aoqi@0 | 120 | * Nobody else should be calling this method. |
aoqi@0 | 121 | */ |
aoqi@0 | 122 | public static <T> WSEndpoint<T> createEndpoint( |
aoqi@0 | 123 | Class<T> implType, boolean processHandlerAnnotation, @Nullable Invoker invoker, |
aoqi@0 | 124 | @Nullable QName serviceName, @Nullable QName portName, |
aoqi@0 | 125 | @Nullable Container container, @Nullable WSBinding binding, |
aoqi@0 | 126 | @Nullable SDDocumentSource primaryWsdl, |
aoqi@0 | 127 | @Nullable Collection<? extends SDDocumentSource> metadata, |
aoqi@0 | 128 | EntityResolver resolver, boolean isTransportSynchronous) { |
aoqi@0 | 129 | return createEndpoint(implType, processHandlerAnnotation, invoker, serviceName, |
aoqi@0 | 130 | portName, container, binding, primaryWsdl, metadata, resolver, isTransportSynchronous, true); |
aoqi@0 | 131 | } |
aoqi@0 | 132 | |
aoqi@0 | 133 | public static <T> WSEndpoint<T> createEndpoint( |
aoqi@0 | 134 | Class<T> implType, boolean processHandlerAnnotation, @Nullable Invoker invoker, |
aoqi@0 | 135 | @Nullable QName serviceName, @Nullable QName portName, |
aoqi@0 | 136 | @Nullable Container container, @Nullable WSBinding binding, |
aoqi@0 | 137 | @Nullable SDDocumentSource primaryWsdl, |
aoqi@0 | 138 | @Nullable Collection<? extends SDDocumentSource> metadata, |
aoqi@0 | 139 | EntityResolver resolver, boolean isTransportSynchronous, boolean isStandard) { |
aoqi@0 | 140 | EndpointFactory factory = container != null ? container.getSPI(EndpointFactory.class) : null; |
aoqi@0 | 141 | if (factory == null) |
aoqi@0 | 142 | factory = EndpointFactory.getInstance(); |
aoqi@0 | 143 | |
aoqi@0 | 144 | return factory.create( |
aoqi@0 | 145 | implType,processHandlerAnnotation, invoker,serviceName,portName,container,binding,primaryWsdl,metadata,resolver,isTransportSynchronous,isStandard); |
aoqi@0 | 146 | } |
aoqi@0 | 147 | |
aoqi@0 | 148 | /** |
aoqi@0 | 149 | * Implements {@link WSEndpoint#create}. |
aoqi@0 | 150 | * |
aoqi@0 | 151 | * No need to take WebServiceContext implementation. When InvokerPipe is |
aoqi@0 | 152 | * instantiated, it calls InstanceResolver to set up a WebServiceContext. |
aoqi@0 | 153 | * We shall only take delegate to getUserPrincipal and isUserInRole from adapter. |
aoqi@0 | 154 | * |
aoqi@0 | 155 | * <p> |
aoqi@0 | 156 | * Nobody else should be calling this method. |
aoqi@0 | 157 | */ |
aoqi@0 | 158 | public <T> WSEndpoint<T> create( |
aoqi@0 | 159 | Class<T> implType, boolean processHandlerAnnotation, @Nullable Invoker invoker, |
aoqi@0 | 160 | @Nullable QName serviceName, @Nullable QName portName, |
aoqi@0 | 161 | @Nullable Container container, @Nullable WSBinding binding, |
aoqi@0 | 162 | @Nullable SDDocumentSource primaryWsdl, |
aoqi@0 | 163 | @Nullable Collection<? extends SDDocumentSource> metadata, |
aoqi@0 | 164 | EntityResolver resolver, boolean isTransportSynchronous) { |
aoqi@0 | 165 | return create(implType, processHandlerAnnotation, invoker, serviceName, |
aoqi@0 | 166 | portName, container, binding, primaryWsdl, metadata, resolver, isTransportSynchronous, |
aoqi@0 | 167 | true); |
aoqi@0 | 168 | |
aoqi@0 | 169 | } |
aoqi@0 | 170 | |
aoqi@0 | 171 | public <T> WSEndpoint<T> create( |
aoqi@0 | 172 | Class<T> implType, boolean processHandlerAnnotation, @Nullable Invoker invoker, |
aoqi@0 | 173 | @Nullable QName serviceName, @Nullable QName portName, |
aoqi@0 | 174 | @Nullable Container container, @Nullable WSBinding binding, |
aoqi@0 | 175 | @Nullable SDDocumentSource primaryWsdl, |
aoqi@0 | 176 | @Nullable Collection<? extends SDDocumentSource> metadata, |
aoqi@0 | 177 | EntityResolver resolver, boolean isTransportSynchronous, boolean isStandard) { |
aoqi@0 | 178 | |
aoqi@0 | 179 | if(implType ==null) |
aoqi@0 | 180 | throw new IllegalArgumentException(); |
aoqi@0 | 181 | |
aoqi@0 | 182 | MetadataReader metadataReader = getExternalMetadatReader(implType, binding); |
aoqi@0 | 183 | |
aoqi@0 | 184 | if (isStandard) { |
aoqi@0 | 185 | verifyImplementorClass(implType, metadataReader); |
aoqi@0 | 186 | } |
aoqi@0 | 187 | |
aoqi@0 | 188 | if (invoker == null) { |
aoqi@0 | 189 | invoker = InstanceResolver.createDefault(implType).createInvoker(); |
aoqi@0 | 190 | } |
aoqi@0 | 191 | |
aoqi@0 | 192 | List<SDDocumentSource> md = new ArrayList<SDDocumentSource>(); |
aoqi@0 | 193 | if(metadata!=null) |
aoqi@0 | 194 | md.addAll(metadata); |
aoqi@0 | 195 | |
aoqi@0 | 196 | if(primaryWsdl!=null && !md.contains(primaryWsdl)) |
aoqi@0 | 197 | md.add(primaryWsdl); |
aoqi@0 | 198 | |
aoqi@0 | 199 | if(container==null) |
aoqi@0 | 200 | container = ContainerResolver.getInstance().getContainer(); |
aoqi@0 | 201 | |
aoqi@0 | 202 | if(serviceName==null) |
aoqi@0 | 203 | serviceName = getDefaultServiceName(implType, metadataReader); |
aoqi@0 | 204 | |
aoqi@0 | 205 | if(portName==null) |
aoqi@0 | 206 | portName = getDefaultPortName(serviceName,implType, metadataReader); |
aoqi@0 | 207 | |
aoqi@0 | 208 | {// error check |
aoqi@0 | 209 | String serviceNS = serviceName.getNamespaceURI(); |
aoqi@0 | 210 | String portNS = portName.getNamespaceURI(); |
aoqi@0 | 211 | if (!serviceNS.equals(portNS)) { |
aoqi@0 | 212 | throw new ServerRtException("wrong.tns.for.port",portNS, serviceNS); |
aoqi@0 | 213 | } |
aoqi@0 | 214 | } |
aoqi@0 | 215 | |
aoqi@0 | 216 | // setting a default binding |
aoqi@0 | 217 | if (binding == null) |
aoqi@0 | 218 | binding = BindingImpl.create(BindingID.parse(implType)); |
aoqi@0 | 219 | |
aoqi@0 | 220 | if ( isStandard && primaryWsdl != null) { |
aoqi@0 | 221 | verifyPrimaryWSDL(primaryWsdl, serviceName); |
aoqi@0 | 222 | } |
aoqi@0 | 223 | |
aoqi@0 | 224 | QName portTypeName = null; |
aoqi@0 | 225 | if (isStandard && implType.getAnnotation(WebServiceProvider.class)==null) { |
aoqi@0 | 226 | portTypeName = RuntimeModeler.getPortTypeName(implType, metadataReader); |
aoqi@0 | 227 | } |
aoqi@0 | 228 | |
aoqi@0 | 229 | // Categorises the documents as WSDL, Schema etc |
aoqi@0 | 230 | List<SDDocumentImpl> docList = categoriseMetadata(md, serviceName, portTypeName); |
aoqi@0 | 231 | // Finds the primary WSDL and makes sure that metadata doesn't have |
aoqi@0 | 232 | // two concrete or abstract WSDLs |
aoqi@0 | 233 | SDDocumentImpl primaryDoc = primaryWsdl != null ? SDDocumentImpl.create(primaryWsdl,serviceName,portTypeName) : findPrimary(docList); |
aoqi@0 | 234 | |
aoqi@0 | 235 | EndpointAwareTube terminal; |
aoqi@0 | 236 | WSDLPort wsdlPort = null; |
aoqi@0 | 237 | AbstractSEIModelImpl seiModel = null; |
aoqi@0 | 238 | // create WSDL model |
aoqi@0 | 239 | if (primaryDoc != null) { |
aoqi@0 | 240 | wsdlPort = getWSDLPort(primaryDoc, docList, serviceName, portName, container, resolver); |
aoqi@0 | 241 | } |
aoqi@0 | 242 | |
aoqi@0 | 243 | WebServiceFeatureList features=((BindingImpl)binding).getFeatures(); |
aoqi@0 | 244 | if (isStandard) { |
aoqi@0 | 245 | features.parseAnnotations(implType); |
aoqi@0 | 246 | } |
aoqi@0 | 247 | PolicyMap policyMap = null; |
aoqi@0 | 248 | // create terminal pipe that invokes the application |
aoqi@0 | 249 | if (isUseProviderTube(implType, isStandard)) { |
aoqi@0 | 250 | //TODO incase of Provider, provide a way to User for complete control of the message processing by giving |
aoqi@0 | 251 | // ability to turn off the WSDL/Policy based features and its associated tubes. |
aoqi@0 | 252 | |
aoqi@0 | 253 | //Even in case of Provider, merge all features configured via WSDL/Policy or deployment configuration |
aoqi@0 | 254 | Iterable<WebServiceFeature> configFtrs; |
aoqi@0 | 255 | if(wsdlPort != null) { |
aoqi@0 | 256 | policyMap = wsdlPort.getOwner().getParent().getPolicyMap(); |
aoqi@0 | 257 | //Merge features from WSDL and other policy configuration |
aoqi@0 | 258 | configFtrs = wsdlPort.getFeatures(); |
aoqi@0 | 259 | } else { |
aoqi@0 | 260 | //No WSDL, so try to merge features from Policy configuration |
aoqi@0 | 261 | policyMap = PolicyResolverFactory.create().resolve( |
aoqi@0 | 262 | new PolicyResolver.ServerContext(null, container, implType, false)); |
aoqi@0 | 263 | configFtrs = PolicyUtil.getPortScopedFeatures(policyMap,serviceName,portName); |
aoqi@0 | 264 | } |
aoqi@0 | 265 | features.mergeFeatures(configFtrs, true); |
aoqi@0 | 266 | terminal = createProviderInvokerTube(implType, binding, invoker, container); |
aoqi@0 | 267 | } else { |
aoqi@0 | 268 | // Create runtime model for non Provider endpoints |
aoqi@0 | 269 | seiModel = createSEIModel(wsdlPort, implType, serviceName, portName, binding, primaryDoc); |
aoqi@0 | 270 | if(binding instanceof SOAPBindingImpl){ |
aoqi@0 | 271 | //set portKnownHeaders on Binding, so that they can be used for MU processing |
aoqi@0 | 272 | ((SOAPBindingImpl)binding).setPortKnownHeaders( |
aoqi@0 | 273 | ((SOAPSEIModel)seiModel).getKnownHeaders()); |
aoqi@0 | 274 | } |
aoqi@0 | 275 | // Generate WSDL for SEI endpoints(not for Provider endpoints) |
aoqi@0 | 276 | if (primaryDoc == null) { |
aoqi@0 | 277 | primaryDoc = generateWSDL(binding, seiModel, docList, container, implType); |
aoqi@0 | 278 | // create WSDL model |
aoqi@0 | 279 | wsdlPort = getWSDLPort(primaryDoc, docList, serviceName, portName, container, resolver); |
aoqi@0 | 280 | seiModel.freeze(wsdlPort); |
aoqi@0 | 281 | } |
aoqi@0 | 282 | policyMap = wsdlPort.getOwner().getParent().getPolicyMap(); |
aoqi@0 | 283 | // New Features might have been added in WSDL through Policy. |
aoqi@0 | 284 | //Merge features from WSDL and other policy configuration |
aoqi@0 | 285 | // This sets only the wsdl features that are not already set(enabled/disabled) |
aoqi@0 | 286 | features.mergeFeatures(wsdlPort.getFeatures(), true); |
aoqi@0 | 287 | terminal = createSEIInvokerTube(seiModel,invoker,binding); |
aoqi@0 | 288 | } |
aoqi@0 | 289 | |
aoqi@0 | 290 | // Process @HandlerChain, if handler-chain is not set via Deployment Descriptor |
aoqi@0 | 291 | if (processHandlerAnnotation) { |
aoqi@0 | 292 | processHandlerAnnotation(binding, implType, serviceName, portName); |
aoqi@0 | 293 | } |
aoqi@0 | 294 | // Selects only required metadata for this endpoint from the passed-in metadata |
aoqi@0 | 295 | if (primaryDoc != null) { |
aoqi@0 | 296 | docList = findMetadataClosure(primaryDoc, docList, resolver); |
aoqi@0 | 297 | } |
aoqi@0 | 298 | |
aoqi@0 | 299 | ServiceDefinitionImpl serviceDefiniton = (primaryDoc != null) ? new ServiceDefinitionImpl(docList, primaryDoc) : null; |
aoqi@0 | 300 | |
aoqi@0 | 301 | return create(serviceName, portName, binding, container, seiModel, wsdlPort, implType, serviceDefiniton, |
aoqi@0 | 302 | terminal, isTransportSynchronous, policyMap); |
aoqi@0 | 303 | } |
aoqi@0 | 304 | |
aoqi@0 | 305 | 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) { |
aoqi@0 | 306 | return new WSEndpointImpl<T>(serviceName, portName, binding, container, seiModel, |
aoqi@0 | 307 | wsdlPort, implType, serviceDefinition, terminal, isTransportSynchronous, policyMap); |
aoqi@0 | 308 | } |
aoqi@0 | 309 | |
aoqi@0 | 310 | protected boolean isUseProviderTube(Class<?> implType, boolean isStandard) { |
aoqi@0 | 311 | return !isStandard || implType.getAnnotation(WebServiceProvider.class)!=null; |
aoqi@0 | 312 | } |
aoqi@0 | 313 | |
aoqi@0 | 314 | protected EndpointAwareTube createSEIInvokerTube(AbstractSEIModelImpl seiModel, Invoker invoker, WSBinding binding) { |
aoqi@0 | 315 | return new SEIInvokerTube(seiModel,invoker,binding); |
aoqi@0 | 316 | } |
aoqi@0 | 317 | |
aoqi@0 | 318 | protected <T> EndpointAwareTube createProviderInvokerTube(final Class<T> implType, final WSBinding binding, |
aoqi@0 | 319 | final Invoker invoker, final Container container) { |
aoqi@0 | 320 | return ProviderInvokerTube.create(implType, binding, invoker, container); |
aoqi@0 | 321 | } |
aoqi@0 | 322 | /** |
aoqi@0 | 323 | * Goes through the original metadata documents and collects the required ones. |
aoqi@0 | 324 | * This done traversing from primary WSDL and its imports until it builds a |
aoqi@0 | 325 | * complete set of documents(transitive closure) for the endpoint. |
aoqi@0 | 326 | * |
aoqi@0 | 327 | * @param primaryDoc primary WSDL doc |
aoqi@0 | 328 | * @param docList complete metadata |
aoqi@0 | 329 | * @return new metadata that doesn't contain extraneous documnets. |
aoqi@0 | 330 | */ |
aoqi@0 | 331 | private static List<SDDocumentImpl> findMetadataClosure(SDDocumentImpl primaryDoc, List<SDDocumentImpl> docList, EntityResolver resolver) { |
aoqi@0 | 332 | // create a map for old metadata |
aoqi@0 | 333 | Map<String, SDDocumentImpl> oldMap = new HashMap<String, SDDocumentImpl>(); |
aoqi@0 | 334 | for(SDDocumentImpl doc : docList) { |
aoqi@0 | 335 | oldMap.put(doc.getSystemId().toString(), doc); |
aoqi@0 | 336 | } |
aoqi@0 | 337 | // create a map for new metadata |
aoqi@0 | 338 | Map<String, SDDocumentImpl> newMap = new HashMap<String, SDDocumentImpl>(); |
aoqi@0 | 339 | newMap.put(primaryDoc.getSystemId().toString(), primaryDoc); |
aoqi@0 | 340 | |
aoqi@0 | 341 | List<String> remaining = new ArrayList<String>(); |
aoqi@0 | 342 | remaining.addAll(primaryDoc.getImports()); |
aoqi@0 | 343 | while(!remaining.isEmpty()) { |
aoqi@0 | 344 | String url = remaining.remove(0); |
aoqi@0 | 345 | SDDocumentImpl doc = oldMap.get(url); |
aoqi@0 | 346 | if (doc == null) { |
aoqi@0 | 347 | // old metadata doesn't have this imported doc, may be external |
aoqi@0 | 348 | if (resolver != null) { |
aoqi@0 | 349 | try { |
aoqi@0 | 350 | InputSource source = resolver.resolveEntity(null, url); |
aoqi@0 | 351 | if (source != null) { |
aoqi@0 | 352 | MutableXMLStreamBuffer xsb = new MutableXMLStreamBuffer(); |
aoqi@0 | 353 | XMLStreamReader reader = XmlUtil.newXMLInputFactory(true).createXMLStreamReader(source.getByteStream()); |
aoqi@0 | 354 | xsb.createFromXMLStreamReader(reader); |
aoqi@0 | 355 | |
aoqi@0 | 356 | SDDocumentSource sdocSource = SDDocumentImpl.create(new URL(url), xsb); |
aoqi@0 | 357 | doc = SDDocumentImpl.create(sdocSource, null, null); |
aoqi@0 | 358 | } |
aoqi@0 | 359 | } catch (Exception ex) { |
aoqi@0 | 360 | ex.printStackTrace(); |
aoqi@0 | 361 | } |
aoqi@0 | 362 | } |
aoqi@0 | 363 | } |
aoqi@0 | 364 | // Check if new metadata already contains this doc |
aoqi@0 | 365 | if (doc != null && !newMap.containsKey(url)) { |
aoqi@0 | 366 | newMap.put(url, doc); |
aoqi@0 | 367 | remaining.addAll(doc.getImports()); |
aoqi@0 | 368 | } |
aoqi@0 | 369 | } |
aoqi@0 | 370 | List<SDDocumentImpl> newMetadata = new ArrayList<SDDocumentImpl>(); |
aoqi@0 | 371 | newMetadata.addAll(newMap.values()); |
aoqi@0 | 372 | return newMetadata; |
aoqi@0 | 373 | } |
aoqi@0 | 374 | |
aoqi@0 | 375 | private static <T> void processHandlerAnnotation(WSBinding binding, Class<T> implType, QName serviceName, QName portName) { |
aoqi@0 | 376 | HandlerAnnotationInfo chainInfo = |
aoqi@0 | 377 | HandlerAnnotationProcessor.buildHandlerInfo( |
aoqi@0 | 378 | implType, serviceName, portName, binding); |
aoqi@0 | 379 | if (chainInfo != null) { |
aoqi@0 | 380 | binding.setHandlerChain(chainInfo.getHandlers()); |
aoqi@0 | 381 | if (binding instanceof SOAPBinding) { |
aoqi@0 | 382 | ((SOAPBinding) binding).setRoles(chainInfo.getRoles()); |
aoqi@0 | 383 | } |
aoqi@0 | 384 | } |
aoqi@0 | 385 | |
aoqi@0 | 386 | } |
aoqi@0 | 387 | |
aoqi@0 | 388 | /** |
aoqi@0 | 389 | * Verifies if the endpoint implementor class has @WebService or @WebServiceProvider |
aoqi@0 | 390 | * annotation |
aoqi@0 | 391 | * |
aoqi@0 | 392 | * @return |
aoqi@0 | 393 | * true if it is a Provider or AsyncProvider endpoint |
aoqi@0 | 394 | * false otherwise |
aoqi@0 | 395 | * @throws java.lang.IllegalArgumentException |
aoqi@0 | 396 | * If it doesn't have any one of @WebService or @WebServiceProvider |
aoqi@0 | 397 | * If it has both @WebService and @WebServiceProvider annotations |
aoqi@0 | 398 | */ |
aoqi@0 | 399 | public static boolean verifyImplementorClass(Class<?> clz) { |
aoqi@0 | 400 | return verifyImplementorClass(clz, null); |
aoqi@0 | 401 | } |
aoqi@0 | 402 | |
aoqi@0 | 403 | /** |
aoqi@0 | 404 | * Verifies if the endpoint implementor class has @WebService or @WebServiceProvider |
aoqi@0 | 405 | * annotation; passing MetadataReader instance allows to read annotations from |
aoqi@0 | 406 | * xml descriptor instead of class's annotations |
aoqi@0 | 407 | * |
aoqi@0 | 408 | * @return |
aoqi@0 | 409 | * true if it is a Provider or AsyncProvider endpoint |
aoqi@0 | 410 | * false otherwise |
aoqi@0 | 411 | * @throws java.lang.IllegalArgumentException |
aoqi@0 | 412 | * If it doesn't have any one of @WebService or @WebServiceProvider |
aoqi@0 | 413 | * If it has both @WebService and @WebServiceProvider annotations |
aoqi@0 | 414 | */ |
aoqi@0 | 415 | public static boolean verifyImplementorClass(Class<?> clz, MetadataReader metadataReader) { |
aoqi@0 | 416 | |
aoqi@0 | 417 | if (metadataReader == null) { |
aoqi@0 | 418 | metadataReader = new ReflectAnnotationReader(); |
aoqi@0 | 419 | } |
aoqi@0 | 420 | |
aoqi@0 | 421 | WebServiceProvider wsProvider = metadataReader.getAnnotation(WebServiceProvider.class, clz); |
aoqi@0 | 422 | WebService ws = metadataReader.getAnnotation(WebService.class, clz); |
aoqi@0 | 423 | if (wsProvider == null && ws == null) { |
aoqi@0 | 424 | throw new IllegalArgumentException(clz +" has neither @WebService nor @WebServiceProvider annotation"); |
aoqi@0 | 425 | } |
aoqi@0 | 426 | if (wsProvider != null && ws != null) { |
aoqi@0 | 427 | throw new IllegalArgumentException(clz +" has both @WebService and @WebServiceProvider annotations"); |
aoqi@0 | 428 | } |
aoqi@0 | 429 | if (wsProvider != null) { |
aoqi@0 | 430 | if (Provider.class.isAssignableFrom(clz) || AsyncProvider.class.isAssignableFrom(clz)) { |
aoqi@0 | 431 | return true; |
aoqi@0 | 432 | } |
aoqi@0 | 433 | throw new IllegalArgumentException(clz +" doesn't implement Provider or AsyncProvider interface"); |
aoqi@0 | 434 | } |
aoqi@0 | 435 | return false; |
aoqi@0 | 436 | } |
aoqi@0 | 437 | |
aoqi@0 | 438 | |
aoqi@0 | 439 | private static AbstractSEIModelImpl createSEIModel(WSDLPort wsdlPort, |
aoqi@0 | 440 | Class<?> implType, @NotNull QName serviceName, @NotNull QName portName, WSBinding binding, |
aoqi@0 | 441 | SDDocumentSource primaryWsdl) { |
aoqi@0 | 442 | DatabindingFactory fac = DatabindingFactory.newInstance(); |
aoqi@0 | 443 | DatabindingConfig config = new DatabindingConfig(); |
aoqi@0 | 444 | config.setEndpointClass(implType); |
aoqi@0 | 445 | config.getMappingInfo().setServiceName(serviceName); |
aoqi@0 | 446 | config.setWsdlPort(wsdlPort); |
aoqi@0 | 447 | config.setWSBinding(binding); |
aoqi@0 | 448 | config.setClassLoader(implType.getClassLoader()); |
aoqi@0 | 449 | config.getMappingInfo().setPortName(portName); |
aoqi@0 | 450 | if (primaryWsdl != null) config.setWsdlURL(primaryWsdl.getSystemId()); |
aoqi@0 | 451 | config.setMetadataReader(getExternalMetadatReader(implType, binding)); |
aoqi@0 | 452 | |
aoqi@0 | 453 | com.sun.xml.internal.ws.db.DatabindingImpl rt = (com.sun.xml.internal.ws.db.DatabindingImpl)fac.createRuntime(config); |
aoqi@0 | 454 | return (AbstractSEIModelImpl) rt.getModel(); |
aoqi@0 | 455 | } |
aoqi@0 | 456 | |
aoqi@0 | 457 | public static MetadataReader getExternalMetadatReader(Class<?> implType, WSBinding binding) { |
aoqi@0 | 458 | com.oracle.webservices.internal.api.databinding.ExternalMetadataFeature ef = binding.getFeature( |
aoqi@0 | 459 | com.oracle.webservices.internal.api.databinding.ExternalMetadataFeature.class); |
aoqi@0 | 460 | // TODO-Miran: would it be necessary to disable secure xml processing? |
aoqi@0 | 461 | if (ef != null) |
aoqi@0 | 462 | return ef.getMetadataReader(implType.getClassLoader(), false); |
aoqi@0 | 463 | return null; |
aoqi@0 | 464 | } |
aoqi@0 | 465 | |
aoqi@0 | 466 | /** |
aoqi@0 | 467 | *Set the mtom enable setting from wsdl model (mtom policy assertion) on to @link WSBinding} if DD has |
aoqi@0 | 468 | * not already set it on BindingID. Also check conflicts. |
aoqi@0 | 469 | */ |
aoqi@0 | 470 | /* |
aoqi@0 | 471 | private static void applyEffectiveMtomSetting(WSDLBoundPortType wsdlBinding, WSBinding binding){ |
aoqi@0 | 472 | if(wsdlBinding.isMTOMEnabled()){ |
aoqi@0 | 473 | BindingID bindingId = binding.getBindingId(); |
aoqi@0 | 474 | if(bindingId.isMTOMEnabled() == null){ |
aoqi@0 | 475 | binding.setMTOMEnabled(true); |
aoqi@0 | 476 | }else if (bindingId.isMTOMEnabled() != null && bindingId.isMTOMEnabled() == Boolean.FALSE){ |
aoqi@0 | 477 | //TODO: i18N |
aoqi@0 | 478 | throw new ServerRtException("Deployment failed! Mtom policy assertion in WSDL is enabled whereas the deplyment descriptor setting wants to disable it!"); |
aoqi@0 | 479 | } |
aoqi@0 | 480 | } |
aoqi@0 | 481 | } |
aoqi@0 | 482 | */ |
aoqi@0 | 483 | /** |
aoqi@0 | 484 | * If service name is not already set via DD or programmatically, it uses |
aoqi@0 | 485 | * annotations {@link WebServiceProvider}, {@link WebService} on implementorClass to get PortName. |
aoqi@0 | 486 | * |
aoqi@0 | 487 | * @return non-null service name |
aoqi@0 | 488 | */ |
aoqi@0 | 489 | public static @NotNull QName getDefaultServiceName(Class<?> implType) { |
aoqi@0 | 490 | return getDefaultServiceName(implType, null); |
aoqi@0 | 491 | } |
aoqi@0 | 492 | |
aoqi@0 | 493 | public static @NotNull QName getDefaultServiceName(Class<?> implType, MetadataReader metadataReader) { |
aoqi@0 | 494 | return getDefaultServiceName(implType, true, metadataReader); |
aoqi@0 | 495 | } |
aoqi@0 | 496 | |
aoqi@0 | 497 | public static @NotNull QName getDefaultServiceName(Class<?> implType, boolean isStandard) { |
aoqi@0 | 498 | return getDefaultServiceName(implType, isStandard, null); |
aoqi@0 | 499 | } |
aoqi@0 | 500 | |
aoqi@0 | 501 | public static @NotNull QName getDefaultServiceName(Class<?> implType, boolean isStandard, MetadataReader metadataReader) { |
aoqi@0 | 502 | if (metadataReader == null) { |
aoqi@0 | 503 | metadataReader = new ReflectAnnotationReader(); |
aoqi@0 | 504 | } |
aoqi@0 | 505 | QName serviceName; |
aoqi@0 | 506 | WebServiceProvider wsProvider = metadataReader.getAnnotation(WebServiceProvider.class, implType); |
aoqi@0 | 507 | if (wsProvider!=null) { |
aoqi@0 | 508 | String tns = wsProvider.targetNamespace(); |
aoqi@0 | 509 | String local = wsProvider.serviceName(); |
aoqi@0 | 510 | serviceName = new QName(tns, local); |
aoqi@0 | 511 | } else { |
aoqi@0 | 512 | serviceName = RuntimeModeler.getServiceName(implType, metadataReader, isStandard); |
aoqi@0 | 513 | } |
aoqi@0 | 514 | assert serviceName != null; |
aoqi@0 | 515 | return serviceName; |
aoqi@0 | 516 | } |
aoqi@0 | 517 | |
aoqi@0 | 518 | /** |
aoqi@0 | 519 | * If portName is not already set via DD or programmatically, it uses |
aoqi@0 | 520 | * annotations on implementorClass to get PortName. |
aoqi@0 | 521 | * |
aoqi@0 | 522 | * @return non-null port name |
aoqi@0 | 523 | */ |
aoqi@0 | 524 | public static @NotNull QName getDefaultPortName(QName serviceName, Class<?> implType) { |
aoqi@0 | 525 | return getDefaultPortName(serviceName, implType, null); |
aoqi@0 | 526 | } |
aoqi@0 | 527 | |
aoqi@0 | 528 | public static @NotNull QName getDefaultPortName(QName serviceName, Class<?> implType, MetadataReader metadataReader) { |
aoqi@0 | 529 | return getDefaultPortName(serviceName, implType, true, metadataReader); |
aoqi@0 | 530 | } |
aoqi@0 | 531 | |
aoqi@0 | 532 | public static @NotNull QName getDefaultPortName(QName serviceName, Class<?> implType, boolean isStandard) { |
aoqi@0 | 533 | return getDefaultPortName(serviceName, implType, isStandard, null); |
aoqi@0 | 534 | } |
aoqi@0 | 535 | |
aoqi@0 | 536 | public static @NotNull QName getDefaultPortName(QName serviceName, Class<?> implType, boolean isStandard, MetadataReader metadataReader) { |
aoqi@0 | 537 | if (metadataReader == null) { |
aoqi@0 | 538 | metadataReader = new ReflectAnnotationReader(); |
aoqi@0 | 539 | } |
aoqi@0 | 540 | QName portName; |
aoqi@0 | 541 | WebServiceProvider wsProvider = metadataReader.getAnnotation(WebServiceProvider.class, implType); |
aoqi@0 | 542 | if (wsProvider!=null) { |
aoqi@0 | 543 | String tns = wsProvider.targetNamespace(); |
aoqi@0 | 544 | String local = wsProvider.portName(); |
aoqi@0 | 545 | portName = new QName(tns, local); |
aoqi@0 | 546 | } else { |
aoqi@0 | 547 | portName = RuntimeModeler.getPortName(implType, metadataReader, serviceName.getNamespaceURI(), isStandard); |
aoqi@0 | 548 | } |
aoqi@0 | 549 | assert portName != null; |
aoqi@0 | 550 | return portName; |
aoqi@0 | 551 | } |
aoqi@0 | 552 | |
aoqi@0 | 553 | /** |
aoqi@0 | 554 | * Returns the wsdl from @WebService, or @WebServiceProvider annotation using |
aoqi@0 | 555 | * wsdlLocation element. |
aoqi@0 | 556 | * |
aoqi@0 | 557 | * @param implType |
aoqi@0 | 558 | * endpoint implementation class |
aoqi@0 | 559 | * make sure that you called {@link #verifyImplementorClass} on it. |
aoqi@0 | 560 | * @return wsdl if there is wsdlLocation, else null |
aoqi@0 | 561 | */ |
aoqi@0 | 562 | public static @Nullable String getWsdlLocation(Class<?> implType) { |
aoqi@0 | 563 | return getWsdlLocation(implType, new ReflectAnnotationReader()); |
aoqi@0 | 564 | } |
aoqi@0 | 565 | |
aoqi@0 | 566 | /** |
aoqi@0 | 567 | * Returns the wsdl from @WebService, or @WebServiceProvider annotation using |
aoqi@0 | 568 | * wsdlLocation element. |
aoqi@0 | 569 | * |
aoqi@0 | 570 | * @param implType |
aoqi@0 | 571 | * endpoint implementation class |
aoqi@0 | 572 | * make sure that you called {@link #verifyImplementorClass} on it. |
aoqi@0 | 573 | * @return wsdl if there is wsdlLocation, else null |
aoqi@0 | 574 | */ |
aoqi@0 | 575 | public static @Nullable String getWsdlLocation(Class<?> implType, MetadataReader metadataReader) { |
aoqi@0 | 576 | |
aoqi@0 | 577 | if (metadataReader == null) { |
aoqi@0 | 578 | metadataReader = new ReflectAnnotationReader(); |
aoqi@0 | 579 | } |
aoqi@0 | 580 | |
aoqi@0 | 581 | WebService ws = metadataReader.getAnnotation(WebService.class, implType); |
aoqi@0 | 582 | if (ws != null) { |
aoqi@0 | 583 | return nullIfEmpty(ws.wsdlLocation()); |
aoqi@0 | 584 | } else { |
aoqi@0 | 585 | WebServiceProvider wsProvider = implType.getAnnotation(WebServiceProvider.class); |
aoqi@0 | 586 | assert wsProvider != null; |
aoqi@0 | 587 | return nullIfEmpty(wsProvider.wsdlLocation()); |
aoqi@0 | 588 | } |
aoqi@0 | 589 | } |
aoqi@0 | 590 | |
aoqi@0 | 591 | private static String nullIfEmpty(String string) { |
aoqi@0 | 592 | if (string.length() < 1) { |
aoqi@0 | 593 | string = null; |
aoqi@0 | 594 | } |
aoqi@0 | 595 | return string; |
aoqi@0 | 596 | } |
aoqi@0 | 597 | |
aoqi@0 | 598 | /** |
aoqi@0 | 599 | * Generates the WSDL and XML Schema for the endpoint if necessary |
aoqi@0 | 600 | * It generates WSDL only for SOAP1.1, and for XSOAP1.2 bindings |
aoqi@0 | 601 | */ |
aoqi@0 | 602 | private static SDDocumentImpl generateWSDL(WSBinding binding, AbstractSEIModelImpl seiModel, List<SDDocumentImpl> docs, |
aoqi@0 | 603 | Container container, Class implType) { |
aoqi@0 | 604 | BindingID bindingId = binding.getBindingId(); |
aoqi@0 | 605 | if (!bindingId.canGenerateWSDL()) { |
aoqi@0 | 606 | throw new ServerRtException("can.not.generate.wsdl", bindingId); |
aoqi@0 | 607 | } |
aoqi@0 | 608 | |
aoqi@0 | 609 | if (bindingId.toString().equals(SOAPBindingImpl.X_SOAP12HTTP_BINDING)) { |
aoqi@0 | 610 | String msg = ServerMessages.GENERATE_NON_STANDARD_WSDL(); |
aoqi@0 | 611 | logger.warning(msg); |
aoqi@0 | 612 | } |
aoqi@0 | 613 | |
aoqi@0 | 614 | // Generate WSDL and schema documents using runtime model |
aoqi@0 | 615 | WSDLGenResolver wsdlResolver = new WSDLGenResolver(docs,seiModel.getServiceQName(),seiModel.getPortTypeName()); |
aoqi@0 | 616 | WSDLGenInfo wsdlGenInfo = new WSDLGenInfo(); |
aoqi@0 | 617 | wsdlGenInfo.setWsdlResolver(wsdlResolver); |
aoqi@0 | 618 | wsdlGenInfo.setContainer(container); |
aoqi@0 | 619 | wsdlGenInfo.setExtensions(ServiceFinder.find(WSDLGeneratorExtension.class).toArray()); |
aoqi@0 | 620 | wsdlGenInfo.setInlineSchemas(false); |
aoqi@0 | 621 | wsdlGenInfo.setSecureXmlProcessingDisabled(isSecureXmlProcessingDisabled(binding.getFeatures())); |
aoqi@0 | 622 | seiModel.getDatabinding().generateWSDL(wsdlGenInfo); |
aoqi@0 | 623 | // WSDLGenerator wsdlGen = new WSDLGenerator(seiModel, wsdlResolver, binding, container, implType, false, |
aoqi@0 | 624 | // ServiceFinder.find(WSDLGeneratorExtension.class).toArray()); |
aoqi@0 | 625 | // wsdlGen.doGeneration(); |
aoqi@0 | 626 | return wsdlResolver.updateDocs(); |
aoqi@0 | 627 | } |
aoqi@0 | 628 | |
aoqi@0 | 629 | private static boolean isSecureXmlProcessingDisabled(WSFeatureList featureList) { |
aoqi@0 | 630 | // TODO-Miran: would it be necessary to disable secure xml processing? |
aoqi@0 | 631 | return false; |
aoqi@0 | 632 | } |
aoqi@0 | 633 | |
aoqi@0 | 634 | /** |
aoqi@0 | 635 | * Builds {@link SDDocumentImpl} from {@link SDDocumentSource}. |
aoqi@0 | 636 | */ |
aoqi@0 | 637 | private static List<SDDocumentImpl> categoriseMetadata( |
aoqi@0 | 638 | List<SDDocumentSource> src, QName serviceName, QName portTypeName) { |
aoqi@0 | 639 | |
aoqi@0 | 640 | List<SDDocumentImpl> r = new ArrayList<SDDocumentImpl>(src.size()); |
aoqi@0 | 641 | for (SDDocumentSource doc : src) { |
aoqi@0 | 642 | r.add(SDDocumentImpl.create(doc,serviceName,portTypeName)); |
aoqi@0 | 643 | } |
aoqi@0 | 644 | return r; |
aoqi@0 | 645 | } |
aoqi@0 | 646 | |
aoqi@0 | 647 | /** |
aoqi@0 | 648 | * Verifies whether the given primaryWsdl contains the given serviceName. |
aoqi@0 | 649 | * If the WSDL doesn't have the service, it throws an WebServiceException. |
aoqi@0 | 650 | */ |
aoqi@0 | 651 | private static void verifyPrimaryWSDL(@NotNull SDDocumentSource primaryWsdl, @NotNull QName serviceName) { |
aoqi@0 | 652 | SDDocumentImpl primaryDoc = SDDocumentImpl.create(primaryWsdl,serviceName,null); |
aoqi@0 | 653 | if (!(primaryDoc instanceof SDDocument.WSDL)) { |
aoqi@0 | 654 | throw new WebServiceException(primaryWsdl.getSystemId()+ |
aoqi@0 | 655 | " is not a WSDL. But it is passed as a primary WSDL"); |
aoqi@0 | 656 | } |
aoqi@0 | 657 | SDDocument.WSDL wsdlDoc = (SDDocument.WSDL)primaryDoc; |
aoqi@0 | 658 | if (!wsdlDoc.hasService()) { |
aoqi@0 | 659 | if(wsdlDoc.getAllServices().isEmpty()) |
aoqi@0 | 660 | throw new WebServiceException("Not a primary WSDL="+primaryWsdl.getSystemId()+ |
aoqi@0 | 661 | " since it doesn't have Service "+serviceName); |
aoqi@0 | 662 | else |
aoqi@0 | 663 | throw new WebServiceException("WSDL "+primaryDoc.getSystemId() |
aoqi@0 | 664 | +" has the following services "+wsdlDoc.getAllServices() |
aoqi@0 | 665 | +" but not "+serviceName+". Maybe you forgot to specify a serviceName and/or targetNamespace in @WebService/@WebServiceProvider?"); |
aoqi@0 | 666 | } |
aoqi@0 | 667 | } |
aoqi@0 | 668 | |
aoqi@0 | 669 | /** |
aoqi@0 | 670 | * Finds the primary WSDL document from the list of metadata documents. If |
aoqi@0 | 671 | * there are two metadata documents that qualify for primary, it throws an |
aoqi@0 | 672 | * exception. If there are two metadata documents that qualify for porttype, |
aoqi@0 | 673 | * it throws an exception. |
aoqi@0 | 674 | * |
aoqi@0 | 675 | * @return primay wsdl document, null if is not there in the docList |
aoqi@0 | 676 | * |
aoqi@0 | 677 | */ |
aoqi@0 | 678 | private static @Nullable SDDocumentImpl findPrimary(@NotNull List<SDDocumentImpl> docList) { |
aoqi@0 | 679 | SDDocumentImpl primaryDoc = null; |
aoqi@0 | 680 | boolean foundConcrete = false; |
aoqi@0 | 681 | boolean foundAbstract = false; |
aoqi@0 | 682 | for(SDDocumentImpl doc : docList) { |
aoqi@0 | 683 | if (doc instanceof SDDocument.WSDL) { |
aoqi@0 | 684 | SDDocument.WSDL wsdlDoc = (SDDocument.WSDL)doc; |
aoqi@0 | 685 | if (wsdlDoc.hasService()) { |
aoqi@0 | 686 | primaryDoc = doc; |
aoqi@0 | 687 | if (foundConcrete) { |
aoqi@0 | 688 | throw new ServerRtException("duplicate.primary.wsdl", doc.getSystemId() ); |
aoqi@0 | 689 | } |
aoqi@0 | 690 | foundConcrete = true; |
aoqi@0 | 691 | } |
aoqi@0 | 692 | if (wsdlDoc.hasPortType()) { |
aoqi@0 | 693 | if (foundAbstract) { |
aoqi@0 | 694 | throw new ServerRtException("duplicate.abstract.wsdl", doc.getSystemId()); |
aoqi@0 | 695 | } |
aoqi@0 | 696 | foundAbstract = true; |
aoqi@0 | 697 | } |
aoqi@0 | 698 | } |
aoqi@0 | 699 | } |
aoqi@0 | 700 | return primaryDoc; |
aoqi@0 | 701 | } |
aoqi@0 | 702 | |
aoqi@0 | 703 | /** |
aoqi@0 | 704 | * Parses the primary WSDL and returns the {@link WSDLPort} for the given service and port names |
aoqi@0 | 705 | * |
aoqi@0 | 706 | * @param primaryWsdl Primary WSDL |
aoqi@0 | 707 | * @param metadata it may contain imported WSDL and schema documents |
aoqi@0 | 708 | * @param serviceName service name in wsdl |
aoqi@0 | 709 | * @param portName port name in WSDL |
aoqi@0 | 710 | * @param container container in which this service is running |
aoqi@0 | 711 | * @return non-null wsdl port object |
aoqi@0 | 712 | */ |
aoqi@0 | 713 | private static @NotNull WSDLPort getWSDLPort(SDDocumentSource primaryWsdl, List<? extends SDDocumentSource> metadata, |
aoqi@0 | 714 | @NotNull QName serviceName, @NotNull QName portName, Container container, |
aoqi@0 | 715 | EntityResolver resolver) { |
aoqi@0 | 716 | URL wsdlUrl = primaryWsdl.getSystemId(); |
aoqi@0 | 717 | try { |
aoqi@0 | 718 | // TODO: delegate to another entity resolver |
aoqi@0 | 719 | WSDLModel wsdlDoc = RuntimeWSDLParser.parse( |
aoqi@0 | 720 | new Parser(primaryWsdl), new EntityResolverImpl(metadata, resolver), |
aoqi@0 | 721 | false, container, ServiceFinder.find(WSDLParserExtension.class).toArray()); |
aoqi@0 | 722 | if(wsdlDoc.getServices().size() == 0) { |
aoqi@0 | 723 | throw new ServerRtException(ServerMessages.localizableRUNTIME_PARSER_WSDL_NOSERVICE_IN_WSDLMODEL(wsdlUrl)); |
aoqi@0 | 724 | } |
aoqi@0 | 725 | WSDLService wsdlService = wsdlDoc.getService(serviceName); |
aoqi@0 | 726 | if (wsdlService == null) { |
aoqi@0 | 727 | throw new ServerRtException(ServerMessages.localizableRUNTIME_PARSER_WSDL_INCORRECTSERVICE(serviceName,wsdlUrl)); |
aoqi@0 | 728 | } |
aoqi@0 | 729 | WSDLPort wsdlPort = wsdlService.get(portName); |
aoqi@0 | 730 | if (wsdlPort == null) { |
aoqi@0 | 731 | throw new ServerRtException(ServerMessages.localizableRUNTIME_PARSER_WSDL_INCORRECTSERVICEPORT(serviceName, portName, wsdlUrl)); |
aoqi@0 | 732 | } |
aoqi@0 | 733 | return wsdlPort; |
aoqi@0 | 734 | } catch (IOException e) { |
aoqi@0 | 735 | throw new ServerRtException("runtime.parser.wsdl", wsdlUrl,e); |
aoqi@0 | 736 | } catch (XMLStreamException e) { |
aoqi@0 | 737 | throw new ServerRtException("runtime.saxparser.exception", e.getMessage(), e.getLocation(), e); |
aoqi@0 | 738 | } catch (SAXException e) { |
aoqi@0 | 739 | throw new ServerRtException("runtime.parser.wsdl", wsdlUrl,e); |
aoqi@0 | 740 | } catch (ServiceConfigurationError e) { |
aoqi@0 | 741 | throw new ServerRtException("runtime.parser.wsdl", wsdlUrl,e); |
aoqi@0 | 742 | } |
aoqi@0 | 743 | } |
aoqi@0 | 744 | |
aoqi@0 | 745 | /** |
aoqi@0 | 746 | * {@link XMLEntityResolver} that can resolve to {@link SDDocumentSource}s. |
aoqi@0 | 747 | */ |
aoqi@0 | 748 | private static final class EntityResolverImpl implements XMLEntityResolver { |
aoqi@0 | 749 | private Map<String,SDDocumentSource> metadata = new HashMap<String,SDDocumentSource>(); |
aoqi@0 | 750 | private EntityResolver resolver; |
aoqi@0 | 751 | |
aoqi@0 | 752 | public EntityResolverImpl(List<? extends SDDocumentSource> metadata, EntityResolver resolver) { |
aoqi@0 | 753 | for (SDDocumentSource doc : metadata) { |
aoqi@0 | 754 | this.metadata.put(doc.getSystemId().toExternalForm(),doc); |
aoqi@0 | 755 | } |
aoqi@0 | 756 | this.resolver = resolver; |
aoqi@0 | 757 | } |
aoqi@0 | 758 | |
aoqi@0 | 759 | public Parser resolveEntity (String publicId, String systemId) throws IOException, XMLStreamException { |
aoqi@0 | 760 | if (systemId != null) { |
aoqi@0 | 761 | SDDocumentSource doc = metadata.get(systemId); |
aoqi@0 | 762 | if (doc != null) |
aoqi@0 | 763 | return new Parser(doc); |
aoqi@0 | 764 | } |
aoqi@0 | 765 | if (resolver != null) { |
aoqi@0 | 766 | try { |
aoqi@0 | 767 | InputSource source = resolver.resolveEntity(publicId, systemId); |
aoqi@0 | 768 | if (source != null) { |
aoqi@0 | 769 | Parser p = new Parser(null, XMLStreamReaderFactory.create(source, true)); |
aoqi@0 | 770 | return p; |
aoqi@0 | 771 | } |
aoqi@0 | 772 | } catch (SAXException e) { |
aoqi@0 | 773 | throw new XMLStreamException(e); |
aoqi@0 | 774 | } |
aoqi@0 | 775 | } |
aoqi@0 | 776 | return null; |
aoqi@0 | 777 | } |
aoqi@0 | 778 | |
aoqi@0 | 779 | } |
aoqi@0 | 780 | |
aoqi@0 | 781 | private static final Logger logger = Logger.getLogger( |
aoqi@0 | 782 | com.sun.xml.internal.ws.util.Constants.LoggingDomain + ".server.endpoint"); |
aoqi@0 | 783 | } |