0001: /*
0002: * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS HEADER.
0003: *
0004: * Copyright 1997-2007 Sun Microsystems, Inc. All rights reserved.
0005: *
0006: * The contents of this file are subject to the terms of either the GNU
0007: * General Public License Version 2 only ("GPL") or the Common Development
0008: * and Distribution License("CDDL") (collectively, the "License"). You
0009: * may not use this file except in compliance with the License. You can obtain
0010: * a copy of the License at https://glassfish.dev.java.net/public/CDDL+GPL.html
0011: * or glassfish/bootstrap/legal/LICENSE.txt. See the License for the specific
0012: * language governing permissions and limitations under the License.
0013: *
0014: * When distributing the software, include this License Header Notice in each
0015: * file and include the License file at glassfish/bootstrap/legal/LICENSE.txt.
0016: * Sun designates this particular file as subject to the "Classpath" exception
0017: * as provided by Sun in the GPL Version 2 section of the License file that
0018: * accompanied this code. If applicable, add the following below the License
0019: * Header, with the fields enclosed by brackets [] replaced by your own
0020: * identifying information: "Portions Copyrighted [year]
0021: * [name of copyright owner]"
0022: *
0023: * Contributor(s):
0024: *
0025: * If you wish your version of this file to be governed by only the CDDL or
0026: * only the GPL Version 2, indicate your decision by adding "[Contributor]
0027: * elects to include this software in this distribution under the [CDDL or GPL
0028: * Version 2] license." If you don't indicate a single choice of license, a
0029: * recipient has the option to distribute your version of this file under
0030: * either the CDDL, the GPL Version 2 or to extend the choice of license to
0031: * its licensees as provided above. However, if you add GPL Version 2 code
0032: * and therefore, elected the GPL Version 2 license, then the option applies
0033: * only if the new code is made subject to such option by the copyright
0034: * holder.
0035: */
0036: package com.sun.tools.ws.processor.modeler.annotation;
0037:
0038: import com.sun.mirror.declaration.*;
0039: import com.sun.mirror.type.*;
0040: import com.sun.mirror.util.SimpleDeclarationVisitor;
0041: import com.sun.mirror.util.SourcePosition;
0042: import com.sun.tools.ws.processor.model.Port;
0043: import com.sun.tools.ws.processor.modeler.JavaSimpleTypeCreator;
0044: import com.sun.tools.ws.processor.modeler.annotation.AnnotationProcessorContext.SEIContext;
0045: import com.sun.tools.ws.resources.WebserviceapMessages;
0046: import com.sun.tools.ws.util.ClassNameInfo;
0047: import com.sun.tools.ws.wsdl.document.soap.SOAPStyle;
0048: import com.sun.tools.ws.wsdl.document.soap.SOAPUse;
0049: import com.sun.xml.ws.developer.Stateful;
0050: import com.sun.xml.ws.model.RuntimeModeler;
0051: import com.sun.xml.ws.util.localization.Localizable;
0052:
0053: import javax.jws.*;
0054: import javax.jws.soap.SOAPBinding;
0055: import javax.jws.soap.SOAPBinding.ParameterStyle;
0056: import java.util.Collection;
0057: import java.util.HashSet;
0058: import java.util.Set;
0059: import java.util.Stack;
0060:
0061: /**
0062: *
0063: * @author WS Development Team
0064: */
0065: public abstract class WebServiceVisitor extends
0066: SimpleDeclarationVisitor implements WebServiceConstants {
0067: protected ModelBuilder builder;
0068: protected String wsdlNamespace;
0069: protected String typeNamespace;
0070: protected Stack<SOAPBinding> soapBindingStack;
0071: protected SOAPBinding typeDeclSOAPBinding;
0072: protected SOAPUse soapUse = SOAPUse.LITERAL;
0073: protected SOAPStyle soapStyle = SOAPStyle.DOCUMENT;
0074: protected boolean wrapped = true;
0075: protected HandlerChain hChain;
0076: protected Port port;
0077: protected String serviceImplName;
0078: protected String endpointInterfaceName;
0079: protected AnnotationProcessorContext context;
0080: protected SEIContext seiContext;
0081: protected boolean processingSEI = false;
0082: protected String serviceName;
0083: protected String packageName;
0084: protected String portName;
0085: protected boolean endpointReferencesInterface = false;
0086: protected boolean hasWebMethods = false;
0087: protected JavaSimpleTypeCreator simpleTypeCreator;
0088: protected TypeDeclaration typeDecl;
0089: protected Set<String> processedMethods;
0090: protected boolean pushedSOAPBinding = false;
0091: protected static final String ANNOTATION_ELEMENT_ERROR = "webserviceap.endpointinteface.plus.element";
0092:
0093: public WebServiceVisitor(ModelBuilder builder,
0094: AnnotationProcessorContext context) {
0095: this .builder = builder;
0096: this .context = context;
0097: this .simpleTypeCreator = new JavaSimpleTypeCreator();
0098: soapBindingStack = new Stack<SOAPBinding>();
0099: processedMethods = new HashSet<String>();
0100: }
0101:
0102: public void visitInterfaceDeclaration(InterfaceDeclaration d) {
0103: WebService webService = d.getAnnotation(WebService.class);
0104: if (!shouldProcessWebService(webService, d))
0105: return;
0106: if (builder.checkAndSetProcessed(d))
0107: return;
0108: typeDecl = d;
0109: if (endpointInterfaceName != null
0110: && !endpointInterfaceName.equals(d.getQualifiedName())) {
0111: builder
0112: .onError(
0113: d.getPosition(),
0114: WebserviceapMessages
0115: .localizableWEBSERVICEAP_ENDPOINTINTERFACES_DO_NOT_MATCH(
0116: endpointInterfaceName, d
0117: .getQualifiedName()));
0118: }
0119: verifySEIAnnotations(webService, d);
0120: endpointInterfaceName = d.getQualifiedName();
0121: processingSEI = true;
0122: preProcessWebService(webService, d);
0123: processWebService(webService, d);
0124: postProcessWebService(webService, d);
0125: }
0126:
0127: public void visitClassDeclaration(ClassDeclaration d) {
0128: WebService webService = d.getAnnotation(WebService.class);
0129: if (!shouldProcessWebService(webService, d))
0130: return;
0131: if (builder.checkAndSetProcessed(d))
0132: return;
0133: typeDeclSOAPBinding = d.getAnnotation(SOAPBinding.class);
0134: typeDecl = d;
0135: if (serviceImplName == null)
0136: serviceImplName = d.getQualifiedName();
0137: String endpointInterfaceName = webService != null ? webService
0138: .endpointInterface() : null;
0139: if (endpointInterfaceName != null
0140: && endpointInterfaceName.length() > 0) {
0141: SourcePosition pos = pos = d.getPosition();
0142: checkForInvalidImplAnnotation(d, SOAPBinding.class);
0143: if (webService.name().length() > 0)
0144: annotationError(
0145: pos,
0146: WebserviceapMessages
0147: .localizableWEBSERVICEAP_ENDPOINTINTEFACE_PLUS_ELEMENT("name"));
0148: endpointReferencesInterface = true;
0149: verifyImplAnnotations(d);
0150: inspectEndpointInterface(endpointInterfaceName, d);
0151: serviceImplName = null;
0152: return;
0153: }
0154: processingSEI = false;
0155: preProcessWebService(webService, d);
0156: processWebService(webService, d);
0157: serviceImplName = null;
0158: postProcessWebService(webService, d);
0159: serviceImplName = null;
0160: }
0161:
0162: protected void verifySEIAnnotations(WebService webService,
0163: InterfaceDeclaration d) {
0164: if (webService.endpointInterface().length() > 0) {
0165: builder
0166: .onError(
0167: d.getPosition(),
0168: WebserviceapMessages
0169: .localizableWEBSERVICEAP_ENDPOINTINTERFACE_ON_INTERFACE(
0170: d.getQualifiedName(),
0171: webService
0172: .endpointInterface()));
0173: }
0174: if (webService.serviceName().length() > 0) {
0175: builder
0176: .onError(
0177: d.getPosition(),
0178: WebserviceapMessages
0179: .localizableWEBSERVICEAP_INVALID_SEI_ANNOTATION_ELEMENT(
0180: "serviceName", d
0181: .getQualifiedName()));
0182: }
0183: if (webService.portName().length() > 0) {
0184: builder
0185: .onError(
0186: d.getPosition(),
0187: WebserviceapMessages
0188: .localizableWEBSERVICEAP_INVALID_SEI_ANNOTATION_ELEMENT(
0189: "portName", d
0190: .getQualifiedName()));
0191: }
0192: }
0193:
0194: protected void verifyImplAnnotations(ClassDeclaration d) {
0195: for (MethodDeclaration method : d.getMethods()) {
0196: checkForInvalidImplAnnotation(method, WebMethod.class);
0197: checkForInvalidImplAnnotation(method, Oneway.class);
0198: checkForInvalidImplAnnotation(method, WebResult.class);
0199: for (ParameterDeclaration param : method.getParameters()) {
0200: checkForInvalidImplAnnotation(param, WebParam.class);
0201: }
0202: }
0203: }
0204:
0205: protected void checkForInvalidSEIAnnotation(InterfaceDeclaration d,
0206: Class annotationClass) {
0207: Object annotation = d.getAnnotation(annotationClass);
0208: if (annotation != null) {
0209: SourcePosition pos = d.getPosition();
0210: annotationError(pos, WebserviceapMessages
0211: .localizableWEBSERVICEAP_INVALID_SEI_ANNOTATION(
0212: annotationClass.getName(), d
0213: .getQualifiedName()));
0214: }
0215: }
0216:
0217: protected void checkForInvalidImplAnnotation(Declaration d,
0218: Class annotationClass) {
0219: Object annotation = d.getAnnotation(annotationClass);
0220: if (annotation != null) {
0221: SourcePosition pos = d.getPosition();
0222: annotationError(
0223: pos,
0224: WebserviceapMessages
0225: .localizableWEBSERVICEAP_ENDPOINTINTEFACE_PLUS_ANNOTATION(annotationClass
0226: .getName()));
0227: }
0228: }
0229:
0230: protected void annotationError(SourcePosition pos,
0231: Localizable message) {
0232: builder.onError(pos, message);
0233: }
0234:
0235: protected void preProcessWebService(WebService webService,
0236: TypeDeclaration d) {
0237: processedMethods = new HashSet<String>();
0238: seiContext = context.getSEIContext(d);
0239: String targetNamespace = null;
0240: if (webService != null)
0241: targetNamespace = webService.targetNamespace();
0242: if (targetNamespace == null || targetNamespace.length() == 0) {
0243: String packageName = d.getPackage().getQualifiedName();
0244: if (packageName == null || packageName.length() == 0) {
0245: builder
0246: .onError(
0247: d.getPosition(),
0248: WebserviceapMessages
0249: .localizableWEBSERVICEAP_NO_PACKAGE_CLASS_MUST_HAVE_TARGETNAMESPACE(d
0250: .getQualifiedName()));
0251: }
0252: targetNamespace = getNamespace(d.getPackage());
0253: }
0254: seiContext.setNamespaceURI(targetNamespace);
0255: if (serviceImplName == null)
0256: serviceImplName = seiContext.getSEIImplName();
0257: if (serviceImplName != null) {
0258: seiContext.setSEIImplName(serviceImplName);
0259: context.addSEIContext(serviceImplName, seiContext);
0260: }
0261: portName = ClassNameInfo.getName(d.getSimpleName().replace(
0262: SIGC_INNERCLASS, SIGC_UNDERSCORE));
0263: ;
0264: packageName = d.getPackage().getQualifiedName();
0265: portName = webService != null && webService.name() != null
0266: && webService.name().length() > 0 ? webService.name()
0267: : portName;
0268: serviceName = ClassNameInfo.getName(d.getQualifiedName())
0269: + SERVICE;
0270: serviceName = webService != null
0271: && webService.serviceName() != null
0272: && webService.serviceName().length() > 0 ? webService
0273: .serviceName() : serviceName;
0274: wsdlNamespace = seiContext.getNamespaceURI();
0275: typeNamespace = wsdlNamespace;
0276:
0277: SOAPBinding soapBinding = d.getAnnotation(SOAPBinding.class);
0278: if (soapBinding != null) {
0279: pushedSOAPBinding = pushSOAPBinding(soapBinding, d, d);
0280: } else if (d.equals(typeDecl)) {
0281: pushedSOAPBinding = pushSOAPBinding(new MySOAPBinding(), d,
0282: d);
0283: }
0284: }
0285:
0286: public static boolean sameStyle(SOAPBinding.Style style,
0287: SOAPStyle soapStyle) {
0288: if (style.equals(SOAPBinding.Style.DOCUMENT)
0289: && soapStyle.equals(SOAPStyle.DOCUMENT))
0290: return true;
0291: if (style.equals(SOAPBinding.Style.RPC)
0292: && soapStyle.equals(SOAPStyle.RPC))
0293: return true;
0294: return false;
0295: }
0296:
0297: protected boolean pushSOAPBinding(SOAPBinding soapBinding,
0298: Declaration bindingDecl, TypeDeclaration classDecl) {
0299: boolean changed = false;
0300: if (!sameStyle(soapBinding.style(), soapStyle)) {
0301: changed = true;
0302: if (pushedSOAPBinding)
0303: builder
0304: .onError(
0305: bindingDecl.getPosition(),
0306: WebserviceapMessages
0307: .localizableWEBSERVICEAP_MIXED_BINDING_STYLE(classDecl
0308: .getQualifiedName()));
0309: }
0310: if (soapBinding.style().equals(SOAPBinding.Style.RPC)) {
0311: soapStyle = SOAPStyle.RPC;
0312: wrapped = true;
0313: if (soapBinding.parameterStyle()
0314: .equals(ParameterStyle.BARE)) {
0315: builder
0316: .onError(
0317: bindingDecl.getPosition(),
0318: WebserviceapMessages
0319: .localizableWEBSERVICEAP_RPC_LITERAL_MUST_NOT_BE_BARE(classDecl
0320: .getQualifiedName()));
0321: }
0322:
0323: } else {
0324: soapStyle = SOAPStyle.DOCUMENT;
0325: if (wrapped != soapBinding.parameterStyle().equals(
0326: ParameterStyle.WRAPPED)) {
0327: wrapped = soapBinding.parameterStyle().equals(
0328: ParameterStyle.WRAPPED);
0329: changed = true;
0330: }
0331: }
0332: if (soapBinding.use().equals(SOAPBinding.Use.ENCODED)) {
0333: String style = "rpc";
0334: if (soapBinding.style().equals(SOAPBinding.Style.DOCUMENT))
0335: style = "document";
0336: builder
0337: .onError(
0338: bindingDecl.getPosition(),
0339: WebserviceapMessages
0340: .localizableWEBSERVICE_ENCODED_NOT_SUPPORTED(
0341: classDecl
0342: .getQualifiedName(),
0343: style));
0344: }
0345: if (changed || soapBindingStack.empty()) {
0346: soapBindingStack.push(soapBinding);
0347: pushedSOAPBinding = true;
0348: }
0349: return changed;
0350: }
0351:
0352: protected SOAPBinding popSOAPBinding() {
0353: if (pushedSOAPBinding)
0354: soapBindingStack.pop();
0355: SOAPBinding soapBinding = null;
0356: if (!soapBindingStack.empty()) {
0357: soapBinding = soapBindingStack.peek();
0358: if (soapBinding.style().equals(SOAPBinding.Style.RPC)) {
0359: soapStyle = SOAPStyle.RPC;
0360: wrapped = true;
0361: } else {
0362: soapStyle = SOAPStyle.DOCUMENT;
0363: wrapped = soapBinding.parameterStyle().equals(
0364: ParameterStyle.WRAPPED);
0365: }
0366: }
0367: return soapBinding;
0368: }
0369:
0370: protected String getNamespace(PackageDeclaration packageDecl) {
0371: return RuntimeModeler.getNamespace(packageDecl
0372: .getQualifiedName());
0373: }
0374:
0375: // abstract protected boolean shouldProcessWebService(WebService webService, InterfaceDeclaration intf);
0376:
0377: // abstract protected boolean shouldProcessWebService(WebService webService, ClassDeclaration decl);
0378: protected boolean shouldProcessWebService(WebService webService,
0379: InterfaceDeclaration intf) {
0380: hasWebMethods = false;
0381: if (webService == null)
0382: builder
0383: .onError(
0384: intf.getPosition(),
0385: WebserviceapMessages
0386: .localizableWEBSERVICEAP_ENDPOINTINTERFACE_HAS_NO_WEBSERVICE_ANNOTATION(intf
0387: .getQualifiedName()));
0388: if (isLegalSEI(intf))
0389: return true;
0390: return false;
0391: }
0392:
0393: protected boolean shouldProcessWebService(WebService webService,
0394: ClassDeclaration classDecl) {
0395: if (webService == null)
0396: return false;
0397: hasWebMethods = hasWebMethods(classDecl);
0398: return isLegalImplementation(webService, classDecl);
0399: }
0400:
0401: abstract protected void processWebService(WebService webService,
0402: TypeDeclaration d);
0403:
0404: protected void postProcessWebService(WebService webService,
0405: InterfaceDeclaration d) {
0406: processMethods(d);
0407: popSOAPBinding();
0408: }
0409:
0410: protected void postProcessWebService(WebService webService,
0411: ClassDeclaration d) {
0412: processMethods(d);
0413: popSOAPBinding();
0414: }
0415:
0416: protected boolean hasWebMethods(ClassDeclaration d) {
0417: if (d.getQualifiedName().equals(JAVA_LANG_OBJECT))
0418: return false;
0419: WebMethod webMethod;
0420: for (MethodDeclaration method : d.getMethods()) {
0421: webMethod = method.getAnnotation(WebMethod.class);
0422: if (webMethod != null) {
0423: if (webMethod.exclude()) {
0424: if (webMethod.operationName().length() > 0)
0425: builder
0426: .onError(
0427: method.getPosition(),
0428: WebserviceapMessages
0429: .localizableWEBSERVICEAP_INVALID_WEBMETHOD_ELEMENT_WITH_EXCLUDE(
0430: "operationName",
0431: d
0432: .getQualifiedName(),
0433: method
0434: .toString()));
0435: if (webMethod.action().length() > 0)
0436: builder
0437: .onError(
0438: method.getPosition(),
0439: WebserviceapMessages
0440: .localizableWEBSERVICEAP_INVALID_WEBMETHOD_ELEMENT_WITH_EXCLUDE(
0441: "action",
0442: d
0443: .getQualifiedName(),
0444: method
0445: .toString()));
0446: } else {
0447: return true;
0448: }
0449: }
0450: }
0451: return false;//hasWebMethods(d.getSuperclass().getDeclaration());
0452: }
0453:
0454: protected void processMethods(InterfaceDeclaration d) {
0455: builder.log("ProcessedMethods Interface: " + d);
0456: hasWebMethods = false;
0457: for (MethodDeclaration methodDecl : d.getMethods()) {
0458: methodDecl.accept(this );
0459: }
0460: for (InterfaceType super Type : d.getSuperinterfaces())
0461: processMethods(super Type.getDeclaration());
0462: }
0463:
0464: protected void processMethods(ClassDeclaration d) {
0465: builder.log("ProcessedMethods Class: " + d);
0466: hasWebMethods = hasWebMethods(d);
0467: if (d.getQualifiedName().equals(JAVA_LANG_OBJECT))
0468: return;
0469: if (d.getAnnotation(WebService.class) != null) {
0470: // Super classes must have @WebService annotations to pick up their methods
0471: for (MethodDeclaration methodDecl : d.getMethods()) {
0472: methodDecl.accept(this );
0473: }
0474: }
0475: if (d.getSuperclass() != null) {
0476: processMethods(d.getSuperclass().getDeclaration());
0477: }
0478: }
0479:
0480: private InterfaceDeclaration getEndpointInterfaceDecl(
0481: String endpointInterfaceName, ClassDeclaration d) {
0482: InterfaceDeclaration intTypeDecl = null;
0483: for (InterfaceType interfaceType : d.getSuperinterfaces()) {
0484: if (endpointInterfaceName.equals(interfaceType.toString())) {
0485: intTypeDecl = interfaceType.getDeclaration();
0486: seiContext = context.getSEIContext(intTypeDecl
0487: .getQualifiedName());
0488: assert (seiContext != null);
0489: seiContext.setImplementsSEI(true);
0490: break;
0491: }
0492: }
0493: if (intTypeDecl == null) {
0494: intTypeDecl = (InterfaceDeclaration) builder
0495: .getTypeDeclaration(endpointInterfaceName);
0496: }
0497: if (intTypeDecl == null)
0498: builder
0499: .onError(WebserviceapMessages
0500: .WEBSERVICEAP_ENDPOINTINTERFACE_CLASS_NOT_FOUND(endpointInterfaceName));
0501: return intTypeDecl;
0502: }
0503:
0504: private void inspectEndpointInterface(String endpointInterfaceName,
0505: ClassDeclaration d) {
0506: TypeDeclaration intTypeDecl = getEndpointInterfaceDecl(
0507: endpointInterfaceName, d);
0508: if (intTypeDecl != null)
0509: intTypeDecl.accept(this );
0510: }
0511:
0512: public void visitMethodDeclaration(MethodDeclaration method) {
0513: // Methods must be public
0514: if (!method.getModifiers().contains(Modifier.PUBLIC))
0515: return;
0516: if (processedMethod(method))
0517: return;
0518: WebMethod webMethod = method.getAnnotation(WebMethod.class);
0519: if (webMethod != null && webMethod.exclude())
0520: return;
0521: SOAPBinding soapBinding = method
0522: .getAnnotation(SOAPBinding.class);
0523: if (soapBinding == null
0524: && !method.getDeclaringType().equals(typeDecl)) {
0525: if (method.getDeclaringType() instanceof ClassDeclaration) {
0526: soapBinding = method.getDeclaringType().getAnnotation(
0527: SOAPBinding.class);
0528: if (soapBinding != null)
0529: builder.log("using " + method.getDeclaringType()
0530: + "'s SOAPBinding.");
0531: else {
0532: soapBinding = new MySOAPBinding();
0533: }
0534: }
0535: }
0536: boolean newBinding = false;
0537: if (soapBinding != null) {
0538: newBinding = pushSOAPBinding(soapBinding, method, typeDecl);
0539: }
0540: try {
0541: if (shouldProcessMethod(method, webMethod)) {
0542: processMethod(method, webMethod);
0543: }
0544: } finally {
0545: if (newBinding) {
0546: popSOAPBinding();
0547: }
0548: }
0549: }
0550:
0551: protected boolean processedMethod(MethodDeclaration method) {
0552: String id = method.toString();
0553: if (processedMethods.contains(id))
0554: return true;
0555: processedMethods.add(id);
0556: return false;
0557: }
0558:
0559: protected boolean shouldProcessMethod(MethodDeclaration method,
0560: WebMethod webMethod) {
0561: builder.log("should process method: " + method.getSimpleName()
0562: + " hasWebMethods: " + hasWebMethods + " ");
0563: if (hasWebMethods && webMethod == null) {
0564: builder.log("webMethod == null");
0565: return false;
0566: }
0567: boolean retval = (endpointReferencesInterface
0568: || method.getDeclaringType().equals(typeDecl) || (method
0569: .getDeclaringType().getAnnotation(WebService.class) != null));
0570: builder.log("endpointReferencesInterface: "
0571: + endpointReferencesInterface);
0572: builder.log("declaring class has WebSevice: "
0573: + (method.getDeclaringType().getAnnotation(
0574: WebService.class) != null));
0575: builder.log("returning: " + retval);
0576: return retval;
0577: }
0578:
0579: abstract protected void processMethod(MethodDeclaration method,
0580: WebMethod webMethod);
0581:
0582: protected boolean isLegalImplementation(WebService webService,
0583: ClassDeclaration classDecl) {
0584:
0585: boolean isStateful = isStateful(classDecl);
0586:
0587: Collection<Modifier> modifiers = classDecl.getModifiers();
0588: if (!modifiers.contains(Modifier.PUBLIC)) {
0589: builder
0590: .onError(
0591: classDecl.getPosition(),
0592: WebserviceapMessages
0593: .localizableWEBSERVICEAP_WEBSERVICE_CLASS_NOT_PUBLIC(classDecl
0594: .getQualifiedName()));
0595: return false;
0596: }
0597: if (modifiers.contains(Modifier.FINAL) && !isStateful) {
0598: builder
0599: .onError(
0600: classDecl.getPosition(),
0601: WebserviceapMessages
0602: .localizableWEBSERVICEAP_WEBSERVICE_CLASS_IS_FINAL(classDecl
0603: .getQualifiedName()));
0604: return false;
0605: }
0606: if (modifiers.contains(Modifier.ABSTRACT) && !isStateful) {
0607: builder
0608: .onError(
0609: classDecl.getPosition(),
0610: WebserviceapMessages
0611: .localizableWEBSERVICEAP_WEBSERVICE_CLASS_IS_ABSTRACT(classDecl
0612: .getQualifiedName()));
0613: return false;
0614: }
0615: boolean hasDefaultConstructor = false;
0616: for (ConstructorDeclaration constructor : classDecl
0617: .getConstructors()) {
0618: if (constructor.getModifiers().contains(Modifier.PUBLIC)
0619: && constructor.getParameters().size() == 0) {
0620: hasDefaultConstructor = true;
0621: break;
0622: }
0623: }
0624: if (!hasDefaultConstructor && !isStateful) {
0625: if (classDecl.getDeclaringType() != null
0626: && !modifiers.contains(Modifier.STATIC)) {
0627: builder
0628: .onError(
0629: classDecl.getPosition(),
0630: WebserviceapMessages
0631: .localizableWEBSERVICEAP_WEBSERVICE_CLASS_IS_INNERCLASS_NOT_STATIC(classDecl
0632: .getQualifiedName()));
0633: return false;
0634: }
0635:
0636: builder
0637: .onError(
0638: classDecl.getPosition(),
0639: WebserviceapMessages
0640: .localizableWEBSERVICEAP_WEBSERVICE_NO_DEFAULT_CONSTRUCTOR(classDecl
0641: .getQualifiedName()));
0642: return false;
0643: }
0644: if (webService.endpointInterface().length() == 0) {
0645: if (!methodsAreLegal(classDecl))
0646: return false;
0647: } else {
0648: InterfaceDeclaration intfDecl = getEndpointInterfaceDecl(
0649: webService.endpointInterface(), classDecl);
0650: if (!classImplementsSEI(classDecl, intfDecl))
0651: return false;
0652: }
0653:
0654: return true;
0655: }
0656:
0657: private boolean isStateful(ClassDeclaration classDecl) {
0658: return classDecl.getAnnotation(Stateful.class) != null;
0659: }
0660:
0661: protected boolean classImplementsSEI(ClassDeclaration classDecl,
0662: InterfaceDeclaration intfDecl) {
0663: for (InterfaceType interfaceType : classDecl
0664: .getSuperinterfaces()) {
0665: if (interfaceType.getDeclaration().equals(intfDecl))
0666: return true;
0667: }
0668: boolean implements Method;
0669: for (MethodDeclaration method : intfDecl.getMethods()) {
0670: implements Method = false;
0671: for (MethodDeclaration classMethod : classDecl.getMethods()) {
0672: if (sameMethod(method, classMethod)) {
0673: implements Method = true;
0674: break;
0675: }
0676: }
0677: if (!implements Method) {
0678: builder
0679: .onError(
0680: method.getPosition(),
0681: WebserviceapMessages
0682: .localizableWEBSERVICEAP_METHOD_NOT_IMPLEMENTED(
0683: intfDecl
0684: .getSimpleName(),
0685: classDecl
0686: .getSimpleName(),
0687: method));
0688: return false;
0689: }
0690: }
0691: return true;
0692: }
0693:
0694: protected boolean sameMethod(MethodDeclaration method1,
0695: MethodDeclaration method2) {
0696: if (!method1.getSimpleName().equals(method2.getSimpleName()))
0697: return false;
0698: if (!method1.getReturnType().equals(method2.getReturnType()))
0699: return false;
0700: ParameterDeclaration[] params1 = method1.getParameters()
0701: .toArray(new ParameterDeclaration[0]);
0702: ParameterDeclaration[] params2 = method2.getParameters()
0703: .toArray(new ParameterDeclaration[0]);
0704: if (params1.length != params2.length)
0705: return false;
0706: int pos = 0;
0707: for (ParameterDeclaration param1 : method1.getParameters()) {
0708: if (!param1.getType().equals(params2[pos++].getType()))
0709: return false;
0710: }
0711: return true;
0712: }
0713:
0714: protected boolean isLegalSEI(InterfaceDeclaration intf) {
0715: for (FieldDeclaration field : intf.getFields())
0716: if (field.getConstantValue() != null) {
0717: builder
0718: .onError(WebserviceapMessages
0719: .WEBSERVICEAP_SEI_CANNOT_CONTAIN_CONSTANT_VALUES(
0720: intf.getQualifiedName(), field
0721: .getSimpleName()));
0722: return false;
0723: }
0724: if (!methodsAreLegal(intf))
0725: return false;
0726: return true;
0727: }
0728:
0729: protected boolean methodsAreLegal(InterfaceDeclaration intfDecl) {
0730: hasWebMethods = false;
0731: for (MethodDeclaration method : intfDecl.getMethods()) {
0732: if (!isLegalMethod(method, intfDecl))
0733: return false;
0734: }
0735: for (InterfaceType super Intf : intfDecl.getSuperinterfaces()) {
0736: if (!methodsAreLegal(super Intf.getDeclaration()))
0737: return false;
0738: }
0739: return true;
0740: }
0741:
0742: protected boolean methodsAreLegal(ClassDeclaration classDecl) {
0743: hasWebMethods = hasWebMethods(classDecl);
0744: for (MethodDeclaration method : classDecl.getMethods()) {
0745: if (!isLegalMethod(method, classDecl))
0746: return false;
0747: }
0748: ClassType super Class = classDecl.getSuperclass();
0749:
0750: if (!super Class.getDeclaration().getQualifiedName().equals(
0751: JAVA_LANG_OBJECT)
0752: && super Class != null
0753: && !methodsAreLegal(super Class.getDeclaration())) {
0754: return false;
0755: }
0756: return true;
0757: }
0758:
0759: protected boolean isLegalMethod(MethodDeclaration method,
0760: TypeDeclaration typeDecl) {
0761: WebMethod webMethod = method.getAnnotation(WebMethod.class);
0762: //SEI cannot have methods with @WebMethod(exclude=true)
0763: if (typeDecl instanceof InterfaceDeclaration
0764: && webMethod != null && webMethod.exclude())
0765: builder
0766: .onError(
0767: method.getPosition(),
0768: WebserviceapMessages
0769: .localizableWEBSERVICEAP_INVALID_SEI_ANNOTATION_ELEMENT_EXCLUDE(
0770: "exclude=true",
0771: typeDecl.getQualifiedName(),
0772: method.toString()));
0773:
0774: if (hasWebMethods && (webMethod == null))
0775: return true;
0776: if (!hasWebMethods && (webMethod != null)
0777: && webMethod.exclude()) {
0778: return true;
0779: }
0780: if (typeDecl instanceof ClassDeclaration
0781: && method.getModifiers().contains(Modifier.ABSTRACT)) {
0782: builder
0783: .onError(
0784: method.getPosition(),
0785: WebserviceapMessages
0786: .localizableWEBSERVICEAP_WEBSERVICE_METHOD_IS_ABSTRACT(
0787: typeDecl.getQualifiedName(),
0788: method.getSimpleName()));
0789: return false;
0790: }
0791:
0792: if (!isLegalType(method.getReturnType())) {
0793: builder
0794: .onError(
0795: method.getPosition(),
0796: WebserviceapMessages
0797: .localizableWEBSERVICEAP_METHOD_RETURN_TYPE_CANNOT_IMPLEMENT_REMOTE(
0798: typeDecl.getQualifiedName(),
0799: method.getSimpleName(),
0800: method.getReturnType()));
0801: }
0802: boolean isOneway = method.getAnnotation(Oneway.class) != null;
0803: if (isOneway && !isValidOnewayMethod(method, typeDecl))
0804: return false;
0805:
0806: SOAPBinding soapBinding = method
0807: .getAnnotation(SOAPBinding.class);
0808: if (soapBinding != null) {
0809: if (soapBinding.style().equals(SOAPBinding.Style.RPC)) {
0810: builder
0811: .onError(
0812: method.getPosition(),
0813: WebserviceapMessages
0814: .localizableWEBSERVICEAP_RPC_SOAPBINDING_NOT_ALLOWED_ON_METHOD(
0815: typeDecl
0816: .getQualifiedName(),
0817: method.toString()));
0818: }
0819: }
0820:
0821: int paramIndex = 0;
0822: for (ParameterDeclaration parameter : method.getParameters()) {
0823: if (!isLegalParameter(parameter, method, typeDecl,
0824: paramIndex++))
0825: return false;
0826: }
0827:
0828: if (!isDocLitWrapped() && soapStyle.equals(SOAPStyle.DOCUMENT)) {
0829: ParameterDeclaration outParam = getOutParameter(method);
0830: int inParams = getModeParameterCount(method,
0831: WebParam.Mode.IN);
0832: int outParams = getModeParameterCount(method,
0833: WebParam.Mode.OUT);
0834: if (inParams != 1) {
0835: builder
0836: .onError(
0837: method.getPosition(),
0838: WebserviceapMessages
0839: .localizableWEBSERVICEAP_DOC_BARE_AND_NO_ONE_IN(
0840: typeDecl
0841: .getQualifiedName(),
0842: method.toString()));
0843: }
0844: if (method.getReturnType() instanceof VoidType) {
0845: if (outParam == null && !isOneway) {
0846: builder
0847: .onError(
0848: method.getPosition(),
0849: WebserviceapMessages
0850: .localizableWEBSERVICEAP_DOC_BARE_NO_OUT(
0851: typeDecl
0852: .getQualifiedName(),
0853: method.toString()));
0854: }
0855: if (outParams != 1) {
0856: if (!isOneway && outParams != 0)
0857: builder
0858: .onError(
0859: method.getPosition(),
0860: WebserviceapMessages
0861: .localizableWEBSERVICEAP_DOC_BARE_NO_RETURN_AND_NO_OUT(
0862: typeDecl
0863: .getQualifiedName(),
0864: method
0865: .toString()));
0866: }
0867: } else {
0868: if (outParams > 0) {
0869: builder
0870: .onError(
0871: outParam.getPosition(),
0872: WebserviceapMessages
0873: .localizableWEBSERVICEAP_DOC_BARE_RETURN_AND_OUT(
0874: typeDecl
0875: .getQualifiedName(),
0876: method.toString()));
0877: }
0878: }
0879: }
0880: return true;
0881: }
0882:
0883: protected boolean isLegalParameter(ParameterDeclaration param,
0884: MethodDeclaration method, TypeDeclaration typeDecl,
0885: int paramIndex) {
0886: if (!isLegalType(param.getType())) {
0887: builder
0888: .onError(
0889: param.getPosition(),
0890: WebserviceapMessages
0891: .localizableWEBSERVICEAP_METHOD_PARAMETER_TYPES_CANNOT_IMPLEMENT_REMOTE(
0892: typeDecl.getQualifiedName(),
0893: method.getSimpleName(),
0894: param.getSimpleName(),
0895: param.getType().toString()));
0896: return false;
0897: }
0898: TypeMirror holderType;
0899: holderType = builder.getHolderValueType(param.getType());
0900: WebParam webParam = param.getAnnotation(WebParam.class);
0901: WebParam.Mode mode = null;
0902: if (webParam != null)
0903: mode = webParam.mode();
0904:
0905: if (holderType != null) {
0906: if (mode != null && mode == WebParam.Mode.IN)
0907: builder
0908: .onError(
0909: param.getPosition(),
0910: WebserviceapMessages
0911: .localizableWEBSERVICEAP_HOLDER_PARAMETERS_MUST_NOT_BE_IN_ONLY(
0912: typeDecl
0913: .getQualifiedName(),
0914: method.toString(),
0915: paramIndex));
0916: } else if (mode != null && mode != WebParam.Mode.IN) {
0917: builder
0918: .onError(
0919: param.getPosition(),
0920: WebserviceapMessages
0921: .localizableWEBSERVICEAP_NON_IN_PARAMETERS_MUST_BE_HOLDER(
0922: typeDecl.getQualifiedName(),
0923: method.toString(),
0924: paramIndex));
0925: }
0926:
0927: return true;
0928: }
0929:
0930: protected boolean isDocLitWrapped() {
0931: return soapStyle.equals(SOAPStyle.DOCUMENT) && wrapped;
0932: }
0933:
0934: protected boolean isValidOnewayMethod(MethodDeclaration method,
0935: TypeDeclaration typeDecl) {
0936: boolean valid = true;
0937: if (!(method.getReturnType() instanceof VoidType)) {
0938: // this is an error, cannot be Oneway and have a return type
0939: builder
0940: .onError(
0941: method.getPosition(),
0942: WebserviceapMessages
0943: .localizableWEBSERVICEAP_ONEWAY_OPERATION_CANNOT_HAVE_RETURN_TYPE(
0944: typeDecl.getQualifiedName(),
0945: method.toString()));
0946: valid = false;
0947: }
0948: ParameterDeclaration outParam = getOutParameter(method);
0949: if (outParam != null) {
0950: builder.onError(outParam.getPosition(),
0951: WebserviceapMessages
0952: .localizableWEBSERVICEAP_ONEWAY_AND_OUT(
0953: typeDecl.getQualifiedName(), method
0954: .toString()));
0955: valid = false;
0956: }
0957: if (!isDocLitWrapped() && soapStyle.equals(SOAPStyle.DOCUMENT)) {
0958: int inCnt = getModeParameterCount(method, WebParam.Mode.IN);
0959: if (inCnt != 1) {
0960: builder
0961: .onError(
0962: method.getPosition(),
0963: WebserviceapMessages
0964: .localizableWEBSERVICEAP_ONEWAY_AND_NOT_ONE_IN(
0965: typeDecl
0966: .getQualifiedName(),
0967: method.toString()));
0968: valid = false;
0969: }
0970: }
0971: ClassDeclaration exDecl;
0972: for (ReferenceType thrownType : method.getThrownTypes()) {
0973: exDecl = ((ClassType) thrownType).getDeclaration();
0974: if (!builder.isRemoteException(exDecl)) {
0975: builder
0976: .onError(
0977: method.getPosition(),
0978: WebserviceapMessages
0979: .localizableWEBSERVICEAP_ONEWAY_OPERATION_CANNOT_DECLARE_EXCEPTIONS(
0980: typeDecl
0981: .getQualifiedName(),
0982: method.toString(),
0983: exDecl
0984: .getQualifiedName()));
0985: valid = false;
0986: }
0987: }
0988: return valid;
0989: }
0990:
0991: protected int getModeParameterCount(MethodDeclaration method,
0992: WebParam.Mode mode) {
0993: WebParam webParam;
0994: int cnt = 0;
0995: for (ParameterDeclaration param : method.getParameters()) {
0996: webParam = param.getAnnotation(WebParam.class);
0997: if (webParam != null) {
0998: if (webParam.header())
0999: continue;
1000: if (isEquivalentModes(mode, webParam.mode()))
1001: cnt++;
1002: } else {
1003: if (isEquivalentModes(mode, WebParam.Mode.IN)) {
1004: cnt++;
1005: }
1006: }
1007: }
1008: return cnt;
1009: }
1010:
1011: protected boolean isEquivalentModes(WebParam.Mode mode1,
1012: WebParam.Mode mode2) {
1013: if (mode1.equals(mode2))
1014: return true;
1015: assert mode1 == WebParam.Mode.IN || mode1 == WebParam.Mode.OUT;
1016: if (mode1 == WebParam.Mode.IN && mode2 != WebParam.Mode.OUT)
1017: return true;
1018: if (mode1 == WebParam.Mode.OUT && mode2 != WebParam.Mode.IN)
1019: return true;
1020: return false;
1021: }
1022:
1023: protected boolean isHolder(ParameterDeclaration param) {
1024: return builder.getHolderValueType(param.getType()) != null;
1025: }
1026:
1027: protected boolean isLegalType(TypeMirror type) {
1028: if (!(type instanceof DeclaredType))
1029: return true;
1030: return !builder
1031: .isRemote(((DeclaredType) type).getDeclaration());
1032: }
1033:
1034: protected ParameterDeclaration getOutParameter(
1035: MethodDeclaration method) {
1036: WebParam webParam;
1037: for (ParameterDeclaration param : method.getParameters()) {
1038: webParam = param.getAnnotation(WebParam.class);
1039: if (webParam != null && webParam.mode() != WebParam.Mode.IN) {
1040: return param;
1041: }
1042: }
1043: return null;
1044: }
1045:
1046: protected static class MySOAPBinding implements SOAPBinding {
1047: public Style style() {
1048: return SOAPBinding.Style.DOCUMENT;
1049: }
1050:
1051: public Use use() {
1052: return SOAPBinding.Use.LITERAL;
1053: }
1054:
1055: public ParameterStyle parameterStyle() {
1056: return SOAPBinding.ParameterStyle.WRAPPED;
1057: }
1058:
1059: public Class<? extends java.lang.annotation.Annotation> annotationType() {
1060: return SOAPBinding.class;
1061: }
1062: }
1063: }
|