0001: /*
0002: * JBoss, Home of Professional Open Source.
0003: * Copyright 2006, Red Hat Middleware LLC, and individual contributors
0004: * as indicated by the @author tags. See the copyright.txt file in the
0005: * distribution for a full listing of individual contributors.
0006: *
0007: * This is free software; you can redistribute it and/or modify it
0008: * under the terms of the GNU Lesser General Public License as
0009: * published by the Free Software Foundation; either version 2.1 of
0010: * the License, or (at your option) any later version.
0011: *
0012: * This software is distributed in the hope that it will be useful,
0013: * but WITHOUT ANY WARRANTY; without even the implied warranty of
0014: * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
0015: * Lesser General Public License for more details.
0016: *
0017: * You should have received a copy of the GNU Lesser General Public
0018: * License along with this software; if not, write to the Free
0019: * Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA
0020: * 02110-1301 USA, or see the FSF site: http://www.fsf.org.
0021: */
0022: package org.jboss.verifier.strategy;
0023:
0024: // $Id: EJBVerifier21.java 57209 2006-09-26 12:21:57Z dimitris@jboss.org $
0025:
0026: import org.jboss.logging.Logger;
0027: import org.jboss.metadata.BeanMetaData;
0028: import org.jboss.metadata.EntityMetaData;
0029: import org.jboss.metadata.MessageDrivenMetaData;
0030: import org.jboss.metadata.SessionMetaData;
0031: import org.jboss.verifier.Section;
0032:
0033: import java.lang.reflect.Method;
0034: import java.util.Arrays;
0035: import java.util.Iterator;
0036:
0037: /**
0038: * EJB 2.1 bean verifier.
0039: *
0040: * @author <a href="mailto:christoph.jung@infor.de">Christoph G. Jung</a>
0041: * @author Thomas.Diesler@jboss.org
0042: *
0043: * @version $Revision: 57209 $
0044: * @since 02.12.2003
0045: */
0046:
0047: public class EJBVerifier21 extends AbstractEJB2xVerifier {
0048: // provide logging
0049: private static Logger log = Logger.getLogger(EJBVerifier21.class);
0050:
0051: /*
0052: * Constructor
0053: */
0054: public EJBVerifier21(VerificationContext context) {
0055: super (context);
0056: }
0057:
0058: public String getMessageBundle() {
0059: return "EJB21Messages.properties";
0060: }
0061:
0062: /***********************************************************************
0063: *
0064: * IMPLEMENTS VERIFICATION STRATEGY INTERFACE
0065: *
0066: ************************************************************************/
0067: public void checkSession(SessionMetaData session) {
0068: boolean localOrRemoteExists = false;
0069: boolean serviceEndpointExists = false;
0070: boolean verified = false;
0071:
0072: if (!verifyBean(session))
0073: return;
0074:
0075: verified = verifySessionBean(session);
0076:
0077: if (hasRemoteInterfaces(session)) {
0078: // Check remote interfaces
0079: localOrRemoteExists = true;
0080: verified = verified && verifySessionRemote(session);
0081: verified = verified && verifySessionHome(session);
0082: }
0083:
0084: if (hasLocalInterfaces(session)) {
0085: // Check local interfaces
0086: localOrRemoteExists = true;
0087: verified = verified && verifySessionLocal(session);
0088: verified = verified && verifySessionLocalHome(session);
0089: }
0090:
0091: if (hasServiceEndpointInterfaces(session)) {
0092: // Check local interfaces
0093: serviceEndpointExists = true;
0094: verified = verified && verifyServiceEndpoint(session);
0095: }
0096:
0097: // The session bean MUST implement either a remote home and
0098: // remote, or local home and local interface, or the service endpoint
0099: // interface. It MAY implement a
0100: // remote home, remote, local home, local interface or service endpoint
0101: // interface
0102: //
0103: // Spec 7.11.1
0104: //
0105: if (!localOrRemoteExists && !serviceEndpointExists) {
0106: fireSpecViolationEvent(session, new Section("7.11.1"));
0107: verified = false;
0108: }
0109:
0110: if (verified) {
0111: // All OK; full steam ahead
0112: fireBeanVerifiedEvent(session);
0113: }
0114: }
0115:
0116: public void checkEntity(EntityMetaData entity) {
0117: if (entity.isCMP1x()) {
0118: cmp1XVerifier.checkEntity(entity);
0119: } else {
0120: checkBmpOrCmp2Entity(entity);
0121: }
0122: }
0123:
0124: public void checkMessageBean(MessageDrivenMetaData mdb) {
0125: boolean beanVerified = false;
0126:
0127: if (!verifyBean(mdb))
0128: return;
0129:
0130: beanVerified = verifyMessageDrivenBean(mdb);
0131:
0132: if (beanVerified) {
0133: // OK, we're done
0134: fireBeanVerifiedEvent(mdb);
0135: }
0136: }
0137:
0138: private void checkBmpOrCmp2Entity(EntityMetaData entity) {
0139: boolean localOrRemoteExists = false;
0140: boolean verified = false;
0141:
0142: if (!verifyBean(entity))
0143: return;
0144:
0145: if (entity.isCMP()) {
0146: verified = verifyCMPEntityBean(entity);
0147: } else if (entity.isBMP()) {
0148: verified = verifyBMPEntityBean(entity);
0149: }
0150:
0151: if (hasRemoteInterfaces(entity)) {
0152: // Check remote interfaces
0153: localOrRemoteExists = true;
0154: verified = verified && verifyEntityRemote(entity);
0155: verified = verified && verifyEntityHome(entity);
0156: }
0157:
0158: if (hasLocalInterfaces(entity)) {
0159: // Check local interfaces
0160: localOrRemoteExists = true;
0161: verified = verified && verifyEntityLocal(entity);
0162: verified = verified && verifyEntityLocalHome(entity);
0163: }
0164:
0165: verified = verified && verifyPrimaryKey(entity);
0166:
0167: if (!localOrRemoteExists) {
0168: // The entity bean MUST implement either a remote home and
0169: // remote, or local home and local interface. It MAY implement
0170: // a remote home, remote, local home or local interface.
0171: //
0172: // Spec 10.6.1 (CMP) / 12.2.1 (BMP)
0173: //
0174: if (entity.isCMP()) {
0175: fireSpecViolationEvent(entity, new Section("10.6.1"));
0176: verified = false;
0177: } else {
0178: fireSpecViolationEvent(entity, new Section("12.2.1"));
0179: verified = false;
0180: }
0181: }
0182:
0183: if (verified) {
0184: fireBeanVerifiedEvent(entity);
0185: }
0186: }
0187:
0188: /**
0189: * Try to load the beans class declared in the <ejb-class>
0190: * element.
0191: *
0192: * @return <code>true</code> if everything went alright
0193: */
0194: protected boolean verifyBean(BeanMetaData theBean) {
0195: String beanName = theBean.getEjbClass();
0196:
0197: if (beanName == null)
0198: return false;
0199:
0200: try {
0201: bean = classloader.loadClass(beanName);
0202: return true;
0203: } catch (ClassNotFoundException cnfe) {
0204: fireSpecViolationEvent(theBean, new Section("22.2.b",
0205: "Class not found on '" + beanName + "': "
0206: + cnfe.getMessage()));
0207: return false;
0208: }
0209: }
0210:
0211: /**
0212: * Check whether the bean has declared local interfaces and whether
0213: * we can load the defined classes
0214: *
0215: * @return <code>true</code> if everything went alright
0216: */
0217: protected boolean hasRemoteInterfaces(BeanMetaData bean) {
0218: boolean status = true;
0219: String homeName = bean.getHome();
0220: String remoteName = bean.getRemote();
0221:
0222: if (homeName == null || remoteName == null)
0223: return false;
0224:
0225: // Verify the <home> class
0226: try {
0227: home = classloader.loadClass(homeName);
0228: } catch (ClassNotFoundException cnfe) {
0229: fireSpecViolationEvent(bean, new Section("22.2.c",
0230: "Class not found on '" + homeName + "': "
0231: + cnfe.getMessage()));
0232: status = false;
0233: }
0234:
0235: // Verify the <remote> class
0236: try {
0237: remote = classloader.loadClass(remoteName);
0238: } catch (ClassNotFoundException cnfe) {
0239: fireSpecViolationEvent(bean, new Section("22.2.d",
0240: "Class not found on '" + remoteName + "': "
0241: + cnfe.getMessage()));
0242: status = false;
0243: }
0244:
0245: return status;
0246: }
0247:
0248: /**
0249: * Check whether the bean has declared local interfaces and whether
0250: * we can load the defined classes
0251: *
0252: * @return <code>true</code> if everything went alright
0253: */
0254: protected boolean hasLocalInterfaces(BeanMetaData bean) {
0255: boolean status = true;
0256: String localHomeName = bean.getLocalHome();
0257: String localName = bean.getLocal();
0258:
0259: if (localHomeName == null || localName == null)
0260: return false;
0261:
0262: // Verify the <local-home> class
0263: try {
0264: localHome = classloader.loadClass(localHomeName);
0265: } catch (ClassNotFoundException cnfe) {
0266: fireSpecViolationEvent(bean, new Section("22.2.e",
0267: "Class not found on '" + localHomeName + "': "
0268: + cnfe.getMessage()));
0269: status = false;
0270: }
0271:
0272: try {
0273: local = classloader.loadClass(localName);
0274: } catch (ClassNotFoundException cnfe) {
0275: fireSpecViolationEvent(bean, new Section("22.2.f",
0276: "Class not found on '" + localName + "': "
0277: + cnfe.getMessage()));
0278: status = false;
0279: }
0280:
0281: return status;
0282: }
0283:
0284: /**
0285: * Verifies the session bean remote home interface against the EJB 2.1
0286: * specification.
0287: *
0288: * @param session XML metadata of the session bean
0289: */
0290: protected boolean verifySessionHome(SessionMetaData session) {
0291: boolean status = true;
0292:
0293: // The home interface of a stateless session bean MUST have one
0294: // create() method that takes no arguments.
0295: //
0296: // The create() method MUST return the session bean's remote
0297: // interface.
0298: //
0299: // There CAN NOT be other create() methods in the home interface.
0300: //
0301: // Spec 7.11.6
0302: //
0303: if (session.isStateless()) {
0304: if (!hasDefaultCreateMethod(home)) {
0305: fireSpecViolationEvent(session,
0306: new Section("7.11.6.d2"));
0307: status = false;
0308: } else {
0309: Method create = getDefaultCreateMethod(home);
0310:
0311: if (hasMoreThanOneCreateMethods(home)) {
0312: fireSpecViolationEvent(session, new Section(
0313: "7.11.6.d2"));
0314: status = false;
0315: }
0316: }
0317: }
0318:
0319: // The session bean's home interface MUST extend the
0320: // javax.ejb.EJBHome interface.
0321: //
0322: // Spec 7.11.6
0323: //
0324: if (!hasEJBHomeInterface(home)) {
0325: fireSpecViolationEvent(session, new Section("7.11.6.a"));
0326: status = false;
0327: }
0328:
0329: // Method arguments defined in the home interface MUST be
0330: // of valid types for RMI/IIOP.
0331: //
0332: // Method return values defined in the home interface MUST
0333: // be of valid types for RMI/IIOP.
0334: //
0335: // Methods defined in the home interface MUST include
0336: // java.rmi.RemoteException in their throws clause.
0337: //
0338: // Spec 7.11.6
0339: ///
0340: Iterator it = Arrays.asList(home.getMethods()).iterator();
0341: while (it.hasNext()) {
0342: Method method = (Method) it.next();
0343:
0344: if (!hasLegalRMIIIOPArguments(method)) {
0345: fireSpecViolationEvent(session, method, new Section(
0346: "7.11.6.b1"));
0347: status = false;
0348: }
0349:
0350: if (!hasLegalRMIIIOPReturnType(method)) {
0351: fireSpecViolationEvent(session, method, new Section(
0352: "7.11.6.b2"));
0353: status = false;
0354: }
0355:
0356: if (!throwsRemoteException(method)) {
0357: fireSpecViolationEvent(session, method, new Section(
0358: "7.11.6.b3"));
0359: status = false;
0360: }
0361: }
0362:
0363: // A session bean's home interface MUST define one or more
0364: // create(...) methods.
0365: //
0366: // Spec 7.11.6
0367: //
0368: if (!hasCreateMethod(home)) {
0369: fireSpecViolationEvent(session, new Section("7.11.6.d1"));
0370: status = false;
0371: }
0372:
0373: // Each create(...) method in the session bean's home interface
0374: // MUST have a matching ejbCreate(...) method in the session
0375: // bean's class.
0376: //
0377: // Each create(...) method in the session bean's home interface
0378: // MUST have the same number and types of arguments to its
0379: // matching ejbCreate(...) method.
0380: //
0381: // The return type for a create(...) method MUST be the session
0382: // bean's remote interface type.
0383: //
0384: // All the exceptions defined in the throws clause of the matching
0385: // ejbCreate(...) method of the enterprise bean class MUST be
0386: // included in the throws clause of a matching create(...) method.
0387: //
0388: // The throws clause of a create(...) method MUST include the
0389: // javax.ejb.CreateException.
0390: //
0391: // Spec 7.11.6
0392: //
0393: Iterator createMethods = getCreateMethods(home);
0394: while (createMethods.hasNext()) {
0395: Method create = (Method) createMethods.next();
0396:
0397: if (!hasMatchingEJBCreate(bean, create)) {
0398: fireSpecViolationEvent(session, create, new Section(
0399: "7.11.6.e"));
0400: status = false;
0401: }
0402:
0403: if (!hasRemoteReturnType(session, create)) {
0404: fireSpecViolationEvent(session, create, new Section(
0405: "7.11.6.f"));
0406: status = false;
0407: }
0408:
0409: if (hasMatchingEJBCreate(bean, create)) {
0410: Method ejbCreate = getMatchingEJBCreate(bean, create);
0411: if (!hasMatchingExceptions(ejbCreate, create)) {
0412: fireSpecViolationEvent(session, create,
0413: new Section("7.11.6.g"));
0414: status = false;
0415: }
0416: }
0417:
0418: if (!throwsCreateException(create)) {
0419: fireSpecViolationEvent(session, create, new Section(
0420: "7.11.6.h"));
0421: status = false;
0422: }
0423: }
0424:
0425: return status;
0426: }
0427:
0428: /**
0429: * Verifies the session bean local home interface against the EJB 2.1
0430: * specification.
0431: *
0432: * @param session parsed metadata of the session bean
0433: */
0434: protected boolean verifySessionLocalHome(SessionMetaData session) {
0435: boolean status = true;
0436:
0437: // The local home interface of a stateless session bean MUST have
0438: // one create() method that takes no arguments.
0439: //
0440: // There CAN NOT be other create() methods in the home interface.
0441: //
0442: // Spec 7.11.8
0443: //
0444: if (session.isStateless()) {
0445: if (!hasDefaultCreateMethod(localHome)) {
0446: fireSpecViolationEvent(session,
0447: new Section("7.11.8.d2"));
0448: status = false;
0449: } else {
0450: Method create = getDefaultCreateMethod(localHome);
0451:
0452: if (hasMoreThanOneCreateMethods(localHome)) {
0453: fireSpecViolationEvent(session, new Section(
0454: "7.11.8.d2"));
0455: status = false;
0456: }
0457: }
0458: }
0459:
0460: // The session bean's home interface MUST extend the
0461: // javax.ejb.EJBLocalHome interface.
0462: //
0463: // Spec 7.11.8
0464: //
0465: if (!hasEJBLocalHomeInterface(localHome)) {
0466: fireSpecViolationEvent(session, new Section("7.11.8.a"));
0467: status = false;
0468: }
0469:
0470: // Methods defined in the local home interface MUST NOT include
0471: // java.rmi.RemoteException in their throws clause.
0472: //
0473: // Spec 7.11.8
0474: //
0475: Iterator it = Arrays.asList(localHome.getMethods()).iterator();
0476: while (it.hasNext()) {
0477: Method method = (Method) it.next();
0478:
0479: if (throwsRemoteException(method)) {
0480: fireSpecViolationEvent(session, method, new Section(
0481: "7.11.8.b"));
0482: status = false;
0483: }
0484: }
0485:
0486: // A session bean's home interface MUST define one or more
0487: // create(...) methods.
0488: //
0489: // Spec 7.11.8
0490: //
0491: if (!hasCreateMethod(localHome)) {
0492: fireSpecViolationEvent(session, new Section("7.11.8.d1"));
0493: status = false;
0494: }
0495:
0496: // Each create(...) method in the session bean's local home
0497: // interface MUST have a matching ejbCreate(...) method in the
0498: // session bean's class.
0499: //
0500: // Each create(...) method in the session bean's home interface
0501: // MUST have the same number and types of arguments to its
0502: // matching ejbCreate(...) method.
0503: //
0504: // The return type for a create(...) method MUST be the session
0505: // bean's local interface type.
0506: //
0507: // All the exceptions defined in the throws clause of the matching
0508: // ejbCreate(...) method of the enterprise bean class MUST be
0509: // included in the throws clause of a matching create(...) method.
0510: //
0511: // The throws clause of a create(...) method MUST include the
0512: // javax.ejb.CreateException.
0513: //
0514: // Spec 7.11.8
0515: //
0516: Iterator createMethods = getCreateMethods(localHome);
0517: while (createMethods.hasNext()) {
0518: Method create = (Method) createMethods.next();
0519:
0520: if (!hasMatchingEJBCreate(bean, create)) {
0521: fireSpecViolationEvent(session, create, new Section(
0522: "7.11.8.e"));
0523: status = false;
0524: }
0525:
0526: if (!hasLocalReturnType(session, create)) {
0527: fireSpecViolationEvent(session, create, new Section(
0528: "7.11.8.f"));
0529: status = false;
0530: }
0531:
0532: if (hasMatchingEJBCreate(bean, create)) {
0533: Method ejbCreate = getMatchingEJBCreate(bean, create);
0534: if (!hasMatchingExceptions(ejbCreate, create)) {
0535: fireSpecViolationEvent(session, create,
0536: new Section("7.11.8.g"));
0537: }
0538: }
0539:
0540: if (!throwsCreateException(create)) {
0541: fireSpecViolationEvent(session, create, new Section(
0542: "7.11.8.h"));
0543: status = false;
0544: }
0545: }
0546:
0547: return status;
0548: }
0549:
0550: /*
0551: * Verify Session Bean Remote Interface
0552: */
0553: protected boolean verifySessionRemote(SessionMetaData session) {
0554: boolean status = true;
0555:
0556: // The remote interface MUST extend the javax.ejb.EJBObject
0557: // interface.
0558: //
0559: // Spec 7.11.5
0560: //
0561: if (!hasEJBObjectInterface(remote)) {
0562: fireSpecViolationEvent(session, new Section("7.11.5.a"));
0563: status = false;
0564: }
0565:
0566: // Method arguments defined in the remote interface MUST be
0567: // of valid types for RMI/IIOP.
0568: //
0569: // Method return values defined in the remote interface MUST
0570: // be of valid types for RMI/IIOP.
0571: //
0572: // Methods defined in the remote interface MUST include
0573: // java.rmi.RemoteException in their throws clause.
0574: //
0575: // Spec 7.11.5
0576: //
0577: Iterator it = Arrays.asList(remote.getMethods()).iterator();
0578: while (it.hasNext()) {
0579: Method method = (Method) it.next();
0580:
0581: if (!hasLegalRMIIIOPArguments(method)) {
0582: fireSpecViolationEvent(session, method, new Section(
0583: "7.11.5.b1"));
0584: status = false;
0585: }
0586:
0587: if (!hasLegalRMIIIOPReturnType(method)) {
0588: fireSpecViolationEvent(session, method, new Section(
0589: "7.11.5.b2"));
0590: status = false;
0591: }
0592:
0593: if (!throwsRemoteException(method)) {
0594: fireSpecViolationEvent(session, method, new Section(
0595: "7.11.5.b3"));
0596: status = false;
0597: }
0598: }
0599:
0600: // For each method defined in the remote interface, there MUST be
0601: // a matching method in the session bean's class. The matching
0602: // method MUST have:
0603: //
0604: // - the same name
0605: // - the same number and types of arguments, and the same
0606: // return type
0607: // - All the exceptions defined in the throws clause of the
0608: // matching method of the session bean class must be defined
0609: // in the throws clause of the method of the remote interface
0610: //
0611: // Spec 7.11.5
0612: //
0613: it = Arrays.asList(remote.getDeclaredMethods()).iterator();
0614: while (it.hasNext()) {
0615: Method remoteMethod = (Method) it.next();
0616:
0617: if (!hasMatchingMethod(bean, remoteMethod)) {
0618: fireSpecViolationEvent(session, remoteMethod,
0619: new Section("7.11.5.d1"));
0620:
0621: status = false;
0622: }
0623:
0624: if (hasMatchingMethod(bean, remoteMethod)) {
0625: try {
0626: Method beanMethod = bean.getMethod(remoteMethod
0627: .getName(), remoteMethod
0628: .getParameterTypes());
0629:
0630: if (!hasMatchingReturnType(remoteMethod, beanMethod)) {
0631: fireSpecViolationEvent(session, remoteMethod,
0632: new Section("7.11.5.d2"));
0633: status = false;
0634: }
0635:
0636: if (!hasMatchingExceptions(beanMethod, remoteMethod)) {
0637: fireSpecViolationEvent(session, remoteMethod,
0638: new Section("7.11.5.d3"));
0639: status = false;
0640: }
0641: } catch (NoSuchMethodException ignored) {
0642: }
0643: }
0644: }
0645:
0646: return status;
0647: }
0648:
0649: /*
0650: * Verify Session Bean Local Interface
0651: */
0652: protected boolean verifySessionLocal(SessionMetaData session) {
0653: boolean status = true;
0654:
0655: // The local interface MUST extend the javax.ejb.EJBLocalObject
0656: // interface.
0657: //
0658: // Spec 7.11.7
0659: //
0660: if (!hasEJBLocalObjectInterface(local)) {
0661: fireSpecViolationEvent(session, new Section("7.11.7.a"));
0662: status = false;
0663: }
0664:
0665: // Methods defined in the local interface MUST NOT include
0666: // java.rmi.RemoteException in their throws clause.
0667: //
0668: // Spec 7.11.7
0669: //
0670: Iterator it = Arrays.asList(local.getMethods()).iterator();
0671: while (it.hasNext()) {
0672: Method method = (Method) it.next();
0673: if (throwsRemoteException(method)) {
0674: fireSpecViolationEvent(session, method, new Section(
0675: "7.11.7.b"));
0676: status = false;
0677: }
0678: }
0679:
0680: // For each method defined in the local interface, there MUST be
0681: // a matching method in the session bean's class. The matching
0682: // method MUST have:
0683: //
0684: // - the same name
0685: // - the same number and types of arguments, and the same
0686: // return type
0687: // - All the exceptions defined in the throws clause of the
0688: // matching method of the session bean class must be defined
0689: // in the throws clause of the method of the remote interface
0690: //
0691: // Spec 7.11.7
0692: //
0693: it = Arrays.asList(local.getDeclaredMethods()).iterator();
0694: while (it.hasNext()) {
0695: Method localMethod = (Method) it.next();
0696:
0697: if (!hasMatchingMethod(bean, localMethod)) {
0698: fireSpecViolationEvent(session, localMethod,
0699: new Section("7.11.7.d1"));
0700: status = false;
0701: }
0702:
0703: if (hasMatchingMethod(bean, localMethod)) {
0704: try {
0705: Method beanMethod = bean
0706: .getMethod(localMethod.getName(),
0707: localMethod.getParameterTypes());
0708:
0709: if (!hasMatchingReturnType(localMethod, beanMethod)) {
0710: fireSpecViolationEvent(session, localMethod,
0711: new Section("7.11.7.d2"));
0712: status = false;
0713: }
0714:
0715: if (!hasMatchingExceptions(beanMethod, localMethod)) {
0716: fireSpecViolationEvent(session, localMethod,
0717: new Section("7.11.7.d3"));
0718: status = false;
0719: }
0720: } catch (NoSuchMethodException ignored) {
0721: }
0722: }
0723: }
0724:
0725: return status;
0726: }
0727:
0728: /*
0729: * Verify Session Bean
0730: */
0731: protected boolean verifySessionBean(SessionMetaData session) {
0732: boolean status = true;
0733:
0734: // A session bean MUST implement, directly or indirectly,
0735: // javax.ejb.SessionBean interface.
0736: //
0737: // Spec 7.11.2
0738: //
0739: if (!hasSessionBeanInterface(bean)) {
0740: fireSpecViolationEvent(session, new Section("7.11.2.a"));
0741: status = false;
0742: }
0743:
0744: // Only a stateful container-managed transaction demarcation
0745: // session bean MAY implement the SessionSynchronization
0746: // interface.
0747: //
0748: // A stateless Session bean MUST NOT implement the
0749: // SessionSynchronization interface.
0750: //
0751: // Spec 7.5.3
0752: //
0753: if (hasSessionSynchronizationInterface(bean)) {
0754: if (session.isStateless()) {
0755: fireSpecViolationEvent(session, new Section("7.5.3.a"));
0756: status = false;
0757: }
0758:
0759: if (session.isBeanManagedTx()) {
0760: fireSpecViolationEvent(session, new Section("7.5.3.b"));
0761: status = false;
0762: }
0763: }
0764:
0765: //
0766: // A session bean MUST implement AT LEAST one ejbCreate method.
0767: //
0768: // Spec 7.11.3
0769: //
0770: if (!hasEJBCreateMethod(bean, true)) {
0771: fireSpecViolationEvent(session, new Section("7.11.3"));
0772: status = false;
0773: }
0774:
0775: // A session with bean-managed transaction demarcation CANNOT
0776: // implement the SessionSynchronization interface.
0777: //
0778: // Spec 7.6.1 (table 2)
0779: //
0780: if (hasSessionSynchronizationInterface(bean)
0781: && session.isBeanManagedTx()) {
0782: fireSpecViolationEvent(session, new Section("7.6.1"));
0783: status = false;
0784: }
0785:
0786: // The session bean class MUST be defined as public.
0787: //
0788: // Spec 7.11.2
0789: //
0790: if (!isPublic(bean)) {
0791: fireSpecViolationEvent(session, new Section("7.11.2.b1"));
0792: status = false;
0793: }
0794:
0795: // The session bean class MUST NOT be final.
0796: //
0797: // Spec 7.11.2
0798: //
0799: if (isFinal(bean)) {
0800: fireSpecViolationEvent(session, new Section("7.11.2.b2"));
0801: status = false;
0802: }
0803:
0804: // The session bean class MUST NOT be abstract.
0805: //
0806: // Spec 7.11.2
0807: //
0808: if (isAbstract(bean)) {
0809: fireSpecViolationEvent(session, new Section("7.11.2.b3"));
0810: status = false;
0811: }
0812:
0813: // The session bean class MUST have a public constructor that
0814: // takes no arguments.
0815: //
0816: // Spec 7.11.2
0817: //
0818: if (!hasDefaultConstructor(bean)) {
0819: fireSpecViolationEvent(session, new Section("7.11.2.c"));
0820: status = false;
0821: }
0822:
0823: // The session bean class MUST NOT define the finalize() method.
0824: //
0825: // Spec 7.11.2
0826: //
0827: if (hasFinalizer(bean)) {
0828: fireSpecViolationEvent(session, new Section("7.11.2.d"));
0829: status = false;
0830: }
0831:
0832: // The ejbCreate(...) method signatures MUST follow these rules:
0833: //
0834: // - The method name MUST have ejbCreate as its prefix
0835: // - The method MUST be declared as public
0836: // - The method MUST NOT be declared as final or static
0837: // - The return type MUST be void
0838: // - The method arguments MUST be legal types for RMI/IIOP
0839: // - The method SHOULD not throw a java.rmi.RemoteException
0840: // (NOTE we don't test for this as it's not a MUST)
0841: //
0842: // Spec 7.11.3
0843: //
0844: if (hasEJBCreateMethod(bean, true)) {
0845: Iterator it = getEJBCreateMethods(bean);
0846: while (it.hasNext()) {
0847: Method ejbCreate = (Method) it.next();
0848:
0849: if (!isPublic(ejbCreate)) {
0850: fireSpecViolationEvent(session, ejbCreate,
0851: new Section("7.11.3.b"));
0852: status = false;
0853: }
0854:
0855: if ((isFinal(ejbCreate)) || (isStatic(ejbCreate))) {
0856: fireSpecViolationEvent(session, ejbCreate,
0857: new Section("7.11.3.c"));
0858: status = false;
0859: }
0860:
0861: if (!hasVoidReturnType(ejbCreate)) {
0862: fireSpecViolationEvent(session, ejbCreate,
0863: new Section("7.11.3.d"));
0864: status = false;
0865: }
0866:
0867: if (!hasLegalRMIIIOPArguments(ejbCreate)) {
0868: fireSpecViolationEvent(session, ejbCreate,
0869: new Section("7.11.3.e"));
0870: status = false;
0871: }
0872: }
0873: }
0874:
0875: return status;
0876: }
0877:
0878: /*
0879: * Verify Entity Bean Home Interface
0880: */
0881: private boolean verifyEntityHome(EntityMetaData entity) {
0882: boolean status = true;
0883:
0884: // Entity bean's home interface MUST extend the javax.ejb.EJBHome
0885: // interface.
0886: //
0887: // Spec 12.2.9
0888: //
0889: if (!hasEJBHomeInterface(home)) {
0890: fireSpecViolationEvent(entity, new Section("12.2.9.a"));
0891: status = false;
0892: }
0893:
0894: // The methods defined in the entity bean's home interface MUST
0895: // have valid RMI-IIOP argument types.
0896: //
0897: // The methods defined in the entity bean's home interface MUST
0898: // have valid RMI-IIOP return types.
0899: //
0900: // The methods defined in the entity bean's home interface MUST
0901: // have java.rmi.RemoteException in their throws clause.
0902: //
0903: // Spec 12.2.9
0904: //
0905: Iterator methods = Arrays.asList(home.getMethods()).iterator();
0906: while (methods.hasNext()) {
0907: Method method = (Method) methods.next();
0908:
0909: if (!hasLegalRMIIIOPArguments(method)) {
0910: fireSpecViolationEvent(entity, method, new Section(
0911: "12.2.9.b1"));
0912: status = false;
0913: }
0914:
0915: if (!hasLegalRMIIIOPReturnType(method)) {
0916: fireSpecViolationEvent(entity, method, new Section(
0917: "12.2.9.b2"));
0918: status = false;
0919: }
0920:
0921: if (!throwsRemoteException(method)) {
0922: fireSpecViolationEvent(entity, method, new Section(
0923: "12.2.9.b3"));
0924: status = false;
0925: }
0926: }
0927:
0928: // Each method defined in the entity bean's home interface must be
0929: // one of the following:
0930: //
0931: // - a create method
0932: // - a finder method
0933: // - a home method
0934: //
0935: // Spec 12.2.9
0936: //
0937: methods = Arrays.asList(home.getMethods()).iterator();
0938: while (methods.hasNext()) {
0939: Method method = (Method) methods.next();
0940:
0941: // Do not check the methods of the javax.ejb.EJBHome interface
0942: if (method.getDeclaringClass().getName().equals(
0943: EJB_HOME_INTERFACE))
0944: continue;
0945:
0946: if (isCreateMethod(method)) {
0947: // Each create(...) method in the entity bean's home
0948: // interface MUST have a matching ejbCreate(...) method in
0949: // the entity bean's class.
0950: //
0951: // Each create(...) method in the entity bean's home
0952: // interface MUST have the same number and types of
0953: // arguments to its matching ejbCreate(...) method.
0954: //
0955: // The return type for a create(...) method MUST be the
0956: // entity bean's remote interface type.
0957: //
0958: // All the exceptions defined in the throws clause of the
0959: // matching ejbCreate(...) and ejbPostCreate(...) methods of
0960: // the enterprise bean class MUST be included in the throws
0961: // clause of a matching create(...) method.
0962: //
0963: // The throws clause of a create(...) method MUST include
0964: // the javax.ejb.CreateException.
0965: //
0966: // Spec 12.2.9
0967: //
0968: if (!hasMatchingEJBCreate(bean, method)) {
0969: fireSpecViolationEvent(entity, method, new Section(
0970: "12.2.9.d"));
0971: status = false;
0972: }
0973:
0974: if (!hasRemoteReturnType(entity, method)) {
0975: fireSpecViolationEvent(entity, method, new Section(
0976: "12.2.9.e"));
0977: status = false;
0978: }
0979:
0980: if (hasMatchingEJBCreate(bean, method)
0981: && hasMatchingEJBPostCreate(bean, method)) {
0982: Method ejbCreate = getMatchingEJBCreate(bean,
0983: method);
0984: Method ejbPostCreate = getMatchingEJBPostCreate(
0985: bean, method);
0986:
0987: if (!(hasMatchingExceptions(ejbCreate, method) && hasMatchingExceptions(
0988: ejbPostCreate, method))) {
0989: fireSpecViolationEvent(entity, method,
0990: new Section("12.2.9.f"));
0991: }
0992: }
0993:
0994: if (!throwsCreateException(method)) {
0995: fireSpecViolationEvent(entity, method, new Section(
0996: "12.2.9.g"));
0997: status = false;
0998: }
0999: } else if (isFinderMethod(method)) {
1000: // Each finder method MUST match one of the ejbFind<METHOD>
1001: // methods defined in the entity bean class.
1002: //
1003: // The matching ejbFind<METHOD> method MUST have the same
1004: // number and types of arguments.
1005: //
1006: // The return type for a find<METHOD> method MUST be the
1007: // entity bean's remote interface type (single-object
1008: // finder) or a collection thereof (for a multi-object
1009: // finder).
1010: //
1011: // All the exceptions defined in the throws clause of an
1012: // ejbFind method of the entity bean class MUST be included
1013: // in the throws clause of the matching find method of the
1014: // home interface.
1015: //
1016: // The throws clause of a finder method MUST include the
1017: // javax.ejb.FinderException.
1018: //
1019: // Spec 12.2.9
1020: //
1021: if (entity.isBMP()) { // Check for BMP violations
1022: if ((!hasMatchingEJBFind(bean, method))) {
1023: fireSpecViolationEvent(entity, method,
1024: new Section("12.2.9.h"));
1025: status = false;
1026: }
1027:
1028: if (!(hasRemoteReturnType(entity, method) || isMultiObjectFinder(method))) {
1029: fireSpecViolationEvent(entity, method,
1030: new Section("12.2.9.j"));
1031: status = false;
1032: }
1033:
1034: if ((hasMatchingEJBFind(bean, method))) {
1035: Method ejbFind = getMatchingEJBFind(bean,
1036: method);
1037: if (!(hasMatchingExceptions(ejbFind, method))) {
1038: fireSpecViolationEvent(entity, method,
1039: new Section("12.2.9.k"));
1040: status = false;
1041: }
1042: }
1043:
1044: if (!throwsFinderException(method)) {
1045: fireSpecViolationEvent(entity, method,
1046: new Section("12.2.9.l"));
1047: status = false;
1048: }
1049: } // if( entity.isBMP() )
1050:
1051: if (entity.isCMP()) {
1052:
1053: if (!(hasRemoteReturnType(entity, method) || isMultiObjectFinder(method))) {
1054: fireSpecViolationEvent(entity, method,
1055: new Section("10.6.10.a"));
1056: status = false;
1057: }
1058:
1059: if (!throwsFinderException(method)) {
1060: fireSpecViolationEvent(entity, method,
1061: new Section("10.6.10.b"));
1062: status = false;
1063: }
1064:
1065: // For every finder method there must be a matching
1066: // <query> element defined in the deployment descriptor
1067: // with the exception of findByPrimaryKey
1068: //
1069: // JBoss Extension: 'findAll' is _also_ ignored.
1070: //
1071: if (!method.getName().equals("findByPrimaryKey")
1072: && !method.getName().equals("findAll")
1073: && !hasMatchingQuery(method, entity)) {
1074: fireSpecViolationEvent(entity, method,
1075: new Section("10.5.6"));
1076: status = false;
1077: }
1078: } // if( entity.isCMP() )
1079: } else // Neither Create nor Finder method
1080: {
1081: // Each home method MUST match a method defined in the
1082: // entity bean class.
1083: //
1084: // The matching ejbHome<METHOD> method MUST have the same
1085: // number and types of arguments, and a matching return
1086: // type.
1087: //
1088: // Spec 12.2.9
1089: //
1090: if (!hasMatchingEJBHome(bean, method)) {
1091: fireSpecViolationEvent(entity, method, new Section(
1092: "12.2.9.m"));
1093: status = false;
1094: }
1095: }
1096: } // while( methods.hasNext() )
1097:
1098: return status;
1099: }
1100:
1101: /*
1102: * Verify Entity Bean Local Home Interface
1103: */
1104: private boolean verifyEntityLocalHome(EntityMetaData entity) {
1105: boolean status = true;
1106:
1107: // Entity bean's local home interface MUST extend the
1108: // javax.ejb.EJBLocalHome interface.
1109: //
1110: // Spec 12.2.11
1111: //
1112: if (!hasEJBLocalHomeInterface(localHome)) {
1113: fireSpecViolationEvent(entity, new Section("12.2.11.a"));
1114: status = false;
1115: }
1116:
1117: // The methods defined in the entity bean's home interface MUST
1118: // NOT have java.rmi.RemoteException in their throws clause.
1119: //
1120: // Spec 12.2.11
1121: //
1122: Iterator homeMethods = Arrays.asList(localHome.getMethods())
1123: .iterator();
1124: while (homeMethods.hasNext()) {
1125: Method method = (Method) homeMethods.next();
1126:
1127: if (throwsRemoteException(method)) {
1128: fireSpecViolationEvent(entity, method, new Section(
1129: "12.2.11.b"));
1130: status = false;
1131: }
1132: }
1133:
1134: // Each method defined in the entity bean's local home interface
1135: // must be one of the following:
1136: //
1137: // - a create method
1138: // - a finder method
1139: // - a home method
1140: //
1141: // Spec 12.2.11
1142: //
1143: homeMethods = Arrays.asList(localHome.getMethods()).iterator();
1144: while (homeMethods.hasNext()) {
1145: Method method = (Method) homeMethods.next();
1146:
1147: // Do not check the methods of the javax.ejb.EJBLocalHome interface
1148: if (method.getDeclaringClass().getName().equals(
1149: EJB_LOCAL_HOME_INTERFACE))
1150: continue;
1151:
1152: if (isCreateMethod(method)) {
1153: // Each create(...) method in the entity bean's local home
1154: // interface MUST have a matching ejbCreate(...) method in
1155: // the entity bean's class.
1156: //
1157: // Each create(...) method in the entity bean's local home
1158: // interface MUST have the same number and types of
1159: // arguments to its matching ejbCreate(...) method.
1160: //
1161: // The return type for a create(...) method MUST be the
1162: // entity bean's local interface type.
1163: //
1164: // All the exceptions defined in the throws clause of the
1165: // matching ejbCreate(...) and ejbPostCreate(...) methods of
1166: // the enterprise bean class MUST be included in the throws
1167: // clause of a matching create(...) method.
1168: //
1169: // The throws clause of a create(...) method MUST include
1170: // the javax.ejb.CreateException.
1171: //
1172: // Spec 12.2.11
1173: //
1174: if (!hasMatchingEJBCreate(bean, method)) {
1175: fireSpecViolationEvent(entity, method, new Section(
1176: "12.2.11.e"));
1177: status = false;
1178: }
1179:
1180: if (!hasLocalReturnType(entity, method)) {
1181: fireSpecViolationEvent(entity, method, new Section(
1182: "12.2.11.f"));
1183: status = false;
1184: }
1185:
1186: if (hasMatchingEJBCreate(bean, method)
1187: && hasMatchingEJBPostCreate(bean, method)) {
1188: Method ejbCreate = getMatchingEJBCreate(bean,
1189: method);
1190: Method ejbPostCreate = getMatchingEJBPostCreate(
1191: bean, method);
1192:
1193: if (!(hasMatchingExceptions(ejbCreate, method) && hasMatchingExceptions(
1194: ejbPostCreate, method))) {
1195: fireSpecViolationEvent(entity, method,
1196: new Section("12.2.11.g"));
1197: }
1198: }
1199:
1200: if (!throwsCreateException(method)) {
1201: fireSpecViolationEvent(entity, method, new Section(
1202: "12.2.11.h"));
1203: status = false;
1204: }
1205: } else if (isFinderMethod(method)) {
1206: // Each finder method MUST match one of the ejbFind<METHOD>
1207: // methods defined in the entity bean class.
1208: //
1209: // The matching ejbFind<METHOD> method MUST have the same
1210: // number and types of arguments.
1211: //
1212: // The return type for a find<METHOD> method MUST be the
1213: // entity bean's local interface type (single-object finder)
1214: // or a collection thereof (for a multi-object finder).
1215: //
1216: // All the exceptions defined in the throws clause of an
1217: // ejbFind method of the entity bean class MUST be included
1218: // in the throws clause of the matching find method of the
1219: // home interface.
1220: //
1221: // The throws clause of a finder method MUST include the
1222: // javax.ejb.FinderException.
1223: //
1224: // Spec 12.2.11
1225: //
1226: if (!(hasLocalReturnType(entity, method) || isMultiObjectFinder(method))) {
1227: fireSpecViolationEvent(entity, method, new Section(
1228: "12.2.11.j"));
1229: status = false;
1230: }
1231:
1232: if (!throwsFinderException(method)) {
1233: fireSpecViolationEvent(entity, method, new Section(
1234: "12.2.11.k"));
1235: status = false;
1236: }
1237:
1238: if (entity.isCMP()) {
1239: // The entity bean class does not implement the finder
1240: // methods. The implementation of the finder methods are
1241: // provided by the Container
1242: //
1243: // Spec 10.6.2
1244: //
1245: if (hasMatchingEJBFind(bean, method)) {
1246: fireSpecViolationEvent(entity, method,
1247: new Section("10.6.2.j"));
1248: status = false;
1249: }
1250:
1251: // For every finder method there must be a matching
1252: // <query> element defined in the deployment descriptor
1253: // with the exception of findByPrimaryKey
1254: //
1255: // JBoss Extension: 'findAll' is _also_ ignored.
1256: //
1257: // Spec 10.5.6
1258: //
1259: if (!method.getName().equals("findByPrimaryKey")
1260: && !method.getName().equals("findAll")
1261: && !hasMatchingQuery(method, entity)) {
1262: fireSpecViolationEvent(entity, method,
1263: new Section("10.5.6"));
1264: status = false;
1265: }
1266: }
1267:
1268: if (entity.isBMP()) {
1269: if (!hasMatchingEJBFind(bean, method)) {
1270: fireSpecViolationEvent(entity, method,
1271: new Section("12.2.11.i"));
1272: status = false;
1273: } else {
1274: Method ejbFind = getMatchingEJBFind(bean,
1275: method);
1276:
1277: if (!(hasMatchingExceptions(ejbFind, method))) {
1278: fireSpecViolationEvent(entity, method,
1279: new Section("12.2.11.l"));
1280: }
1281: }
1282: }
1283: } else {
1284: // Each home method MUST match a method defined in the
1285: // entity bean class.
1286: //
1287: // The matching ejbHome<METHOD> method MUST have the same
1288: // number and types of arguments, and a matching return
1289: // type.
1290: //
1291: // Spec 12.2.9
1292: //
1293: if (!hasMatchingEJBHome(bean, method)) {
1294: fireSpecViolationEvent(entity, method, new Section(
1295: "12.2.11.m"));
1296: status = false;
1297: }
1298: }
1299: } // while( homeMethods.hasNext() )
1300:
1301: return status;
1302: }
1303:
1304: /*
1305: * Verify Entity Bean Local Interface
1306: */
1307: private boolean verifyEntityLocal(EntityMetaData entity) {
1308: boolean status = true;
1309:
1310: // Entity bean's local interface MUST extend
1311: // the javax.ejb.EJBLocalObject interface.
1312: //
1313: // Spec 12.2.10
1314: //
1315: if (!hasEJBLocalObjectInterface(local)) {
1316: fireSpecViolationEvent(entity, new Section("12.2.10.a"));
1317: status = false;
1318: }
1319:
1320: // The methods defined in the entity bean's local interface MUST
1321: // NOT have java.rmi.RemoteException in their throws clause.
1322: //
1323: // Spec 12.2.10
1324: //
1325: Iterator localMethods = Arrays.asList(local.getMethods())
1326: .iterator();
1327: while (localMethods.hasNext()) {
1328: Method method = (Method) localMethods.next();
1329:
1330: if (throwsRemoteException(method)) {
1331: fireSpecViolationEvent(entity, method, new Section(
1332: "12.2.10.b"));
1333: status = false;
1334: }
1335: }
1336:
1337: // For each method defined in the local interface, there MUST be
1338: // a matching method in the entity bean's class. The matching
1339: // method MUST have:
1340: //
1341: // - The same name.
1342: // - The same number and types of its arguments.
1343: // - The same return type.
1344: // - All the exceptions defined in the throws clause of the
1345: // matching method of the enterprise Bean class must be
1346: // defined in the throws clause of the method of the local
1347: // interface.
1348: //
1349: // Spec 12.2.10
1350: //
1351: localMethods = Arrays.asList(local.getMethods()).iterator();
1352: while (localMethods.hasNext()) {
1353: Method method = (Method) localMethods.next();
1354:
1355: // Do not check the methods of the javax.ejb.EJBLocalObject
1356: // interface
1357: if (method.getDeclaringClass().getName().equals(
1358: EJB_LOCAL_OBJECT_INTERFACE))
1359: continue;
1360:
1361: if (!hasMatchingMethod(bean, method)) {
1362: fireSpecViolationEvent(entity, method, new Section(
1363: "12.2.10.c"));
1364: status = false;
1365: }
1366:
1367: if (hasMatchingMethod(bean, method)) {
1368: try {
1369: Method beanMethod = bean.getMethod(
1370: method.getName(), method
1371: .getParameterTypes());
1372:
1373: if (!hasMatchingReturnType(beanMethod, method)) {
1374: fireSpecViolationEvent(entity, method,
1375: new Section("12.2.10.d"));
1376: status = false;
1377: }
1378:
1379: if (!hasMatchingExceptions(beanMethod, method)) {
1380: fireSpecViolationEvent(entity, method,
1381: new Section("12.2.10.e"));
1382:
1383: status = false;
1384: }
1385: } catch (NoSuchMethodException ignored) {
1386: }
1387: }
1388: }
1389:
1390: return status;
1391: }
1392:
1393: /*
1394: * Verify Entity Bean Remote Interface
1395: */
1396: private boolean verifyEntityRemote(EntityMetaData entity) {
1397: boolean status = true;
1398:
1399: // Entity bean's remote interface MUST extend
1400: // the javax.ejb.EJBObject interface.
1401: //
1402: // Spec 9.2.7
1403: //
1404: if (!hasEJBObjectInterface(remote)) {
1405: fireSpecViolationEvent(entity, new Section("9.2.7.a"));
1406: status = false;
1407: }
1408:
1409: // The methods defined in the entity bean's remote interface MUST
1410: // have valid RMI-IIOP argument types.
1411: //
1412: // The methods defined in the entity bean's home interface MUST
1413: // have valid RMI-IIOP return types.
1414: //
1415: // The methods defined in the entity bean's home interface MUST
1416: // have java.rmi.RemoteException in their throws clause.
1417: //
1418: // Spec 9.2.7
1419: //
1420: Iterator it = Arrays.asList(remote.getMethods()).iterator();
1421: while (it.hasNext()) {
1422: Method method = (Method) it.next();
1423:
1424: if (!hasLegalRMIIIOPArguments(method)) {
1425: fireSpecViolationEvent(entity, method, new Section(
1426: "9.2.7.b"));
1427: status = false;
1428: }
1429:
1430: if (!hasLegalRMIIIOPReturnType(method)) {
1431: fireSpecViolationEvent(entity, method, new Section(
1432: "9.2.7.c"));
1433: status = false;
1434: }
1435:
1436: if (!hasLegalRMIIIOPExceptionTypes(method)) {
1437: fireSpecViolationEvent(entity, method, new Section(
1438: "9.2.7.h"));
1439: status = false;
1440: }
1441:
1442: if (!throwsRemoteException(method)) {
1443: fireSpecViolationEvent(entity, method, new Section(
1444: "9.2.7.d"));
1445: status = false;
1446: }
1447: }
1448:
1449: // For each method defined in the remote interface, there MUST be
1450: // a matching method in the entity bean's class. The matching
1451: // method MUST have:
1452: //
1453: // - The same name.
1454: // - The same number and types of its arguments.
1455: // - The same return type.
1456: // - All the exceptions defined in the throws clause of the
1457: // matching method of the enterprise Bean class must be
1458: // defined in the throws clause of the method of the remote
1459: // interface.
1460: //
1461: // Spec 9.2.7
1462: //
1463: it = Arrays.asList(remote.getMethods()).iterator();
1464: while (it.hasNext()) {
1465: Method method = (Method) it.next();
1466:
1467: // Do not check the methods of the javax.ejb.EJBObject interface
1468: if (method.getDeclaringClass().getName().equals(
1469: EJB_OBJECT_INTERFACE))
1470: continue;
1471:
1472: if (!hasMatchingMethod(bean, method)) {
1473: fireSpecViolationEvent(entity, method, new Section(
1474: "9.2.7.e"));
1475: status = false;
1476: }
1477:
1478: if (hasMatchingMethod(bean, method)) {
1479: try {
1480: Method beanMethod = bean.getMethod(
1481: method.getName(), method
1482: .getParameterTypes());
1483:
1484: if (!hasMatchingReturnType(beanMethod, method)) {
1485: fireSpecViolationEvent(entity, method,
1486: new Section("9.2.7.f"));
1487: status = false;
1488: }
1489:
1490: if (!hasMatchingExceptions(beanMethod, method)) {
1491: fireSpecViolationEvent(entity, method,
1492: new Section("9.2.7.g"));
1493: status = false;
1494: }
1495: } catch (NoSuchMethodException ignored) {
1496: }
1497: }
1498: }
1499:
1500: return status;
1501: }
1502:
1503: /*
1504: * Verify Entity Bean Class
1505: */
1506: private boolean verifyCMPEntityBean(EntityMetaData entity) {
1507: boolean status = true;
1508:
1509: // The enterprise bean class MUST implement, directly or
1510: // indirectly, the javax.ejb.EntityBean interface.
1511: //
1512: // Spec 10.6.2
1513: //
1514: if (!hasEntityBeanInterface(bean)) {
1515: fireSpecViolationEvent(entity, new Section("10.6.2.a"));
1516: status = false;
1517: }
1518:
1519: // The entity bean class MUST be defined as public and abstract.
1520: //
1521: // Spec 10.6.2
1522: //
1523: if (!isPublic(bean) || !isAbstract(bean)) {
1524: fireSpecViolationEvent(entity, new Section("10.6.2.b"));
1525: status = false;
1526: }
1527:
1528: // The entity bean class MUST define a public constructor that
1529: // takes no arguments
1530: //
1531: // Spec 10.6.2
1532: //
1533: if (!hasDefaultConstructor(bean)) {
1534: fireSpecViolationEvent(entity, new Section("10.6.2.c"));
1535: status = false;
1536: }
1537:
1538: // The entity bean class MUST NOT define the finalize() method.
1539: //
1540: // Spec 10.6.2
1541: //
1542: if (hasFinalizer(bean)) {
1543: fireSpecViolationEvent(entity, new Section("10.6.2.d"));
1544: status = false;
1545: }
1546:
1547: // The ejbCreate(...) method signatures MUST follow these rules:
1548: //
1549: // - The method MUST be declared as public
1550: // - The method MUST NOT be declared as final or static
1551: // - The return type MUST be the entity bean's primary key type
1552: // --- Only if method is on remote home ---
1553: // - The method arguments MUST be legal types for RMI/IIOP
1554: // - The method return value type MUST be legal type for RMI/IIOP
1555: // --- End of only if method is on remote home ---
1556: // - The method must define the javax.ejb.CreateException
1557: //
1558: // Spec 10.6.4
1559: //
1560: if (hasEJBCreateMethod(bean, false)) {
1561: Iterator it = getEJBCreateMethods(bean);
1562: while (it.hasNext()) {
1563: Method ejbCreate = (Method) it.next();
1564: if (!isPublic(ejbCreate)) {
1565: fireSpecViolationEvent(entity, ejbCreate,
1566: new Section("10.6.4.b"));
1567: status = false;
1568: }
1569:
1570: if ((isFinal(ejbCreate)) || (isStatic(ejbCreate))) {
1571: fireSpecViolationEvent(entity, ejbCreate,
1572: new Section("10.6.4.c"));
1573: status = false;
1574: }
1575:
1576: if (!hasPrimaryKeyReturnType(entity, ejbCreate)) {
1577: fireSpecViolationEvent(entity, ejbCreate,
1578: new Section("10.6.4.d"));
1579: status = false;
1580: }
1581:
1582: /* FIXME
1583: * This is only true if the method is on the remote home
1584: * interface
1585: if (!hasLegalRMIIIOPArguments(ejbCreate)) {
1586: fireSpecViolationEvent(entity, ejbCreate, new Section("10.6.4.d"));
1587: status = false;
1588: }
1589:
1590: if (!hasLegalRMIIIOPReturnType(ejbCreate)) {
1591: fireSpecViolationEvent(entity, ejbCreate, new Section("10.5.4.f"));
1592: status = false;
1593: }
1594: */
1595:
1596: if (!throwsCreateException(ejbCreate)) {
1597: fireSpecViolationEvent(entity, ejbCreate,
1598: new Section("10.6.4.g"));
1599: status = false;
1600: }
1601: }
1602: }
1603:
1604: // For each ejbCreate(...) method, the entity bean class MUST
1605: // define a matching ejbPostCreate(...) method.
1606: //
1607: // The ejbPostCreate(...) method MUST follow these rules:
1608: //
1609: // - the method MUST be declared as public
1610: // - the method MUST NOT be declared as final or static
1611: // - the return type MUST be void
1612: // - the method arguments MUST be the same as the matching
1613: // ejbCreate(...) method
1614: //
1615: // Spec 10.6.5
1616: //
1617: if (hasEJBCreateMethod(bean, false)) {
1618: Iterator it = getEJBCreateMethods(bean);
1619:
1620: while (it.hasNext()) {
1621: Method ejbCreate = (Method) it.next();
1622:
1623: if (!hasMatchingEJBPostCreate(bean, ejbCreate)) {
1624: fireSpecViolationEvent(entity, ejbCreate,
1625: new Section("10.6.5.a"));
1626: status = false;
1627: }
1628:
1629: if (hasMatchingEJBPostCreate(bean, ejbCreate)) {
1630: Method ejbPostCreate = getMatchingEJBPostCreate(
1631: bean, ejbCreate);
1632:
1633: if (!isPublic(ejbPostCreate)) {
1634: fireSpecViolationEvent(entity, ejbPostCreate,
1635: new Section("10.6.5.b"));
1636: status = false;
1637: }
1638:
1639: if (isStatic(ejbPostCreate)) {
1640: fireSpecViolationEvent(entity, ejbPostCreate,
1641: new Section("10.6.5.c"));
1642: status = false;
1643: }
1644:
1645: if (isFinal(ejbPostCreate)) {
1646: fireSpecViolationEvent(entity, ejbPostCreate,
1647: new Section("10.6.5.d"));
1648: status = false;
1649: }
1650:
1651: if (!hasVoidReturnType(ejbPostCreate)) {
1652: fireSpecViolationEvent(entity, ejbPostCreate,
1653: new Section("10.6.5.e"));
1654: status = false;
1655: }
1656: }
1657: }
1658: }
1659:
1660: // The ejbHome(...) method signatures MUST follow these rules:
1661: //
1662: // - The method name MUST have ejbHome as its prefix.
1663: // - The method MUST be declared as public
1664: // - The method MUST NOT be declared as static.
1665: // - The method MUST NOT define the java.rmi.RemoteException
1666: //
1667: // Spec 10.6.6
1668: //
1669: Iterator it = getEjbHomeMethods(bean);
1670: while (it.hasNext()) {
1671: Method ejbHome = (Method) it.next();
1672: if (!isPublic(ejbHome)) {
1673: fireSpecViolationEvent(entity, ejbHome, new Section(
1674: "10.6.6.a"));
1675: status = false;
1676: }
1677:
1678: if (isStatic(ejbHome)) {
1679: fireSpecViolationEvent(entity, ejbHome, new Section(
1680: "10.6.6.b"));
1681: status = false;
1682: }
1683:
1684: if (throwsRemoteException(ejbHome)) {
1685: fireSpecViolationEvent(entity, ejbHome, new Section(
1686: "10.6.6.c"));
1687: status = false;
1688: }
1689: }
1690:
1691: // The CMP entity bean MUST implement get and set accessor methods for
1692: // each field within the abstract persistance schema.
1693: //
1694: // Spec 10.6.2
1695: //
1696: it = entity.getCMPFields();
1697: while (it.hasNext()) {
1698: String fieldName = (String) it.next();
1699: String getName = "get"
1700: + fieldName.substring(0, 1).toUpperCase()
1701: + fieldName.substring(1);
1702: Class fieldType = null;
1703:
1704: try {
1705: Method m = bean.getMethod(getName, new Class[0]);
1706: fieldType = m.getReturnType();
1707:
1708: // The getter must not return 'void' according to the JavaBeans
1709: // Spec
1710: if (fieldType == Void.TYPE) {
1711: fireSpecViolationEvent(entity, new Section(
1712: "jb.7.1.b", "Field: " + fieldName));
1713: }
1714: } catch (NoSuchMethodException nsme) {
1715: fireSpecViolationEvent(entity, new Section("10.6.2.g",
1716: "Field: " + fieldName));
1717: status = false;
1718: }
1719:
1720: String setName = "set"
1721: + fieldName.substring(0, 1).toUpperCase()
1722: + fieldName.substring(1);
1723: Class[] args = new Class[1];
1724: args[0] = fieldType;
1725:
1726: try {
1727: Method m = bean.getMethod(setName, args);
1728: fieldType = m.getReturnType();
1729:
1730: // According to the JavaBeans Spec, a setter method must
1731: // return 'void'
1732: if (fieldType != Void.TYPE) {
1733: fireSpecViolationEvent(entity, new Section(
1734: "jb.7.1.a", "Field: " + fieldName));
1735: }
1736: } catch (NoSuchMethodException nsme) {
1737: // Try with java.util.Collection
1738: //
1739: // FIXME: This should only be tried for CMR methods; a CMP
1740: // setter cannot accept a Collection!
1741: try {
1742: args[0] = classloader
1743: .loadClass("java.util.Collection");
1744: Method m = bean.getMethod(setName, args);
1745: } catch (NoSuchMethodException nsme2) {
1746: fireSpecViolationEvent(entity, new Section(
1747: "10.6.2.h", "Field: " + fieldName));
1748: status = false;
1749: } catch (ClassNotFoundException cnfe) {
1750: // Something is really broken
1751: }
1752: }
1753: }
1754:
1755: // The ejbSelect(...) method signatures MUST follow these rules:
1756: //
1757: // - The method name MUST have ejbSelect as its prefix.
1758: // - The method MUST be declared as public
1759: // - The method MUST be declared as abstract.
1760: // - The method MUST define the javax.ejb.FinderException
1761: //
1762: // Spec 10.6.7
1763: //
1764: it = getEjbSelectMethods(bean);
1765: while (it.hasNext()) {
1766: Method ejbSelect = (Method) it.next();
1767:
1768: if (!isPublic(ejbSelect)) {
1769: fireSpecViolationEvent(entity, ejbSelect, new Section(
1770: "10.6.7.a"));
1771: status = false;
1772: }
1773:
1774: if (!isAbstract(ejbSelect)) {
1775: fireSpecViolationEvent(entity, ejbSelect, new Section(
1776: "10.6.7.b"));
1777: status = false;
1778: }
1779:
1780: if (!throwsFinderException(ejbSelect)) {
1781: fireSpecViolationEvent(entity, ejbSelect, new Section(
1782: "10.6.7.c"));
1783: status = false;
1784: }
1785:
1786: if (!hasMatchingQuery(ejbSelect, entity)) {
1787: fireSpecViolationEvent(entity, ejbSelect, new Section(
1788: "10.5.7"));
1789: status = false;
1790: }
1791: }
1792:
1793: // A CMP Entity Bean must not define Finder methods.
1794: //
1795: // Spec 10.6.2
1796: //
1797: if (hasFinderMethod(bean)) {
1798: fireSpecViolationEvent(entity, new Section("10.6.2.i"));
1799: status = false;
1800: }
1801:
1802: return status;
1803: }
1804:
1805: /*
1806: * Verify BMP Entity Class
1807: */
1808: private boolean verifyBMPEntityBean(EntityMetaData entity) {
1809: boolean status = true;
1810:
1811: // The enterprise bean class MUST implement, directly or
1812: // indirectly, the javax.ejb.EntityBean interface.
1813: //
1814: // Spec 12.2.2
1815: //
1816: if (!hasEntityBeanInterface(bean)) {
1817: fireSpecViolationEvent(entity, new Section("12.2.2.a"));
1818: status = false;
1819: }
1820:
1821: // The entity bean class MUST be defined as public and NOT abstract.
1822: //
1823: // Spec 12.2.2
1824: //
1825: if (!isPublic(bean) || isAbstract(bean)) {
1826: fireSpecViolationEvent(entity, new Section("12.2.2.b"));
1827: status = false;
1828: }
1829:
1830: // The entity bean class MUST NOT be defined as final.
1831: //
1832: // Spec 12.2.2
1833: //
1834: if (isFinal(bean)) {
1835: fireSpecViolationEvent(entity, new Section("12.2.2.c"));
1836: status = false;
1837: }
1838:
1839: // The entity bean class MUST define a public constructor that
1840: // takes no arguments
1841: //
1842: // Spec 12.2.2
1843: //
1844: if (!hasDefaultConstructor(bean)) {
1845: fireSpecViolationEvent(entity, new Section("12.2.2.d"));
1846: status = false;
1847: }
1848:
1849: // The entity bean class MUST NOT define the finalize() method.
1850: //
1851: // Spec 12.2.2
1852: //
1853: if (hasFinalizer(bean)) {
1854: fireSpecViolationEvent(entity, new Section("12.2.2.e"));
1855: status = false;
1856: }
1857:
1858: // The ejbCreate(...) method signatures MUST follow these rules:
1859: //
1860: // - The method MUST be declared as public
1861: // - The method MUST NOT be declared as final or static
1862: // - The return type MUST be the entity bean's primary key type
1863: // --- If the method is on the remote home interface ---
1864: // - The method arguments MUST be legal types for RMI/IIOP
1865: // - The method return value type MUST be legal type for RMI/IIOP
1866: // --- End if the method is on the remote home interface ---
1867: //
1868: // Spec 12.2.3
1869: //
1870: if (hasEJBCreateMethod(bean, false)) {
1871: Iterator it = getEJBCreateMethods(bean);
1872: while (it.hasNext()) {
1873: Method ejbCreate = (Method) it.next();
1874: if (!isPublic(ejbCreate)) {
1875: fireSpecViolationEvent(entity, ejbCreate,
1876: new Section("12.2.3.a"));
1877: status = false;
1878: }
1879:
1880: if ((isFinal(ejbCreate)) || (isStatic(ejbCreate))) {
1881: fireSpecViolationEvent(entity, ejbCreate,
1882: new Section("12.2.3.b"));
1883: status = false;
1884: }
1885:
1886: if (!hasPrimaryKeyReturnType(entity, ejbCreate)) {
1887: fireSpecViolationEvent(entity, ejbCreate,
1888: new Section("12.2.3.c"));
1889: status = false;
1890: }
1891:
1892: /* FIXME
1893: * This code needs to only be invoked if the method is on the
1894: * remote home.
1895: if (!hasLegalRMIIIOPArguments(ejbCreate)) {
1896: fireSpecViolationEvent(entity, ejbCreate, new Section("9.2.3.d"));
1897: status = false;
1898: }
1899: if (!hasLegalRMIIIOPReturnType(ejbCreate)) {
1900: fireSpecViolationEvent(entity, ejbCreate, new Section("9.2.3.e"));
1901: status = false;
1902: }
1903: */
1904: }
1905: }
1906:
1907: // For each ejbCreate(...) method, the entity bean class MUST
1908: // define a matching ejbPostCreate(...) method.
1909: //
1910: // The ejbPostCreate(...) method MUST follow these rules:
1911: //
1912: // - the method MUST be declared as public
1913: // - the method MUST NOT be declared as final or static
1914: // - the return type MUST be void
1915: // - the method arguments MUST be the same as the matching
1916: // ejbCreate(...) method
1917: //
1918: // Spec 12.2.4
1919: //
1920: if (hasEJBCreateMethod(bean, false)) {
1921: Iterator it = getEJBCreateMethods(bean);
1922: while (it.hasNext()) {
1923: Method ejbCreate = (Method) it.next();
1924:
1925: if (!hasMatchingEJBPostCreate(bean, ejbCreate)) {
1926: fireSpecViolationEvent(entity, ejbCreate,
1927: new Section("12.2.4.a"));
1928: status = false;
1929: }
1930:
1931: if (hasMatchingEJBPostCreate(bean, ejbCreate)) {
1932: Method ejbPostCreate = getMatchingEJBPostCreate(
1933: bean, ejbCreate);
1934:
1935: if (!isPublic(ejbPostCreate)) {
1936: fireSpecViolationEvent(entity, ejbPostCreate,
1937: new Section("12.2.4.b"));
1938: status = false;
1939: }
1940:
1941: if (isStatic(ejbPostCreate)
1942: || isFinal(ejbPostCreate)) {
1943: fireSpecViolationEvent(entity, ejbPostCreate,
1944: new Section("12.2.4.c"));
1945: status = false;
1946: }
1947:
1948: if (!hasVoidReturnType(ejbPostCreate)) {
1949: fireSpecViolationEvent(entity, ejbPostCreate,
1950: new Section("12.2.4.d"));
1951: status = false;
1952: }
1953: }
1954: }
1955: }
1956:
1957: // Every entity bean MUST define the ejbFindByPrimaryKey method.
1958: //
1959: // The return type for the ejbFindByPrimaryKey method MUST be the
1960: // primary key type.
1961: //
1962: // The ejbFindByPrimaryKey method MUST be a single-object finder.
1963: //
1964: // Spec 12.2.5
1965: //
1966: if (!hasEJBFindByPrimaryKey(bean)) {
1967: fireSpecViolationEvent(entity, new Section("12.2.5.e"));
1968: status = false;
1969: }
1970:
1971: if (hasEJBFindByPrimaryKey(bean)) {
1972: Method ejbFindByPrimaryKey = getEJBFindByPrimaryKey(bean);
1973:
1974: if (!hasPrimaryKeyReturnType(entity, ejbFindByPrimaryKey)) {
1975: fireSpecViolationEvent(entity, ejbFindByPrimaryKey,
1976: new Section("12.2.5.e1"));
1977: status = false;
1978: }
1979:
1980: if (!isSingleObjectFinder(entity, ejbFindByPrimaryKey)) {
1981: fireSpecViolationEvent(entity, ejbFindByPrimaryKey,
1982: new Section("12.2.5.e2"));
1983: status = false;
1984: }
1985: }
1986:
1987: // A finder method MUST be declared as public.
1988: //
1989: // A finder method MUST NOT be declared as static.
1990: //
1991: // A finder method MUST NOT be declared as final.
1992: //
1993: // The finder method argument types MUST be legal types for
1994: // RMI/IIOP
1995: //
1996: // The finder method return type MUST be either the entity bean's
1997: // primary key type, or java.lang.util.Enumeration interface or
1998: // java.lang.util.Collection interface.
1999: //
2000: // Spec 12.2.5
2001: //
2002: if (hasFinderMethod(bean)) {
2003: Iterator it = getEJBFindMethods(bean);
2004: while (it.hasNext()) {
2005: Method finder = (Method) it.next();
2006:
2007: if (!isPublic(finder)) {
2008: fireSpecViolationEvent(entity, finder, new Section(
2009: "12.2.5.a"));
2010: status = false;
2011: }
2012:
2013: if (isFinal(finder) || isStatic(finder)) {
2014: fireSpecViolationEvent(entity, finder, new Section(
2015: "12.2.5.b"));
2016: status = false;
2017: }
2018:
2019: /** FIXME
2020: * this path should only get invoked if the finder is on the
2021: * remote interface.
2022: if (!hasLegalRMIIIOPArguments(finder)) {
2023: fireSpecViolationEvent(entity, finder, new Section("12.2.5.c"));
2024: status = false;
2025: }
2026: */
2027:
2028: if (!(isSingleObjectFinder(entity, finder) || isMultiObjectFinder(finder))) {
2029: fireSpecViolationEvent(entity, finder, new Section(
2030: "12.2.5.d"));
2031: status = false;
2032: }
2033: }
2034: }
2035:
2036: // The ejbHome(...) method signatures MUST follow these rules:
2037: //
2038: // - The method name MUST have ejbHome as its prefix.
2039: // - The method MUST be declared as public
2040: // - The method MUST NOT be declared as static.
2041: // - The method MUST NOT define the java.rmi.RemoteException
2042: //
2043: // Spec 10.6.6
2044: //
2045: Iterator it = getEjbHomeMethods(bean);
2046: while (it.hasNext()) {
2047: Method ejbHome = (Method) it.next();
2048:
2049: if (!isPublic(ejbHome)) {
2050: fireSpecViolationEvent(entity, ejbHome, new Section(
2051: "10.6.6.a"));
2052: status = false;
2053: }
2054:
2055: if (isStatic(ejbHome)) {
2056: fireSpecViolationEvent(entity, ejbHome, new Section(
2057: "10.6.6.b"));
2058: status = false;
2059: }
2060:
2061: if (throwsRemoteException(ejbHome)) {
2062: fireSpecViolationEvent(entity, ejbHome, new Section(
2063: "10.6.6.c"));
2064: status = false;
2065: }
2066: }
2067:
2068: return status;
2069: }
2070:
2071: /*
2072: * Verify Primary Key
2073: */
2074: private boolean verifyPrimaryKey(EntityMetaData entity) {
2075: boolean status = true;
2076: boolean cmp = entity.isCMP();
2077:
2078: if (entity.getPrimaryKeyClass() == null
2079: || entity.getPrimaryKeyClass().length() == 0) {
2080: if (cmp)
2081: fireSpecViolationEvent(entity, new Section("10.6.1.a"));
2082: else
2083: fireSpecViolationEvent(entity, new Section("12.2.1.a"));
2084:
2085: // We can't get any further if there's no PK class specified!
2086: return false;
2087: }
2088:
2089: // FIXME - Still missing the bits from 10.8.2 for CMP primary
2090: // keys. Primarily the class must be public, all fields in the
2091: // class must be public and the fields must also be a subset of
2092: // the CMP fields within the bean.
2093: //
2094: Class cls = null;
2095: try {
2096: cls = classloader.loadClass(entity.getPrimaryKeyClass());
2097: } catch (ClassNotFoundException e) {
2098: if (cmp)
2099: fireSpecViolationEvent(entity, new Section("10.6.13.a"));
2100: else
2101: fireSpecViolationEvent(entity, new Section("12.2.12.a"));
2102:
2103: // Can't do any other checks if the class is null!
2104: return false;
2105: }
2106:
2107: // The primary key type must be a valid type in RMI-IIOP.
2108: //
2109: // Spec 10.6.13 & 12.2.12
2110: //
2111: if (!isRMIIDLValueType(cls)) {
2112: if (cmp)
2113: fireSpecViolationEvent(entity, new Section("10.6.13.b"));
2114: else
2115: fireSpecViolationEvent(entity, new Section("12.2.12.b"));
2116: status = false;
2117: }
2118:
2119: // No primary key field specified, just a primary key class.
2120: if (entity.getPrimKeyField() == null
2121: || entity.getPrimKeyField().length() == 0) {
2122: // This is a check for some interesting implementation of
2123: // equals() and hashCode(). I am not sure how well it works in
2124: // the end.
2125: //
2126: if (!cls.getName().equals("java.lang.Object")) {
2127: Object one, two;
2128:
2129: try {
2130: one = cls.newInstance();
2131: two = cls.newInstance();
2132: try {
2133: if (!one.equals(two)) {
2134: if (cmp) {
2135: // fireSpecViolationEvent(entity, new Section("10.6.13.c"));
2136: log
2137: .warn("Default instances of primary key: "
2138: + cls
2139: + " do not equate, check your equals method");
2140: } else {
2141: //fireSpecViolationEvent(entity, new Section("12.2.12.c"));
2142: log
2143: .warn("Default instances of primary key: "
2144: + cls
2145: + " do not equate, check your equals method");
2146: }
2147: status = true;
2148: }
2149: } catch (NullPointerException e) {
2150: // That's OK - the implementor expected the fields to
2151: // have values
2152: }
2153:
2154: try {
2155: if (one.hashCode() != two.hashCode()) {
2156: if (cmp) {
2157: //fireSpecViolationEvent(entity, new Section("10.6.13.d"));
2158: log
2159: .warn("Default instances of primary key: "
2160: + cls
2161: + " do not have the same hash, check your hashCode method");
2162: } else {
2163: //fireSpecViolationEvent(entity, new Section("12.2.12.d"));
2164: log
2165: .warn("Default instances of primary key: "
2166: + cls
2167: + " do not have the same hash, check your hashCode method");
2168: }
2169: status = true;
2170: }
2171: } catch (NullPointerException e) {
2172: // That's OK - the implementor expected the fields to have values
2173: }
2174: } catch (IllegalAccessException e) {
2175: // If CMP primary key class MUST have a public
2176: // constructor with no parameters. 10.8.2.a
2177: ///
2178: if (cmp) {
2179: fireSpecViolationEvent(entity, new Section(
2180: "10.8.2.a"));
2181: status = false;
2182: }
2183: } catch (InstantiationException e) {
2184: //Not sure what condition this is at the moment - JMW
2185: //fireSpecViolationEvent(entity, new Section("9.2.9.a"));
2186: //status = false;
2187: }
2188: }
2189: } else {
2190: // BMP Beans MUST not include the primkey-field element in
2191: // their deployment descriptor. Deployment descriptor comment
2192: //
2193: if (entity.isBMP()) {
2194: fireSpecViolationEvent(entity, new Section("dd.a"));
2195: status = false;
2196: }
2197:
2198: // The primary keyfield MUST be a CMP field within the
2199: // entity bean.
2200: //
2201: // Spec 10.8.1
2202: //
2203: boolean found = false;
2204: Iterator it = entity.getCMPFields();
2205: while (it.hasNext()) {
2206: String fieldName = (String) it.next();
2207: if (fieldName.equals(entity.getPrimKeyField())) {
2208: found = true;
2209: break;
2210: }
2211: }
2212:
2213: if (!found) {
2214: status = false;
2215: fireSpecViolationEvent(entity, new Section("10.8.1.b"));
2216: }
2217:
2218: try {
2219: // The class of the primary key field MUST match the
2220: // primary key class specified for the entity bean. We
2221: // figure out the class of this field by getting the
2222: // return type of the get<FieldName> accessor method.
2223: //
2224: // Spec 10.8.1
2225: //
2226: String pkField = entity.getPrimKeyField();
2227: String methodName = "get"
2228: + pkField.substring(0, 1).toUpperCase()
2229: + pkField.substring(1);
2230:
2231: Method method = bean
2232: .getMethod(methodName, new Class[0]);
2233: if (!entity.getPrimaryKeyClass().equals(
2234: method.getReturnType().getName())) {
2235: status = false;
2236: fireSpecViolationEvent(entity, new Section(
2237: "10.8.1.a"));
2238: }
2239:
2240: } catch (NoSuchMethodException e) {
2241: // The primary keyfield MUST be a CMP field within the
2242: // entity bean.
2243: //
2244: // Spec 10.8.1
2245: //
2246: status = false;
2247: fireSpecViolationEvent(entity, new Section("10.8.1.b"));
2248: }
2249: }
2250:
2251: return status;
2252: }
2253:
2254: /*
2255: * Verify Message Driven Bean
2256: */
2257: protected boolean verifyMessageDrivenBean(
2258: MessageDrivenMetaData mdBean) {
2259: boolean status = true;
2260:
2261: // A message driven bean MUST implement, directly or indirectly,
2262: // javax.ejb.MessageDrivenBean interface.
2263: //
2264: // Spec 15.7.2
2265: //
2266: if (!hasMessageDrivenBeanInterface(bean)) {
2267: fireSpecViolationEvent(mdBean, new Section("15.7.2.a"));
2268: status = false;
2269: }
2270:
2271: // The class must implement, directly or indirectly, the message listener interface required by the messaging
2272: // type that it supports. In the case of JMS, this is the javax.jms.MessageListener interface.
2273: //
2274: // Spec 15.7.2
2275: //
2276: if (!isAssignableFrom(mdBean.getMessagingType(), bean)) {
2277: fireSpecViolationEvent(mdBean, new Section("15.7.2.b"));
2278: status = false;
2279: }
2280:
2281: // The message driven bean class MUST be defined as public.
2282: //
2283: // Spec 15.7.2
2284: //
2285: if (!isPublic(bean)) {
2286: fireSpecViolationEvent(mdBean, new Section("15.7.2.c1"));
2287: status = false;
2288: }
2289:
2290: // The message driven bean class MUST NOT be final.
2291: //
2292: // Spec 15.7.2
2293: //
2294: if (isFinal(bean)) {
2295: fireSpecViolationEvent(mdBean, new Section("15.7.2.c2"));
2296: status = false;
2297: }
2298:
2299: // The message driven bean class MUST NOT be abstract.
2300: //
2301: // Spec 15.7.2
2302: //
2303: if (isAbstract(bean)) {
2304: fireSpecViolationEvent(mdBean, new Section("15.7.2.c3"));
2305: status = false;
2306: }
2307:
2308: // The message driven bean class MUST have a public constructor that
2309: // takes no arguments.
2310: //
2311: // Spec 15.7.2
2312: //
2313: if (!hasDefaultConstructor(bean)) {
2314: fireSpecViolationEvent(mdBean, new Section("15.7.2.d"));
2315: status = false;
2316: }
2317:
2318: // The message driven bean class MUST NOT define the finalize() method.
2319: //
2320: // Spec 15.7.2
2321: //
2322: if (hasFinalizer(bean)) {
2323: fireSpecViolationEvent(mdBean, new Section("15.7.2.e"));
2324: status = false;
2325: }
2326:
2327: // A message driven bean MUST implement the ejbCreate() method.
2328: // The ejbCreate() method signature MUST follow these rules:
2329: //
2330: // - The method name MUST be ejbCreate
2331: // - The method MUST be declared as public
2332: // - The method MUST NOT be declared as final or static
2333: // - The return type MUST be void
2334: // - The method arguments MUST have no arguments.
2335: // - The method MUST NOT define any application exceptions.
2336: //
2337: // Spec 15.7.2, 3
2338: //
2339: if (hasEJBCreateMethod(bean, false)) {
2340: Iterator it = getEJBCreateMethods(bean);
2341: Method ejbCreate = (Method) it.next();
2342:
2343: if (!isPublic(ejbCreate)) {
2344: fireSpecViolationEvent(mdBean, ejbCreate, new Section(
2345: "15.7.3.b"));
2346: status = false;
2347: }
2348:
2349: if ((isFinal(ejbCreate)) || (isStatic(ejbCreate))) {
2350: fireSpecViolationEvent(mdBean, ejbCreate, new Section(
2351: "15.7.3.c"));
2352: status = false;
2353: }
2354:
2355: if (!hasVoidReturnType(ejbCreate)) {
2356: fireSpecViolationEvent(mdBean, ejbCreate, new Section(
2357: "15.7.3.d"));
2358: status = false;
2359: }
2360:
2361: if (!hasNoArguments(ejbCreate)) {
2362: fireSpecViolationEvent(mdBean, ejbCreate, new Section(
2363: "15.7.3.e"));
2364: status = false;
2365: }
2366:
2367: if (!throwsNoException(ejbCreate)) {
2368: fireSpecViolationEvent(mdBean, ejbCreate, new Section(
2369: "15.7.3.f"));
2370: status = false;
2371: }
2372:
2373: if (it.hasNext()) {
2374: fireSpecViolationEvent(mdBean, new Section("15.7.3.a"));
2375: status = false;
2376: }
2377: } else {
2378: fireSpecViolationEvent(mdBean, new Section("15.7.3.a"));
2379: status = false;
2380: }
2381:
2382: // The message-driven bean class must define the message listener methods. The signature of a message
2383: // listener method must follow these rules:
2384: //
2385: // - The method MUST be declared as public
2386: // - The method MUST NOT be declared as final or static
2387: //
2388: // Spec 15.7.4
2389: //
2390:
2391: Class messageListener = null;
2392: try {
2393: messageListener = classloader.loadClass(mdBean
2394: .getMessagingType());
2395: } catch (ClassNotFoundException cnfe) {
2396: fireSpecViolationEvent(mdBean, new Section("15.7.2.b",
2397: "Class not found on '" + mdBean.getMessagingType()
2398: + "': " + cnfe.getMessage()));
2399: status = false;
2400:
2401: }
2402:
2403: if (messageListener != null) {
2404: Method[] methods = bean.getMethods();
2405: for (int i = 0; i < methods.length; ++i) {
2406: if (methods[i].getDeclaringClass().equals(
2407: messageListener)) {
2408: if (!isPublic(methods[i])) {
2409: fireSpecViolationEvent(mdBean, methods[i],
2410: new Section("15.7.4.b"));
2411: status = false;
2412: }
2413:
2414: if ((isFinal(methods[i])) || (isStatic(methods[i]))) {
2415: fireSpecViolationEvent(mdBean, methods[i],
2416: new Section("15.7.4.c"));
2417: status = false;
2418: }
2419: }
2420: }
2421: }
2422:
2423: // A message driven bean MUST implement the ejbRemove() method.
2424: // The ejbRemove() method signature MUST follow these rules:
2425: //
2426: // - The method name MUST be ejbRemove
2427: // - The method MUST be declared as public
2428: // - The method MUST NOT be declared as final or static
2429: // - The return type MUST be void
2430: // - The method MUST have no arguments.
2431: // - The method MUST NOT define any application exceptions.
2432: //
2433: // Spec 15.7.5
2434: //
2435: if (hasEJBRemoveMethod(bean)) {
2436: Iterator it = getEJBRemoveMethods(bean);
2437: Method ejbRemove = (Method) it.next();
2438:
2439: if (!isPublic(ejbRemove)) {
2440: fireSpecViolationEvent(mdBean, ejbRemove, new Section(
2441: "15.7.5.b"));
2442: status = false;
2443: }
2444:
2445: if ((isFinal(ejbRemove)) || (isStatic(ejbRemove))) {
2446: fireSpecViolationEvent(mdBean, ejbRemove, new Section(
2447: "15.7.5.c"));
2448: status = false;
2449: }
2450:
2451: if (!hasVoidReturnType(ejbRemove)) {
2452: fireSpecViolationEvent(mdBean, ejbRemove, new Section(
2453: "15.7.5.d"));
2454: status = false;
2455: }
2456:
2457: if (!hasNoArguments(ejbRemove)) {
2458: fireSpecViolationEvent(mdBean, ejbRemove, new Section(
2459: "15.7.5.e"));
2460: status = false;
2461: }
2462:
2463: if (!throwsNoException(ejbRemove)) {
2464: fireSpecViolationEvent(mdBean, ejbRemove, new Section(
2465: "15.7.5.f"));
2466: status = false;
2467: }
2468:
2469: if (it.hasNext()) {
2470: fireSpecViolationEvent(mdBean, new Section("15.7.5.a"));
2471: status = false;
2472: }
2473: } else {
2474: fireSpecViolationEvent(mdBean, new Section("15.7.5.a"));
2475: status = false;
2476: }
2477:
2478: return status;
2479: }
2480:
2481: /**
2482: * Verify Session Bean Service Endpoint
2483: * @param session
2484: * @return
2485: */
2486: protected boolean verifyServiceEndpoint(SessionMetaData session) {
2487: boolean status = true;
2488:
2489: // The service endpoint interface MUST extend the java.rmi.Remote
2490: // interface.
2491: //
2492: // Spec 7.11.9
2493: //
2494: if (!hasRemoteInterface(serviceEndpointInterface)) {
2495: fireSpecViolationEvent(session, new Section("7.11.9.a"));
2496: status = false;
2497: }
2498:
2499: // Method arguments defined in the service-endpoint interface MUST be
2500: // of valid types for RMI/JAXRPC.
2501: //
2502: // Method return values defined in the remote interface MUST
2503: // be of valid types for RMI/JAXRPC.
2504: //
2505: // Methods defined in the remote interface MUST include
2506: // java.rmi.RemoteException in their throws clause.
2507: //
2508: // Spec 7.11.9
2509: //
2510: Iterator it = Arrays.asList(
2511: serviceEndpointInterface.getMethods()).iterator();
2512: while (it.hasNext()) {
2513: Method method = (Method) it.next();
2514:
2515: if (!hasLegalJAXRPCArguments(method)) {
2516: fireSpecViolationEvent(session, method, new Section(
2517: "7.11.9.b1"));
2518: status = false;
2519: }
2520:
2521: if (!hasLegalJAXRPCReturnType(method)) {
2522: fireSpecViolationEvent(session, method, new Section(
2523: "7.11.9.b2"));
2524: status = false;
2525: }
2526:
2527: if (!throwsRemoteException(method)) {
2528: fireSpecViolationEvent(session, method, new Section(
2529: "7.11.9.b3"));
2530: status = false;
2531: }
2532: }
2533:
2534: // For each method defined in the web service interface, there MUST be
2535: // a matching method in the session bean's class. The matching
2536: // method MUST have:
2537: //
2538: // - the same name
2539: // - the same number and types of arguments, and the same
2540: // return type
2541: // - All the exceptions defined in the throws clause of the
2542: // matching method of the session bean class must be defined
2543: // in the throws clause of the method of the remote interface
2544: //
2545: // Spec 7.11.5
2546: //
2547: it = Arrays.asList(
2548: serviceEndpointInterface.getDeclaredMethods())
2549: .iterator();
2550: while (it.hasNext()) {
2551: Method seiMethod = (Method) it.next();
2552:
2553: if (!hasMatchingMethod(bean, seiMethod)) {
2554: fireSpecViolationEvent(session, seiMethod, new Section(
2555: "7.11.9.c"));
2556: status = false;
2557: } else {
2558: try {
2559: Method beanMethod = bean.getMethod(seiMethod
2560: .getName(), seiMethod.getParameterTypes());
2561: if (!hasMatchingReturnType(seiMethod, beanMethod)) {
2562: fireSpecViolationEvent(session, seiMethod,
2563: new Section("7.11.9.c1"));
2564: status = false;
2565: }
2566:
2567: if (!hasMatchingExceptions(beanMethod, seiMethod)) {
2568: fireSpecViolationEvent(session, seiMethod,
2569: new Section("7.11.59.c2"));
2570: status = false;
2571: }
2572: } catch (NoSuchMethodException ignored) {
2573: }
2574: }
2575: }
2576:
2577: return status;
2578: }
2579:
2580: /**
2581: * @param method
2582: * @return
2583: */
2584: protected boolean hasLegalJAXRPCReturnType(Method method) {
2585: return isJAXRPCType(method.getReturnType());
2586: }
2587:
2588: /**
2589: * @param class1
2590: * @return
2591: */
2592: protected boolean isJAXRPCType(Class class1) {
2593: // TODO this should be implemented along the jaxrpc spec
2594: return isRMIIDLValueType(class1);
2595: }
2596:
2597: /**
2598: * @param method
2599: * @return
2600: */
2601: protected boolean hasLegalJAXRPCArguments(Method method) {
2602: Class[] params = method.getParameterTypes();
2603:
2604: for (int i = 0; i < params.length; ++i) {
2605: if (!isJAXRPCType(params[i]))
2606: return false;
2607: }
2608:
2609: return true;
2610: }
2611:
2612: /**
2613: * Check whether the bean has declared service endpoint interfaces and whether
2614: * we can load the defined classes
2615: * @param bean
2616: * @return <code>true</code> if everything went alright
2617: */
2618: protected boolean hasServiceEndpointInterfaces(SessionMetaData bean) {
2619: boolean status = true;
2620: String seiName = bean.getServiceEndpoint();
2621:
2622: if (seiName == null)
2623: return false;
2624:
2625: // Verify the <service-endpoint> class
2626: try {
2627: serviceEndpointInterface = classloader.loadClass(seiName);
2628: } catch (ClassNotFoundException cnfe) {
2629: fireSpecViolationEvent(bean, new Section("23.2",
2630: "Class not found on '" + seiName + "': "
2631: + cnfe.getMessage()));
2632: status = false;
2633: }
2634:
2635: return status;
2636: }
2637:
2638: }
|