Save This Page
Home » jboss-5.0.0.CR1-src » org » jboss » verifier » strategy » [javadoc | source]
    1   /*
    2   * JBoss, Home of Professional Open Source
    3   * Copyright 2005, JBoss Inc., and individual contributors as indicated
    4   * by the @authors tag. See the copyright.txt in the distribution for a
    5   * full listing of individual contributors.
    6   *
    7   * This is free software; you can redistribute it and/or modify it
    8   * under the terms of the GNU Lesser General Public License as
    9   * published by the Free Software Foundation; either version 2.1 of
   10   * the License, or (at your option) any later version.
   11   *
   12   * This software is distributed in the hope that it will be useful,
   13   * but WITHOUT ANY WARRANTY; without even the implied warranty of
   14   * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
   15   * Lesser General Public License for more details.
   16   *
   17   * You should have received a copy of the GNU Lesser General Public
   18   * License along with this software; if not, write to the Free
   19   * Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA
   20   * 02110-1301 USA, or see the FSF site: http://www.fsf.org.
   21   */
   22   package org.jboss.verifier.strategy;
   23   
   24   // $Id: EJBVerifier20.java 41248 2006-02-17 08:31:12Z starksm $
   25   
   26   import org.jboss.logging.Logger;
   27   import org.jboss.metadata.BeanMetaData;
   28   import org.jboss.metadata.EntityMetaData;
   29   import org.jboss.metadata.MessageDrivenMetaData;
   30   import org.jboss.metadata.SessionMetaData;
   31   import org.jboss.verifier.Section;
   32   
   33   import java.lang.reflect.Method;
   34   import java.util.Arrays;
   35   import java.util.Iterator;
   36   
   37   /**
   38    * EJB 2.0 bean verifier.
   39    *
   40    * @author Juha Lindfors   (jplindfo@helsinki.fi)
   41    * @author Jay Walters     (jwalters@computer.org)
   42    * @author <a href="mailto:criege@riege.com">Christian Riege</a>
   43    * @author Thomas.Diesler@jboss.org
   44    *
   45    * @version $Revision: 41248 $
   46    * @since   JDK 1.3
   47    */
   48   public class EJBVerifier20 extends AbstractEJB2xVerifier
   49   {
   50      private static Logger log = Logger.getLogger(EJBVerifier20.class);
   51   
   52      /*
   53       * Constructor
   54       */
   55      public EJBVerifier20(VerificationContext context)
   56      {
   57         super(context);
   58      }
   59   
   60      public String getMessageBundle()
   61      {
   62         return "EJB20Messages.properties";
   63      }
   64   
   65      /***********************************************************************
   66       *
   67       *    IMPLEMENTS VERIFICATION STRATEGY INTERFACE
   68       *
   69       ************************************************************************/
   70      public void checkSession(SessionMetaData session)
   71      {
   72         boolean localOrRemoteExists = false;
   73         boolean verified = false;
   74   
   75         if (!verifyBean(session))
   76            return;
   77   
   78         verified = verifySessionBean(session);
   79   
   80         if (hasRemoteInterfaces(session))
   81         {
   82            // Check remote interfaces
   83            localOrRemoteExists = true;
   84            verified = verified && verifySessionRemote(session);
   85            verified = verified && verifySessionHome(session);
   86         }
   87   
   88         if (hasLocalInterfaces(session))
   89         {
   90            // Check local interfaces
   91            localOrRemoteExists = true;
   92            verified = verified && verifySessionLocal(session);
   93            verified = verified && verifySessionLocalHome(session);
   94         }
   95   
   96         // The session bean MUST implement either a remote home and
   97         // remote, or local home and local interface.  It MAY implement a
   98         // remote home, remote, local home or local interface.
   99         //
  100         // Spec 7.10.1
  101         //
  102         if (!localOrRemoteExists)
  103         {
  104            fireSpecViolationEvent(session, new Section("7.10.1"));
  105            verified = false;
  106         }
  107   
  108         if (verified)
  109         {
  110            // All OK; full steam ahead
  111            fireBeanVerifiedEvent(session);
  112         }
  113      }
  114   
  115      public void checkEntity(EntityMetaData entity)
  116      {
  117         if (entity.isCMP1x())
  118         {
  119            cmp1XVerifier.checkEntity(entity);
  120         }
  121         else
  122         {
  123            checkBmpOrCmp2Entity(entity);
  124         }
  125      }
  126   
  127      public void checkMessageBean(MessageDrivenMetaData mdb)
  128      {
  129         boolean beanVerified = false;
  130   
  131         if (!verifyBean(mdb))
  132            return;
  133   
  134         beanVerified = verifyMessageDrivenBean(mdb);
  135   
  136         if (beanVerified)
  137         {
  138            // OK, we're done
  139            fireBeanVerifiedEvent(mdb);
  140         }
  141      }
  142   
  143      private void checkBmpOrCmp2Entity(EntityMetaData entity)
  144      {
  145         boolean localOrRemoteExists = false;
  146         boolean verified = false;
  147   
  148         if (!verifyBean(entity))
  149            return;
  150   
  151         if (entity.isCMP())
  152         {
  153            verified = verifyCMPEntityBean(entity);
  154         }
  155         else if (entity.isBMP())
  156         {
  157            verified = verifyBMPEntityBean(entity);
  158         }
  159   
  160         if (hasRemoteInterfaces(entity))
  161         {
  162            // Check remote interfaces
  163            localOrRemoteExists = true;
  164            verified = verified && verifyEntityRemote(entity);
  165            verified = verified && verifyEntityHome(entity);
  166         }
  167   
  168         if (hasLocalInterfaces(entity))
  169         {
  170            // Check local interfaces
  171            localOrRemoteExists = true;
  172            verified = verified && verifyEntityLocal(entity);
  173            verified = verified && verifyEntityLocalHome(entity);
  174         }
  175   
  176         verified = verified && verifyPrimaryKey(entity);
  177   
  178         if (!localOrRemoteExists)
  179         {
  180            // The entity bean MUST implement either a remote home and
  181            // remote, or local home and local interface.  It MAY implement
  182            // a remote home, remote, local home or local interface.
  183            //
  184            // Spec 10.6.1 (CMP) / 12.2.1 (BMP)
  185            //
  186            if (entity.isCMP())
  187            {
  188               fireSpecViolationEvent(entity, new Section("10.6.1"));
  189               verified = false;
  190            }
  191            else
  192            {
  193               fireSpecViolationEvent(entity, new Section("12.2.1"));
  194               verified = false;
  195            }
  196         }
  197   
  198         if (verified)
  199         {
  200            fireBeanVerifiedEvent(entity);
  201         }
  202      }
  203   
  204      /**
  205       * Try to load the beans class declared in the &lt;ejb-class&gt;
  206       * element.
  207       *
  208       * @return <code>true</code> if everything went alright
  209       */
  210      protected boolean verifyBean(BeanMetaData theBean)
  211      {
  212         String beanName = theBean.getEjbClass();
  213   
  214         if (beanName == null)
  215            return false;
  216   
  217         try
  218         {
  219            bean = classloader.loadClass(beanName);
  220            return true;
  221         }
  222         catch (ClassNotFoundException cnfe)
  223         {
  224            fireSpecViolationEvent(theBean, new Section("22.2.b",
  225                    "Class not found on '" + beanName + "': " + cnfe.getMessage()));
  226            return false;
  227         }
  228      }
  229   
  230      /**
  231       * Check whether the bean has declared local interfaces and whether
  232       * we can load the defined classes
  233       *
  234       * @return <code>true</code> if everything went alright
  235       */
  236      protected boolean hasRemoteInterfaces(BeanMetaData bean)
  237      {
  238         boolean status = true;
  239         String homeName = bean.getHome();
  240         String remoteName = bean.getRemote();
  241   
  242         if (homeName == null || remoteName == null)
  243            return false;
  244   
  245         // Verify the <home> class
  246         try
  247         {
  248            home = classloader.loadClass(homeName);
  249         }
  250         catch (ClassNotFoundException cnfe)
  251         {
  252            fireSpecViolationEvent(bean, new Section("22.2.c",
  253                    "Class not found on '" + homeName + "': " + cnfe.getMessage()));
  254            status = false;
  255         }
  256   
  257         // Verify the <remote> class
  258         try
  259         {
  260            remote = classloader.loadClass(remoteName);
  261         }
  262         catch (ClassNotFoundException cnfe)
  263         {
  264            fireSpecViolationEvent(bean, new Section("22.2.d",
  265                    "Class not found on '" + remoteName + "': " + cnfe.getMessage()));
  266            status = false;
  267         }
  268   
  269         return status;
  270      }
  271   
  272      /**
  273       * Check whether the bean has declared local interfaces and whether
  274       * we can load the defined classes
  275       *
  276       * @return <code>true</code> if everything went alright
  277       */
  278      protected boolean hasLocalInterfaces(BeanMetaData bean)
  279      {
  280         boolean status = true;
  281         String localHomeName = bean.getLocalHome();
  282         String localName = bean.getLocal();
  283   
  284         if (localHomeName == null || localName == null)
  285            return false;
  286   
  287         // Verify the <local-home> class
  288         try
  289         {
  290            localHome = classloader.loadClass(localHomeName);
  291         }
  292         catch (ClassNotFoundException cnfe)
  293         {
  294            fireSpecViolationEvent(bean, new Section("22.2.e",
  295                    "Class not found on '" + localHomeName + "': " +
  296                    cnfe.getMessage()));
  297            status = false;
  298         }
  299   
  300         try
  301         {
  302            local = classloader.loadClass(localName);
  303         }
  304         catch (ClassNotFoundException cnfe)
  305         {
  306            fireSpecViolationEvent(bean, new Section("22.2.f",
  307                    "Class not found on '" + localName + "': " + cnfe.getMessage()));
  308            status = false;
  309         }
  310   
  311         return status;
  312      }
  313   
  314      /**
  315       * Verifies the session bean remote home interface against the EJB 2.0
  316       * specification.
  317       *
  318       * @param   session     XML metadata of the session bean
  319       */
  320      protected boolean verifySessionHome(SessionMetaData session)
  321      {
  322         boolean status = true;
  323   
  324         // The home interface of a stateless session bean MUST have one
  325         // create() method that takes no arguments.
  326         //
  327         // The create() method MUST return the session bean's remote
  328         // interface.
  329         //
  330         // There CAN NOT be other create() methods in the home interface.
  331         //
  332         // Spec 7.10.6
  333         //
  334         if (session.isStateless())
  335         {
  336            if (!hasDefaultCreateMethod(home))
  337            {
  338               fireSpecViolationEvent(session, new Section("7.10.6.d2"));
  339               status = false;
  340            }
  341            else
  342            {
  343               Method create = getDefaultCreateMethod(home);
  344   
  345               if (hasMoreThanOneCreateMethods(home))
  346               {
  347                  fireSpecViolationEvent(session, new Section("7.10.6.d2"));
  348                  status = false;
  349               }
  350            }
  351         }
  352   
  353         // The session bean's home interface MUST extend the
  354         // javax.ejb.EJBHome interface.
  355         //
  356         // Spec 7.10.6
  357         //
  358         if (!hasEJBHomeInterface(home))
  359         {
  360            fireSpecViolationEvent(session, new Section("7.10.6.a"));
  361            status = false;
  362         }
  363   
  364         // Method arguments defined in the home interface MUST be
  365         // of valid types for RMI/IIOP.
  366         //
  367         // Method return values defined in the home interface MUST
  368         // be of valid types for RMI/IIOP.
  369         //
  370         // Methods defined in the home interface MUST include
  371         // java.rmi.RemoteException in their throws clause.
  372         //
  373         // Spec 7.10.6
  374         ///
  375         Iterator it = Arrays.asList(home.getMethods()).iterator();
  376         while (it.hasNext())
  377         {
  378            Method method = (Method)it.next();
  379   
  380            if (!hasLegalRMIIIOPArguments(method))
  381            {
  382               fireSpecViolationEvent(session, method, new Section("7.10.6.b1"));
  383               status = false;
  384            }
  385   
  386            if (!hasLegalRMIIIOPReturnType(method))
  387            {
  388               fireSpecViolationEvent(session, method, new Section("7.10.6.b2"));
  389               status = false;
  390            }
  391   
  392            if (!throwsRemoteException(method))
  393            {
  394               fireSpecViolationEvent(session, method, new Section("7.10.6.b3"));
  395               status = false;
  396            }
  397         }
  398   
  399         // A session bean's home interface MUST define one or more
  400         // create(...) methods.
  401         //
  402         // Spec 7.10.6
  403         //
  404         if (!hasCreateMethod(home))
  405         {
  406            fireSpecViolationEvent(session, new Section("7.10.6.d1"));
  407            status = false;
  408         }
  409   
  410         // Each create(...) method in the session bean's home interface
  411         // MUST have a matching ejbCreate(...) method in the session
  412         // bean's class.
  413         //
  414         // Each create(...) method in the session bean's home interface
  415         // MUST have the same number and types of arguments to its
  416         // matching ejbCreate(...) method.
  417         //
  418         // The return type for a create(...) method MUST be the session
  419         // bean's remote interface type.
  420         //
  421         // All the exceptions defined in the throws clause of the matching
  422         // ejbCreate(...) method of the enterprise bean class MUST be
  423         // included in the throws clause of a matching create(...) method.
  424         //
  425         // The throws clause of a create(...) method MUST include the
  426         // javax.ejb.CreateException.
  427         //
  428         // Spec 7.10.6
  429         //
  430         Iterator createMethods = getCreateMethods(home);
  431         while (createMethods.hasNext())
  432         {
  433            Method create = (Method)createMethods.next();
  434   
  435            if (!hasMatchingEJBCreate(bean, create))
  436            {
  437               fireSpecViolationEvent(session, create, new Section("7.10.6.e"));
  438               status = false;
  439            }
  440   
  441            if (!hasRemoteReturnType(session, create))
  442            {
  443               fireSpecViolationEvent(session, create, new Section("7.10.6.f"));
  444               status = false;
  445            }
  446   
  447            if (hasMatchingEJBCreate(bean, create))
  448            {
  449               Method ejbCreate = getMatchingEJBCreate(bean, create);
  450               if (!hasMatchingExceptions(ejbCreate, create))
  451               {
  452                  fireSpecViolationEvent(session, create,
  453                          new Section("7.10.6.g"));
  454                  status = false;
  455               }
  456            }
  457   
  458            if (!throwsCreateException(create))
  459            {
  460               fireSpecViolationEvent(session, create, new Section("7.10.6.h"));
  461               status = false;
  462            }
  463         }
  464   
  465         return status;
  466      }
  467   
  468      /**
  469       * Verifies the session bean local home interface against the EJB 2.0
  470       * specification.
  471       *
  472       * @param session parsed metadata of the session bean
  473       */
  474      protected boolean verifySessionLocalHome(SessionMetaData session)
  475      {
  476         boolean status = true;
  477   
  478         // The local home interface of a stateless session bean MUST have
  479         // one create() method that takes no arguments.
  480         //
  481         // There CAN NOT be other create() methods in the home interface.
  482         //
  483         // Spec 7.10.8
  484         //
  485         if (session.isStateless())
  486         {
  487            if (!hasDefaultCreateMethod(localHome))
  488            {
  489               fireSpecViolationEvent(session, new Section("7.10.8.d2"));
  490               status = false;
  491            }
  492            else
  493            {
  494               Method create = getDefaultCreateMethod(localHome);
  495   
  496               if (hasMoreThanOneCreateMethods(localHome))
  497               {
  498                  fireSpecViolationEvent(session, new Section("7.10.8.d2"));
  499                  status = false;
  500               }
  501            }
  502         }
  503   
  504         // The session bean's home interface MUST extend the
  505         // javax.ejb.EJBLocalHome interface.
  506         //
  507         // Spec 7.10.8
  508         //
  509         if (!hasEJBLocalHomeInterface(localHome))
  510         {
  511            fireSpecViolationEvent(session, new Section("7.10.8.a"));
  512            status = false;
  513         }
  514   
  515         // Methods defined in the local home interface MUST NOT include
  516         // java.rmi.RemoteException in their throws clause.
  517         //
  518         // Spec 7.10.8
  519         //
  520         Iterator it = Arrays.asList(localHome.getMethods()).iterator();
  521         while (it.hasNext())
  522         {
  523            Method method = (Method)it.next();
  524   
  525            if (throwsRemoteException(method))
  526            {
  527               fireSpecViolationEvent(session, method, new Section("7.10.8.b"));
  528               status = false;
  529            }
  530         }
  531   
  532         // A session bean's home interface MUST define one or more
  533         // create(...) methods.
  534         //
  535         // Spec 7.10.8
  536         //
  537         if (!hasCreateMethod(localHome))
  538         {
  539            fireSpecViolationEvent(session, new Section("7.10.8.d1"));
  540            status = false;
  541         }
  542   
  543         // Each create(...) method in the session bean's local home
  544         // interface MUST have a matching ejbCreate(...) method in the
  545         // session bean's class.
  546         //
  547         // Each create(...) method in the session bean's home interface
  548         // MUST have the same number and types of arguments to its
  549         // matching ejbCreate(...) method.
  550         //
  551         // The return type for a create(...) method MUST be the session
  552         // bean's local interface type.
  553         //
  554         // All the exceptions defined in the throws clause of the matching
  555         // ejbCreate(...) method of the enterprise bean class MUST be
  556         // included in the throws clause of a matching create(...) method.
  557         //
  558         // The throws clause of a create(...) method MUST include the
  559         // javax.ejb.CreateException.
  560         //
  561         // Spec 7.10.8
  562         //
  563         Iterator createMethods = getCreateMethods(localHome);
  564         while (createMethods.hasNext())
  565         {
  566            Method create = (Method)createMethods.next();
  567   
  568            if (!hasMatchingEJBCreate(bean, create))
  569            {
  570               fireSpecViolationEvent(session, create,
  571                       new Section("7.10.8.e"));
  572               status = false;
  573            }
  574   
  575            if (!hasLocalReturnType(session, create))
  576            {
  577               fireSpecViolationEvent(session, create,
  578                       new Section("7.10.8.f"));
  579               status = false;
  580            }
  581   
  582            if (hasMatchingEJBCreate(bean, create))
  583            {
  584               Method ejbCreate = getMatchingEJBCreate(bean, create);
  585               if (!hasMatchingExceptions(ejbCreate, create))
  586               {
  587                  fireSpecViolationEvent(session, create,
  588                          new Section("7.10.8.g"));
  589               }
  590            }
  591   
  592            if (!throwsCreateException(create))
  593            {
  594               fireSpecViolationEvent(session, create,
  595                       new Section("7.10.8.h"));
  596               status = false;
  597            }
  598         }
  599   
  600         return status;
  601      }
  602   
  603      /*
  604       * Verify Session Bean Remote Interface
  605       */
  606      protected boolean verifySessionRemote(SessionMetaData session)
  607      {
  608         boolean status = true;
  609   
  610         // The remote interface MUST extend the javax.ejb.EJBObject
  611         // interface.
  612         //
  613         // Spec 7.10.5
  614         //
  615         if (!hasEJBObjectInterface(remote))
  616         {
  617            fireSpecViolationEvent(session, new Section("7.10.5.a"));
  618            status = false;
  619         }
  620   
  621         // Method arguments defined in the remote interface MUST be
  622         // of valid types for RMI/IIOP.
  623         //
  624         // Method return values defined in the remote interface MUST
  625         // be of valid types for RMI/IIOP.
  626         //
  627         // Methods defined in the remote interface MUST include
  628         // java.rmi.RemoteException in their throws clause.
  629         //
  630         // Spec 7.10.5
  631         //
  632         Iterator it = Arrays.asList(remote.getMethods()).iterator();
  633         while (it.hasNext())
  634         {
  635            Method method = (Method)it.next();
  636   
  637            if (!hasLegalRMIIIOPArguments(method))
  638            {
  639               fireSpecViolationEvent(session, method, new Section("7.10.5.b1"));
  640               status = false;
  641            }
  642   
  643            if (!hasLegalRMIIIOPReturnType(method))
  644            {
  645               fireSpecViolationEvent(session, method, new Section("7.10.5.b2"));
  646               status = false;
  647            }
  648   
  649            if (!throwsRemoteException(method))
  650            {
  651               fireSpecViolationEvent(session, method, new Section("7.10.5.b3"));
  652               status = false;
  653            }
  654         }
  655   
  656         // For each method defined in the remote interface, there MUST be
  657         // a matching method in the session bean's class. The matching
  658         // method MUST have:
  659         //
  660         //  - the same name
  661         //  - the same number and types of arguments, and the same
  662         //    return type
  663         //  - All the exceptions defined in the throws clause of the
  664         //    matching method of the session bean class must be defined
  665         //    in the throws clause of the method of the remote interface
  666         //
  667         // Spec 7.10.5
  668         //
  669         it = Arrays.asList(remote.getDeclaredMethods()).iterator();
  670         while (it.hasNext())
  671         {
  672            Method remoteMethod = (Method)it.next();
  673   
  674            if (!hasMatchingMethod(bean, remoteMethod))
  675            {
  676               fireSpecViolationEvent(session, remoteMethod,
  677                       new Section("7.10.5.d1"));
  678   
  679               status = false;
  680            }
  681   
  682            if (hasMatchingMethod(bean, remoteMethod))
  683            {
  684               try
  685               {
  686                  Method beanMethod = bean.getMethod(remoteMethod.getName(),
  687                          remoteMethod.getParameterTypes());
  688   
  689                  if (!hasMatchingReturnType(remoteMethod, beanMethod))
  690                  {
  691                     fireSpecViolationEvent(session, remoteMethod,
  692                             new Section("7.10.5.d2"));
  693                     status = false;
  694                  }
  695   
  696                  if (!hasMatchingExceptions(beanMethod, remoteMethod))
  697                  {
  698                     fireSpecViolationEvent(session, remoteMethod,
  699                             new Section("7.10.5.d3"));
  700                     status = false;
  701                  }
  702               }
  703               catch (NoSuchMethodException ignored)
  704               {
  705               }
  706            }
  707         }
  708   
  709         return status;
  710      }
  711   
  712      /*
  713       * Verify Session Bean Local Interface
  714       */
  715      protected boolean verifySessionLocal(SessionMetaData session)
  716      {
  717         boolean status = true;
  718   
  719         // The local interface MUST extend the javax.ejb.EJBLocalObject
  720         // interface.
  721         //
  722         // Spec 7.10.7
  723         //
  724         if (!hasEJBLocalObjectInterface(local))
  725         {
  726            fireSpecViolationEvent(session, new Section("7.10.7.a"));
  727            status = false;
  728         }
  729   
  730         // Methods defined in the local interface MUST NOT include
  731         // java.rmi.RemoteException in their throws clause.
  732         //
  733         // Spec 7.10.7
  734         //
  735         Iterator it = Arrays.asList(local.getMethods()).iterator();
  736         while (it.hasNext())
  737         {
  738            Method method = (Method)it.next();
  739            if (throwsRemoteException(method))
  740            {
  741               fireSpecViolationEvent(session, method, new Section("7.10.7.b"));
  742               status = false;
  743            }
  744         }
  745   
  746         // For each method defined in the local interface, there MUST be
  747         // a matching method in the session bean's class. The matching
  748         // method MUST have:
  749         //
  750         //  - the same name
  751         //  - the same number and types of arguments, and the same
  752         //    return type
  753         //  - All the exceptions defined in the throws clause of the
  754         //    matching method of the session bean class must be defined
  755         //    in the throws clause of the method of the remote interface
  756         //
  757         // Spec 7.10.7
  758         //
  759         it = Arrays.asList(local.getDeclaredMethods()).iterator();
  760         while (it.hasNext())
  761         {
  762            Method localMethod = (Method)it.next();
  763   
  764            if (!hasMatchingMethod(bean, localMethod))
  765            {
  766               fireSpecViolationEvent(session, localMethod,
  767                       new Section("7.10.7.d1"));
  768               status = false;
  769            }
  770   
  771            if (hasMatchingMethod(bean, localMethod))
  772            {
  773               try
  774               {
  775                  Method beanMethod = bean.getMethod(localMethod.getName(),
  776                          localMethod.getParameterTypes());
  777   
  778                  if (!hasMatchingReturnType(localMethod, beanMethod))
  779                  {
  780                     fireSpecViolationEvent(session, localMethod,
  781                             new Section("7.10.7.d2"));
  782                     status = false;
  783                  }
  784   
  785                  if (!hasMatchingExceptions(beanMethod, localMethod))
  786                  {
  787                     fireSpecViolationEvent(session, localMethod,
  788                             new Section("7.10.7.d3"));
  789                     status = false;
  790                  }
  791               }
  792               catch (NoSuchMethodException ignored)
  793               {
  794               }
  795            }
  796         }
  797   
  798         return status;
  799      }
  800   
  801      /*
  802       * Verify Session Bean
  803       */
  804      protected boolean verifySessionBean(SessionMetaData session)
  805      {
  806         boolean status = true;
  807   
  808         // A session bean MUST implement, directly or indirectly,
  809         // javax.ejb.SessionBean interface.
  810         //
  811         // Spec 7.10.2
  812         //
  813         if (!hasSessionBeanInterface(bean))
  814         {
  815            fireSpecViolationEvent(session, new Section("7.10.2.a"));
  816            status = false;
  817         }
  818   
  819         // Only a stateful container-managed transaction demarcation
  820         // session bean MAY implement the SessionSynchronization
  821         // interface.
  822         //
  823         // A stateless Session bean MUST NOT implement the
  824         // SessionSynchronization interface.
  825         //
  826         // Spec 7.5.3
  827         //
  828         if (hasSessionSynchronizationInterface(bean))
  829         {
  830            if (session.isStateless())
  831            {
  832               fireSpecViolationEvent(session, new Section("7.5.3.a"));
  833               status = false;
  834            }
  835   
  836            if (session.isBeanManagedTx())
  837            {
  838               fireSpecViolationEvent(session, new Section("7.5.3.b"));
  839               status = false;
  840            }
  841         }
  842   
  843         //
  844         // A session bean MUST implement AT LEAST one ejbCreate method.
  845         //
  846         // Spec 7.10.3
  847         //
  848         if (!hasEJBCreateMethod(bean, true))
  849         {
  850            fireSpecViolationEvent(session, new Section("7.10.3"));
  851            status = false;
  852         }
  853   
  854         // A session with bean-managed transaction demarcation CANNOT
  855         // implement the SessionSynchronization interface.
  856         //
  857         // Spec 7.6.1 (table 2)
  858         //
  859         if (hasSessionSynchronizationInterface(bean)
  860                 && session.isBeanManagedTx())
  861         {
  862            fireSpecViolationEvent(session, new Section("7.6.1"));
  863            status = false;
  864         }
  865   
  866         // The session bean class MUST be defined as public.
  867         //
  868         // Spec 7.10.2
  869         //
  870         if (!isPublic(bean))
  871         {
  872            fireSpecViolationEvent(session, new Section("7.10.2.b1"));
  873            status = false;
  874         }
  875   
  876         // The session bean class MUST NOT be final.
  877         //
  878         // Spec 7.10.2
  879         //
  880         if (isFinal(bean))
  881         {
  882            fireSpecViolationEvent(session, new Section("7.10.2.b2"));
  883            status = false;
  884         }
  885   
  886         // The session bean class MUST NOT be abstract.
  887         //
  888         // Spec 7.10.2
  889         //
  890         if (isAbstract(bean))
  891         {
  892            fireSpecViolationEvent(session, new Section("7.10.2.b3"));
  893            status = false;
  894         }
  895   
  896         // The session bean class MUST have a public constructor that
  897         // takes no arguments.
  898         //
  899         // Spec 7.10.2
  900         //
  901         if (!hasDefaultConstructor(bean))
  902         {
  903            fireSpecViolationEvent(session, new Section("7.10.2.c"));
  904            status = false;
  905         }
  906   
  907         // The session bean class MUST NOT define the finalize() method.
  908         //
  909         // Spec 7.10.2
  910         //
  911         if (hasFinalizer(bean))
  912         {
  913            fireSpecViolationEvent(session, new Section("7.10.2.d"));
  914            status = false;
  915         }
  916   
  917         // The ejbCreate(...) method signatures MUST follow these rules:
  918         //
  919         //      - The method name MUST have ejbCreate as its prefix
  920         //      - The method MUST be declared as public
  921         //      - The method MUST NOT be declared as final or static
  922         //      - The return type MUST be void
  923         //      - The method arguments MUST be legal types for RMI/IIOP
  924         //      - The method SHOULD not throw a java.rmi.RemoteException
  925         //        (NOTE we don't test for this as it's not a MUST)
  926         //
  927         // Spec 7.10.3
  928         //
  929         if (hasEJBCreateMethod(bean, true))
  930         {
  931            Iterator it = getEJBCreateMethods(bean);
  932            while (it.hasNext())
  933            {
  934               Method ejbCreate = (Method)it.next();
  935   
  936               if (!isPublic(ejbCreate))
  937               {
  938                  fireSpecViolationEvent(session, ejbCreate,
  939                          new Section("7.10.3.b"));
  940                  status = false;
  941               }
  942   
  943               if ((isFinal(ejbCreate)) || (isStatic(ejbCreate)))
  944               {
  945                  fireSpecViolationEvent(session, ejbCreate,
  946                          new Section("7.10.3.c"));
  947                  status = false;
  948               }
  949   
  950               if (!hasVoidReturnType(ejbCreate))
  951               {
  952                  fireSpecViolationEvent(session, ejbCreate,
  953                          new Section("7.10.3.d"));
  954                  status = false;
  955               }
  956   
  957               if (!hasLegalRMIIIOPArguments(ejbCreate))
  958               {
  959                  fireSpecViolationEvent(session, ejbCreate,
  960                          new Section("7.10.3.e"));
  961                  status = false;
  962               }
  963            }
  964         }
  965   
  966         return status;
  967      }
  968   
  969      /*
  970       * Verify Entity Bean Home Interface
  971       */
  972      private boolean verifyEntityHome(EntityMetaData entity)
  973      {
  974         boolean status = true;
  975   
  976         // Entity bean's home interface MUST extend the javax.ejb.EJBHome
  977         // interface.
  978         //
  979         // Spec 12.2.9
  980         //
  981         if (!hasEJBHomeInterface(home))
  982         {
  983            fireSpecViolationEvent(entity, new Section("12.2.9.a"));
  984            status = false;
  985         }
  986   
  987         // The methods defined in the entity bean's home interface MUST
  988         // have valid RMI-IIOP argument types.
  989         //
  990         // The methods defined in the entity bean's home interface MUST
  991         // have valid RMI-IIOP return types.
  992         //
  993         // The methods defined in the entity bean's home interface MUST
  994         // have java.rmi.RemoteException in their throws clause.
  995         //
  996         // Spec 12.2.9
  997         //
  998         Iterator methods = Arrays.asList(home.getMethods()).iterator();
  999         while (methods.hasNext())
 1000         {
 1001            Method method = (Method)methods.next();
 1002   
 1003            if (!hasLegalRMIIIOPArguments(method))
 1004            {
 1005               fireSpecViolationEvent(entity, method,
 1006                       new Section("12.2.9.b1"));
 1007               status = false;
 1008            }
 1009   
 1010            if (!hasLegalRMIIIOPReturnType(method))
 1011            {
 1012               fireSpecViolationEvent(entity, method,
 1013                       new Section("12.2.9.b2"));
 1014               status = false;
 1015            }
 1016   
 1017            if (!throwsRemoteException(method))
 1018            {
 1019               fireSpecViolationEvent(entity, method,
 1020                       new Section("12.2.9.b3"));
 1021               status = false;
 1022            }
 1023         }
 1024   
 1025         // Each method defined in the entity bean's home interface must be
 1026         // one of the following:
 1027         //
 1028         //    - a create method
 1029         //    - a finder method
 1030         //    - a home method
 1031         //
 1032         // Spec 12.2.9
 1033         //
 1034         methods = Arrays.asList(home.getMethods()).iterator();
 1035         while (methods.hasNext())
 1036         {
 1037            Method method = (Method)methods.next();
 1038   
 1039            // Do not check the methods of the javax.ejb.EJBHome interface
 1040            if (method.getDeclaringClass().getName().equals(EJB_HOME_INTERFACE))
 1041               continue;
 1042   
 1043            if (isCreateMethod(method))
 1044            {
 1045               // Each create(...) method in the entity bean's home
 1046               // interface MUST have a matching ejbCreate(...) method in
 1047               // the entity bean's class.
 1048               //
 1049               // Each create(...) method in the entity bean's home
 1050               // interface MUST have the same number and types of
 1051               // arguments to its matching ejbCreate(...) method.
 1052               //
 1053               // The return type for a create(...) method MUST be the
 1054               // entity bean's remote interface type.
 1055               //
 1056               // All the exceptions defined in the throws clause of the
 1057               // matching ejbCreate(...) and ejbPostCreate(...) methods of
 1058               // the enterprise bean class MUST be included in the throws
 1059               // clause of a matching create(...) method.
 1060               //
 1061               // The throws clause of a create(...) method MUST include
 1062               // the javax.ejb.CreateException.
 1063               //
 1064               // Spec 12.2.9
 1065               //
 1066               if (!hasMatchingEJBCreate(bean, method))
 1067               {
 1068                  fireSpecViolationEvent(entity, method, new Section("12.2.9.d"));
 1069                  status = false;
 1070               }
 1071   
 1072               if (!hasRemoteReturnType(entity, method))
 1073               {
 1074                  fireSpecViolationEvent(entity, method, new Section("12.2.9.e"));
 1075                  status = false;
 1076               }
 1077   
 1078               if (hasMatchingEJBCreate(bean, method)
 1079                       && hasMatchingEJBPostCreate(bean, method))
 1080               {
 1081                  Method ejbCreate = getMatchingEJBCreate(bean, method);
 1082                  Method ejbPostCreate = getMatchingEJBPostCreate(bean, method);
 1083   
 1084                  if (!(hasMatchingExceptions(ejbCreate, method)
 1085                          && hasMatchingExceptions(ejbPostCreate, method)))
 1086                  {
 1087                     fireSpecViolationEvent(entity, method,
 1088                             new Section("12.2.9.f"));
 1089                  }
 1090               }
 1091   
 1092               if (!throwsCreateException(method))
 1093               {
 1094                  fireSpecViolationEvent(entity, method, new Section("12.2.9.g"));
 1095                  status = false;
 1096               }
 1097            }
 1098            else if (isFinderMethod(method))
 1099            {
 1100               // Each finder method MUST match one of the ejbFind<METHOD>
 1101               // methods defined in the entity bean class.
 1102               //
 1103               // The matching ejbFind<METHOD> method MUST have the same
 1104               // number and types of arguments.
 1105               //
 1106               // The return type for a find<METHOD> method MUST be the
 1107               // entity bean's remote interface type (single-object
 1108               // finder) or a collection thereof (for a multi-object
 1109               // finder).
 1110               //
 1111               // All the exceptions defined in the throws clause of an
 1112               // ejbFind method of the entity bean class MUST be included
 1113               // in the throws clause of the matching find method of the
 1114               // home interface.
 1115               //
 1116               // The throws clause of a finder method MUST include the
 1117               // javax.ejb.FinderException.
 1118               //
 1119               // Spec 12.2.9
 1120               //
 1121               if (entity.isBMP())
 1122               {  // Check for BMP violations
 1123                  if ((!hasMatchingEJBFind(bean, method)))
 1124                  {
 1125                     fireSpecViolationEvent(entity, method,
 1126                             new Section("12.2.9.h"));
 1127                     status = false;
 1128                  }
 1129   
 1130                  if (!(hasRemoteReturnType(entity, method)
 1131                          || isMultiObjectFinder(method)))
 1132                  {
 1133                     fireSpecViolationEvent(entity, method,
 1134                             new Section("12.2.9.j"));
 1135                     status = false;
 1136                  }
 1137   
 1138                  if ((hasMatchingEJBFind(bean, method)))
 1139                  {
 1140                     Method ejbFind = getMatchingEJBFind(bean, method);
 1141                     if (!(hasMatchingExceptions(ejbFind, method)))
 1142                     {
 1143                        fireSpecViolationEvent(entity, method,
 1144                                new Section("12.2.9.k"));
 1145                        status = false;
 1146                     }
 1147                  }
 1148   
 1149                  if (!throwsFinderException(method))
 1150                  {
 1151                     fireSpecViolationEvent(entity, method,
 1152                             new Section("12.2.9.l"));
 1153                     status = false;
 1154                  }
 1155               } // if( entity.isBMP() )
 1156   
 1157               if (entity.isCMP())
 1158               {
 1159   
 1160                  if (!(hasRemoteReturnType(entity, method)
 1161                          || isMultiObjectFinder(method)))
 1162                  {
 1163                     fireSpecViolationEvent(entity, method,
 1164                             new Section("10.6.10.a"));
 1165                     status = false;
 1166                  }
 1167   
 1168                  if (!throwsFinderException(method))
 1169                  {
 1170                     fireSpecViolationEvent(entity, method,
 1171                             new Section("10.6.10.b"));
 1172                     status = false;
 1173                  }
 1174   
 1175                  // For every finder method there must be a matching
 1176                  // <query> element defined in the deployment descriptor
 1177                  // with the exception of findByPrimaryKey
 1178                  //
 1179                  // JBoss Extension: 'findAll' is _also_ ignored.
 1180                  //
 1181                  if (!method.getName().equals("findByPrimaryKey")
 1182                          && !method.getName().equals("findAll")
 1183                          && !hasMatchingQuery(method, entity))
 1184                  {
 1185                     fireSpecViolationEvent(entity, method,
 1186                             new Section("10.5.6"));
 1187                     status = false;
 1188                  }
 1189               } // if( entity.isCMP() )
 1190            }
 1191            else   // Neither Create nor Finder method
 1192            {
 1193               // Each home method MUST match a method defined in the
 1194               // entity bean class.
 1195               //
 1196               // The matching ejbHome<METHOD> method MUST have the same
 1197               // number and types of arguments, and a matching return
 1198               // type.
 1199               //
 1200               // Spec 12.2.9
 1201               //
 1202               if (!hasMatchingEJBHome(bean, method))
 1203               {
 1204                  fireSpecViolationEvent(entity, method,
 1205                          new Section("12.2.9.m"));
 1206                  status = false;
 1207               }
 1208            }
 1209         } // while( methods.hasNext() )
 1210   
 1211   
 1212         return status;
 1213      }
 1214   
 1215      /*
 1216       * Verify Entity Bean Local Home Interface
 1217       */
 1218      private boolean verifyEntityLocalHome(EntityMetaData entity)
 1219      {
 1220         boolean status = true;
 1221   
 1222         // Entity bean's local home interface MUST extend the
 1223         // javax.ejb.EJBLocalHome interface.
 1224         //
 1225         // Spec 12.2.11
 1226         //
 1227         if (!hasEJBLocalHomeInterface(localHome))
 1228         {
 1229            fireSpecViolationEvent(entity, new Section("12.2.11.a"));
 1230            status = false;
 1231         }
 1232   
 1233         // The methods defined in the entity bean's home interface MUST
 1234         // NOT have java.rmi.RemoteException in their throws clause.
 1235         //
 1236         // Spec 12.2.11
 1237         //
 1238         Iterator homeMethods = Arrays.asList(localHome.getMethods()).iterator();
 1239         while (homeMethods.hasNext())
 1240         {
 1241            Method method = (Method)homeMethods.next();
 1242   
 1243            if (throwsRemoteException(method))
 1244            {
 1245               fireSpecViolationEvent(entity, method, new Section("12.2.11.b"));
 1246               status = false;
 1247            }
 1248         }
 1249   
 1250         // Each method defined in the entity bean's local home interface
 1251         // must be one of the following:
 1252         //
 1253         //    - a create method
 1254         //    - a finder method
 1255         //    - a home method
 1256         //
 1257         // Spec 12.2.11
 1258         //
 1259         homeMethods = Arrays.asList(localHome.getMethods()).iterator();
 1260         while (homeMethods.hasNext())
 1261         {
 1262            Method method = (Method)homeMethods.next();
 1263   
 1264            // Do not check the methods of the javax.ejb.EJBLocalHome interface
 1265            if (method.getDeclaringClass().getName().equals(EJB_LOCAL_HOME_INTERFACE))
 1266               continue;
 1267   
 1268            if (isCreateMethod(method))
 1269            {
 1270               // Each create(...) method in the entity bean's local home
 1271               // interface MUST have a matching ejbCreate(...) method in
 1272               // the entity bean's class.
 1273               //
 1274               // Each create(...) method in the entity bean's local home
 1275               // interface MUST have the same number and types of
 1276               // arguments to its matching ejbCreate(...) method.
 1277               //
 1278               // The return type for a create(...) method MUST be the
 1279               // entity bean's local interface type.
 1280               //
 1281               // All the exceptions defined in the throws clause of the
 1282               // matching ejbCreate(...) and ejbPostCreate(...) methods of
 1283               // the enterprise bean class MUST be included in the throws
 1284               // clause of a matching create(...) method.
 1285               //
 1286               // The throws clause of a create(...) method MUST include
 1287               // the javax.ejb.CreateException.
 1288               //
 1289               // Spec 12.2.11
 1290               //
 1291               if (!hasMatchingEJBCreate(bean, method))
 1292               {
 1293                  fireSpecViolationEvent(entity, method,
 1294                          new Section("12.2.11.e"));
 1295                  status = false;
 1296               }
 1297   
 1298               if (!hasLocalReturnType(entity, method))
 1299               {
 1300                  fireSpecViolationEvent(entity, method,
 1301                          new Section("12.2.11.f"));
 1302                  status = false;
 1303               }
 1304   
 1305               if (hasMatchingEJBCreate(bean, method)
 1306                       && hasMatchingEJBPostCreate(bean, method))
 1307               {
 1308                  Method ejbCreate = getMatchingEJBCreate(bean, method);
 1309                  Method ejbPostCreate = getMatchingEJBPostCreate(bean, method);
 1310   
 1311                  if (!(hasMatchingExceptions(ejbCreate, method)
 1312                          && hasMatchingExceptions(ejbPostCreate, method)))
 1313                  {
 1314                     fireSpecViolationEvent(entity, method,
 1315                             new Section("12.2.11.g"));
 1316                  }
 1317               }
 1318   
 1319               if (!throwsCreateException(method))
 1320               {
 1321                  fireSpecViolationEvent(entity, method,
 1322                          new Section("12.2.11.h"));
 1323                  status = false;
 1324               }
 1325            }
 1326            else if (isFinderMethod(method))
 1327            {
 1328               // Each finder method MUST match one of the ejbFind<METHOD>
 1329               // methods defined in the entity bean class.
 1330               //
 1331               // The matching ejbFind<METHOD> method MUST have the same
 1332               // number and types of arguments.
 1333               //
 1334               // The return type for a find<METHOD> method MUST be the
 1335               // entity bean's local interface type (single-object finder)
 1336               // or a collection thereof (for a multi-object finder).
 1337               //
 1338               // All the exceptions defined in the throws clause of an
 1339               // ejbFind method of the entity bean class MUST be included
 1340               // in the throws clause of the matching find method of the
 1341               // home interface.
 1342               //
 1343               // The throws clause of a finder method MUST include the
 1344               // javax.ejb.FinderException.
 1345               //
 1346               // Spec 12.2.11
 1347               //
 1348               if (!(hasLocalReturnType(entity, method)
 1349                       || isMultiObjectFinder(method)))
 1350               {
 1351                  fireSpecViolationEvent(entity, method,
 1352                          new Section("12.2.11.j"));
 1353                  status = false;
 1354               }
 1355   
 1356               if (!throwsFinderException(method))
 1357               {
 1358                  fireSpecViolationEvent(entity, method,
 1359                          new Section("12.2.11.k"));
 1360                  status = false;
 1361               }
 1362   
 1363               if (entity.isCMP())
 1364               {
 1365                  // The entity bean class does not implement the finder
 1366                  // methods. The implementation of the finder methods are
 1367                  // provided by the Container
 1368                  //
 1369                  // Spec 10.6.2
 1370                  //
 1371                  if (hasMatchingEJBFind(bean, method))
 1372                  {
 1373                     fireSpecViolationEvent(entity, method,
 1374                             new Section("10.6.2.j"));
 1375                     status = false;
 1376                  }
 1377   
 1378                  // For every finder method there must be a matching
 1379                  // <query> element defined in the deployment descriptor
 1380                  // with the exception of findByPrimaryKey
 1381                  //
 1382                  // JBoss Extension: 'findAll' is _also_ ignored.
 1383                  //
 1384                  // Spec 10.5.6
 1385                  //
 1386                  if (!method.getName().equals("findByPrimaryKey")
 1387                          && !method.getName().equals("findAll")
 1388                          && !hasMatchingQuery(method, entity))
 1389                  {
 1390                     fireSpecViolationEvent(entity, method,
 1391                             new Section("10.5.6"));
 1392                     status = false;
 1393                  }
 1394               }
 1395   
 1396               if (entity.isBMP())
 1397               {
 1398                  if (!hasMatchingEJBFind(bean, method))
 1399                  {
 1400                     fireSpecViolationEvent(entity, method,
 1401                             new Section("12.2.11.i"));
 1402                     status = false;
 1403                  }
 1404                  else
 1405                  {
 1406                     Method ejbFind = getMatchingEJBFind(bean, method);
 1407   
 1408                     if (!(hasMatchingExceptions(ejbFind, method)))
 1409                     {
 1410                        fireSpecViolationEvent(entity, method,
 1411                                new Section("12.2.11.l"));
 1412                     }
 1413                  }
 1414               }
 1415            }
 1416            else
 1417            {
 1418               // Each home method MUST match a method defined in the
 1419               // entity bean class.
 1420               //
 1421               // The matching ejbHome<METHOD> method MUST have the same
 1422               // number and types of arguments, and a matching return
 1423               // type.
 1424               //
 1425               // Spec 12.2.9
 1426               //
 1427               if (!hasMatchingEJBHome(bean, method))
 1428               {
 1429                  fireSpecViolationEvent(entity, method,
 1430                          new Section("12.2.11.m"));
 1431                  status = false;
 1432               }
 1433            }
 1434         } // while( homeMethods.hasNext() )
 1435   
 1436         return status;
 1437      }
 1438   
 1439      /*
 1440       * Verify Entity Bean Local Interface
 1441       */
 1442      private boolean verifyEntityLocal(EntityMetaData entity)
 1443      {
 1444         boolean status = true;
 1445   
 1446         // Entity bean's local interface MUST extend
 1447         // the javax.ejb.EJBLocalObject interface.
 1448         //
 1449         // Spec 12.2.10
 1450         //
 1451         if (!hasEJBLocalObjectInterface(local))
 1452         {
 1453            fireSpecViolationEvent(entity, new Section("12.2.10.a"));
 1454            status = false;
 1455         }
 1456   
 1457         // The methods defined in the entity bean's local interface MUST
 1458         // NOT have java.rmi.RemoteException in their throws clause.
 1459         //
 1460         // Spec 12.2.10
 1461         //
 1462         Iterator localMethods = Arrays.asList(local.getMethods()).iterator();
 1463         while (localMethods.hasNext())
 1464         {
 1465            Method method = (Method)localMethods.next();
 1466   
 1467            if (throwsRemoteException(method))
 1468            {
 1469               fireSpecViolationEvent(entity, method, new Section("12.2.10.b"));
 1470               status = false;
 1471            }
 1472         }
 1473   
 1474         // For each method defined in the local interface, there MUST be
 1475         // a matching method in the entity bean's class. The matching
 1476         // method MUST have:
 1477         //
 1478         //     - The same name.
 1479         //     - The same number and types of its arguments.
 1480         //     - The same return type.
 1481         //     - All the exceptions defined in the throws clause of the
 1482         //       matching method of the enterprise Bean class must be
 1483         //       defined in the throws clause of the method of the local
 1484         //       interface.
 1485         //
 1486         // Spec 12.2.10
 1487         //
 1488         localMethods = Arrays.asList(local.getMethods()).iterator();
 1489         while (localMethods.hasNext())
 1490         {
 1491            Method method = (Method)localMethods.next();
 1492   
 1493            // Do not check the methods of the javax.ejb.EJBLocalObject
 1494            // interface
 1495            if (method.getDeclaringClass().getName().equals(EJB_LOCAL_OBJECT_INTERFACE))
 1496               continue;
 1497   
 1498            if (!hasMatchingMethod(bean, method))
 1499            {
 1500               fireSpecViolationEvent(entity, method, new Section("12.2.10.c"));
 1501               status = false;
 1502            }
 1503   
 1504            if (hasMatchingMethod(bean, method))
 1505            {
 1506               try
 1507               {
 1508                  Method beanMethod = bean.getMethod(method.getName(),
 1509                          method.getParameterTypes());
 1510   
 1511                  if (!hasMatchingReturnType(beanMethod, method))
 1512                  {
 1513                     fireSpecViolationEvent(entity, method,
 1514                             new Section("12.2.10.d"));
 1515                     status = false;
 1516                  }
 1517   
 1518                  if (!hasMatchingExceptions(beanMethod, method))
 1519                  {
 1520                     fireSpecViolationEvent(entity, method,
 1521                             new Section("12.2.10.e"));
 1522   
 1523                     status = false;
 1524                  }
 1525               }
 1526               catch (NoSuchMethodException ignored)
 1527               {
 1528               }
 1529            }
 1530         }
 1531   
 1532         return status;
 1533      }
 1534   
 1535      /*
 1536       * Verify Entity Bean Remote Interface
 1537       */
 1538      private boolean verifyEntityRemote(EntityMetaData entity)
 1539      {
 1540         boolean status = true;
 1541   
 1542         // Entity bean's remote interface MUST extend
 1543         // the javax.ejb.EJBObject interface.
 1544         //
 1545         // Spec 9.2.7
 1546         //
 1547         if (!hasEJBObjectInterface(remote))
 1548         {
 1549            fireSpecViolationEvent(entity, new Section("9.2.7.a"));
 1550            status = false;
 1551         }
 1552   
 1553         // The methods defined in the entity bean's remote interface MUST
 1554         // have valid RMI-IIOP argument types.
 1555         //
 1556         // The methods defined in the entity bean's home interface MUST
 1557         // have valid RMI-IIOP return types.
 1558         //
 1559         // The methods defined in the entity bean's home interface MUST
 1560         // have java.rmi.RemoteException in their throws clause.
 1561         //
 1562         // Spec 9.2.7
 1563         //
 1564         Iterator it = Arrays.asList(remote.getMethods()).iterator();
 1565         while (it.hasNext())
 1566         {
 1567            Method method = (Method)it.next();
 1568   
 1569            if (!hasLegalRMIIIOPArguments(method))
 1570            {
 1571               fireSpecViolationEvent(entity, method, new Section("9.2.7.b"));
 1572               status = false;
 1573            }
 1574   
 1575            if (!hasLegalRMIIIOPReturnType(method))
 1576            {
 1577               fireSpecViolationEvent(entity, method, new Section("9.2.7.c"));
 1578               status = false;
 1579            }
 1580   
 1581            if (!hasLegalRMIIIOPExceptionTypes(method))
 1582            {
 1583               fireSpecViolationEvent(entity, method, new Section("9.2.7.h"));
 1584               status = false;
 1585            }
 1586   
 1587            if (!throwsRemoteException(method))
 1588            {
 1589               fireSpecViolationEvent(entity, method, new Section("9.2.7.d"));
 1590               status = false;
 1591            }
 1592         }
 1593   
 1594         // For each method defined in the remote interface, there MUST be
 1595         // a matching method in the entity bean's class. The matching
 1596         // method MUST have:
 1597         //
 1598         //     - The same name.
 1599         //     - The same number and types of its arguments.
 1600         //     - The same return type.
 1601         //     - All the exceptions defined in the throws clause of the
 1602         //       matching method of the enterprise Bean class must be
 1603         //       defined in the throws clause of the method of the remote
 1604         //       interface.
 1605         //
 1606         // Spec 9.2.7
 1607         //
 1608         it = Arrays.asList(remote.getMethods()).iterator();
 1609         while (it.hasNext())
 1610         {
 1611            Method method = (Method)it.next();
 1612   
 1613            // Do not check the methods of the javax.ejb.EJBObject interface
 1614            if (method.getDeclaringClass().getName().equals(EJB_OBJECT_INTERFACE))
 1615               continue;
 1616   
 1617            if (!hasMatchingMethod(bean, method))
 1618            {
 1619               fireSpecViolationEvent(entity, method, new Section("9.2.7.e"));
 1620               status = false;
 1621            }
 1622   
 1623            if (hasMatchingMethod(bean, method))
 1624            {
 1625               try
 1626               {
 1627                  Method beanMethod = bean.getMethod(method.getName(),
 1628                          method.getParameterTypes());
 1629   
 1630                  if (!hasMatchingReturnType(beanMethod, method))
 1631                  {
 1632                     fireSpecViolationEvent(entity, method,
 1633                             new Section("9.2.7.f"));
 1634                     status = false;
 1635                  }
 1636   
 1637                  if (!hasMatchingExceptions(beanMethod, method))
 1638                  {
 1639                     fireSpecViolationEvent(entity, method,
 1640                             new Section("9.2.7.g"));
 1641                     status = false;
 1642                  }
 1643               }
 1644               catch (NoSuchMethodException ignored)
 1645               {
 1646               }
 1647            }
 1648         }
 1649   
 1650         return status;
 1651      }
 1652   
 1653      /*
 1654       * Verify Entity Bean Class
 1655       */
 1656      private boolean verifyCMPEntityBean(EntityMetaData entity)
 1657      {
 1658         boolean status = true;
 1659   
 1660         // The enterprise bean class MUST implement, directly or
 1661         // indirectly, the javax.ejb.EntityBean interface.
 1662         //
 1663         // Spec 10.6.2
 1664         //
 1665         if (!hasEntityBeanInterface(bean))
 1666         {
 1667            fireSpecViolationEvent(entity, new Section("10.6.2.a"));
 1668            status = false;
 1669         }
 1670   
 1671         // The entity bean class MUST be defined as public and abstract.
 1672         //
 1673         // Spec 10.6.2
 1674         //
 1675         if (!isPublic(bean) || !isAbstract(bean))
 1676         {
 1677            fireSpecViolationEvent(entity, new Section("10.6.2.b"));
 1678            status = false;
 1679         }
 1680   
 1681         // The entity bean class MUST define a public constructor that
 1682         // takes no arguments
 1683         //
 1684         // Spec 10.6.2
 1685         //
 1686         if (!hasDefaultConstructor(bean))
 1687         {
 1688            fireSpecViolationEvent(entity, new Section("10.6.2.c"));
 1689            status = false;
 1690         }
 1691   
 1692         // The entity bean class MUST NOT define the finalize() method.
 1693         //
 1694         // Spec 10.6.2
 1695         //
 1696         if (hasFinalizer(bean))
 1697         {
 1698            fireSpecViolationEvent(entity, new Section("10.6.2.d"));
 1699            status = false;
 1700         }
 1701   
 1702         // The ejbCreate(...) method signatures MUST follow these rules:
 1703         //
 1704         //      - The method MUST be declared as public
 1705         //      - The method MUST NOT be declared as final or static
 1706         //      - The return type MUST be the entity bean's primary key type
 1707         //      --- Only if method is on remote home ---
 1708         //      - The method arguments MUST be legal types for RMI/IIOP
 1709         //      - The method return value type MUST be legal type for RMI/IIOP
 1710         //      --- End of only if method is on remote home ---
 1711         //      - The method must define the javax.ejb.CreateException
 1712         //
 1713         // Spec 10.6.4
 1714         //
 1715         if (hasEJBCreateMethod(bean, false))
 1716         {
 1717            Iterator it = getEJBCreateMethods(bean);
 1718            while (it.hasNext())
 1719            {
 1720               Method ejbCreate = (Method)it.next();
 1721               if (!isPublic(ejbCreate))
 1722               {
 1723                  fireSpecViolationEvent(entity, ejbCreate,
 1724                          new Section("10.6.4.b"));
 1725                  status = false;
 1726               }
 1727   
 1728               if ((isFinal(ejbCreate)) || (isStatic(ejbCreate)))
 1729               {
 1730                  fireSpecViolationEvent(entity, ejbCreate,
 1731                          new Section("10.6.4.c"));
 1732                  status = false;
 1733               }
 1734   
 1735               if (!hasPrimaryKeyReturnType(entity, ejbCreate))
 1736               {
 1737                  fireSpecViolationEvent(entity, ejbCreate,
 1738                          new Section("10.6.4.d"));
 1739                  status = false;
 1740               }
 1741   
 1742               /* FIXME
 1743                *  This is only true if the method is on the remote home
 1744                * interface
 1745                if (!hasLegalRMIIIOPArguments(ejbCreate)) {
 1746                fireSpecViolationEvent(entity, ejbCreate, new Section("10.6.4.d"));
 1747                status = false;
 1748                }
 1749   
 1750                if (!hasLegalRMIIIOPReturnType(ejbCreate)) {
 1751                fireSpecViolationEvent(entity, ejbCreate, new Section("10.5.4.f"));
 1752                status = false;
 1753                }
 1754                */
 1755   
 1756               if (!throwsCreateException(ejbCreate))
 1757               {
 1758                  fireSpecViolationEvent(entity, ejbCreate,
 1759                          new Section("10.6.4.g"));
 1760                  status = false;
 1761               }
 1762            }
 1763         }
 1764   
 1765         // For each ejbCreate(...) method, the entity bean class MUST
 1766         // define a matching ejbPostCreate(...) method.
 1767         //
 1768         // The ejbPostCreate(...) method MUST follow these rules:
 1769         //
 1770         //   - the method MUST be declared as public
 1771         //   - the method MUST NOT be declared as final or static
 1772         //   - the return type MUST be void
 1773         //   - the method arguments MUST be the same as the matching
 1774         //     ejbCreate(...) method
 1775         //
 1776         // Spec 10.6.5
 1777         //
 1778         if (hasEJBCreateMethod(bean, false))
 1779         {
 1780            Iterator it = getEJBCreateMethods(bean);
 1781   
 1782            while (it.hasNext())
 1783            {
 1784               Method ejbCreate = (Method)it.next();
 1785   
 1786               if (!hasMatchingEJBPostCreate(bean, ejbCreate))
 1787               {
 1788                  fireSpecViolationEvent(entity, ejbCreate,
 1789                          new Section("10.6.5.a"));
 1790                  status = false;
 1791               }
 1792   
 1793               if (hasMatchingEJBPostCreate(bean, ejbCreate))
 1794               {
 1795                  Method ejbPostCreate = getMatchingEJBPostCreate(bean,
 1796                          ejbCreate);
 1797   
 1798                  if (!isPublic(ejbPostCreate))
 1799                  {
 1800                     fireSpecViolationEvent(entity, ejbPostCreate,
 1801                             new Section("10.6.5.b"));
 1802                     status = false;
 1803                  }
 1804   
 1805                  if (isStatic(ejbPostCreate))
 1806                  {
 1807                     fireSpecViolationEvent(entity, ejbPostCreate,
 1808                             new Section("10.6.5.c"));
 1809                     status = false;
 1810                  }
 1811   
 1812                  if (isFinal(ejbPostCreate))
 1813                  {
 1814                     fireSpecViolationEvent(entity, ejbPostCreate,
 1815                             new Section("10.6.5.d"));
 1816                     status = false;
 1817                  }
 1818   
 1819                  if (!hasVoidReturnType(ejbPostCreate))
 1820                  {
 1821                     fireSpecViolationEvent(entity, ejbPostCreate,
 1822                             new Section("10.6.5.e"));
 1823                     status = false;
 1824                  }
 1825               }
 1826            }
 1827         }
 1828   
 1829         // The ejbHome(...) method signatures MUST follow these rules:
 1830         //
 1831         //      - The method name MUST have ejbHome as its prefix.
 1832         //      - The method MUST be declared as public
 1833         //      - The method MUST NOT be declared as static.
 1834         //      - The method MUST NOT define the java.rmi.RemoteException
 1835         //
 1836         // Spec 10.6.6
 1837         //
 1838         Iterator it = getEjbHomeMethods(bean);
 1839         while (it.hasNext())
 1840         {
 1841            Method ejbHome = (Method)it.next();
 1842            if (!isPublic(ejbHome))
 1843            {
 1844               fireSpecViolationEvent(entity, ejbHome, new Section("10.6.6.a"));
 1845               status = false;
 1846            }
 1847   
 1848            if (isStatic(ejbHome))
 1849            {
 1850               fireSpecViolationEvent(entity, ejbHome, new Section("10.6.6.b"));
 1851               status = false;
 1852            }
 1853   
 1854            if (throwsRemoteException(ejbHome))
 1855            {
 1856               fireSpecViolationEvent(entity, ejbHome, new Section("10.6.6.c"));
 1857               status = false;
 1858            }
 1859         }
 1860   
 1861         // The CMP entity bean MUST implement get and set accessor methods for
 1862         // each field within the abstract persistance schema.
 1863         //
 1864         // Spec 10.6.2
 1865         //
 1866         it = entity.getCMPFields();
 1867         while (it.hasNext())
 1868         {
 1869            String fieldName = (String)it.next();
 1870            String getName = "get" + fieldName.substring(0, 1).toUpperCase() +
 1871                    fieldName.substring(1);
 1872            Class fieldType = null;
 1873   
 1874            try
 1875            {
 1876               Method m = bean.getMethod(getName, new Class[0]);
 1877               fieldType = m.getReturnType();
 1878   
 1879               // The getter must not return 'void' according to the JavaBeans
 1880               // Spec
 1881               if (fieldType == Void.TYPE)
 1882               {
 1883                  fireSpecViolationEvent(entity,
 1884                          new Section("jb.7.1.b", "Field: " + fieldName));
 1885               }
 1886            }
 1887            catch (NoSuchMethodException nsme)
 1888            {
 1889               fireSpecViolationEvent(entity,
 1890                       new Section("10.6.2.g", "Field: " + fieldName));
 1891               status = false;
 1892            }
 1893   
 1894            String setName = "set" + fieldName.substring(0, 1).toUpperCase() +
 1895                    fieldName.substring(1);
 1896            Class[] args = new Class[1];
 1897            args[0] = fieldType;
 1898   
 1899            try
 1900            {
 1901               Method m = bean.getMethod(setName, args);
 1902               fieldType = m.getReturnType();
 1903   
 1904               // According to the JavaBeans Spec, a setter method must
 1905               // return 'void'
 1906               if (fieldType != Void.TYPE)
 1907               {
 1908                  fireSpecViolationEvent(entity,
 1909                          new Section("jb.7.1.a", "Field: " + fieldName));
 1910               }
 1911            }
 1912            catch (NoSuchMethodException nsme)
 1913            {
 1914               // Try with java.util.Collection
 1915               //
 1916               // FIXME: This should only be tried for CMR methods; a CMP
 1917               //        setter cannot accept a Collection!
 1918               try
 1919               {
 1920                  args[0] = classloader.loadClass("java.util.Collection");
 1921                  Method m = bean.getMethod(setName, args);
 1922               }
 1923               catch (NoSuchMethodException nsme2)
 1924               {
 1925                  fireSpecViolationEvent(entity,
 1926                          new Section("10.6.2.h", "Field: " + fieldName));
 1927                  status = false;
 1928               }
 1929               catch (ClassNotFoundException cnfe)
 1930               {
 1931                  // Something is really broken
 1932               }
 1933            }
 1934         }
 1935   
 1936         // The ejbSelect(...) method signatures MUST follow these rules:
 1937         //
 1938         //      - The method name MUST have ejbSelect as its prefix.
 1939         //      - The method MUST be declared as public
 1940         //      - The method MUST be declared as abstract.
 1941         //      - The method MUST define the javax.ejb.FinderException
 1942         //
 1943         // Spec 10.6.7
 1944         //
 1945         it = getEjbSelectMethods(bean);
 1946         while (it.hasNext())
 1947         {
 1948            Method ejbSelect = (Method)it.next();
 1949   
 1950            if (!isPublic(ejbSelect))
 1951            {
 1952               fireSpecViolationEvent(entity, ejbSelect, new Section("10.6.7.a"));
 1953               status = false;
 1954            }
 1955   
 1956            if (!isAbstract(ejbSelect))
 1957            {
 1958               fireSpecViolationEvent(entity, ejbSelect, new Section("10.6.7.b"));
 1959               status = false;
 1960            }
 1961   
 1962            if (!throwsFinderException(ejbSelect))
 1963            {
 1964               fireSpecViolationEvent(entity, ejbSelect, new Section("10.6.7.c"));
 1965               status = false;
 1966            }
 1967   
 1968            if (!hasMatchingQuery(ejbSelect, entity))
 1969            {
 1970               fireSpecViolationEvent(entity, ejbSelect, new Section("10.5.7"));
 1971               status = false;
 1972            }
 1973         }
 1974   
 1975         // A CMP Entity Bean must not define Finder methods.
 1976         //
 1977         // Spec 10.6.2
 1978         //
 1979         if (hasFinderMethod(bean))
 1980         {
 1981            fireSpecViolationEvent(entity, new Section("10.6.2.i"));
 1982            status = false;
 1983         }
 1984   
 1985         return status;
 1986      }
 1987   
 1988      /*
 1989       * Verify BMP Entity Class
 1990       */
 1991      private boolean verifyBMPEntityBean(EntityMetaData entity)
 1992      {
 1993         boolean status = true;
 1994   
 1995         // The enterprise bean class MUST implement, directly or
 1996         // indirectly, the javax.ejb.EntityBean interface.
 1997         //
 1998         // Spec 12.2.2
 1999         //
 2000         if (!hasEntityBeanInterface(bean))
 2001         {
 2002            fireSpecViolationEvent(entity, new Section("12.2.2.a"));
 2003            status = false;
 2004         }
 2005   
 2006         // The entity bean class MUST be defined as public and NOT abstract.
 2007         //
 2008         // Spec 12.2.2
 2009         //
 2010         if (!isPublic(bean) || isAbstract(bean))
 2011         {
 2012            fireSpecViolationEvent(entity, new Section("12.2.2.b"));
 2013            status = false;
 2014         }
 2015   
 2016         // The entity bean class MUST NOT be defined as final.
 2017         //
 2018         // Spec 12.2.2
 2019         //
 2020         if (isFinal(bean))
 2021         {
 2022            fireSpecViolationEvent(entity, new Section("12.2.2.c"));
 2023            status = false;
 2024         }
 2025   
 2026         // The entity bean class MUST define a public constructor that
 2027         // takes no arguments
 2028         //
 2029         // Spec 12.2.2
 2030         //
 2031         if (!hasDefaultConstructor(bean))
 2032         {
 2033            fireSpecViolationEvent(entity, new Section("12.2.2.d"));
 2034            status = false;
 2035         }
 2036   
 2037         // The entity bean class MUST NOT define the finalize() method.
 2038         //
 2039         // Spec 12.2.2
 2040         //
 2041         if (hasFinalizer(bean))
 2042         {
 2043            fireSpecViolationEvent(entity, new Section("12.2.2.e"));
 2044            status = false;
 2045         }
 2046   
 2047         // The ejbCreate(...) method signatures MUST follow these rules:
 2048         //
 2049         //      - The method MUST be declared as public
 2050         //      - The method MUST NOT be declared as final or static
 2051         //      - The return type MUST be the entity bean's primary key type
 2052         //      --- If the method is on the remote home interface ---
 2053         //      - The method arguments MUST be legal types for RMI/IIOP
 2054         //      - The method return value type MUST be legal type for RMI/IIOP
 2055         //      --- End if the method is on the remote home interface ---
 2056         //
 2057         // Spec 12.2.3
 2058         //
 2059         if (hasEJBCreateMethod(bean, false))
 2060         {
 2061            Iterator it = getEJBCreateMethods(bean);
 2062            while (it.hasNext())
 2063            {
 2064               Method ejbCreate = (Method)it.next();
 2065               if (!isPublic(ejbCreate))
 2066               {
 2067                  fireSpecViolationEvent(entity, ejbCreate,
 2068                          new Section("12.2.3.a"));
 2069                  status = false;
 2070               }
 2071   
 2072               if ((isFinal(ejbCreate)) || (isStatic(ejbCreate)))
 2073               {
 2074                  fireSpecViolationEvent(entity, ejbCreate,
 2075                          new Section("12.2.3.b"));
 2076                  status = false;
 2077               }
 2078   
 2079               if (!hasPrimaryKeyReturnType(entity, ejbCreate))
 2080               {
 2081                  fireSpecViolationEvent(entity, ejbCreate,
 2082                          new Section("12.2.3.c"));
 2083                  status = false;
 2084               }
 2085   
 2086               /* FIXME
 2087                * This code needs to only be invoked if the method is on the
 2088                * remote home.
 2089                if (!hasLegalRMIIIOPArguments(ejbCreate)) {
 2090                fireSpecViolationEvent(entity, ejbCreate, new Section("9.2.3.d"));
 2091                status = false;
 2092                }
 2093                if (!hasLegalRMIIIOPReturnType(ejbCreate)) {
 2094                fireSpecViolationEvent(entity, ejbCreate, new Section("9.2.3.e"));
 2095                status = false;
 2096                }
 2097               */
 2098            }
 2099         }
 2100   
 2101         // For each ejbCreate(...) method, the entity bean class MUST
 2102         // define a matching ejbPostCreate(...) method.
 2103         //
 2104         // The ejbPostCreate(...) method MUST follow these rules:
 2105         //
 2106         //   - the method MUST be declared as public
 2107         //   - the method MUST NOT be declared as final or static
 2108         //   - the return type MUST be void
 2109         //   - the method arguments MUST be the same as the matching
 2110         //     ejbCreate(...) method
 2111         //
 2112         // Spec 12.2.4
 2113         //
 2114         if (hasEJBCreateMethod(bean, false))
 2115         {
 2116            Iterator it = getEJBCreateMethods(bean);
 2117            while (it.hasNext())
 2118            {
 2119               Method ejbCreate = (Method)it.next();
 2120   
 2121               if (!hasMatchingEJBPostCreate(bean, ejbCreate))
 2122               {
 2123                  fireSpecViolationEvent(entity, ejbCreate,
 2124                          new Section("12.2.4.a"));
 2125                  status = false;
 2126               }
 2127   
 2128               if (hasMatchingEJBPostCreate(bean, ejbCreate))
 2129               {
 2130                  Method ejbPostCreate = getMatchingEJBPostCreate(bean,
 2131                          ejbCreate);
 2132   
 2133                  if (!isPublic(ejbPostCreate))
 2134                  {
 2135                     fireSpecViolationEvent(entity, ejbPostCreate,
 2136                             new Section("12.2.4.b"));
 2137                     status = false;
 2138                  }
 2139   
 2140                  if (isStatic(ejbPostCreate) || isFinal(ejbPostCreate))
 2141                  {
 2142                     fireSpecViolationEvent(entity, ejbPostCreate,
 2143                             new Section("12.2.4.c"));
 2144                     status = false;
 2145                  }
 2146   
 2147                  if (!hasVoidReturnType(ejbPostCreate))
 2148                  {
 2149                     fireSpecViolationEvent(entity, ejbPostCreate,
 2150                             new Section("12.2.4.d"));
 2151                     status = false;
 2152                  }
 2153               }
 2154            }
 2155         }
 2156   
 2157         // Every entity bean MUST define the ejbFindByPrimaryKey method.
 2158         //
 2159         // The return type for the ejbFindByPrimaryKey method MUST be the
 2160         // primary key type.
 2161         //
 2162         // The ejbFindByPrimaryKey method MUST be a single-object finder.
 2163         //
 2164         // Spec 12.2.5
 2165         //
 2166         if (!hasEJBFindByPrimaryKey(bean))
 2167         {
 2168            fireSpecViolationEvent(entity, new Section("12.2.5.e"));
 2169            status = false;
 2170         }
 2171   
 2172         if (hasEJBFindByPrimaryKey(bean))
 2173         {
 2174            Method ejbFindByPrimaryKey = getEJBFindByPrimaryKey(bean);
 2175   
 2176            if (!hasPrimaryKeyReturnType(entity, ejbFindByPrimaryKey))
 2177            {
 2178               fireSpecViolationEvent(entity, ejbFindByPrimaryKey,
 2179                       new Section("12.2.5.e1"));
 2180               status = false;
 2181            }
 2182   
 2183            if (!isSingleObjectFinder(entity, ejbFindByPrimaryKey))
 2184            {
 2185               fireSpecViolationEvent(entity, ejbFindByPrimaryKey,
 2186                       new Section("12.2.5.e2"));
 2187               status = false;
 2188            }
 2189         }
 2190   
 2191         // A finder method MUST be declared as public.
 2192         //
 2193         // A finder method MUST NOT be declared as static.
 2194         //
 2195         // A finder method MUST NOT be declared as final.
 2196         //
 2197         // The finder method argument types MUST be legal types for
 2198         // RMI/IIOP
 2199         //
 2200         // The finder method return type MUST be either the entity bean's
 2201         // primary key type, or java.lang.util.Enumeration interface or
 2202         // java.lang.util.Collection interface.
 2203         //
 2204         // Spec 12.2.5
 2205         //
 2206         if (hasFinderMethod(bean))
 2207         {
 2208            Iterator it = getEJBFindMethods(bean);
 2209            while (it.hasNext())
 2210            {
 2211               Method finder = (Method)it.next();
 2212   
 2213               if (!isPublic(finder))
 2214               {
 2215                  fireSpecViolationEvent(entity, finder, new Section("12.2.5.a"));
 2216                  status = false;
 2217               }
 2218   
 2219               if (isFinal(finder) || isStatic(finder))
 2220               {
 2221                  fireSpecViolationEvent(entity, finder, new Section("12.2.5.b"));
 2222                  status = false;
 2223               }
 2224   
 2225               /** FIXME
 2226                * this path should only get invoked if the finder is on the
 2227                * remote interface.
 2228                if (!hasLegalRMIIIOPArguments(finder)) {
 2229                fireSpecViolationEvent(entity, finder, new Section("12.2.5.c"));
 2230                status = false;
 2231                }
 2232                */
 2233   
 2234               if (!(isSingleObjectFinder(entity, finder)
 2235                       || isMultiObjectFinder(finder)))
 2236               {
 2237                  fireSpecViolationEvent(entity, finder, new Section("12.2.5.d"));
 2238                  status = false;
 2239               }
 2240            }
 2241         }
 2242   
 2243         // The ejbHome(...) method signatures MUST follow these rules:
 2244         //
 2245         //      - The method name MUST have ejbHome as its prefix.
 2246         //      - The method MUST be declared as public
 2247         //      - The method MUST NOT be declared as static.
 2248         //      - The method MUST NOT define the java.rmi.RemoteException
 2249         //
 2250         // Spec 10.6.6
 2251         //
 2252         Iterator it = getEjbHomeMethods(bean);
 2253         while (it.hasNext())
 2254         {
 2255            Method ejbHome = (Method)it.next();
 2256   
 2257            if (!isPublic(ejbHome))
 2258            {
 2259               fireSpecViolationEvent(entity, ejbHome, new Section("10.6.6.a"));
 2260               status = false;
 2261            }
 2262   
 2263            if (isStatic(ejbHome))
 2264            {
 2265               fireSpecViolationEvent(entity, ejbHome, new Section("10.6.6.b"));
 2266               status = false;
 2267            }
 2268   
 2269            if (throwsRemoteException(ejbHome))
 2270            {
 2271               fireSpecViolationEvent(entity, ejbHome, new Section("10.6.6.c"));
 2272               status = false;
 2273            }
 2274         }
 2275   
 2276         return status;
 2277      }
 2278   
 2279      /*
 2280       * Verify Primary Key
 2281       */
 2282      private boolean verifyPrimaryKey(EntityMetaData entity)
 2283      {
 2284         boolean status = true;
 2285         boolean cmp = entity.isCMP();
 2286   
 2287         if (entity.getPrimaryKeyClass() == null
 2288                 || entity.getPrimaryKeyClass().length() == 0)
 2289         {
 2290            if (cmp)
 2291               fireSpecViolationEvent(entity, new Section("10.6.1.a"));
 2292            else
 2293               fireSpecViolationEvent(entity, new Section("12.2.1.a"));
 2294   
 2295            // We can't get any further if there's no PK class specified!
 2296            return false;
 2297         }
 2298   
 2299         // FIXME - Still missing the bits from 10.8.2 for CMP primary
 2300         // keys.  Primarily the class must be public, all fields in the
 2301         // class must be public and the fields must also be a subset of
 2302         // the CMP fields within the bean.
 2303         //
 2304         Class cls = null;
 2305         try
 2306         {
 2307            cls = classloader.loadClass(entity.getPrimaryKeyClass());
 2308         }
 2309         catch (ClassNotFoundException e)
 2310         {
 2311            if (cmp)
 2312               fireSpecViolationEvent(entity, new Section("10.6.13.a"));
 2313            else
 2314               fireSpecViolationEvent(entity, new Section("12.2.12.a"));
 2315   
 2316            // Can't do any other checks if the class is null!
 2317            return false;
 2318         }
 2319   
 2320         // The primary key type must be a valid type in RMI-IIOP.
 2321         //
 2322         // Spec 10.6.13 & 12.2.12
 2323         //
 2324         if (!isRMIIDLValueType(cls))
 2325         {
 2326            if (cmp)
 2327               fireSpecViolationEvent(entity, new Section("10.6.13.b"));
 2328            else
 2329               fireSpecViolationEvent(entity, new Section("12.2.12.b"));
 2330            status = false;
 2331         }
 2332   
 2333         // No primary key field specified, just a primary key class.
 2334         if (entity.getPrimKeyField() == null ||
 2335                 entity.getPrimKeyField().length() == 0)
 2336         {
 2337            // This is a check for some interesting implementation of
 2338            // equals() and hashCode().  I am not sure how well it works in
 2339            // the end.
 2340            //
 2341            if (!cls.getName().equals("java.lang.Object"))
 2342            {
 2343               Object one, two;
 2344   
 2345               try
 2346               {
 2347                  one = cls.newInstance();
 2348                  two = cls.newInstance();
 2349                  try
 2350                  {
 2351                     if (!one.equals(two))
 2352                     {
 2353                        if (cmp)
 2354                        {
 2355                           // fireSpecViolationEvent(entity, new Section("10.6.13.c"));
 2356                           log.warn("Default instances of primary key: " + cls
 2357                                   + " do not equate, check your equals method");
 2358                        }
 2359                        else
 2360                        {
 2361                           //fireSpecViolationEvent(entity, new Section("12.2.12.c"));
 2362                           log.warn("Default instances of primary key: " + cls
 2363                                   + " do not equate, check your equals method");
 2364                        }
 2365                        status = true;
 2366                     }
 2367                  }
 2368                  catch (NullPointerException e)
 2369                  {
 2370                     // That's OK - the implementor expected the fields to
 2371                     // have values
 2372                  }
 2373   
 2374                  try
 2375                  {
 2376                     if (one.hashCode() != two.hashCode())
 2377                     {
 2378                        if (cmp)
 2379                        {
 2380                           //fireSpecViolationEvent(entity, new Section("10.6.13.d"));
 2381                           log.warn("Default instances of primary key: " + cls
 2382                                   + " do not have the same hash, check your hashCode method");
 2383                        }
 2384                        else
 2385                        {
 2386                           //fireSpecViolationEvent(entity, new Section("12.2.12.d"));
 2387                           log.warn("Default instances of primary key: " + cls
 2388                                   + " do not have the same hash, check your hashCode method");
 2389                        }
 2390                        status = true;
 2391                     }
 2392                  }
 2393                  catch (NullPointerException e)
 2394                  {
 2395                     // That's OK - the implementor expected the fields to have values
 2396                  }
 2397               }
 2398               catch (IllegalAccessException e)
 2399               {
 2400                  // If CMP primary key class MUST have a public
 2401                  // constructor with no parameters.  10.8.2.a
 2402                  ///
 2403                  if (cmp)
 2404                  {
 2405                     fireSpecViolationEvent(entity, new Section("10.8.2.a"));
 2406                     status = false;
 2407                  }
 2408               }
 2409               catch (InstantiationException e)
 2410               {
 2411                  //Not sure what condition this is at the moment - JMW
 2412                  //fireSpecViolationEvent(entity, new Section("9.2.9.a"));
 2413                  //status = false;
 2414               }
 2415            }
 2416         }
 2417         else
 2418         {
 2419            //  BMP Beans MUST not include the primkey-field element in
 2420            //  their deployment descriptor.  Deployment descriptor comment
 2421            //
 2422            if (entity.isBMP())
 2423            {
 2424               fireSpecViolationEvent(entity, new Section("dd.a"));
 2425               status = false;
 2426            }
 2427   
 2428            // The primary keyfield MUST be a CMP field within the
 2429            // entity bean.
 2430            //
 2431            // Spec 10.8.1
 2432            //
 2433            boolean found = false;
 2434            Iterator it = entity.getCMPFields();
 2435            while (it.hasNext())
 2436            {
 2437               String fieldName = (String)it.next();
 2438               if (fieldName.equals(entity.getPrimKeyField()))
 2439               {
 2440                  found = true;
 2441                  break;
 2442               }
 2443            }
 2444   
 2445            if (!found)
 2446            {
 2447               status = false;
 2448               fireSpecViolationEvent(entity, new Section("10.8.1.b"));
 2449            }
 2450   
 2451            try
 2452            {
 2453               // The class of the primary key field MUST match the
 2454               // primary key class specified for the entity bean.  We
 2455               // figure out the class of this field by getting the
 2456               // return type of the get<FieldName> accessor method.
 2457               //
 2458               // Spec 10.8.1
 2459               //
 2460               String pkField = entity.getPrimKeyField();
 2461               String methodName = "get" +
 2462                       pkField.substring(0, 1).toUpperCase() + pkField.substring(1);
 2463   
 2464               Method method = bean.getMethod(methodName, new Class[0]);
 2465               if (!entity.getPrimaryKeyClass().equals(method.getReturnType().getName())
 2466               )
 2467               {
 2468                  status = false;
 2469                  fireSpecViolationEvent(entity, new Section("10.8.1.a"));
 2470               }
 2471   
 2472            }
 2473            catch (NoSuchMethodException e)
 2474            {
 2475               // The primary keyfield MUST be a CMP field within the
 2476               // entity bean.
 2477               //
 2478               // Spec 10.8.1
 2479               //
 2480               status = false;
 2481               fireSpecViolationEvent(entity, new Section("10.8.1.b"));
 2482            }
 2483         }
 2484   
 2485         return status;
 2486      }
 2487   
 2488      /*
 2489       * Verify Message Driven Bean
 2490       */
 2491      protected boolean verifyMessageDrivenBean(MessageDrivenMetaData mdBean)
 2492      {
 2493         boolean status = true;
 2494   
 2495         // A message driven bean MUST implement, directly or indirectly,
 2496         // javax.ejb.MessageDrivenBean interface.
 2497         //
 2498         // Spec 15.7.2
 2499         //
 2500         if (!hasMessageDrivenBeanInterface(bean))
 2501         {
 2502            fireSpecViolationEvent(mdBean, new Section("15.7.2.a"));
 2503            status = false;
 2504         }
 2505   
 2506         // A message driven bean MUST implement, directly or indirectly,
 2507         // javax.jms.MessageListener interface.
 2508         //
 2509         // Spec 15.7.2
 2510         //
 2511         if (!hasMessageListenerInterface(bean))
 2512         {
 2513            fireSpecViolationEvent(mdBean, new Section("15.7.2.b"));
 2514            status = false;
 2515         }
 2516   
 2517         // The message driven bean class MUST be defined as public.
 2518         //
 2519         // Spec 15.7.2
 2520         //
 2521         if (!isPublic(bean))
 2522         {
 2523            fireSpecViolationEvent(mdBean, new Section("15.7.2.c1"));
 2524            status = false;
 2525         }
 2526   
 2527         // The message driven bean class MUST NOT be final.
 2528         //
 2529         // Spec 15.7.2
 2530         //
 2531         if (isFinal(bean))
 2532         {
 2533            fireSpecViolationEvent(mdBean, new Section("15.7.2.c2"));
 2534            status = false;
 2535         }
 2536   
 2537         // The message driven bean class MUST NOT be abstract.
 2538         //
 2539         // Spec 15.7.2
 2540         //
 2541         if (isAbstract(bean))
 2542         {
 2543            fireSpecViolationEvent(mdBean, new Section("15.7.2.c3"));
 2544            status = false;
 2545         }
 2546   
 2547         // The message driven bean class MUST have a public constructor that
 2548         // takes no arguments.
 2549         //
 2550         // Spec 15.7.2
 2551         //
 2552         if (!hasDefaultConstructor(bean))
 2553         {
 2554            fireSpecViolationEvent(mdBean, new Section("15.7.2.d"));
 2555            status = false;
 2556         }
 2557   
 2558         // The message driven bean class MUST NOT define the finalize() method.
 2559         //
 2560         // Spec 15.7.2
 2561         //
 2562         if (hasFinalizer(bean))
 2563         {
 2564            fireSpecViolationEvent(mdBean, new Section("15.7.2.e"));
 2565            status = false;
 2566         }
 2567   
 2568         // A message driven bean MUST implement the ejbCreate() method.
 2569         // The ejbCreate() method signature MUST follow these rules:
 2570         //
 2571         //      - The method name MUST be ejbCreate
 2572         //      - The method MUST be declared as public
 2573         //      - The method MUST NOT be declared as final or static
 2574         //      - The return type MUST be void
 2575         //      - The method arguments MUST have no arguments.
 2576         //      - The method MUST NOT define any application exceptions.
 2577         //
 2578         // Spec 15.7.2, 3
 2579         //
 2580         if (hasEJBCreateMethod(bean, false))
 2581         {
 2582            Iterator it = getEJBCreateMethods(bean);
 2583            Method ejbCreate = (Method)it.next();
 2584   
 2585            if (!isPublic(ejbCreate))
 2586            {
 2587               fireSpecViolationEvent(mdBean, ejbCreate, new Section("15.7.3.b"));
 2588               status = false;
 2589            }
 2590   
 2591            if ((isFinal(ejbCreate)) || (isStatic(ejbCreate)))
 2592            {
 2593               fireSpecViolationEvent(mdBean, ejbCreate, new Section("15.7.3.c"));
 2594               status = false;
 2595            }
 2596   
 2597            if (!hasVoidReturnType(ejbCreate))
 2598            {
 2599               fireSpecViolationEvent(mdBean, ejbCreate, new Section("15.7.3.d"));
 2600               status = false;
 2601            }
 2602   
 2603            if (!hasNoArguments(ejbCreate))
 2604            {
 2605               fireSpecViolationEvent(mdBean, ejbCreate, new Section("15.7.3.e"));
 2606               status = false;
 2607            }
 2608   
 2609            if (!throwsNoException(ejbCreate))
 2610            {
 2611               fireSpecViolationEvent(mdBean, ejbCreate, new Section("15.7.3.f"));
 2612               status = false;
 2613            }
 2614   
 2615            if (it.hasNext())
 2616            {
 2617               fireSpecViolationEvent(mdBean, new Section("15.7.3.a"));
 2618               status = false;
 2619            }
 2620         }
 2621         else
 2622         {
 2623            fireSpecViolationEvent(mdBean, new Section("15.7.3.a"));
 2624            status = false;
 2625         }
 2626   
 2627         // A message driven bean MUST implement the onMessage(...) method.
 2628         // The onMessage() method signature MUST follow these rules:
 2629         //
 2630         //      - The method name MUST be onMessage
 2631         //      - The method MUST be declared as public
 2632         //      - The method MUST NOT be declared as final or static
 2633         //      - The return type MUST be void
 2634         //      - The method arguments MUST have a single argument of type
 2635         //        javax.jms.Message.
 2636         //      - The method MUST NOT define any application exceptions.
 2637         //
 2638         // Spec 15.7.4
 2639         //
 2640         if (hasOnMessageMethod(bean))
 2641         {
 2642            Iterator it = getOnMessageMethods(bean);
 2643            Method onMessage = (Method)it.next();
 2644   
 2645            if (!isPublic(onMessage))
 2646            {
 2647               fireSpecViolationEvent(mdBean, onMessage, new Section("15.7.4.b"));
 2648               status = false;
 2649            }
 2650   
 2651            if ((isFinal(onMessage)) || (isStatic(onMessage)))
 2652            {
 2653               fireSpecViolationEvent(mdBean, onMessage, new Section("15.7.4.c"));
 2654               status = false;
 2655            }
 2656   
 2657            try
 2658            {
 2659               Class message = classloader.loadClass("javax.jms.Message");
 2660               if (!hasSingleArgument(onMessage, message))
 2661               {
 2662                  fireSpecViolationEvent(mdBean, onMessage,
 2663                          new Section("15.7.4.e"));
 2664                  status = false;
 2665               }
 2666   
 2667               if (!throwsNoException(onMessage))
 2668               {
 2669                  fireSpecViolationEvent(mdBean, onMessage,
 2670                          new Section("15.7.4.f"));
 2671                  status = false;
 2672               }
 2673   
 2674               if (it.hasNext())
 2675               {
 2676                  fireSpecViolationEvent(mdBean, new Section("15.7.4.a"));
 2677                  status = false;
 2678               }
 2679            }
 2680            catch (ClassNotFoundException cnfe)
 2681            {
 2682               // javax.jms.Message is not available?!
 2683            }
 2684         }
 2685         else
 2686         {
 2687            fireSpecViolationEvent(mdBean, new Section("15.7.4.a"));
 2688            status = false;
 2689         }
 2690   
 2691         // A message driven bean MUST implement the ejbRemove() method.
 2692         // The ejbRemove() method signature MUST follow these rules:
 2693         //
 2694         //      - The method name MUST be ejbRemove
 2695         //      - The method MUST be declared as public
 2696         //      - The method MUST NOT be declared as final or static
 2697         //      - The return type MUST be void
 2698         //      - The method MUST have no arguments.
 2699         //      - The method MUST NOT define any application exceptions.
 2700         //
 2701         // Spec 15.7.5
 2702         //
 2703         if (hasEJBRemoveMethod(bean))
 2704         {
 2705            Iterator it = getEJBRemoveMethods(bean);
 2706            Method ejbRemove = (Method)it.next();
 2707   
 2708            if (!isPublic(ejbRemove))
 2709            {
 2710               fireSpecViolationEvent(mdBean, ejbRemove, new Section("15.7.5.b"));
 2711               status = false;
 2712            }
 2713   
 2714            if ((isFinal(ejbRemove)) || (isStatic(ejbRemove)))
 2715            {
 2716               fireSpecViolationEvent(mdBean, ejbRemove, new Section("15.7.5.c"));
 2717               status = false;
 2718            }
 2719   
 2720            if (!hasVoidReturnType(ejbRemove))
 2721            {
 2722               fireSpecViolationEvent(mdBean, ejbRemove, new Section("15.7.5.d"));
 2723               status = false;
 2724            }
 2725   
 2726            if (!hasNoArguments(ejbRemove))
 2727            {
 2728               fireSpecViolationEvent(mdBean, ejbRemove, new Section("15.7.5.e"));
 2729               status = false;
 2730            }
 2731   
 2732            if (!throwsNoException(ejbRemove))
 2733            {
 2734               fireSpecViolationEvent(mdBean, ejbRemove, new Section("15.7.5.f"));
 2735               status = false;
 2736            }
 2737   
 2738            if (it.hasNext())
 2739            {
 2740               fireSpecViolationEvent(mdBean, new Section("15.7.5.a"));
 2741               status = false;
 2742            }
 2743         }
 2744         else
 2745         {
 2746            fireSpecViolationEvent(mdBean, new Section("15.7.5.a"));
 2747            status = false;
 2748         }
 2749   
 2750         return status;
 2751      }
 2752   
 2753   }
 2754   
 2755   /*
 2756   vim:ts=3:sw=3:et
 2757   */

Save This Page
Home » jboss-5.0.0.CR1-src » org » jboss » verifier » strategy » [javadoc | source]