1.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000 1.2 +++ b/src/share/jaxws_classes/com/sun/tools/internal/ws/processor/modeler/annotation/WebServiceVisitor.java Wed Apr 27 01:27:09 2016 +0800 1.3 @@ -0,0 +1,870 @@ 1.4 +/* 1.5 + * Copyright (c) 1997, 2013, Oracle and/or its affiliates. All rights reserved. 1.6 + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. 1.7 + * 1.8 + * This code is free software; you can redistribute it and/or modify it 1.9 + * under the terms of the GNU General Public License version 2 only, as 1.10 + * published by the Free Software Foundation. Oracle designates this 1.11 + * particular file as subject to the "Classpath" exception as provided 1.12 + * by Oracle in the LICENSE file that accompanied this code. 1.13 + * 1.14 + * This code is distributed in the hope that it will be useful, but WITHOUT 1.15 + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or 1.16 + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License 1.17 + * version 2 for more details (a copy is included in the LICENSE file that 1.18 + * accompanied this code). 1.19 + * 1.20 + * You should have received a copy of the GNU General Public License version 1.21 + * 2 along with this work; if not, write to the Free Software Foundation, 1.22 + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. 1.23 + * 1.24 + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA 1.25 + * or visit www.oracle.com if you need additional information or have any 1.26 + * questions. 1.27 + */ 1.28 + 1.29 +package com.sun.tools.internal.ws.processor.modeler.annotation; 1.30 + 1.31 +import com.sun.tools.internal.ws.processor.model.Port; 1.32 +import com.sun.tools.internal.ws.resources.WebserviceapMessages; 1.33 +import com.sun.tools.internal.ws.util.ClassNameInfo; 1.34 +import com.sun.tools.internal.ws.wsdl.document.soap.SOAPStyle; 1.35 +import com.sun.xml.internal.ws.model.RuntimeModeler; 1.36 + 1.37 +import javax.annotation.processing.ProcessingEnvironment; 1.38 +import javax.jws.Oneway; 1.39 +import javax.jws.WebMethod; 1.40 +import javax.jws.WebParam; 1.41 +import javax.jws.WebResult; 1.42 +import javax.jws.WebService; 1.43 +import javax.jws.soap.SOAPBinding; 1.44 +import javax.jws.soap.SOAPBinding.ParameterStyle; 1.45 +import javax.lang.model.element.Element; 1.46 +import javax.lang.model.element.ElementKind; 1.47 +import javax.lang.model.element.ExecutableElement; 1.48 +import javax.lang.model.element.Modifier; 1.49 +import javax.lang.model.element.Name; 1.50 +import javax.lang.model.element.PackageElement; 1.51 +import javax.lang.model.element.TypeElement; 1.52 +import javax.lang.model.element.VariableElement; 1.53 +import javax.lang.model.type.DeclaredType; 1.54 +import javax.lang.model.type.NoType; 1.55 +import javax.lang.model.type.TypeKind; 1.56 +import javax.lang.model.type.TypeMirror; 1.57 +import javax.lang.model.util.ElementFilter; 1.58 +import javax.lang.model.util.SimpleElementVisitor6; 1.59 +import javax.lang.model.util.SimpleTypeVisitor6; 1.60 +import javax.lang.model.util.Types; 1.61 +import java.lang.annotation.Annotation; 1.62 +import java.util.Collection; 1.63 +import java.util.HashSet; 1.64 +import java.util.List; 1.65 +import java.util.Set; 1.66 +import java.util.Stack; 1.67 + 1.68 +/** 1.69 + * @author WS Development Team 1.70 + */ 1.71 +public abstract class WebServiceVisitor extends SimpleElementVisitor6<Void, Object> { 1.72 + 1.73 + protected ModelBuilder builder; 1.74 + protected String wsdlNamespace; 1.75 + protected String typeNamespace; 1.76 + protected Stack<SOAPBinding> soapBindingStack; 1.77 + protected SOAPBinding typeElementSoapBinding; 1.78 + protected SOAPStyle soapStyle = SOAPStyle.DOCUMENT; 1.79 + protected boolean wrapped = true; 1.80 + protected Port port; 1.81 + protected Name serviceImplName; 1.82 + protected Name endpointInterfaceName; 1.83 + protected AnnotationProcessorContext context; 1.84 + protected AnnotationProcessorContext.SeiContext seiContext; 1.85 + protected boolean processingSei = false; 1.86 + protected String serviceName; 1.87 + protected Name packageName; 1.88 + protected String portName; 1.89 + protected boolean endpointReferencesInterface = false; 1.90 + protected boolean hasWebMethods = false; 1.91 + protected TypeElement typeElement; 1.92 + protected Set<String> processedMethods; 1.93 + protected boolean pushedSoapBinding = false; 1.94 + 1.95 + private static final NoTypeVisitor NO_TYPE_VISITOR = new NoTypeVisitor(); 1.96 + 1.97 + public WebServiceVisitor(ModelBuilder builder, AnnotationProcessorContext context) { 1.98 + this.builder = builder; 1.99 + this.context = context; 1.100 + soapBindingStack = new Stack<SOAPBinding>(); 1.101 + processedMethods = new HashSet<String>(); 1.102 + } 1.103 + 1.104 + @Override 1.105 + public Void visitType(TypeElement e, Object o) { 1.106 + WebService webService = e.getAnnotation(WebService.class); 1.107 + if (!shouldProcessWebService(webService, e)) 1.108 + return null; 1.109 + if (builder.checkAndSetProcessed(e)) 1.110 + return null; 1.111 + typeElement = e; 1.112 + 1.113 + switch (e.getKind()) { 1.114 + case INTERFACE: { 1.115 + if (endpointInterfaceName != null && !endpointInterfaceName.equals(e.getQualifiedName())) { 1.116 + builder.processError(WebserviceapMessages.WEBSERVICEAP_ENDPOINTINTERFACES_DO_NOT_MATCH(endpointInterfaceName, e.getQualifiedName()), e); 1.117 + } 1.118 + verifySeiAnnotations(webService, e); 1.119 + endpointInterfaceName = e.getQualifiedName(); 1.120 + processingSei = true; 1.121 + preProcessWebService(webService, e); 1.122 + processWebService(webService, e); 1.123 + postProcessWebService(webService, e); 1.124 + break; 1.125 + } 1.126 + case CLASS: { 1.127 + typeElementSoapBinding = e.getAnnotation(SOAPBinding.class); 1.128 + if (serviceImplName == null) 1.129 + serviceImplName = e.getQualifiedName(); 1.130 + String endpointInterfaceName = webService != null ? webService.endpointInterface() : null; 1.131 + if (endpointInterfaceName != null && endpointInterfaceName.length() > 0) { 1.132 + checkForInvalidImplAnnotation(e, SOAPBinding.class); 1.133 + if (webService.name().length() > 0) 1.134 + builder.processError(WebserviceapMessages.WEBSERVICEAP_ENDPOINTINTEFACE_PLUS_ELEMENT("name"), e); 1.135 + endpointReferencesInterface = true; 1.136 + verifyImplAnnotations(e); 1.137 + inspectEndpointInterface(endpointInterfaceName, e); 1.138 + serviceImplName = null; 1.139 + return null; 1.140 + } 1.141 + processingSei = false; 1.142 + preProcessWebService(webService, e); 1.143 + processWebService(webService, e); 1.144 + serviceImplName = null; 1.145 + postProcessWebService(webService, e); 1.146 + serviceImplName = null; 1.147 + break; 1.148 + } 1.149 + default: 1.150 + break; 1.151 + } 1.152 + return null; 1.153 + } 1.154 + 1.155 + protected void verifySeiAnnotations(WebService webService, TypeElement d) { 1.156 + if (webService.endpointInterface().length() > 0) { 1.157 + builder.processError(WebserviceapMessages.WEBSERVICEAP_ENDPOINTINTERFACE_ON_INTERFACE( 1.158 + d.getQualifiedName(), webService.endpointInterface()), d); 1.159 + } 1.160 + if (webService.serviceName().length() > 0) { 1.161 + builder.processError(WebserviceapMessages.WEBSERVICEAP_INVALID_SEI_ANNOTATION_ELEMENT( 1.162 + "serviceName", d.getQualifiedName()), d); 1.163 + } 1.164 + if (webService.portName().length() > 0) { 1.165 + builder.processError(WebserviceapMessages.WEBSERVICEAP_INVALID_SEI_ANNOTATION_ELEMENT( 1.166 + "portName", d.getQualifiedName()), d); 1.167 + } 1.168 + } 1.169 + 1.170 + protected void verifyImplAnnotations(TypeElement d) { 1.171 + for (ExecutableElement method : ElementFilter.methodsIn(d.getEnclosedElements())) { 1.172 + checkForInvalidImplAnnotation(method, WebMethod.class); 1.173 + checkForInvalidImplAnnotation(method, Oneway.class); 1.174 + checkForInvalidImplAnnotation(method, WebResult.class); 1.175 + for (VariableElement param : method.getParameters()) { 1.176 + checkForInvalidImplAnnotation(param, WebParam.class); 1.177 + } 1.178 + } 1.179 + } 1.180 + 1.181 + protected void checkForInvalidSeiAnnotation(TypeElement element, Class annotationClass) { 1.182 + Object annotation = element.getAnnotation(annotationClass); 1.183 + if (annotation != null) { 1.184 + builder.processError(WebserviceapMessages.WEBSERVICEAP_INVALID_SEI_ANNOTATION( 1.185 + annotationClass.getName(), element.getQualifiedName()), element); 1.186 + } 1.187 + } 1.188 + 1.189 + protected void checkForInvalidImplAnnotation(Element element, Class annotationClass) { 1.190 + Object annotation = element.getAnnotation(annotationClass); 1.191 + if (annotation != null) { 1.192 + builder.processError(WebserviceapMessages.WEBSERVICEAP_ENDPOINTINTEFACE_PLUS_ANNOTATION(annotationClass.getName()), element); 1.193 + } 1.194 + } 1.195 + 1.196 + protected void preProcessWebService(WebService webService, TypeElement element) { 1.197 + processedMethods = new HashSet<String>(); 1.198 + seiContext = context.getSeiContext(element); 1.199 + String targetNamespace = null; 1.200 + if (webService != null) 1.201 + targetNamespace = webService.targetNamespace(); 1.202 + PackageElement packageElement = builder.getProcessingEnvironment().getElementUtils().getPackageOf(element); 1.203 + if (targetNamespace == null || targetNamespace.length() == 0) { 1.204 + String packageName = packageElement.getQualifiedName().toString(); 1.205 + if (packageName == null || packageName.length() == 0) { 1.206 + builder.processError(WebserviceapMessages.WEBSERVICEAP_NO_PACKAGE_CLASS_MUST_HAVE_TARGETNAMESPACE( 1.207 + element.getQualifiedName()), element); 1.208 + } 1.209 + targetNamespace = RuntimeModeler.getNamespace(packageName); 1.210 + } 1.211 + seiContext.setNamespaceUri(targetNamespace); 1.212 + if (serviceImplName == null) 1.213 + serviceImplName = seiContext.getSeiImplName(); 1.214 + if (serviceImplName != null) { 1.215 + seiContext.setSeiImplName(serviceImplName); 1.216 + context.addSeiContext(serviceImplName, seiContext); 1.217 + } 1.218 + portName = ClassNameInfo.getName(element.getSimpleName().toString().replace('$', '_')); 1.219 + packageName = packageElement.getQualifiedName(); 1.220 + portName = webService != null && webService.name() != null && webService.name().length() > 0 ? 1.221 + webService.name() : portName; 1.222 + serviceName = ClassNameInfo.getName(element.getQualifiedName().toString()) + WebServiceConstants.SERVICE.getValue(); 1.223 + serviceName = webService != null && webService.serviceName() != null && webService.serviceName().length() > 0 ? 1.224 + webService.serviceName() : serviceName; 1.225 + wsdlNamespace = seiContext.getNamespaceUri(); 1.226 + typeNamespace = wsdlNamespace; 1.227 + 1.228 + SOAPBinding soapBinding = element.getAnnotation(SOAPBinding.class); 1.229 + if (soapBinding != null) { 1.230 + pushedSoapBinding = pushSoapBinding(soapBinding, element, element); 1.231 + } else if (element.equals(typeElement)) { 1.232 + pushedSoapBinding = pushSoapBinding(new MySoapBinding(), element, element); 1.233 + } 1.234 + } 1.235 + 1.236 + public static boolean sameStyle(SOAPBinding.Style style, SOAPStyle soapStyle) { 1.237 + return style.equals(SOAPBinding.Style.DOCUMENT) 1.238 + && soapStyle.equals(SOAPStyle.DOCUMENT) 1.239 + || style.equals(SOAPBinding.Style.RPC) 1.240 + && soapStyle.equals(SOAPStyle.RPC); 1.241 + } 1.242 + 1.243 + protected boolean pushSoapBinding(SOAPBinding soapBinding, Element bindingElement, TypeElement classElement) { 1.244 + boolean changed = false; 1.245 + if (!sameStyle(soapBinding.style(), soapStyle)) { 1.246 + changed = true; 1.247 + if (pushedSoapBinding) 1.248 + builder.processError(WebserviceapMessages.WEBSERVICEAP_MIXED_BINDING_STYLE( 1.249 + classElement.getQualifiedName()), bindingElement); 1.250 + } 1.251 + if (soapBinding.style().equals(SOAPBinding.Style.RPC)) { 1.252 + soapStyle = SOAPStyle.RPC; 1.253 + wrapped = true; 1.254 + if (soapBinding.parameterStyle().equals(ParameterStyle.BARE)) { 1.255 + builder.processError(WebserviceapMessages.WEBSERVICEAP_RPC_LITERAL_MUST_NOT_BE_BARE( 1.256 + classElement.getQualifiedName()), bindingElement); 1.257 + } 1.258 + } else { 1.259 + soapStyle = SOAPStyle.DOCUMENT; 1.260 + if (wrapped != soapBinding.parameterStyle().equals(ParameterStyle.WRAPPED)) { 1.261 + wrapped = soapBinding.parameterStyle().equals(ParameterStyle.WRAPPED); 1.262 + changed = true; 1.263 + } 1.264 + } 1.265 + if (soapBinding.use().equals(SOAPBinding.Use.ENCODED)) { 1.266 + String style = "rpc"; 1.267 + if (soapBinding.style().equals(SOAPBinding.Style.DOCUMENT)) 1.268 + style = "document"; 1.269 + builder.processError(WebserviceapMessages.WEBSERVICE_ENCODED_NOT_SUPPORTED( 1.270 + classElement.getQualifiedName(), style), bindingElement); 1.271 + } 1.272 + if (changed || soapBindingStack.empty()) { 1.273 + soapBindingStack.push(soapBinding); 1.274 + pushedSoapBinding = true; 1.275 + } 1.276 + return changed; 1.277 + } 1.278 + 1.279 + protected SOAPBinding popSoapBinding() { 1.280 + if (pushedSoapBinding) 1.281 + soapBindingStack.pop(); 1.282 + SOAPBinding soapBinding = null; 1.283 + if (!soapBindingStack.empty()) { 1.284 + soapBinding = soapBindingStack.peek(); 1.285 + if (soapBinding.style().equals(SOAPBinding.Style.RPC)) { 1.286 + soapStyle = SOAPStyle.RPC; 1.287 + wrapped = true; 1.288 + } else { 1.289 + soapStyle = SOAPStyle.DOCUMENT; 1.290 + wrapped = soapBinding.parameterStyle().equals(ParameterStyle.WRAPPED); 1.291 + } 1.292 + } else { 1.293 + pushedSoapBinding = false; 1.294 + } 1.295 + return soapBinding; 1.296 + } 1.297 + 1.298 + protected String getNamespace(PackageElement packageElement) { 1.299 + return RuntimeModeler.getNamespace(packageElement.getQualifiedName().toString()); 1.300 + } 1.301 + 1.302 + protected boolean shouldProcessWebService(WebService webService, TypeElement element) { 1.303 + switch (element.getKind()) { 1.304 + case INTERFACE: { 1.305 + hasWebMethods = false; 1.306 + if (webService == null) 1.307 + builder.processError(WebserviceapMessages.WEBSERVICEAP_ENDPOINTINTERFACE_HAS_NO_WEBSERVICE_ANNOTATION( 1.308 + element.getQualifiedName()), element); 1.309 + 1.310 + SOAPBinding soapBinding = element.getAnnotation(SOAPBinding.class); 1.311 + if (soapBinding != null 1.312 + && soapBinding.style() == SOAPBinding.Style.RPC 1.313 + && soapBinding.parameterStyle() == SOAPBinding.ParameterStyle.BARE) { 1.314 + builder.processError(WebserviceapMessages.WEBSERVICEAP_INVALID_SOAPBINDING_PARAMETERSTYLE( 1.315 + soapBinding, element), element); 1.316 + return false; 1.317 + } 1.318 + return isLegalSei(element); 1.319 + } 1.320 + case CLASS: { 1.321 + if (webService == null) 1.322 + return false; 1.323 + hasWebMethods = hasWebMethods(element); 1.324 + SOAPBinding soapBinding = element.getAnnotation(SOAPBinding.class); 1.325 + if (soapBinding != null 1.326 + && soapBinding.style() == SOAPBinding.Style.RPC 1.327 + && soapBinding.parameterStyle() == SOAPBinding.ParameterStyle.BARE) { 1.328 + builder.processError(WebserviceapMessages.WEBSERVICEAP_INVALID_SOAPBINDING_PARAMETERSTYLE( 1.329 + soapBinding, element), element); 1.330 + return false; 1.331 + } 1.332 + return isLegalImplementation(webService, element); 1.333 + } 1.334 + default: { 1.335 + throw new IllegalArgumentException("Class or Interface was expecting. But element: " + element); 1.336 + } 1.337 + } 1.338 + } 1.339 + 1.340 + abstract protected void processWebService(WebService webService, TypeElement element); 1.341 + 1.342 + protected void postProcessWebService(WebService webService, TypeElement element) { 1.343 + processMethods(element); 1.344 + popSoapBinding(); 1.345 + } 1.346 + 1.347 + protected boolean hasWebMethods(TypeElement element) { 1.348 + if (element.getQualifiedName().toString().equals(Object.class.getName())) 1.349 + return false; 1.350 + WebMethod webMethod; 1.351 + for (ExecutableElement method : ElementFilter.methodsIn(element.getEnclosedElements())) { 1.352 + webMethod = method.getAnnotation(WebMethod.class); 1.353 + if (webMethod != null) { 1.354 + if (webMethod.exclude()) { 1.355 + if (webMethod.operationName().length() > 0) 1.356 + builder.processError(WebserviceapMessages.WEBSERVICEAP_INVALID_WEBMETHOD_ELEMENT_WITH_EXCLUDE( 1.357 + "operationName", element.getQualifiedName(), method.toString()), method); 1.358 + if (webMethod.action().length() > 0) 1.359 + builder.processError(WebserviceapMessages.WEBSERVICEAP_INVALID_WEBMETHOD_ELEMENT_WITH_EXCLUDE( 1.360 + "action", element.getQualifiedName(), method.toString()), method); 1.361 + } else { 1.362 + return true; 1.363 + } 1.364 + } 1.365 + } 1.366 + return false;//hasWebMethods(d.getSuperclass().getDeclaration()); 1.367 + } 1.368 + 1.369 + protected void processMethods(TypeElement element) { 1.370 + switch (element.getKind()) { 1.371 + case INTERFACE: { 1.372 + builder.log("ProcessedMethods Interface: " + element); 1.373 + hasWebMethods = false; 1.374 + for (ExecutableElement method : ElementFilter.methodsIn(element.getEnclosedElements())) { 1.375 + method.accept(this, null); 1.376 + } 1.377 + for (TypeMirror superType : element.getInterfaces()) 1.378 + processMethods((TypeElement) ((DeclaredType) superType).asElement()); 1.379 + break; 1.380 + } 1.381 + case CLASS: { 1.382 + builder.log("ProcessedMethods Class: " + element); 1.383 + hasWebMethods = hasWebMethods(element); 1.384 + if (element.getQualifiedName().toString().equals(Object.class.getName())) 1.385 + return; 1.386 + if (element.getAnnotation(WebService.class) != null) { 1.387 + // Super classes must have @WebService annotations to pick up their methods 1.388 + for (ExecutableElement method : ElementFilter.methodsIn(element.getEnclosedElements())) { 1.389 + method.accept(this, null); 1.390 + } 1.391 + } 1.392 + TypeMirror superclass = element.getSuperclass(); 1.393 + if (!superclass.getKind().equals(TypeKind.NONE)) { 1.394 + processMethods((TypeElement) ((DeclaredType) superclass).asElement()); 1.395 + } 1.396 + break; 1.397 + } 1.398 + default: 1.399 + break; 1.400 + } 1.401 + } 1.402 + 1.403 + private TypeElement getEndpointInterfaceElement(String endpointInterfaceName, TypeElement element) { 1.404 + TypeElement intTypeElement = null; 1.405 + for (TypeMirror interfaceType : element.getInterfaces()) { 1.406 + if (endpointInterfaceName.equals(interfaceType.toString())) { 1.407 + intTypeElement = (TypeElement) ((DeclaredType) interfaceType).asElement(); 1.408 + seiContext = context.getSeiContext(intTypeElement.getQualifiedName()); 1.409 + assert (seiContext != null); 1.410 + seiContext.setImplementsSei(true); 1.411 + break; 1.412 + } 1.413 + } 1.414 + if (intTypeElement == null) { 1.415 + intTypeElement = builder.getProcessingEnvironment().getElementUtils().getTypeElement(endpointInterfaceName); 1.416 + } 1.417 + if (intTypeElement == null) 1.418 + builder.processError(WebserviceapMessages.WEBSERVICEAP_ENDPOINTINTERFACE_CLASS_NOT_FOUND(endpointInterfaceName)); 1.419 + return intTypeElement; 1.420 + } 1.421 + 1.422 + private void inspectEndpointInterface(String endpointInterfaceName, TypeElement d) { 1.423 + TypeElement intTypeElement = getEndpointInterfaceElement(endpointInterfaceName, d); 1.424 + if (intTypeElement != null) 1.425 + intTypeElement.accept(this, null); 1.426 + } 1.427 + 1.428 + @Override 1.429 + public Void visitExecutable(ExecutableElement method, Object o) { 1.430 + // Methods must be public 1.431 + if (!method.getModifiers().contains(Modifier.PUBLIC)) 1.432 + return null; 1.433 + if (processedMethod(method)) 1.434 + return null; 1.435 + WebMethod webMethod = method.getAnnotation(WebMethod.class); 1.436 + if (webMethod != null && webMethod.exclude()) 1.437 + return null; 1.438 + SOAPBinding soapBinding = method.getAnnotation(SOAPBinding.class); 1.439 + if (soapBinding == null && !method.getEnclosingElement().equals(typeElement)) { 1.440 + if (method.getEnclosingElement().getKind().equals(ElementKind.CLASS)) { 1.441 + soapBinding = method.getEnclosingElement().getAnnotation(SOAPBinding.class); 1.442 + if (soapBinding != null) 1.443 + builder.log("using " + method.getEnclosingElement() + "'s SOAPBinding."); 1.444 + else { 1.445 + soapBinding = new MySoapBinding(); 1.446 + } 1.447 + } 1.448 + } 1.449 + boolean newBinding = false; 1.450 + if (soapBinding != null) { 1.451 + newBinding = pushSoapBinding(soapBinding, method, typeElement); 1.452 + } 1.453 + try { 1.454 + if (shouldProcessMethod(method, webMethod)) { 1.455 + processMethod(method, webMethod); 1.456 + } 1.457 + } finally { 1.458 + if (newBinding) { 1.459 + popSoapBinding(); 1.460 + } 1.461 + } 1.462 + return null; 1.463 + } 1.464 + 1.465 + protected boolean processedMethod(ExecutableElement method) { 1.466 + String id = method.toString(); 1.467 + if (processedMethods.contains(id)) 1.468 + return true; 1.469 + processedMethods.add(id); 1.470 + return false; 1.471 + } 1.472 + 1.473 + protected boolean shouldProcessMethod(ExecutableElement method, WebMethod webMethod) { 1.474 + builder.log("should process method: " + method.getSimpleName() + " hasWebMethods: " + hasWebMethods + " "); 1.475 + /* 1.476 + Fix for https://jax-ws.dev.java.net/issues/show_bug.cgi?id=577 1.477 + if (hasWebMethods && webMethod == null) { 1.478 + builder.log("webMethod == null"); 1.479 + return false; 1.480 + } 1.481 + */ 1.482 + Collection<Modifier> modifiers = method.getModifiers(); 1.483 + boolean staticFinal = modifiers.contains(Modifier.STATIC) || modifiers.contains(Modifier.FINAL); 1.484 + if (staticFinal) { 1.485 + if (webMethod != null) { 1.486 + builder.processError(WebserviceapMessages.WEBSERVICEAP_WEBSERVICE_METHOD_IS_STATIC_OR_FINAL(method.getEnclosingElement(), 1.487 + method), method); 1.488 + } 1.489 + return false; 1.490 + } 1.491 + boolean result = (endpointReferencesInterface || 1.492 + method.getEnclosingElement().equals(typeElement) || 1.493 + (method.getEnclosingElement().getAnnotation(WebService.class) != null)); 1.494 + builder.log("endpointReferencesInterface: " + endpointReferencesInterface); 1.495 + builder.log("declaring class has WebService: " + (method.getEnclosingElement().getAnnotation(WebService.class) != null)); 1.496 + builder.log("returning: " + result); 1.497 + return result; 1.498 + } 1.499 + 1.500 + abstract protected void processMethod(ExecutableElement method, WebMethod webMethod); 1.501 + 1.502 + protected boolean isLegalImplementation(WebService webService, TypeElement classElement) { 1.503 + boolean isStateful = isStateful(classElement); 1.504 + 1.505 + Collection<Modifier> modifiers = classElement.getModifiers(); 1.506 + if (!modifiers.contains(Modifier.PUBLIC)) { 1.507 + builder.processError(WebserviceapMessages.WEBSERVICEAP_WEBSERVICE_CLASS_NOT_PUBLIC(classElement.getQualifiedName()), classElement); 1.508 + return false; 1.509 + } 1.510 + if (modifiers.contains(Modifier.FINAL) && !isStateful) { 1.511 + builder.processError(WebserviceapMessages.WEBSERVICEAP_WEBSERVICE_CLASS_IS_FINAL(classElement.getQualifiedName()), classElement); 1.512 + return false; 1.513 + } 1.514 + if (modifiers.contains(Modifier.ABSTRACT) && !isStateful) { 1.515 + builder.processError(WebserviceapMessages.WEBSERVICEAP_WEBSERVICE_CLASS_IS_ABSTRACT(classElement.getQualifiedName()), classElement); 1.516 + return false; 1.517 + } 1.518 + boolean hasDefaultConstructor = false; 1.519 + for (ExecutableElement constructor : ElementFilter.constructorsIn(classElement.getEnclosedElements())) { 1.520 + if (constructor.getModifiers().contains(Modifier.PUBLIC) && 1.521 + constructor.getParameters().isEmpty()) { 1.522 + hasDefaultConstructor = true; 1.523 + break; 1.524 + } 1.525 + } 1.526 + if (!hasDefaultConstructor && !isStateful) { 1.527 + if (classElement.getEnclosingElement() != null && !modifiers.contains(Modifier.STATIC)) { 1.528 + builder.processError(WebserviceapMessages.WEBSERVICEAP_WEBSERVICE_CLASS_IS_INNERCLASS_NOT_STATIC( 1.529 + classElement.getQualifiedName()), classElement); 1.530 + return false; 1.531 + } 1.532 + 1.533 + builder.processError(WebserviceapMessages.WEBSERVICEAP_WEBSERVICE_NO_DEFAULT_CONSTRUCTOR( 1.534 + classElement.getQualifiedName()), classElement); 1.535 + return false; 1.536 + } 1.537 + if (webService.endpointInterface().isEmpty()) { 1.538 + if (!methodsAreLegal(classElement)) 1.539 + return false; 1.540 + } else { 1.541 + TypeElement interfaceElement = getEndpointInterfaceElement(webService.endpointInterface(), classElement); 1.542 + if (!classImplementsSei(classElement, interfaceElement)) 1.543 + return false; 1.544 + } 1.545 + 1.546 + return true; 1.547 + } 1.548 + 1.549 + private boolean isStateful(TypeElement classElement) { 1.550 + try { 1.551 + // We don't want dependency on rt-ha module as its not integrated in JDK 1.552 + return classElement.getAnnotation((Class<? extends Annotation>) Class.forName("com.sun.xml.internal.ws.developer.Stateful")) != null; 1.553 + } catch (ClassNotFoundException e) { 1.554 + //ignore 1.555 + } 1.556 + return false; 1.557 + } 1.558 + 1.559 + protected boolean classImplementsSei(TypeElement classElement, TypeElement interfaceElement) { 1.560 + for (TypeMirror interfaceType : classElement.getInterfaces()) { 1.561 + if (((DeclaredType) interfaceType).asElement().equals(interfaceElement)) 1.562 + return true; 1.563 + } 1.564 + List<ExecutableElement> classMethods = getClassMethods(classElement); 1.565 + boolean implementsMethod; 1.566 + for (ExecutableElement interfaceMethod : ElementFilter.methodsIn(interfaceElement.getEnclosedElements())) { 1.567 + implementsMethod = false; 1.568 + for (ExecutableElement classMethod : classMethods) { 1.569 + if (sameMethod(interfaceMethod, classMethod)) { 1.570 + implementsMethod = true; 1.571 + classMethods.remove(classMethod); 1.572 + break; 1.573 + } 1.574 + } 1.575 + if (!implementsMethod) { 1.576 + builder.processError(WebserviceapMessages.WEBSERVICEAP_METHOD_NOT_IMPLEMENTED(interfaceElement.getSimpleName(), classElement.getSimpleName(), interfaceMethod), interfaceMethod); 1.577 + return false; 1.578 + } 1.579 + } 1.580 + return true; 1.581 + } 1.582 + 1.583 + private static List<ExecutableElement> getClassMethods(TypeElement classElement) { 1.584 + if (classElement.getQualifiedName().toString().equals(Object.class.getName())) // we don't need Object's methods 1.585 + return null; 1.586 + TypeElement superclassElement = (TypeElement) ((DeclaredType) classElement.getSuperclass()).asElement(); 1.587 + List<ExecutableElement> superclassesMethods = getClassMethods(superclassElement); 1.588 + List<ExecutableElement> classMethods = ElementFilter.methodsIn(classElement.getEnclosedElements()); 1.589 + if (superclassesMethods == null) 1.590 + return classMethods; 1.591 + else 1.592 + superclassesMethods.addAll(classMethods); 1.593 + return superclassesMethods; 1.594 + } 1.595 + 1.596 + protected boolean sameMethod(ExecutableElement method1, ExecutableElement method2) { 1.597 + if (!method1.getSimpleName().equals(method2.getSimpleName())) 1.598 + return false; 1.599 + Types typeUtils = builder.getProcessingEnvironment().getTypeUtils(); 1.600 + if(!typeUtils.isSameType(method1.getReturnType(), method2.getReturnType()) 1.601 + && !typeUtils.isSubtype(method2.getReturnType(), method1.getReturnType())) 1.602 + return false; 1.603 + List<? extends VariableElement> parameters1 = method1.getParameters(); 1.604 + List<? extends VariableElement> parameters2 = method2.getParameters(); 1.605 + if (parameters1.size() != parameters2.size()) 1.606 + return false; 1.607 + for (int i = 0; i < parameters1.size(); i++) { 1.608 + if (!typeUtils.isSameType(parameters1.get(i).asType(), parameters2.get(i).asType())) 1.609 + return false; 1.610 + } 1.611 + return true; 1.612 + } 1.613 + 1.614 + protected boolean isLegalSei(TypeElement interfaceElement) { 1.615 + for (VariableElement field : ElementFilter.fieldsIn(interfaceElement.getEnclosedElements())) 1.616 + if (field.getConstantValue() != null) { 1.617 + builder.processError(WebserviceapMessages.WEBSERVICEAP_SEI_CANNOT_CONTAIN_CONSTANT_VALUES( 1.618 + interfaceElement.getQualifiedName(), field.getSimpleName())); 1.619 + return false; 1.620 + } 1.621 + return methodsAreLegal(interfaceElement); 1.622 + } 1.623 + 1.624 + protected boolean methodsAreLegal(TypeElement element) { 1.625 + switch (element.getKind()) { 1.626 + case INTERFACE: { 1.627 + hasWebMethods = false; 1.628 + for (ExecutableElement method : ElementFilter.methodsIn(element.getEnclosedElements())) { 1.629 + if (!isLegalMethod(method, element)) 1.630 + return false; 1.631 + } 1.632 + for (TypeMirror superInterface : element.getInterfaces()) { 1.633 + if (!methodsAreLegal((TypeElement) ((DeclaredType) superInterface).asElement())) 1.634 + return false; 1.635 + } 1.636 + return true; 1.637 + } 1.638 + case CLASS: { 1.639 + hasWebMethods = hasWebMethods(element); 1.640 + for (ExecutableElement method : ElementFilter.methodsIn(element.getEnclosedElements())) { 1.641 + if (!method.getModifiers().contains(Modifier.PUBLIC)) 1.642 + continue; // let's validate only public methods 1.643 + if (!isLegalMethod(method, element)) 1.644 + return false; 1.645 + } 1.646 + DeclaredType superClass = (DeclaredType) element.getSuperclass(); 1.647 + 1.648 + TypeElement tE = (TypeElement) superClass.asElement(); 1.649 + return tE.getQualifiedName().toString().equals(Object.class.getName()) 1.650 + || methodsAreLegal(tE); 1.651 + } 1.652 + default: { 1.653 + throw new IllegalArgumentException("Class or interface was expecting. But element: " + element); 1.654 + } 1.655 + } 1.656 + } 1.657 + 1.658 + protected boolean isLegalMethod(ExecutableElement method, TypeElement typeElement) { 1.659 + WebMethod webMethod = method.getAnnotation(WebMethod.class); 1.660 + //SEI cannot have methods with @WebMethod(exclude=true) 1.661 + if (typeElement.getKind().equals(ElementKind.INTERFACE) && webMethod != null && webMethod.exclude()) 1.662 + builder.processError(WebserviceapMessages.WEBSERVICEAP_INVALID_SEI_ANNOTATION_ELEMENT_EXCLUDE("exclude=true", typeElement.getQualifiedName(), method.toString()), method); 1.663 + // With https://jax-ws.dev.java.net/issues/show_bug.cgi?id=577, hasWebMethods has no effect 1.664 + if (hasWebMethods && webMethod == null) // backwards compatibility (for legacyWebMethod computation) 1.665 + return true; 1.666 + 1.667 + if ((webMethod != null) && webMethod.exclude()) { 1.668 + return true; 1.669 + } 1.670 + /* 1.671 + This check is not needed as Impl class is already checked that it is not abstract. 1.672 + if (typeElement instanceof TypeElement && method.getModifiers().contains(Modifier.ABSTRACT)) { // use Kind.equals instead of instanceOf 1.673 + builder.processError(method.getPosition(), WebserviceapMessages.WEBSERVICEAP_WEBSERVICE_METHOD_IS_ABSTRACT(typeElement.getQualifiedName(), method.getSimpleName())); 1.674 + return false; 1.675 + } 1.676 + */ 1.677 + TypeMirror returnType = method.getReturnType(); 1.678 + if (!isLegalType(returnType)) { 1.679 + builder.processError(WebserviceapMessages.WEBSERVICEAP_METHOD_RETURN_TYPE_CANNOT_IMPLEMENT_REMOTE(typeElement.getQualifiedName(), 1.680 + method.getSimpleName(), 1.681 + returnType), method); 1.682 + } 1.683 + boolean isOneWay = method.getAnnotation(Oneway.class) != null; 1.684 + if (isOneWay && !isValidOneWayMethod(method, typeElement)) 1.685 + return false; 1.686 + 1.687 + SOAPBinding soapBinding = method.getAnnotation(SOAPBinding.class); 1.688 + if (soapBinding != null) { 1.689 + if (soapBinding.style().equals(SOAPBinding.Style.RPC)) { 1.690 + builder.processError(WebserviceapMessages.WEBSERVICEAP_RPC_SOAPBINDING_NOT_ALLOWED_ON_METHOD(typeElement.getQualifiedName(), method.toString()), method); 1.691 + } 1.692 + } 1.693 + 1.694 + int paramIndex = 0; 1.695 + for (VariableElement parameter : method.getParameters()) { 1.696 + if (!isLegalParameter(parameter, method, typeElement, paramIndex++)) 1.697 + return false; 1.698 + } 1.699 + 1.700 + if (!isDocLitWrapped() && soapStyle.equals(SOAPStyle.DOCUMENT)) { 1.701 + VariableElement outParam = getOutParameter(method); 1.702 + int inParams = getModeParameterCount(method, WebParam.Mode.IN); 1.703 + int outParams = getModeParameterCount(method, WebParam.Mode.OUT); 1.704 + if (inParams != 1) { 1.705 + builder.processError(WebserviceapMessages.WEBSERVICEAP_DOC_BARE_AND_NO_ONE_IN(typeElement.getQualifiedName(), method.toString()), method); 1.706 + } 1.707 + if (returnType.accept(NO_TYPE_VISITOR, null)) { 1.708 + if (outParam == null && !isOneWay) { 1.709 + builder.processError(WebserviceapMessages.WEBSERVICEAP_DOC_BARE_NO_OUT(typeElement.getQualifiedName(), method.toString()), method); 1.710 + } 1.711 + if (outParams != 1) { 1.712 + if (!isOneWay && outParams != 0) 1.713 + builder.processError(WebserviceapMessages.WEBSERVICEAP_DOC_BARE_NO_RETURN_AND_NO_OUT(typeElement.getQualifiedName(), method.toString()), method); 1.714 + } 1.715 + } else { 1.716 + if (outParams > 0) { 1.717 + builder.processError(WebserviceapMessages.WEBSERVICEAP_DOC_BARE_RETURN_AND_OUT(typeElement.getQualifiedName(), method.toString()), outParam); 1.718 + } 1.719 + } 1.720 + } 1.721 + return true; 1.722 + } 1.723 + 1.724 + protected boolean isLegalParameter(VariableElement param, 1.725 + ExecutableElement method, 1.726 + TypeElement typeElement, 1.727 + int paramIndex) { 1.728 + if (!isLegalType(param.asType())) { 1.729 + builder.processError(WebserviceapMessages.WEBSERVICEAP_METHOD_PARAMETER_TYPES_CANNOT_IMPLEMENT_REMOTE(typeElement.getQualifiedName(), 1.730 + method.getSimpleName(), 1.731 + param.getSimpleName(), 1.732 + param.asType().toString()), param); 1.733 + return false; 1.734 + } 1.735 + TypeMirror holderType; 1.736 + holderType = builder.getHolderValueType(param.asType()); 1.737 + WebParam webParam = param.getAnnotation(WebParam.class); 1.738 + WebParam.Mode mode = null; 1.739 + if (webParam != null) 1.740 + mode = webParam.mode(); 1.741 + 1.742 + if (holderType != null) { 1.743 + if (mode != null && mode == WebParam.Mode.IN) 1.744 + builder.processError(WebserviceapMessages.WEBSERVICEAP_HOLDER_PARAMETERS_MUST_NOT_BE_IN_ONLY(typeElement.getQualifiedName(), method.toString(), paramIndex), param); 1.745 + } else if (mode != null && mode != WebParam.Mode.IN) { 1.746 + builder.processError(WebserviceapMessages.WEBSERVICEAP_NON_IN_PARAMETERS_MUST_BE_HOLDER(typeElement.getQualifiedName(), method.toString(), paramIndex), param); 1.747 + } 1.748 + 1.749 + return true; 1.750 + } 1.751 + 1.752 + protected boolean isDocLitWrapped() { 1.753 + return soapStyle.equals(SOAPStyle.DOCUMENT) && wrapped; 1.754 + } 1.755 + 1.756 + private static final class NoTypeVisitor extends SimpleTypeVisitor6<Boolean, Void> { 1.757 + 1.758 + @Override 1.759 + public Boolean visitNoType(NoType t, Void o) { 1.760 + return true; 1.761 + } 1.762 + 1.763 + @Override 1.764 + protected Boolean defaultAction(TypeMirror e, Void aVoid) { 1.765 + return false; 1.766 + } 1.767 + } 1.768 + 1.769 + protected boolean isValidOneWayMethod(ExecutableElement method, TypeElement typeElement) { 1.770 + boolean valid = true; 1.771 + if (!(method.getReturnType().accept(NO_TYPE_VISITOR, null))) { 1.772 + // this is an error, cannot be OneWay and have a return type 1.773 + builder.processError(WebserviceapMessages.WEBSERVICEAP_ONEWAY_OPERATION_CANNOT_HAVE_RETURN_TYPE(typeElement.getQualifiedName(), method.toString()), method); 1.774 + valid = false; 1.775 + } 1.776 + VariableElement outParam = getOutParameter(method); 1.777 + if (outParam != null) { 1.778 + builder.processError(WebserviceapMessages.WEBSERVICEAP_ONEWAY_AND_OUT(typeElement.getQualifiedName(), method.toString()), outParam); 1.779 + valid = false; 1.780 + } 1.781 + if (!isDocLitWrapped() && soapStyle.equals(SOAPStyle.DOCUMENT)) { 1.782 + int inCnt = getModeParameterCount(method, WebParam.Mode.IN); 1.783 + if (inCnt != 1) { 1.784 + builder.processError(WebserviceapMessages.WEBSERVICEAP_ONEWAY_AND_NOT_ONE_IN(typeElement.getQualifiedName(), method.toString()), method); 1.785 + valid = false; 1.786 + } 1.787 + } 1.788 + for (TypeMirror thrownType : method.getThrownTypes()) { 1.789 + TypeElement thrownElement = (TypeElement) ((DeclaredType) thrownType).asElement(); 1.790 + if (builder.isServiceException(thrownType)) { 1.791 + builder.processError(WebserviceapMessages.WEBSERVICEAP_ONEWAY_OPERATION_CANNOT_DECLARE_EXCEPTIONS( 1.792 + typeElement.getQualifiedName(), method.toString(), thrownElement.getQualifiedName()), method); 1.793 + valid = false; 1.794 + } 1.795 + } 1.796 + return valid; 1.797 + } 1.798 + 1.799 + protected int getModeParameterCount(ExecutableElement method, WebParam.Mode mode) { 1.800 + WebParam webParam; 1.801 + int cnt = 0; 1.802 + for (VariableElement param : method.getParameters()) { 1.803 + webParam = param.getAnnotation(WebParam.class); 1.804 + if (webParam != null) { 1.805 + if (webParam.header()) 1.806 + continue; 1.807 + if (isEquivalentModes(mode, webParam.mode())) 1.808 + cnt++; 1.809 + } else { 1.810 + if (isEquivalentModes(mode, WebParam.Mode.IN)) { 1.811 + cnt++; 1.812 + } 1.813 + } 1.814 + } 1.815 + return cnt; 1.816 + } 1.817 + 1.818 + protected boolean isEquivalentModes(WebParam.Mode mode1, WebParam.Mode mode2) { 1.819 + if (mode1.equals(mode2)) 1.820 + return true; 1.821 + assert mode1 == WebParam.Mode.IN || mode1 == WebParam.Mode.OUT; 1.822 + return (mode1 == WebParam.Mode.IN && mode2 != WebParam.Mode.OUT) || (mode1 == WebParam.Mode.OUT && mode2 != WebParam.Mode.IN); 1.823 + } 1.824 + 1.825 + protected boolean isHolder(VariableElement param) { 1.826 + return builder.getHolderValueType(param.asType()) != null; 1.827 + } 1.828 + 1.829 + protected boolean isLegalType(TypeMirror type) { 1.830 + if (!(type != null && type.getKind().equals(TypeKind.DECLARED))) 1.831 + return true; 1.832 + TypeElement tE = (TypeElement) ((DeclaredType) type).asElement(); 1.833 + if (tE == null) { 1.834 + // can be null, if this type's declaration is unknown. This may be the result of a processing error, such as a missing class file. 1.835 + builder.processError(WebserviceapMessages.WEBSERVICEAP_COULD_NOT_FIND_TYPEDECL(type.toString(), context.getRound())); 1.836 + } 1.837 + return !builder.isRemote(tE); 1.838 + } 1.839 + 1.840 + protected VariableElement getOutParameter(ExecutableElement method) { 1.841 + WebParam webParam; 1.842 + for (VariableElement param : method.getParameters()) { 1.843 + webParam = param.getAnnotation(WebParam.class); 1.844 + if (webParam != null && webParam.mode() != WebParam.Mode.IN) { 1.845 + return param; 1.846 + } 1.847 + } 1.848 + return null; 1.849 + } 1.850 + 1.851 + protected static class MySoapBinding implements SOAPBinding { 1.852 + 1.853 + @Override 1.854 + public Style style() { 1.855 + return SOAPBinding.Style.DOCUMENT; 1.856 + } 1.857 + 1.858 + @Override 1.859 + public Use use() { 1.860 + return SOAPBinding.Use.LITERAL; 1.861 + } 1.862 + 1.863 + @Override 1.864 + public ParameterStyle parameterStyle() { 1.865 + return SOAPBinding.ParameterStyle.WRAPPED; 1.866 + } 1.867 + 1.868 + @Override 1.869 + public Class<? extends java.lang.annotation.Annotation> annotationType() { 1.870 + return SOAPBinding.class; 1.871 + } 1.872 + } 1.873 +}