src/share/jaxws_classes/com/sun/tools/internal/ws/processor/modeler/annotation/WebServiceVisitor.java

Thu, 31 Aug 2017 15:18:52 +0800

author
aoqi
date
Thu, 31 Aug 2017 15:18:52 +0800
changeset 637
9c07ef4934dd
parent 368
0989ad8c0860
parent 0
373ffda63c9a
permissions
-rw-r--r--

merge

     1 /*
     2  * Copyright (c) 1997, 2013, Oracle and/or its affiliates. All rights reserved.
     3  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
     4  *
     5  * This code is free software; you can redistribute it and/or modify it
     6  * under the terms of the GNU General Public License version 2 only, as
     7  * published by the Free Software Foundation.  Oracle designates this
     8  * particular file as subject to the "Classpath" exception as provided
     9  * by Oracle in the LICENSE file that accompanied this code.
    10  *
    11  * This code is distributed in the hope that it will be useful, but WITHOUT
    12  * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
    13  * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
    14  * version 2 for more details (a copy is included in the LICENSE file that
    15  * accompanied this code).
    16  *
    17  * You should have received a copy of the GNU General Public License version
    18  * 2 along with this work; if not, write to the Free Software Foundation,
    19  * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
    20  *
    21  * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
    22  * or visit www.oracle.com if you need additional information or have any
    23  * questions.
    24  */
    26 package com.sun.tools.internal.ws.processor.modeler.annotation;
    28 import com.sun.tools.internal.ws.processor.model.Port;
    29 import com.sun.tools.internal.ws.resources.WebserviceapMessages;
    30 import com.sun.tools.internal.ws.util.ClassNameInfo;
    31 import com.sun.tools.internal.ws.wsdl.document.soap.SOAPStyle;
    32 import com.sun.xml.internal.ws.model.RuntimeModeler;
    34 import javax.annotation.processing.ProcessingEnvironment;
    35 import javax.jws.Oneway;
    36 import javax.jws.WebMethod;
    37 import javax.jws.WebParam;
    38 import javax.jws.WebResult;
    39 import javax.jws.WebService;
    40 import javax.jws.soap.SOAPBinding;
    41 import javax.jws.soap.SOAPBinding.ParameterStyle;
    42 import javax.lang.model.element.Element;
    43 import javax.lang.model.element.ElementKind;
    44 import javax.lang.model.element.ExecutableElement;
    45 import javax.lang.model.element.Modifier;
    46 import javax.lang.model.element.Name;
    47 import javax.lang.model.element.PackageElement;
    48 import javax.lang.model.element.TypeElement;
    49 import javax.lang.model.element.VariableElement;
    50 import javax.lang.model.type.DeclaredType;
    51 import javax.lang.model.type.NoType;
    52 import javax.lang.model.type.TypeKind;
    53 import javax.lang.model.type.TypeMirror;
    54 import javax.lang.model.util.ElementFilter;
    55 import javax.lang.model.util.SimpleElementVisitor6;
    56 import javax.lang.model.util.SimpleTypeVisitor6;
    57 import javax.lang.model.util.Types;
    58 import java.lang.annotation.Annotation;
    59 import java.util.Collection;
    60 import java.util.HashSet;
    61 import java.util.List;
    62 import java.util.Set;
    63 import java.util.Stack;
    65 /**
    66  * @author WS Development Team
    67  */
    68 public abstract class WebServiceVisitor extends SimpleElementVisitor6<Void, Object> {
    70     protected ModelBuilder builder;
    71     protected String wsdlNamespace;
    72     protected String typeNamespace;
    73     protected Stack<SOAPBinding> soapBindingStack;
    74     protected SOAPBinding typeElementSoapBinding;
    75     protected SOAPStyle soapStyle = SOAPStyle.DOCUMENT;
    76     protected boolean wrapped = true;
    77     protected Port port;
    78     protected Name serviceImplName;
    79     protected Name endpointInterfaceName;
    80     protected AnnotationProcessorContext context;
    81     protected AnnotationProcessorContext.SeiContext seiContext;
    82     protected boolean processingSei = false;
    83     protected String serviceName;
    84     protected Name packageName;
    85     protected String portName;
    86     protected boolean endpointReferencesInterface = false;
    87     protected boolean hasWebMethods = false;
    88     protected TypeElement typeElement;
    89     protected Set<String> processedMethods;
    90     protected boolean pushedSoapBinding = false;
    92     private static final NoTypeVisitor NO_TYPE_VISITOR = new NoTypeVisitor();
    94     public WebServiceVisitor(ModelBuilder builder, AnnotationProcessorContext context) {
    95         this.builder = builder;
    96         this.context = context;
    97         soapBindingStack = new Stack<SOAPBinding>();
    98         processedMethods = new HashSet<String>();
    99     }
   101     @Override
   102     public Void visitType(TypeElement e, Object o) {
   103         WebService webService = e.getAnnotation(WebService.class);
   104         if (!shouldProcessWebService(webService, e))
   105             return null;
   106         if (builder.checkAndSetProcessed(e))
   107             return null;
   108         typeElement = e;
   110         switch (e.getKind()) {
   111             case INTERFACE: {
   112                 if (endpointInterfaceName != null && !endpointInterfaceName.equals(e.getQualifiedName())) {
   113                     builder.processError(WebserviceapMessages.WEBSERVICEAP_ENDPOINTINTERFACES_DO_NOT_MATCH(endpointInterfaceName, e.getQualifiedName()), e);
   114                 }
   115                 verifySeiAnnotations(webService, e);
   116                 endpointInterfaceName = e.getQualifiedName();
   117                 processingSei = true;
   118                 preProcessWebService(webService, e);
   119                 processWebService(webService, e);
   120                 postProcessWebService(webService, e);
   121                 break;
   122             }
   123             case CLASS: {
   124                 typeElementSoapBinding = e.getAnnotation(SOAPBinding.class);
   125                 if (serviceImplName == null)
   126                     serviceImplName = e.getQualifiedName();
   127                 String endpointInterfaceName = webService != null ? webService.endpointInterface() : null;
   128                 if (endpointInterfaceName != null && endpointInterfaceName.length() > 0) {
   129                     checkForInvalidImplAnnotation(e, SOAPBinding.class);
   130                     if (webService.name().length() > 0)
   131                         builder.processError(WebserviceapMessages.WEBSERVICEAP_ENDPOINTINTEFACE_PLUS_ELEMENT("name"), e);
   132                     endpointReferencesInterface = true;
   133                     verifyImplAnnotations(e);
   134                     inspectEndpointInterface(endpointInterfaceName, e);
   135                     serviceImplName = null;
   136                     return null;
   137                 }
   138                 processingSei = false;
   139                 preProcessWebService(webService, e);
   140                 processWebService(webService, e);
   141                 serviceImplName = null;
   142                 postProcessWebService(webService, e);
   143                 serviceImplName = null;
   144                 break;
   145             }
   146             default:
   147                 break;
   148         }
   149         return null;
   150     }
   152     protected void verifySeiAnnotations(WebService webService, TypeElement d) {
   153         if (webService.endpointInterface().length() > 0) {
   154             builder.processError(WebserviceapMessages.WEBSERVICEAP_ENDPOINTINTERFACE_ON_INTERFACE(
   155                     d.getQualifiedName(), webService.endpointInterface()), d);
   156         }
   157         if (webService.serviceName().length() > 0) {
   158             builder.processError(WebserviceapMessages.WEBSERVICEAP_INVALID_SEI_ANNOTATION_ELEMENT(
   159                     "serviceName", d.getQualifiedName()), d);
   160         }
   161         if (webService.portName().length() > 0) {
   162             builder.processError(WebserviceapMessages.WEBSERVICEAP_INVALID_SEI_ANNOTATION_ELEMENT(
   163                     "portName", d.getQualifiedName()), d);
   164         }
   165     }
   167     protected void verifyImplAnnotations(TypeElement d) {
   168         for (ExecutableElement method : ElementFilter.methodsIn(d.getEnclosedElements())) {
   169             checkForInvalidImplAnnotation(method, WebMethod.class);
   170             checkForInvalidImplAnnotation(method, Oneway.class);
   171             checkForInvalidImplAnnotation(method, WebResult.class);
   172             for (VariableElement param : method.getParameters()) {
   173                 checkForInvalidImplAnnotation(param, WebParam.class);
   174             }
   175         }
   176     }
   178     protected void checkForInvalidSeiAnnotation(TypeElement element, Class annotationClass) {
   179         Object annotation = element.getAnnotation(annotationClass);
   180         if (annotation != null) {
   181             builder.processError(WebserviceapMessages.WEBSERVICEAP_INVALID_SEI_ANNOTATION(
   182                     annotationClass.getName(), element.getQualifiedName()), element);
   183         }
   184     }
   186     protected void checkForInvalidImplAnnotation(Element element, Class annotationClass) {
   187         Object annotation = element.getAnnotation(annotationClass);
   188         if (annotation != null) {
   189             builder.processError(WebserviceapMessages.WEBSERVICEAP_ENDPOINTINTEFACE_PLUS_ANNOTATION(annotationClass.getName()), element);
   190         }
   191     }
   193     protected void preProcessWebService(WebService webService, TypeElement element) {
   194         processedMethods = new HashSet<String>();
   195         seiContext = context.getSeiContext(element);
   196         String targetNamespace = null;
   197         if (webService != null)
   198             targetNamespace = webService.targetNamespace();
   199         PackageElement packageElement = builder.getProcessingEnvironment().getElementUtils().getPackageOf(element);
   200         if (targetNamespace == null || targetNamespace.length() == 0) {
   201             String packageName = packageElement.getQualifiedName().toString();
   202             if (packageName == null || packageName.length() == 0) {
   203                 builder.processError(WebserviceapMessages.WEBSERVICEAP_NO_PACKAGE_CLASS_MUST_HAVE_TARGETNAMESPACE(
   204                         element.getQualifiedName()), element);
   205             }
   206             targetNamespace = RuntimeModeler.getNamespace(packageName);
   207         }
   208         seiContext.setNamespaceUri(targetNamespace);
   209         if (serviceImplName == null)
   210             serviceImplName = seiContext.getSeiImplName();
   211         if (serviceImplName != null) {
   212             seiContext.setSeiImplName(serviceImplName);
   213             context.addSeiContext(serviceImplName, seiContext);
   214         }
   215         portName = ClassNameInfo.getName(element.getSimpleName().toString().replace('$', '_'));
   216         packageName = packageElement.getQualifiedName();
   217         portName = webService != null && webService.name() != null && webService.name().length() > 0 ?
   218                 webService.name() : portName;
   219         serviceName = ClassNameInfo.getName(element.getQualifiedName().toString()) + WebServiceConstants.SERVICE.getValue();
   220         serviceName = webService != null && webService.serviceName() != null && webService.serviceName().length() > 0 ?
   221                 webService.serviceName() : serviceName;
   222         wsdlNamespace = seiContext.getNamespaceUri();
   223         typeNamespace = wsdlNamespace;
   225         SOAPBinding soapBinding = element.getAnnotation(SOAPBinding.class);
   226         if (soapBinding != null) {
   227             pushedSoapBinding = pushSoapBinding(soapBinding, element, element);
   228         } else if (element.equals(typeElement)) {
   229             pushedSoapBinding = pushSoapBinding(new MySoapBinding(), element, element);
   230         }
   231     }
   233     public static boolean sameStyle(SOAPBinding.Style style, SOAPStyle soapStyle) {
   234         return style.equals(SOAPBinding.Style.DOCUMENT)
   235                 && soapStyle.equals(SOAPStyle.DOCUMENT)
   236                 || style.equals(SOAPBinding.Style.RPC)
   237                 && soapStyle.equals(SOAPStyle.RPC);
   238     }
   240     protected boolean pushSoapBinding(SOAPBinding soapBinding, Element bindingElement, TypeElement classElement) {
   241         boolean changed = false;
   242         if (!sameStyle(soapBinding.style(), soapStyle)) {
   243             changed = true;
   244             if (pushedSoapBinding)
   245                 builder.processError(WebserviceapMessages.WEBSERVICEAP_MIXED_BINDING_STYLE(
   246                         classElement.getQualifiedName()), bindingElement);
   247         }
   248         if (soapBinding.style().equals(SOAPBinding.Style.RPC)) {
   249             soapStyle = SOAPStyle.RPC;
   250             wrapped = true;
   251             if (soapBinding.parameterStyle().equals(ParameterStyle.BARE)) {
   252                 builder.processError(WebserviceapMessages.WEBSERVICEAP_RPC_LITERAL_MUST_NOT_BE_BARE(
   253                         classElement.getQualifiedName()), bindingElement);
   254             }
   255         } else {
   256             soapStyle = SOAPStyle.DOCUMENT;
   257             if (wrapped != soapBinding.parameterStyle().equals(ParameterStyle.WRAPPED)) {
   258                 wrapped = soapBinding.parameterStyle().equals(ParameterStyle.WRAPPED);
   259                 changed = true;
   260             }
   261         }
   262         if (soapBinding.use().equals(SOAPBinding.Use.ENCODED)) {
   263             String style = "rpc";
   264             if (soapBinding.style().equals(SOAPBinding.Style.DOCUMENT))
   265                 style = "document";
   266             builder.processError(WebserviceapMessages.WEBSERVICE_ENCODED_NOT_SUPPORTED(
   267                     classElement.getQualifiedName(), style), bindingElement);
   268         }
   269         if (changed || soapBindingStack.empty()) {
   270             soapBindingStack.push(soapBinding);
   271             pushedSoapBinding = true;
   272         }
   273         return changed;
   274     }
   276     protected SOAPBinding popSoapBinding() {
   277         if (pushedSoapBinding)
   278             soapBindingStack.pop();
   279         SOAPBinding soapBinding = null;
   280         if (!soapBindingStack.empty()) {
   281             soapBinding = soapBindingStack.peek();
   282             if (soapBinding.style().equals(SOAPBinding.Style.RPC)) {
   283                 soapStyle = SOAPStyle.RPC;
   284                 wrapped = true;
   285             } else {
   286                 soapStyle = SOAPStyle.DOCUMENT;
   287                 wrapped = soapBinding.parameterStyle().equals(ParameterStyle.WRAPPED);
   288             }
   289         } else {
   290                 pushedSoapBinding = false;
   291         }
   292         return soapBinding;
   293     }
   295     protected String getNamespace(PackageElement packageElement) {
   296         return RuntimeModeler.getNamespace(packageElement.getQualifiedName().toString());
   297     }
   299     protected boolean shouldProcessWebService(WebService webService, TypeElement element) {
   300         switch (element.getKind()) {
   301             case INTERFACE: {
   302                 hasWebMethods = false;
   303                 if (webService == null)
   304                     builder.processError(WebserviceapMessages.WEBSERVICEAP_ENDPOINTINTERFACE_HAS_NO_WEBSERVICE_ANNOTATION(
   305                             element.getQualifiedName()), element);
   307                 SOAPBinding soapBinding = element.getAnnotation(SOAPBinding.class);
   308                 if (soapBinding != null
   309                         && soapBinding.style() == SOAPBinding.Style.RPC
   310                         && soapBinding.parameterStyle() == SOAPBinding.ParameterStyle.BARE) {
   311                     builder.processError(WebserviceapMessages.WEBSERVICEAP_INVALID_SOAPBINDING_PARAMETERSTYLE(
   312                             soapBinding, element), element);
   313                     return false;
   314                 }
   315                 return isLegalSei(element);
   316             }
   317             case CLASS: {
   318                 if (webService == null)
   319                     return false;
   320                 hasWebMethods = hasWebMethods(element);
   321                 SOAPBinding soapBinding = element.getAnnotation(SOAPBinding.class);
   322                 if (soapBinding != null
   323                         && soapBinding.style() == SOAPBinding.Style.RPC
   324                         && soapBinding.parameterStyle() == SOAPBinding.ParameterStyle.BARE) {
   325                     builder.processError(WebserviceapMessages.WEBSERVICEAP_INVALID_SOAPBINDING_PARAMETERSTYLE(
   326                             soapBinding, element), element);
   327                     return false;
   328                 }
   329                 return isLegalImplementation(webService, element);
   330             }
   331             default: {
   332                 throw new IllegalArgumentException("Class or Interface was expecting. But element: " + element);
   333             }
   334         }
   335     }
   337     abstract protected void processWebService(WebService webService, TypeElement element);
   339     protected void postProcessWebService(WebService webService, TypeElement element) {
   340         processMethods(element);
   341         popSoapBinding();
   342     }
   344     protected boolean hasWebMethods(TypeElement element) {
   345         if (element.getQualifiedName().toString().equals(Object.class.getName()))
   346             return false;
   347         WebMethod webMethod;
   348         for (ExecutableElement method : ElementFilter.methodsIn(element.getEnclosedElements())) {
   349             webMethod = method.getAnnotation(WebMethod.class);
   350             if (webMethod != null) {
   351                 if (webMethod.exclude()) {
   352                     if (webMethod.operationName().length() > 0)
   353                         builder.processError(WebserviceapMessages.WEBSERVICEAP_INVALID_WEBMETHOD_ELEMENT_WITH_EXCLUDE(
   354                                 "operationName", element.getQualifiedName(), method.toString()), method);
   355                     if (webMethod.action().length() > 0)
   356                         builder.processError(WebserviceapMessages.WEBSERVICEAP_INVALID_WEBMETHOD_ELEMENT_WITH_EXCLUDE(
   357                                 "action", element.getQualifiedName(), method.toString()), method);
   358                 } else {
   359                     return true;
   360                 }
   361             }
   362         }
   363         return false;//hasWebMethods(d.getSuperclass().getDeclaration());
   364     }
   366     protected void processMethods(TypeElement element) {
   367         switch (element.getKind()) {
   368             case INTERFACE: {
   369                 builder.log("ProcessedMethods Interface: " + element);
   370                 hasWebMethods = false;
   371                 for (ExecutableElement method : ElementFilter.methodsIn(element.getEnclosedElements())) {
   372                     method.accept(this, null);
   373                 }
   374                 for (TypeMirror superType : element.getInterfaces())
   375                     processMethods((TypeElement) ((DeclaredType) superType).asElement());
   376                 break;
   377             }
   378             case CLASS: {
   379                 builder.log("ProcessedMethods Class: " + element);
   380                 hasWebMethods = hasWebMethods(element);
   381                 if (element.getQualifiedName().toString().equals(Object.class.getName()))
   382                     return;
   383                 if (element.getAnnotation(WebService.class) != null) {
   384                     // Super classes must have @WebService annotations to pick up their methods
   385                     for (ExecutableElement method : ElementFilter.methodsIn(element.getEnclosedElements())) {
   386                         method.accept(this, null);
   387                     }
   388                 }
   389                 TypeMirror superclass = element.getSuperclass();
   390                 if (!superclass.getKind().equals(TypeKind.NONE)) {
   391                     processMethods((TypeElement) ((DeclaredType) superclass).asElement());
   392                 }
   393                 break;
   394             }
   395             default:
   396                 break;
   397         }
   398     }
   400     private TypeElement getEndpointInterfaceElement(String endpointInterfaceName, TypeElement element) {
   401         TypeElement intTypeElement = null;
   402         for (TypeMirror interfaceType : element.getInterfaces()) {
   403             if (endpointInterfaceName.equals(interfaceType.toString())) {
   404                 intTypeElement = (TypeElement) ((DeclaredType) interfaceType).asElement();
   405                 seiContext = context.getSeiContext(intTypeElement.getQualifiedName());
   406                 assert (seiContext != null);
   407                 seiContext.setImplementsSei(true);
   408                 break;
   409             }
   410         }
   411         if (intTypeElement == null) {
   412             intTypeElement = builder.getProcessingEnvironment().getElementUtils().getTypeElement(endpointInterfaceName);
   413         }
   414         if (intTypeElement == null)
   415             builder.processError(WebserviceapMessages.WEBSERVICEAP_ENDPOINTINTERFACE_CLASS_NOT_FOUND(endpointInterfaceName));
   416         return intTypeElement;
   417     }
   419     private void inspectEndpointInterface(String endpointInterfaceName, TypeElement d) {
   420         TypeElement intTypeElement = getEndpointInterfaceElement(endpointInterfaceName, d);
   421         if (intTypeElement != null)
   422             intTypeElement.accept(this, null);
   423     }
   425     @Override
   426     public Void visitExecutable(ExecutableElement method, Object o) {
   427         // Methods must be public
   428         if (!method.getModifiers().contains(Modifier.PUBLIC))
   429             return null;
   430         if (processedMethod(method))
   431             return null;
   432         WebMethod webMethod = method.getAnnotation(WebMethod.class);
   433         if (webMethod != null && webMethod.exclude())
   434             return null;
   435         SOAPBinding soapBinding = method.getAnnotation(SOAPBinding.class);
   436         if (soapBinding == null && !method.getEnclosingElement().equals(typeElement)) {
   437             if (method.getEnclosingElement().getKind().equals(ElementKind.CLASS)) {
   438                 soapBinding = method.getEnclosingElement().getAnnotation(SOAPBinding.class);
   439                 if (soapBinding != null)
   440                     builder.log("using " + method.getEnclosingElement() + "'s SOAPBinding.");
   441                 else {
   442                     soapBinding = new MySoapBinding();
   443                 }
   444             }
   445         }
   446         boolean newBinding = false;
   447         if (soapBinding != null) {
   448             newBinding = pushSoapBinding(soapBinding, method, typeElement);
   449         }
   450         try {
   451             if (shouldProcessMethod(method, webMethod)) {
   452                 processMethod(method, webMethod);
   453             }
   454         } finally {
   455             if (newBinding) {
   456                 popSoapBinding();
   457             }
   458         }
   459         return null;
   460     }
   462     protected boolean processedMethod(ExecutableElement method) {
   463         String id = method.toString();
   464         if (processedMethods.contains(id))
   465             return true;
   466         processedMethods.add(id);
   467         return false;
   468     }
   470     protected boolean shouldProcessMethod(ExecutableElement method, WebMethod webMethod) {
   471         builder.log("should process method: " + method.getSimpleName() + " hasWebMethods: " + hasWebMethods + " ");
   472         /*
   473         Fix for https://jax-ws.dev.java.net/issues/show_bug.cgi?id=577
   474         if (hasWebMethods && webMethod == null) {
   475             builder.log("webMethod == null");
   476             return false;
   477         }
   478         */
   479         Collection<Modifier> modifiers = method.getModifiers();
   480         boolean staticFinal = modifiers.contains(Modifier.STATIC) || modifiers.contains(Modifier.FINAL);
   481         if (staticFinal) {
   482             if (webMethod != null) {
   483                 builder.processError(WebserviceapMessages.WEBSERVICEAP_WEBSERVICE_METHOD_IS_STATIC_OR_FINAL(method.getEnclosingElement(),
   484                         method), method);
   485             }
   486             return false;
   487         }
   488         boolean result = (endpointReferencesInterface ||
   489                 method.getEnclosingElement().equals(typeElement) ||
   490                 (method.getEnclosingElement().getAnnotation(WebService.class) != null));
   491         builder.log("endpointReferencesInterface: " + endpointReferencesInterface);
   492         builder.log("declaring class has WebService: " + (method.getEnclosingElement().getAnnotation(WebService.class) != null));
   493         builder.log("returning: " + result);
   494         return result;
   495     }
   497     abstract protected void processMethod(ExecutableElement method, WebMethod webMethod);
   499     protected boolean isLegalImplementation(WebService webService, TypeElement classElement) {
   500         boolean isStateful = isStateful(classElement);
   502         Collection<Modifier> modifiers = classElement.getModifiers();
   503         if (!modifiers.contains(Modifier.PUBLIC)) {
   504             builder.processError(WebserviceapMessages.WEBSERVICEAP_WEBSERVICE_CLASS_NOT_PUBLIC(classElement.getQualifiedName()), classElement);
   505             return false;
   506         }
   507         if (modifiers.contains(Modifier.FINAL) && !isStateful) {
   508             builder.processError(WebserviceapMessages.WEBSERVICEAP_WEBSERVICE_CLASS_IS_FINAL(classElement.getQualifiedName()), classElement);
   509             return false;
   510         }
   511         if (modifiers.contains(Modifier.ABSTRACT) && !isStateful) {
   512             builder.processError(WebserviceapMessages.WEBSERVICEAP_WEBSERVICE_CLASS_IS_ABSTRACT(classElement.getQualifiedName()), classElement);
   513             return false;
   514         }
   515         boolean hasDefaultConstructor = false;
   516         for (ExecutableElement constructor : ElementFilter.constructorsIn(classElement.getEnclosedElements())) {
   517             if (constructor.getModifiers().contains(Modifier.PUBLIC) &&
   518                     constructor.getParameters().isEmpty()) {
   519                 hasDefaultConstructor = true;
   520                 break;
   521             }
   522         }
   523         if (!hasDefaultConstructor && !isStateful) {
   524             if (classElement.getEnclosingElement() != null && !modifiers.contains(Modifier.STATIC)) {
   525                 builder.processError(WebserviceapMessages.WEBSERVICEAP_WEBSERVICE_CLASS_IS_INNERCLASS_NOT_STATIC(
   526                         classElement.getQualifiedName()), classElement);
   527                 return false;
   528             }
   530             builder.processError(WebserviceapMessages.WEBSERVICEAP_WEBSERVICE_NO_DEFAULT_CONSTRUCTOR(
   531                     classElement.getQualifiedName()), classElement);
   532             return false;
   533         }
   534         if (webService.endpointInterface().isEmpty()) {
   535             if (!methodsAreLegal(classElement))
   536                 return false;
   537         } else {
   538             TypeElement interfaceElement = getEndpointInterfaceElement(webService.endpointInterface(), classElement);
   539             if (!classImplementsSei(classElement, interfaceElement))
   540                 return false;
   541         }
   543         return true;
   544     }
   546     private boolean isStateful(TypeElement classElement) {
   547         try {
   548             // We don't want dependency on rt-ha module as its not integrated in JDK
   549             return classElement.getAnnotation((Class<? extends Annotation>) Class.forName("com.sun.xml.internal.ws.developer.Stateful")) != null;
   550         } catch (ClassNotFoundException e) {
   551             //ignore
   552         }
   553         return false;
   554     }
   556     protected boolean classImplementsSei(TypeElement classElement, TypeElement interfaceElement) {
   557         for (TypeMirror interfaceType : classElement.getInterfaces()) {
   558             if (((DeclaredType) interfaceType).asElement().equals(interfaceElement))
   559                 return true;
   560         }
   561         List<ExecutableElement> classMethods = getClassMethods(classElement);
   562         boolean implementsMethod;
   563         for (ExecutableElement interfaceMethod : ElementFilter.methodsIn(interfaceElement.getEnclosedElements())) {
   564             implementsMethod = false;
   565             for (ExecutableElement classMethod : classMethods) {
   566                 if (sameMethod(interfaceMethod, classMethod)) {
   567                     implementsMethod = true;
   568                     classMethods.remove(classMethod);
   569                     break;
   570                 }
   571             }
   572             if (!implementsMethod) {
   573                 builder.processError(WebserviceapMessages.WEBSERVICEAP_METHOD_NOT_IMPLEMENTED(interfaceElement.getSimpleName(), classElement.getSimpleName(), interfaceMethod), interfaceMethod);
   574                 return false;
   575             }
   576         }
   577         return true;
   578     }
   580     private static List<ExecutableElement> getClassMethods(TypeElement classElement) {
   581         if (classElement.getQualifiedName().toString().equals(Object.class.getName())) // we don't need Object's methods
   582             return null;
   583         TypeElement superclassElement = (TypeElement) ((DeclaredType) classElement.getSuperclass()).asElement();
   584         List<ExecutableElement> superclassesMethods = getClassMethods(superclassElement);
   585         List<ExecutableElement> classMethods = ElementFilter.methodsIn(classElement.getEnclosedElements());
   586         if (superclassesMethods == null)
   587             return classMethods;
   588         else
   589             superclassesMethods.addAll(classMethods);
   590         return superclassesMethods;
   591     }
   593     protected boolean sameMethod(ExecutableElement method1, ExecutableElement method2) {
   594         if (!method1.getSimpleName().equals(method2.getSimpleName()))
   595             return false;
   596         Types typeUtils = builder.getProcessingEnvironment().getTypeUtils();
   597         if(!typeUtils.isSameType(method1.getReturnType(), method2.getReturnType())
   598                 && !typeUtils.isSubtype(method2.getReturnType(), method1.getReturnType()))
   599             return false;
   600         List<? extends VariableElement> parameters1 = method1.getParameters();
   601         List<? extends VariableElement> parameters2 = method2.getParameters();
   602         if (parameters1.size() != parameters2.size())
   603             return false;
   604         for (int i = 0; i < parameters1.size(); i++) {
   605             if (!typeUtils.isSameType(parameters1.get(i).asType(), parameters2.get(i).asType()))
   606                 return false;
   607         }
   608         return true;
   609     }
   611     protected boolean isLegalSei(TypeElement interfaceElement) {
   612         for (VariableElement field : ElementFilter.fieldsIn(interfaceElement.getEnclosedElements()))
   613             if (field.getConstantValue() != null) {
   614                 builder.processError(WebserviceapMessages.WEBSERVICEAP_SEI_CANNOT_CONTAIN_CONSTANT_VALUES(
   615                         interfaceElement.getQualifiedName(), field.getSimpleName()));
   616                 return false;
   617             }
   618         return methodsAreLegal(interfaceElement);
   619     }
   621     protected boolean methodsAreLegal(TypeElement element) {
   622         switch (element.getKind()) {
   623             case INTERFACE: {
   624                 hasWebMethods = false;
   625                 for (ExecutableElement method : ElementFilter.methodsIn(element.getEnclosedElements())) {
   626                     if (!isLegalMethod(method, element))
   627                         return false;
   628                 }
   629                 for (TypeMirror superInterface : element.getInterfaces()) {
   630                     if (!methodsAreLegal((TypeElement) ((DeclaredType) superInterface).asElement()))
   631                         return false;
   632                 }
   633                 return true;
   634             }
   635             case CLASS: {
   636                 hasWebMethods = hasWebMethods(element);
   637                 for (ExecutableElement method : ElementFilter.methodsIn(element.getEnclosedElements())) {
   638                     if (!method.getModifiers().contains(Modifier.PUBLIC))
   639                         continue; // let's validate only public methods
   640                     if (!isLegalMethod(method, element))
   641                         return false;
   642                 }
   643                 DeclaredType superClass = (DeclaredType) element.getSuperclass();
   645                 TypeElement tE = (TypeElement) superClass.asElement();
   646                 return tE.getQualifiedName().toString().equals(Object.class.getName())
   647                         || methodsAreLegal(tE);
   648             }
   649             default: {
   650                 throw new IllegalArgumentException("Class or interface was expecting. But element: " + element);
   651             }
   652         }
   653     }
   655     protected boolean isLegalMethod(ExecutableElement method, TypeElement typeElement) {
   656         WebMethod webMethod = method.getAnnotation(WebMethod.class);
   657         //SEI cannot have methods with @WebMethod(exclude=true)
   658         if (typeElement.getKind().equals(ElementKind.INTERFACE) && webMethod != null && webMethod.exclude())
   659             builder.processError(WebserviceapMessages.WEBSERVICEAP_INVALID_SEI_ANNOTATION_ELEMENT_EXCLUDE("exclude=true", typeElement.getQualifiedName(), method.toString()), method);
   660         // With https://jax-ws.dev.java.net/issues/show_bug.cgi?id=577, hasWebMethods has no effect
   661         if (hasWebMethods && webMethod == null) // backwards compatibility (for legacyWebMethod computation)
   662             return true;
   664         if ((webMethod != null) && webMethod.exclude()) {
   665             return true;
   666         }
   667         /*
   668         This check is not needed as Impl class is already checked that it is not abstract.
   669         if (typeElement instanceof TypeElement && method.getModifiers().contains(Modifier.ABSTRACT)) {  // use Kind.equals instead of instanceOf
   670             builder.processError(method.getPosition(), WebserviceapMessages.WEBSERVICEAP_WEBSERVICE_METHOD_IS_ABSTRACT(typeElement.getQualifiedName(), method.getSimpleName()));
   671             return false;
   672         }
   673         */
   674         TypeMirror returnType = method.getReturnType();
   675         if (!isLegalType(returnType)) {
   676             builder.processError(WebserviceapMessages.WEBSERVICEAP_METHOD_RETURN_TYPE_CANNOT_IMPLEMENT_REMOTE(typeElement.getQualifiedName(),
   677                     method.getSimpleName(),
   678                     returnType), method);
   679         }
   680         boolean isOneWay = method.getAnnotation(Oneway.class) != null;
   681         if (isOneWay && !isValidOneWayMethod(method, typeElement))
   682             return false;
   684         SOAPBinding soapBinding = method.getAnnotation(SOAPBinding.class);
   685         if (soapBinding != null) {
   686             if (soapBinding.style().equals(SOAPBinding.Style.RPC)) {
   687                 builder.processError(WebserviceapMessages.WEBSERVICEAP_RPC_SOAPBINDING_NOT_ALLOWED_ON_METHOD(typeElement.getQualifiedName(), method.toString()), method);
   688             }
   689         }
   691         int paramIndex = 0;
   692         for (VariableElement parameter : method.getParameters()) {
   693             if (!isLegalParameter(parameter, method, typeElement, paramIndex++))
   694                 return false;
   695         }
   697         if (!isDocLitWrapped() && soapStyle.equals(SOAPStyle.DOCUMENT)) {
   698             VariableElement outParam = getOutParameter(method);
   699             int inParams = getModeParameterCount(method, WebParam.Mode.IN);
   700             int outParams = getModeParameterCount(method, WebParam.Mode.OUT);
   701             if (inParams != 1) {
   702                 builder.processError(WebserviceapMessages.WEBSERVICEAP_DOC_BARE_AND_NO_ONE_IN(typeElement.getQualifiedName(), method.toString()), method);
   703             }
   704             if (returnType.accept(NO_TYPE_VISITOR, null)) {
   705                 if (outParam == null && !isOneWay) {
   706                     builder.processError(WebserviceapMessages.WEBSERVICEAP_DOC_BARE_NO_OUT(typeElement.getQualifiedName(), method.toString()), method);
   707                 }
   708                 if (outParams != 1) {
   709                     if (!isOneWay && outParams != 0)
   710                         builder.processError(WebserviceapMessages.WEBSERVICEAP_DOC_BARE_NO_RETURN_AND_NO_OUT(typeElement.getQualifiedName(), method.toString()), method);
   711                 }
   712             } else {
   713                 if (outParams > 0) {
   714                     builder.processError(WebserviceapMessages.WEBSERVICEAP_DOC_BARE_RETURN_AND_OUT(typeElement.getQualifiedName(), method.toString()), outParam);
   715                 }
   716             }
   717         }
   718         return true;
   719     }
   721     protected boolean isLegalParameter(VariableElement param,
   722                                        ExecutableElement method,
   723                                        TypeElement typeElement,
   724                                        int paramIndex) {
   725         if (!isLegalType(param.asType())) {
   726             builder.processError(WebserviceapMessages.WEBSERVICEAP_METHOD_PARAMETER_TYPES_CANNOT_IMPLEMENT_REMOTE(typeElement.getQualifiedName(),
   727                     method.getSimpleName(),
   728                     param.getSimpleName(),
   729                     param.asType().toString()), param);
   730             return false;
   731         }
   732         TypeMirror holderType;
   733         holderType = builder.getHolderValueType(param.asType());
   734         WebParam webParam = param.getAnnotation(WebParam.class);
   735         WebParam.Mode mode = null;
   736         if (webParam != null)
   737             mode = webParam.mode();
   739         if (holderType != null) {
   740             if (mode != null && mode == WebParam.Mode.IN)
   741                 builder.processError(WebserviceapMessages.WEBSERVICEAP_HOLDER_PARAMETERS_MUST_NOT_BE_IN_ONLY(typeElement.getQualifiedName(), method.toString(), paramIndex), param);
   742         } else if (mode != null && mode != WebParam.Mode.IN) {
   743             builder.processError(WebserviceapMessages.WEBSERVICEAP_NON_IN_PARAMETERS_MUST_BE_HOLDER(typeElement.getQualifiedName(), method.toString(), paramIndex), param);
   744         }
   746         return true;
   747     }
   749     protected boolean isDocLitWrapped() {
   750         return soapStyle.equals(SOAPStyle.DOCUMENT) && wrapped;
   751     }
   753     private static final class NoTypeVisitor extends SimpleTypeVisitor6<Boolean, Void> {
   755         @Override
   756         public Boolean visitNoType(NoType t, Void o) {
   757             return true;
   758         }
   760         @Override
   761         protected Boolean defaultAction(TypeMirror e, Void aVoid) {
   762             return false;
   763         }
   764     }
   766     protected boolean isValidOneWayMethod(ExecutableElement method, TypeElement typeElement) {
   767         boolean valid = true;
   768         if (!(method.getReturnType().accept(NO_TYPE_VISITOR, null))) {
   769             // this is an error, cannot be OneWay and have a return type
   770             builder.processError(WebserviceapMessages.WEBSERVICEAP_ONEWAY_OPERATION_CANNOT_HAVE_RETURN_TYPE(typeElement.getQualifiedName(), method.toString()), method);
   771             valid = false;
   772         }
   773         VariableElement outParam = getOutParameter(method);
   774         if (outParam != null) {
   775             builder.processError(WebserviceapMessages.WEBSERVICEAP_ONEWAY_AND_OUT(typeElement.getQualifiedName(), method.toString()), outParam);
   776             valid = false;
   777         }
   778         if (!isDocLitWrapped() && soapStyle.equals(SOAPStyle.DOCUMENT)) {
   779             int inCnt = getModeParameterCount(method, WebParam.Mode.IN);
   780             if (inCnt != 1) {
   781                 builder.processError(WebserviceapMessages.WEBSERVICEAP_ONEWAY_AND_NOT_ONE_IN(typeElement.getQualifiedName(), method.toString()), method);
   782                 valid = false;
   783             }
   784         }
   785         for (TypeMirror thrownType : method.getThrownTypes()) {
   786             TypeElement thrownElement = (TypeElement) ((DeclaredType) thrownType).asElement();
   787             if (builder.isServiceException(thrownType)) {
   788                 builder.processError(WebserviceapMessages.WEBSERVICEAP_ONEWAY_OPERATION_CANNOT_DECLARE_EXCEPTIONS(
   789                         typeElement.getQualifiedName(), method.toString(), thrownElement.getQualifiedName()), method);
   790                 valid = false;
   791             }
   792         }
   793         return valid;
   794     }
   796     protected int getModeParameterCount(ExecutableElement method, WebParam.Mode mode) {
   797         WebParam webParam;
   798         int cnt = 0;
   799         for (VariableElement param : method.getParameters()) {
   800             webParam = param.getAnnotation(WebParam.class);
   801             if (webParam != null) {
   802                 if (webParam.header())
   803                     continue;
   804                 if (isEquivalentModes(mode, webParam.mode()))
   805                     cnt++;
   806             } else {
   807                 if (isEquivalentModes(mode, WebParam.Mode.IN)) {
   808                     cnt++;
   809                 }
   810             }
   811         }
   812         return cnt;
   813     }
   815     protected boolean isEquivalentModes(WebParam.Mode mode1, WebParam.Mode mode2) {
   816         if (mode1.equals(mode2))
   817             return true;
   818         assert mode1 == WebParam.Mode.IN || mode1 == WebParam.Mode.OUT;
   819         return (mode1 == WebParam.Mode.IN && mode2 != WebParam.Mode.OUT) || (mode1 == WebParam.Mode.OUT && mode2 != WebParam.Mode.IN);
   820     }
   822     protected boolean isHolder(VariableElement param) {
   823         return builder.getHolderValueType(param.asType()) != null;
   824     }
   826     protected boolean isLegalType(TypeMirror type) {
   827         if (!(type != null && type.getKind().equals(TypeKind.DECLARED)))
   828             return true;
   829         TypeElement tE = (TypeElement) ((DeclaredType) type).asElement();
   830         if (tE == null) {
   831             // 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.
   832             builder.processError(WebserviceapMessages.WEBSERVICEAP_COULD_NOT_FIND_TYPEDECL(type.toString(), context.getRound()));
   833         }
   834         return !builder.isRemote(tE);
   835     }
   837     protected VariableElement getOutParameter(ExecutableElement method) {
   838         WebParam webParam;
   839         for (VariableElement param : method.getParameters()) {
   840             webParam = param.getAnnotation(WebParam.class);
   841             if (webParam != null && webParam.mode() != WebParam.Mode.IN) {
   842                 return param;
   843             }
   844         }
   845         return null;
   846     }
   848     protected static class MySoapBinding implements SOAPBinding {
   850         @Override
   851         public Style style() {
   852             return SOAPBinding.Style.DOCUMENT;
   853         }
   855         @Override
   856         public Use use() {
   857             return SOAPBinding.Use.LITERAL;
   858         }
   860         @Override
   861         public ParameterStyle parameterStyle() {
   862             return SOAPBinding.ParameterStyle.WRAPPED;
   863         }
   865         @Override
   866         public Class<? extends java.lang.annotation.Annotation> annotationType() {
   867             return SOAPBinding.class;
   868         }
   869     }
   870 }

mercurial