325N/A/*
325N/A * Copyright (c) 1997, 2010, Oracle and/or its affiliates. All rights reserved.
325N/A * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
325N/A *
325N/A * This code is free software; you can redistribute it and/or modify it
325N/A * under the terms of the GNU General Public License version 2 only, as
325N/A * published by the Free Software Foundation. Oracle designates this
325N/A * particular file as subject to the "Classpath" exception as provided
325N/A * by Oracle in the LICENSE file that accompanied this code.
325N/A *
325N/A * This code is distributed in the hope that it will be useful, but WITHOUT
325N/A * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
325N/A * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
325N/A * version 2 for more details (a copy is included in the LICENSE file that
325N/A * accompanied this code).
325N/A *
325N/A * You should have received a copy of the GNU General Public License version
325N/A * 2 along with this work; if not, write to the Free Software Foundation,
325N/A * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
325N/A *
325N/A * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
325N/A * or visit www.oracle.com if you need additional information or have any
325N/A * questions.
325N/A */
325N/A
325N/Apackage com.sun.tools.internal.ws.processor.modeler.annotation;
325N/A
325N/A
325N/Aimport com.sun.mirror.declaration.*;
325N/Aimport com.sun.mirror.type.*;
325N/Aimport com.sun.mirror.util.SimpleDeclarationVisitor;
325N/Aimport com.sun.mirror.util.SourcePosition;
325N/Aimport com.sun.tools.internal.ws.processor.model.Port;
325N/Aimport com.sun.tools.internal.ws.processor.modeler.JavaSimpleTypeCreator;
325N/Aimport com.sun.tools.internal.ws.processor.modeler.annotation.AnnotationProcessorContext.SEIContext;
325N/Aimport com.sun.tools.internal.ws.resources.WebserviceapMessages;
325N/Aimport com.sun.tools.internal.ws.util.ClassNameInfo;
325N/Aimport com.sun.tools.internal.ws.wsdl.document.soap.SOAPStyle;
325N/Aimport com.sun.tools.internal.ws.wsdl.document.soap.SOAPUse;
325N/Aimport com.sun.xml.internal.ws.model.RuntimeModeler;
325N/Aimport com.sun.xml.internal.ws.util.localization.Localizable;
325N/A
325N/Aimport javax.jws.*;
325N/Aimport javax.jws.soap.SOAPBinding;
325N/Aimport javax.jws.soap.SOAPBinding.ParameterStyle;
325N/Aimport java.lang.annotation.Annotation;
325N/Aimport java.util.Collection;
325N/Aimport java.util.HashSet;
325N/Aimport java.util.Set;
325N/Aimport java.util.Stack;
325N/A
325N/A/**
325N/A *
325N/A * @author WS Development Team
325N/A */
325N/Apublic abstract class WebServiceVisitor extends SimpleDeclarationVisitor implements WebServiceConstants {
325N/A protected ModelBuilder builder;
325N/A protected String wsdlNamespace;
325N/A protected String typeNamespace;
325N/A protected Stack<SOAPBinding> soapBindingStack;
325N/A protected SOAPBinding typeDeclSOAPBinding;
325N/A protected SOAPUse soapUse = SOAPUse.LITERAL;
325N/A protected SOAPStyle soapStyle = SOAPStyle.DOCUMENT;
325N/A protected boolean wrapped = true;
325N/A protected HandlerChain hChain;
325N/A protected Port port;
325N/A protected String serviceImplName;
325N/A protected String endpointInterfaceName;
325N/A protected AnnotationProcessorContext context;
325N/A protected SEIContext seiContext;
325N/A protected boolean processingSEI = false;
325N/A protected String serviceName;
325N/A protected String packageName;
325N/A protected String portName;
325N/A protected boolean endpointReferencesInterface = false;
325N/A protected boolean hasWebMethods = false;
325N/A protected JavaSimpleTypeCreator simpleTypeCreator;
325N/A protected TypeDeclaration typeDecl;
325N/A protected Set<String> processedMethods;
325N/A protected boolean pushedSOAPBinding = false;
325N/A protected static final String ANNOTATION_ELEMENT_ERROR = "webserviceap.endpointinteface.plus.element";
325N/A
325N/A
325N/A
325N/A public WebServiceVisitor(ModelBuilder builder, AnnotationProcessorContext context) {
325N/A this.builder = builder;
325N/A this.context = context;
325N/A this.simpleTypeCreator = new JavaSimpleTypeCreator();
325N/A soapBindingStack = new Stack<SOAPBinding>();
325N/A processedMethods = new HashSet<String>();
325N/A }
325N/A
325N/A public void visitInterfaceDeclaration(InterfaceDeclaration d) {
325N/A WebService webService = d.getAnnotation(WebService.class);
325N/A if (!shouldProcessWebService(webService, d))
325N/A return;
325N/A if (builder.checkAndSetProcessed(d))
325N/A return;
325N/A typeDecl = d;
325N/A if (endpointInterfaceName != null && !endpointInterfaceName.equals(d.getQualifiedName())) {
325N/A builder.onError(d.getPosition(), WebserviceapMessages.localizableWEBSERVICEAP_ENDPOINTINTERFACES_DO_NOT_MATCH(endpointInterfaceName, d.getQualifiedName()));
325N/A }
325N/A verifySEIAnnotations(webService, d);
325N/A endpointInterfaceName = d.getQualifiedName();
325N/A processingSEI = true;
325N/A preProcessWebService(webService, d);
325N/A processWebService(webService, d);
325N/A postProcessWebService(webService, d);
325N/A }
325N/A
325N/A public void visitClassDeclaration(ClassDeclaration d) {
325N/A WebService webService = d.getAnnotation(WebService.class);
325N/A if (!shouldProcessWebService(webService, d))
325N/A return;
325N/A if (builder.checkAndSetProcessed(d))
325N/A return;
325N/A typeDeclSOAPBinding = d.getAnnotation(SOAPBinding.class);
325N/A typeDecl = d;
325N/A if (serviceImplName == null)
325N/A serviceImplName = d.getQualifiedName();
325N/A String endpointInterfaceName = webService != null ? webService.endpointInterface() : null;
325N/A if (endpointInterfaceName != null && endpointInterfaceName.length() > 0) {
325N/A SourcePosition pos = pos = d.getPosition();
325N/A checkForInvalidImplAnnotation(d, SOAPBinding.class);
325N/A if (webService.name().length() > 0)
325N/A annotationError(pos, WebserviceapMessages.localizableWEBSERVICEAP_ENDPOINTINTEFACE_PLUS_ELEMENT("name"));
325N/A endpointReferencesInterface = true;
325N/A verifyImplAnnotations(d);
325N/A inspectEndpointInterface(endpointInterfaceName, d);
325N/A serviceImplName = null;
325N/A return;
325N/A }
325N/A processingSEI = false;
325N/A preProcessWebService(webService, d);
325N/A processWebService(webService, d);
325N/A serviceImplName = null;
325N/A postProcessWebService(webService, d);
325N/A serviceImplName = null;
325N/A }
325N/A
325N/A protected void verifySEIAnnotations(WebService webService, InterfaceDeclaration d) {
325N/A if (webService.endpointInterface().length() > 0) {
325N/A builder.onError(d.getPosition(), WebserviceapMessages.localizableWEBSERVICEAP_ENDPOINTINTERFACE_ON_INTERFACE(d.getQualifiedName(), webService.endpointInterface()));
325N/A }
325N/A if (webService.serviceName().length() > 0) {
325N/A builder.onError(d.getPosition(), WebserviceapMessages.localizableWEBSERVICEAP_INVALID_SEI_ANNOTATION_ELEMENT("serviceName", d.getQualifiedName()));
325N/A }
325N/A if (webService.portName().length() > 0) {
325N/A builder.onError(d.getPosition(), WebserviceapMessages.localizableWEBSERVICEAP_INVALID_SEI_ANNOTATION_ELEMENT("portName", d.getQualifiedName()));
325N/A }
325N/A }
325N/A
325N/A protected void verifyImplAnnotations(ClassDeclaration d) {
325N/A for (MethodDeclaration method : d.getMethods()) {
325N/A checkForInvalidImplAnnotation(method, WebMethod.class);
325N/A checkForInvalidImplAnnotation(method, Oneway.class);
325N/A checkForInvalidImplAnnotation(method, WebResult.class);
325N/A for (ParameterDeclaration param : method.getParameters()) {
325N/A checkForInvalidImplAnnotation(param, WebParam.class);
325N/A }
325N/A }
325N/A }
325N/A
325N/A protected void checkForInvalidSEIAnnotation(InterfaceDeclaration d, Class annotationClass) {
325N/A Object annotation = d.getAnnotation(annotationClass);
325N/A if (annotation != null) {
325N/A SourcePosition pos = d.getPosition();
325N/A annotationError(pos, WebserviceapMessages.localizableWEBSERVICEAP_INVALID_SEI_ANNOTATION(annotationClass.getName(), d.getQualifiedName()));
325N/A }
325N/A }
325N/A
325N/A protected void checkForInvalidImplAnnotation(Declaration d, Class annotationClass) {
325N/A Object annotation = d.getAnnotation(annotationClass);
325N/A if (annotation != null) {
325N/A SourcePosition pos = d.getPosition();
325N/A annotationError(pos, WebserviceapMessages.localizableWEBSERVICEAP_ENDPOINTINTEFACE_PLUS_ANNOTATION(annotationClass.getName()));
325N/A }
325N/A }
325N/A
325N/A protected void annotationError(SourcePosition pos, Localizable message) {
325N/A builder.onError(pos, message);
325N/A }
325N/A
325N/A
325N/A protected void preProcessWebService(WebService webService, TypeDeclaration d) {
325N/A processedMethods = new HashSet<String>();
325N/A seiContext = context.getSEIContext(d);
325N/A String targetNamespace = null;
325N/A if (webService != null)
325N/A targetNamespace = webService.targetNamespace();
325N/A if (targetNamespace == null || targetNamespace.length() == 0) {
325N/A String packageName = d.getPackage().getQualifiedName();
325N/A if (packageName == null || packageName.length() == 0) {
325N/A builder.onError(d.getPosition(), WebserviceapMessages.localizableWEBSERVICEAP_NO_PACKAGE_CLASS_MUST_HAVE_TARGETNAMESPACE(d.getQualifiedName()));
325N/A }
325N/A targetNamespace = getNamespace(d.getPackage());
325N/A }
325N/A seiContext.setNamespaceURI(targetNamespace);
325N/A if (serviceImplName == null)
325N/A serviceImplName = seiContext.getSEIImplName();
325N/A if (serviceImplName != null) {
325N/A seiContext.setSEIImplName(serviceImplName);
325N/A context.addSEIContext(serviceImplName, seiContext);
325N/A }
325N/A portName = ClassNameInfo.getName(
325N/A d.getSimpleName().replace(
325N/A SIGC_INNERCLASS,
325N/A SIGC_UNDERSCORE));;
325N/A packageName = d.getPackage().getQualifiedName();
325N/A portName = webService != null && webService.name() != null && webService.name().length() >0 ?
325N/A webService.name() : portName;
325N/A serviceName = ClassNameInfo.getName(d.getQualifiedName())+SERVICE;
325N/A serviceName = webService != null && webService.serviceName() != null &&
325N/A webService.serviceName().length() > 0 ?
325N/A webService.serviceName() : serviceName;
325N/A wsdlNamespace = seiContext.getNamespaceURI();
325N/A typeNamespace = wsdlNamespace;
325N/A
325N/A SOAPBinding soapBinding = d.getAnnotation(SOAPBinding.class);
325N/A if (soapBinding != null) {
325N/A pushedSOAPBinding = pushSOAPBinding(soapBinding, d, d);
325N/A } else if (d.equals(typeDecl)) {
325N/A pushedSOAPBinding = pushSOAPBinding(new MySOAPBinding(), d, d);
325N/A }
325N/A }
325N/A
325N/A public static boolean sameStyle(SOAPBinding.Style style, SOAPStyle soapStyle) {
325N/A if (style.equals(SOAPBinding.Style.DOCUMENT) &&
325N/A soapStyle.equals(SOAPStyle.DOCUMENT))
325N/A return true;
325N/A if (style.equals(SOAPBinding.Style.RPC) &&
325N/A soapStyle.equals(SOAPStyle.RPC))
325N/A return true;
325N/A return false;
325N/A }
325N/A
325N/A protected boolean pushSOAPBinding(SOAPBinding soapBinding, Declaration bindingDecl,
325N/A TypeDeclaration classDecl) {
325N/A boolean changed = false;
325N/A if (!sameStyle(soapBinding.style(), soapStyle)) {
325N/A changed = true;
325N/A if (pushedSOAPBinding)
325N/A builder.onError(bindingDecl.getPosition(), WebserviceapMessages.localizableWEBSERVICEAP_MIXED_BINDING_STYLE(classDecl.getQualifiedName()));
325N/A }
325N/A if (soapBinding.style().equals(SOAPBinding.Style.RPC)) {
325N/A soapStyle = SOAPStyle.RPC;
325N/A wrapped = true;
325N/A if (soapBinding.parameterStyle().equals(ParameterStyle.BARE)) {
325N/A builder.onError(bindingDecl.getPosition(), WebserviceapMessages.localizableWEBSERVICEAP_RPC_LITERAL_MUST_NOT_BE_BARE(classDecl.getQualifiedName()));
325N/A }
325N/A
325N/A } else {
325N/A soapStyle = SOAPStyle.DOCUMENT;
325N/A if (wrapped != soapBinding.parameterStyle().equals(ParameterStyle.WRAPPED)) {
325N/A wrapped = soapBinding.parameterStyle().equals(ParameterStyle.WRAPPED);
325N/A changed = true;
325N/A }
325N/A }
325N/A if (soapBinding.use().equals(SOAPBinding.Use.ENCODED)) {
325N/A String style = "rpc";
325N/A if(soapBinding.style().equals(SOAPBinding.Style.DOCUMENT))
325N/A style = "document";
325N/A builder.onError(bindingDecl.getPosition(), WebserviceapMessages.localizableWEBSERVICE_ENCODED_NOT_SUPPORTED(classDecl.getQualifiedName(), style));
325N/A }
325N/A if (changed || soapBindingStack.empty()) {
325N/A soapBindingStack.push(soapBinding);
325N/A pushedSOAPBinding = true;
325N/A }
325N/A return changed;
325N/A }
325N/A
325N/A
325N/A protected SOAPBinding popSOAPBinding() {
325N/A if (pushedSOAPBinding)
325N/A soapBindingStack.pop();
325N/A SOAPBinding soapBinding = null;
325N/A if (!soapBindingStack.empty()) {
325N/A soapBinding = soapBindingStack.peek();
325N/A if (soapBinding.style().equals(SOAPBinding.Style.RPC)) {
325N/A soapStyle = SOAPStyle.RPC;
325N/A wrapped = true;
325N/A } else {
325N/A soapStyle = SOAPStyle.DOCUMENT;
325N/A wrapped = soapBinding.parameterStyle().equals(ParameterStyle.WRAPPED);
325N/A }
325N/A }
325N/A return soapBinding;
325N/A }
325N/A
325N/A protected String getNamespace(PackageDeclaration packageDecl) {
325N/A return RuntimeModeler.getNamespace(packageDecl.getQualifiedName());
325N/A }
325N/A
325N/A// abstract protected boolean shouldProcessWebService(WebService webService, InterfaceDeclaration intf);
325N/A
325N/A// abstract protected boolean shouldProcessWebService(WebService webService, ClassDeclaration decl);
325N/A protected boolean shouldProcessWebService(WebService webService, InterfaceDeclaration intf) {
325N/A hasWebMethods = false;
325N/A if (webService == null)
325N/A builder.onError(intf.getPosition(), WebserviceapMessages.localizableWEBSERVICEAP_ENDPOINTINTERFACE_HAS_NO_WEBSERVICE_ANNOTATION(intf.getQualifiedName()));
325N/A
325N/A SOAPBinding soapBinding = intf.getAnnotation(SOAPBinding.class);
325N/A if(soapBinding != null && soapBinding.style() == SOAPBinding.Style.RPC && soapBinding.parameterStyle() == SOAPBinding.ParameterStyle.BARE) {
325N/A builder.onError(intf.getPosition(), WebserviceapMessages.localizableWEBSERVICEAP_INVALID_SOAPBINDING_PARAMETERSTYLE(soapBinding, intf));
325N/A return false;
325N/A }
325N/A
325N/A if (isLegalSEI(intf))
325N/A return true;
325N/A return false;
325N/A }
325N/A
325N/A protected boolean shouldProcessWebService(WebService webService, ClassDeclaration classDecl) {
325N/A if (webService == null)
325N/A return false;
325N/A hasWebMethods = hasWebMethods(classDecl);
325N/A SOAPBinding soapBinding = classDecl.getAnnotation(SOAPBinding.class);
325N/A if(soapBinding != null && soapBinding.style() == SOAPBinding.Style.RPC && soapBinding.parameterStyle() == SOAPBinding.ParameterStyle.BARE) {
325N/A builder.onError(classDecl.getPosition(), WebserviceapMessages.localizableWEBSERVICEAP_INVALID_SOAPBINDING_PARAMETERSTYLE(soapBinding, classDecl));
325N/A return false;
325N/A }
325N/A return isLegalImplementation(webService, classDecl);
325N/A }
325N/A
325N/A abstract protected void processWebService(WebService webService, TypeDeclaration d);
325N/A
325N/A protected void postProcessWebService(WebService webService, InterfaceDeclaration d) {
325N/A processMethods(d);
325N/A popSOAPBinding();
325N/A }
325N/A
325N/A protected void postProcessWebService(WebService webService, ClassDeclaration d) {
325N/A processMethods(d);
325N/A popSOAPBinding();
325N/A }
325N/A
325N/A
325N/A protected boolean hasWebMethods(ClassDeclaration d) {
325N/A if (d.getQualifiedName().equals(JAVA_LANG_OBJECT))
325N/A return false;
325N/A WebMethod webMethod;
325N/A for (MethodDeclaration method : d.getMethods()) {
325N/A webMethod = method.getAnnotation(WebMethod.class);
325N/A if (webMethod != null) {
325N/A if (webMethod.exclude()) {
325N/A if (webMethod.operationName().length() > 0)
325N/A builder.onError(method.getPosition(), WebserviceapMessages.localizableWEBSERVICEAP_INVALID_WEBMETHOD_ELEMENT_WITH_EXCLUDE("operationName", d.getQualifiedName(), method.toString()));
325N/A if (webMethod.action().length() > 0)
325N/A builder.onError(method.getPosition(), WebserviceapMessages.localizableWEBSERVICEAP_INVALID_WEBMETHOD_ELEMENT_WITH_EXCLUDE("action", d.getQualifiedName(), method.toString()));
325N/A } else {
325N/A return true;
325N/A }
325N/A }
325N/A }
325N/A return false;//hasWebMethods(d.getSuperclass().getDeclaration());
325N/A }
325N/A
325N/A protected void processMethods(InterfaceDeclaration d) {
325N/A builder.log("ProcessedMethods Interface: "+d);
325N/A hasWebMethods = false;
325N/A for (MethodDeclaration methodDecl : d.getMethods()) {
325N/A methodDecl.accept(this);
325N/A }
325N/A for (InterfaceType superType : d.getSuperinterfaces())
325N/A processMethods(superType.getDeclaration());
325N/A }
325N/A
325N/A protected void processMethods(ClassDeclaration d) {
325N/A builder.log("ProcessedMethods Class: "+d);
325N/A hasWebMethods = hasWebMethods(d);
325N/A if (d.getQualifiedName().equals(JAVA_LANG_OBJECT))
325N/A return;
325N/A if (d.getAnnotation(WebService.class) != null) {
325N/A // Super classes must have @WebService annotations to pick up their methods
325N/A for (MethodDeclaration methodDecl : d.getMethods()) {
325N/A methodDecl.accept(this);
325N/A }
325N/A }
325N/A if (d.getSuperclass() != null) {
325N/A processMethods(d.getSuperclass().getDeclaration());
325N/A }
325N/A }
325N/A
325N/A private InterfaceDeclaration getEndpointInterfaceDecl(String endpointInterfaceName,
325N/A ClassDeclaration d) {
325N/A InterfaceDeclaration intTypeDecl = null;
325N/A for (InterfaceType interfaceType : d.getSuperinterfaces()) {
325N/A if (endpointInterfaceName.equals(interfaceType.toString())) {
325N/A intTypeDecl = interfaceType.getDeclaration();
325N/A seiContext = context.getSEIContext(intTypeDecl.getQualifiedName());
325N/A assert(seiContext != null);
325N/A seiContext.setImplementsSEI(true);
325N/A break;
325N/A }
325N/A }
325N/A if (intTypeDecl == null) {
325N/A intTypeDecl = (InterfaceDeclaration)builder.getTypeDeclaration(endpointInterfaceName);
325N/A }
325N/A if (intTypeDecl == null)
325N/A builder.onError(WebserviceapMessages.WEBSERVICEAP_ENDPOINTINTERFACE_CLASS_NOT_FOUND(endpointInterfaceName));
325N/A return intTypeDecl;
325N/A }
325N/A
325N/A
325N/A private void inspectEndpointInterface(String endpointInterfaceName, ClassDeclaration d) {
325N/A TypeDeclaration intTypeDecl = getEndpointInterfaceDecl(endpointInterfaceName, d);
325N/A if (intTypeDecl != null)
325N/A intTypeDecl.accept(this);
325N/A }
325N/A
325N/A public void visitMethodDeclaration(MethodDeclaration method) {
325N/A // Methods must be public
325N/A if (!method.getModifiers().contains(Modifier.PUBLIC))
325N/A return;
325N/A if (processedMethod(method))
325N/A return;
325N/A WebMethod webMethod = method.getAnnotation(WebMethod.class);
325N/A if (webMethod != null && webMethod.exclude())
325N/A return;
325N/A SOAPBinding soapBinding = method.getAnnotation(SOAPBinding.class);
325N/A if (soapBinding == null && !method.getDeclaringType().equals(typeDecl)) {
325N/A if (method.getDeclaringType() instanceof ClassDeclaration) {
325N/A soapBinding = method.getDeclaringType().getAnnotation(SOAPBinding.class);
325N/A if (soapBinding != null)
325N/A builder.log("using "+method.getDeclaringType()+"'s SOAPBinding.");
325N/A else {
325N/A soapBinding = new MySOAPBinding();
325N/A }
325N/A }
325N/A }
325N/A boolean newBinding = false;
325N/A if (soapBinding != null) {
325N/A newBinding = pushSOAPBinding(soapBinding, method, typeDecl);
325N/A }
325N/A try {
325N/A if (shouldProcessMethod(method, webMethod)) {
325N/A processMethod(method, webMethod);
325N/A }
325N/A } finally {
325N/A if (newBinding) {
325N/A popSOAPBinding();
325N/A }
325N/A }
325N/A }
325N/A
325N/A protected boolean processedMethod(MethodDeclaration method) {
325N/A String id = method.toString();
325N/A if (processedMethods.contains(id))
325N/A return true;
325N/A processedMethods.add(id);
325N/A return false;
325N/A }
325N/A
325N/A
325N/A protected boolean shouldProcessMethod(MethodDeclaration method, WebMethod webMethod) {
325N/A builder.log("should process method: "+method.getSimpleName()+" hasWebMethods: "+ hasWebMethods+" ");
325N/A /*
325N/A Fix for https://jax-ws.dev.java.net/issues/show_bug.cgi?id=577
325N/A if (hasWebMethods && webMethod == null) {
325N/A builder.log("webMethod == null");
325N/A return false;
325N/A }
325N/A */
325N/A Collection<Modifier> modifiers = method.getModifiers();
325N/A boolean staticFinal = modifiers.contains(Modifier.STATIC) || modifiers.contains(Modifier.FINAL);
325N/A if (staticFinal) {
325N/A if (webMethod != null) {
325N/A builder.onError(method.getPosition(), WebserviceapMessages.localizableWEBSERVICEAP_WEBSERVICE_METHOD_IS_STATIC_OR_FINAL(method.getDeclaringType(), method));
325N/A }
325N/A return false;
325N/A }
325N/A boolean retval = (endpointReferencesInterface ||
325N/A method.getDeclaringType().equals(typeDecl) ||
325N/A (method.getDeclaringType().getAnnotation(WebService.class) != null));
325N/A builder.log("endpointReferencesInterface: "+endpointReferencesInterface);
325N/A builder.log("declaring class has WebSevice: "+(method.getDeclaringType().getAnnotation(WebService.class) != null));
325N/A builder.log("returning: "+retval);
325N/A return retval;
325N/A }
325N/A
325N/A abstract protected void processMethod(MethodDeclaration method, WebMethod webMethod);
325N/A
325N/A
325N/A protected boolean isLegalImplementation(WebService webService, ClassDeclaration classDecl) {
325N/A
325N/A boolean isStateful = isStateful(classDecl);
325N/A
325N/A Collection<Modifier> modifiers = classDecl.getModifiers();
325N/A if (!modifiers.contains(Modifier.PUBLIC)){
325N/A builder.onError(classDecl.getPosition(), WebserviceapMessages.localizableWEBSERVICEAP_WEBSERVICE_CLASS_NOT_PUBLIC(classDecl.getQualifiedName()));
325N/A return false;
325N/A }
325N/A if (modifiers.contains(Modifier.FINAL) && !isStateful) {
325N/A builder.onError(classDecl.getPosition(), WebserviceapMessages.localizableWEBSERVICEAP_WEBSERVICE_CLASS_IS_FINAL(classDecl.getQualifiedName()));
325N/A return false;
325N/A }
325N/A if (modifiers.contains(Modifier.ABSTRACT) && !isStateful) {
325N/A builder.onError(classDecl.getPosition(), WebserviceapMessages.localizableWEBSERVICEAP_WEBSERVICE_CLASS_IS_ABSTRACT(classDecl.getQualifiedName()));
325N/A return false;
325N/A }
325N/A boolean hasDefaultConstructor = false;
325N/A for (ConstructorDeclaration constructor : classDecl.getConstructors()) {
325N/A if (constructor.getModifiers().contains(Modifier.PUBLIC) &&
325N/A constructor.getParameters().size() == 0) {
325N/A hasDefaultConstructor = true;
325N/A break;
325N/A }
325N/A }
325N/A if (!hasDefaultConstructor && !isStateful) {
325N/A if (classDecl.getDeclaringType() != null && !modifiers.contains(Modifier.STATIC)) {
325N/A builder.onError(classDecl.getPosition(), WebserviceapMessages.localizableWEBSERVICEAP_WEBSERVICE_CLASS_IS_INNERCLASS_NOT_STATIC(classDecl.getQualifiedName()));
325N/A return false;
325N/A }
325N/A
325N/A builder.onError(classDecl.getPosition(), WebserviceapMessages.localizableWEBSERVICEAP_WEBSERVICE_NO_DEFAULT_CONSTRUCTOR(classDecl.getQualifiedName()));
325N/A return false;
325N/A }
325N/A if (webService.endpointInterface().length() == 0) {
325N/A if (!methodsAreLegal(classDecl))
325N/A return false;
325N/A } else {
325N/A InterfaceDeclaration intfDecl = getEndpointInterfaceDecl(webService.endpointInterface(), classDecl);
325N/A if (!classImplementsSEI(classDecl, intfDecl))
325N/A return false;
325N/A }
325N/A
325N/A return true;
325N/A }
325N/A
325N/A private boolean isStateful(ClassDeclaration classDecl){
325N/A try {
325N/A // We don't want dependency on rt-ha module as its not integrated in JDK
325N/A return classDecl.getAnnotation((Class <? extends Annotation>)Class.forName("com.sun.xml.internal.ws.developer.Stateful"))!=null;
325N/A } catch (ClassNotFoundException e) {
325N/A //ignore
325N/A }
325N/A return false;
325N/A }
325N/A
325N/A protected boolean classImplementsSEI(ClassDeclaration classDecl,
325N/A InterfaceDeclaration intfDecl) {
325N/A for (InterfaceType interfaceType : classDecl.getSuperinterfaces()) {
325N/A if (interfaceType.getDeclaration().equals(intfDecl))
325N/A return true;
325N/A }
325N/A boolean implementsMethod;
325N/A for (MethodDeclaration method : intfDecl.getMethods()) {
325N/A implementsMethod = false;
325N/A for (MethodDeclaration classMethod : classDecl.getMethods()) {
325N/A if (sameMethod(method, classMethod)) {
325N/A implementsMethod = true;
325N/A break;
325N/A }
325N/A }
325N/A if (!implementsMethod) {
325N/A builder.onError(method.getPosition(), WebserviceapMessages.localizableWEBSERVICEAP_METHOD_NOT_IMPLEMENTED(intfDecl.getSimpleName(), classDecl.getSimpleName(), method));
325N/A return false;
325N/A }
325N/A }
325N/A return true;
325N/A }
325N/A
325N/A protected boolean sameMethod(MethodDeclaration method1, MethodDeclaration method2) {
325N/A if (!method1.getSimpleName().equals(method2.getSimpleName()))
325N/A return false;
325N/A if (!method1.getReturnType().equals(method2.getReturnType()))
325N/A return false;
325N/A ParameterDeclaration[] params1 = method1.getParameters().toArray(new ParameterDeclaration[0]);
325N/A ParameterDeclaration[] params2 = method2.getParameters().toArray(new ParameterDeclaration[0]);
325N/A if (params1.length != params2.length)
325N/A return false;
325N/A int pos = 0;
325N/A for (ParameterDeclaration param1 : method1.getParameters()) {
325N/A if (!param1.getType().equals(params2[pos++].getType()))
325N/A return false;
325N/A }
325N/A return true;
325N/A }
325N/A
325N/A protected boolean isLegalSEI(InterfaceDeclaration intf) {
325N/A for (FieldDeclaration field : intf.getFields())
325N/A if (field.getConstantValue() != null) {
325N/A builder.onError(WebserviceapMessages.WEBSERVICEAP_SEI_CANNOT_CONTAIN_CONSTANT_VALUES(intf.getQualifiedName(), field.getSimpleName()));
325N/A return false;
325N/A }
325N/A if (!methodsAreLegal(intf))
325N/A return false;
325N/A return true;
325N/A }
325N/A
325N/A protected boolean methodsAreLegal(InterfaceDeclaration intfDecl) {
325N/A hasWebMethods = false;
325N/A for (MethodDeclaration method : intfDecl.getMethods()) {
325N/A if (!isLegalMethod(method, intfDecl))
325N/A return false;
325N/A }
325N/A for (InterfaceType superIntf : intfDecl.getSuperinterfaces()) {
325N/A if (!methodsAreLegal(superIntf.getDeclaration()))
325N/A return false;
325N/A }
325N/A return true;
325N/A }
325N/A
325N/A protected boolean methodsAreLegal(ClassDeclaration classDecl) {
325N/A hasWebMethods = hasWebMethods(classDecl);
325N/A for (MethodDeclaration method : classDecl.getMethods()) {
325N/A if (!isLegalMethod(method, classDecl))
325N/A return false;
325N/A }
325N/A ClassType superClass = classDecl.getSuperclass();
325N/A
325N/A if (!superClass.getDeclaration().getQualifiedName().equals(JAVA_LANG_OBJECT) && !methodsAreLegal(superClass.getDeclaration())) {
325N/A return false;
325N/A }
325N/A return true;
325N/A }
325N/A
325N/A
325N/A protected boolean isLegalMethod(MethodDeclaration method, TypeDeclaration typeDecl) {
325N/A WebMethod webMethod = method.getAnnotation(WebMethod.class);
325N/A //SEI cannot have methods with @WebMethod(exclude=true)
325N/A if (typeDecl instanceof InterfaceDeclaration && webMethod != null && webMethod.exclude())
325N/A builder.onError(method.getPosition(), WebserviceapMessages.localizableWEBSERVICEAP_INVALID_SEI_ANNOTATION_ELEMENT_EXCLUDE("exclude=true", typeDecl.getQualifiedName(), method.toString()));
325N/A // With https://jax-ws.dev.java.net/issues/show_bug.cgi?id=577, hasWebMethods has no effect
325N/A // if (hasWebMethods && (webMethod == null))
325N/A // return true;
325N/A
325N/A if ((webMethod !=null) && webMethod.exclude()) {
325N/A return true;
325N/A }
325N/A /*
325N/A This check is not needed as Impl class is already checked that it is not abstract.
325N/A if (typeDecl instanceof ClassDeclaration && method.getModifiers().contains(Modifier.ABSTRACT)) {
325N/A builder.onError(method.getPosition(), WebserviceapMessages.localizableWEBSERVICEAP_WEBSERVICE_METHOD_IS_ABSTRACT(typeDecl.getQualifiedName(), method.getSimpleName()));
325N/A return false;
325N/A }
325N/A */
325N/A if (!isLegalType(method.getReturnType())) {
325N/A builder.onError(method.getPosition(), WebserviceapMessages.localizableWEBSERVICEAP_METHOD_RETURN_TYPE_CANNOT_IMPLEMENT_REMOTE(typeDecl.getQualifiedName(),
325N/A method.getSimpleName(),
325N/A method.getReturnType()));
325N/A }
325N/A boolean isOneway = method.getAnnotation(Oneway.class) != null;
325N/A if (isOneway && !isValidOnewayMethod(method, typeDecl))
325N/A return false;
325N/A
325N/A
325N/A SOAPBinding soapBinding = method.getAnnotation(SOAPBinding.class);
325N/A if (soapBinding != null) {
325N/A if (soapBinding.style().equals(SOAPBinding.Style.RPC)) {
325N/A builder.onError(method.getPosition(), WebserviceapMessages.localizableWEBSERVICEAP_RPC_SOAPBINDING_NOT_ALLOWED_ON_METHOD(typeDecl.getQualifiedName(), method.toString()));
325N/A }
325N/A }
325N/A
325N/A int paramIndex = 0;
325N/A for (ParameterDeclaration parameter : method.getParameters()) {
325N/A if (!isLegalParameter(parameter, method, typeDecl, paramIndex++))
325N/A return false;
325N/A }
325N/A
325N/A if (!isDocLitWrapped() &&
325N/A soapStyle.equals(SOAPStyle.DOCUMENT)) {
325N/A ParameterDeclaration outParam = getOutParameter(method);
325N/A int inParams = getModeParameterCount(method, WebParam.Mode.IN);
325N/A int outParams = getModeParameterCount(method, WebParam.Mode.OUT);
325N/A if (inParams != 1) {
325N/A builder.onError(method.getPosition(), WebserviceapMessages.localizableWEBSERVICEAP_DOC_BARE_AND_NO_ONE_IN(typeDecl.getQualifiedName(), method.toString()));
325N/A }
325N/A if (method.getReturnType() instanceof VoidType) {
325N/A if (outParam == null && !isOneway) {
325N/A builder.onError(method.getPosition(), WebserviceapMessages.localizableWEBSERVICEAP_DOC_BARE_NO_OUT(typeDecl.getQualifiedName(), method.toString()));
325N/A }
325N/A if (outParams != 1) {
325N/A if (!isOneway && outParams != 0)
325N/A builder.onError(method.getPosition(), WebserviceapMessages.localizableWEBSERVICEAP_DOC_BARE_NO_RETURN_AND_NO_OUT(typeDecl.getQualifiedName(), method.toString()));
325N/A }
325N/A } else {
325N/A if (outParams > 0) {
325N/A builder.onError(outParam.getPosition(), WebserviceapMessages.localizableWEBSERVICEAP_DOC_BARE_RETURN_AND_OUT(typeDecl.getQualifiedName(), method.toString()));
325N/A }
325N/A }
325N/A }
325N/A return true;
325N/A }
325N/A
325N/A protected boolean isLegalParameter(ParameterDeclaration param,
325N/A MethodDeclaration method,
325N/A TypeDeclaration typeDecl,
325N/A int paramIndex) {
325N/A if (!isLegalType(param.getType())) {
325N/A builder.onError(param.getPosition(), WebserviceapMessages.localizableWEBSERVICEAP_METHOD_PARAMETER_TYPES_CANNOT_IMPLEMENT_REMOTE(typeDecl.getQualifiedName(),
325N/A method.getSimpleName(),
325N/A param.getSimpleName(),
325N/A param.getType().toString()));
325N/A return false;
325N/A }
325N/A TypeMirror holderType;
325N/A holderType = builder.getHolderValueType(param.getType());
325N/A WebParam webParam = param.getAnnotation(WebParam.class);
325N/A WebParam.Mode mode = null;
325N/A if (webParam != null)
325N/A mode = webParam.mode();
325N/A
325N/A if (holderType != null) {
325N/A if (mode != null && mode==WebParam.Mode.IN)
325N/A builder.onError(param.getPosition(), WebserviceapMessages.localizableWEBSERVICEAP_HOLDER_PARAMETERS_MUST_NOT_BE_IN_ONLY(typeDecl.getQualifiedName(), method.toString(), paramIndex));
325N/A } else if (mode != null && mode!=WebParam.Mode.IN) {
325N/A builder.onError(param.getPosition(), WebserviceapMessages.localizableWEBSERVICEAP_NON_IN_PARAMETERS_MUST_BE_HOLDER(typeDecl.getQualifiedName(), method.toString(), paramIndex));
325N/A }
325N/A
325N/A
325N/A
325N/A return true;
325N/A }
325N/A
325N/A protected boolean isDocLitWrapped() {
325N/A return soapStyle.equals(SOAPStyle.DOCUMENT) && wrapped;
325N/A }
325N/A
325N/A protected boolean isValidOnewayMethod(MethodDeclaration method, TypeDeclaration typeDecl) {
325N/A boolean valid = true;
325N/A if (!(method.getReturnType() instanceof VoidType)) {
325N/A // this is an error, cannot be Oneway and have a return type
325N/A builder.onError(method.getPosition(), WebserviceapMessages.localizableWEBSERVICEAP_ONEWAY_OPERATION_CANNOT_HAVE_RETURN_TYPE(typeDecl.getQualifiedName(), method.toString()));
325N/A valid = false;
325N/A }
325N/A ParameterDeclaration outParam = getOutParameter(method);
325N/A if (outParam != null) {
325N/A builder.onError(outParam.getPosition(), WebserviceapMessages.localizableWEBSERVICEAP_ONEWAY_AND_OUT(typeDecl.getQualifiedName(), method.toString()));
325N/A valid = false;
325N/A }
325N/A if (!isDocLitWrapped() && soapStyle.equals(SOAPStyle.DOCUMENT)) {
325N/A int inCnt = getModeParameterCount(method, WebParam.Mode.IN);
325N/A if (inCnt != 1) {
325N/A builder.onError(method.getPosition(), WebserviceapMessages.localizableWEBSERVICEAP_ONEWAY_AND_NOT_ONE_IN(typeDecl.getQualifiedName(), method.toString()));
325N/A valid = false;
325N/A }
325N/A }
325N/A ClassDeclaration exDecl;
325N/A for (ReferenceType thrownType : method.getThrownTypes()) {
325N/A exDecl = ((ClassType)thrownType).getDeclaration();
325N/A if (builder.isServiceException(exDecl)) {
325N/A builder.onError(method.getPosition(), WebserviceapMessages.localizableWEBSERVICEAP_ONEWAY_OPERATION_CANNOT_DECLARE_EXCEPTIONS(typeDecl.getQualifiedName(), method.toString(), exDecl.getQualifiedName()));
325N/A valid = false;
325N/A }
325N/A }
325N/A return valid;
325N/A }
325N/A
325N/A protected int getModeParameterCount(MethodDeclaration method, WebParam.Mode mode) {
325N/A WebParam webParam;
325N/A int cnt = 0;
325N/A for (ParameterDeclaration param : method.getParameters()) {
325N/A webParam = param.getAnnotation(WebParam.class);
325N/A if (webParam != null) {
325N/A if (webParam.header())
325N/A continue;
325N/A if (isEquivalentModes(mode, webParam.mode()))
325N/A cnt++;
325N/A } else {
325N/A if (isEquivalentModes(mode, WebParam.Mode.IN)) {
325N/A cnt++;
325N/A }
325N/A }
325N/A }
325N/A return cnt;
325N/A }
325N/A
325N/A protected boolean isEquivalentModes(WebParam.Mode mode1, WebParam.Mode mode2) {
325N/A if (mode1.equals(mode2))
325N/A return true;
325N/A assert mode1==WebParam.Mode.IN || mode1==WebParam.Mode.OUT;
325N/A if (mode1==WebParam.Mode.IN && mode2!=WebParam.Mode.OUT)
325N/A return true;
325N/A if (mode1==WebParam.Mode.OUT && mode2!=WebParam.Mode.IN)
325N/A return true;
325N/A return false;
325N/A }
325N/A
325N/A protected boolean isHolder(ParameterDeclaration param) {
325N/A return builder.getHolderValueType(param.getType()) != null;
325N/A }
325N/A
325N/A protected boolean isLegalType(TypeMirror type) {
325N/A if (!(type instanceof DeclaredType))
325N/A return true;
325N/A TypeDeclaration typeDecl = ((DeclaredType)type).getDeclaration();
325N/A if(typeDecl == null) {
325N/A // 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.
325N/A builder.onError(WebserviceapMessages.WEBSERVICEAP_COULD_NOT_FIND_TYPEDECL(type.toString(), context.getRound()));
325N/A }
325N/A return !builder.isRemote(typeDecl);
325N/A }
325N/A
325N/A protected ParameterDeclaration getOutParameter(MethodDeclaration method) {
325N/A WebParam webParam;
325N/A for (ParameterDeclaration param : method.getParameters()) {
325N/A webParam = param.getAnnotation(WebParam.class);
325N/A if (webParam != null && webParam.mode()!=WebParam.Mode.IN) {
325N/A return param;
325N/A }
325N/A }
325N/A return null;
325N/A }
325N/A
325N/A protected static class MySOAPBinding implements SOAPBinding {
325N/A public Style style() {return SOAPBinding.Style.DOCUMENT;}
325N/A public Use use() {return SOAPBinding.Use.LITERAL; }
325N/A public ParameterStyle parameterStyle() { return SOAPBinding.ParameterStyle.WRAPPED;}
325N/A public Class<? extends java.lang.annotation.Annotation> annotationType() {
325N/A return SOAPBinding.class;
325N/A }
325N/A }
325N/A}