KickJava   Java API By Example, From Geeks To Geeks.

Java > Open Source Codes > org > jboss > verifier > strategy > EJBVerifier11


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: EJBVerifier11.java 41248 2006-02-17 08:31:12Z starksm $
25

26 import org.jboss.metadata.EntityMetaData;
27 import org.jboss.metadata.SessionMetaData;
28 import org.jboss.verifier.Section;
29
30 import java.lang.reflect.Field JavaDoc;
31 import java.lang.reflect.Method JavaDoc;
32 import java.util.Arrays JavaDoc;
33 import java.util.Iterator JavaDoc;
34
35
36 /**
37  * Concrete implementation of the <code>VerificationStrategy</code> interface.
38  * This class implements the verification of both session and entity beans for
39  * Enterprise JavaBeans v1.1 specification.
40  *
41  * For more detailed documentation, refer to the
42  * <a HREF="http://java.sun.com/products/ejb/docs.html">Enterprise JavaBeans v1.1, Final Release</a>
43  *
44  * @see org.jboss.verifier.strategy.AbstractVerifier
45  *
46  * @author <a HREF="mailto:juha.lindfors@jboss.org">Juha Lindfors</a>
47  * @author Aaron Mulder (ammulder@alumni.princeton.edu)
48  * @author Vinay Menon (menonv@cpw.co.uk)
49  * @author Thomas.Diesler@jboss.org
50  *
51  * @version $Revision: 41248 $
52  * @since JDK 1.3
53  */

54 public class EJBVerifier11 extends AbstractVerifier
55 {
56
57    /**
58     * Constructs the verifier object.
59     *
60     * @param context context for application information
61     */

62    public EJBVerifier11(VerificationContext context)
63    {
64       super(context);
65    }
66
67    public String JavaDoc getMessageBundle()
68    {
69       return "EJB11Messages.properties";
70    }
71
72    /***********************************************************************
73     *
74     * IMPLEMENTS VERIFICATION STRATEGY INTERFACE
75     *
76     ************************************************************************/

77
78    /**
79     * Verifies the session bean class, home interface and remote interface
80     * against the EJB 1.1 specification.
81     *
82     * @param session XML metadata of the session bean
83     */

84    public void checkSession(SessionMetaData session)
85    {
86       boolean beanVerified = false;
87       boolean homeVerified = false;
88       boolean remoteVerified = false;
89
90       beanVerified = verifySessionBean(session);
91       homeVerified = verifySessionHome(session);
92       remoteVerified = verifySessionRemote(session);
93
94       if (beanVerified && homeVerified && remoteVerified)
95       {
96          /*
97           * Verification for this session bean done. Fire the event
98           * to tell listeneres everything is ok.
99           */

100          fireBeanVerifiedEvent(session);
101       }
102    }
103
104    /**
105     * Verifies the entity bean class, home interface, remote interface and
106     * primary key class against the EJB 1.1 specification.
107     *
108     * @param entity XML metadata of the session bean
109     */

110    public void checkEntity(EntityMetaData entity)
111    {
112       boolean pkVerified = false;
113       boolean beanVerified = false;
114       boolean homeVerified = false;
115       boolean remoteVerified = false;
116
117       beanVerified = verifyEntityBean(entity);
118       homeVerified = verifyEntityHome(entity);
119       remoteVerified = verifyEntityRemote(entity);
120       pkVerified = verifyPrimaryKey(entity);
121
122       if (beanVerified && homeVerified && remoteVerified && pkVerified)
123       {
124          /*
125           * Verification for this entity bean done. Fire the event
126           * to tell listeneres everything is ok.
127           */

128          fireBeanVerifiedEvent(entity);
129       }
130    }
131
132    public boolean isCreateMethod(Method JavaDoc m)
133    {
134       return m.getName().equals(CREATE_METHOD);
135    }
136
137    public boolean isEjbCreateMethod(Method JavaDoc m)
138    {
139       return m.getName().equals(EJB_CREATE_METHOD);
140    }
141
142
143 /*
144  *****************************************************************************
145  *
146  * VERIFY SESSION BEAN HOME INTERFACE
147  *
148  *****************************************************************************
149  */

150
151    /**
152     * Verifies the session bean home interface against the EJB 1.1
153     * specification.
154     *
155     * @param session XML metadata of the session bean
156     */

157    private boolean verifySessionHome(SessionMetaData session)
158    {
159       /*
160        * Indicates whether we issued warnings or not during verification.
161        * This boolean is returned to the caller.
162        */

163       boolean status = true;
164
165       String JavaDoc name = session.getHome();
166       if (name == null)
167          return false;
168
169       try
170       {
171          Class JavaDoc home = classloader.loadClass(name);
172
173          /*
174           * The home interface of a stateless session bean MUST have one
175           * create() method that takes no arguments.
176           *
177           * The create() method MUST return the session bean's remote
178           * interface.
179           *
180           * There CAN NOT be other create() methods in the home interface.
181           *
182           * Spec 6.8
183           */

184          if (session.isStateless())
185          {
186             if (!hasDefaultCreateMethod(home))
187             {
188                fireSpecViolationEvent(session, new Section("6.8.a"));
189                status = false;
190             }
191             else
192             {
193                Method JavaDoc create = getDefaultCreateMethod(home);
194
195                if (!hasRemoteReturnType(session, create))
196                {
197                   fireSpecViolationEvent(session, create, new Section("6.8.b"));
198                   ;
199                   status = false;
200                }
201
202                if (hasMoreThanOneCreateMethods(home))
203                {
204                   fireSpecViolationEvent(session, new Section("6.8.c"));
205                   status = false;
206                }
207             }
208          }
209
210          /*
211           * The session bean's home interface MUST extend the
212           * javax.ejb.EJBHome interface.
213           *
214           * Spec 6.10.6
215           */

216          if (!hasEJBHomeInterface(home))
217          {
218             fireSpecViolationEvent(session, new Section("6.10.6.a"));
219             status = false;
220          }
221
222          /*
223           * Method arguments defined in the home interface MUST be
224           * of valid types for RMI/IIOP.
225           *
226           * Method return values defined in the home interface MUST
227           * be of valid types for RMI/IIOP.
228           *
229           * Methods defined in the home interface MUST include
230           * java.rmi.RemoteException in their throws clause.
231           *
232           * Spec 6.10.6
233           */

234          Iterator JavaDoc it = Arrays.asList(home.getMethods()).iterator();
235          while (it.hasNext())
236          {
237             Method JavaDoc method = (Method JavaDoc)it.next();
238
239             if (!hasLegalRMIIIOPArguments(method))
240             {
241                fireSpecViolationEvent(session, method, new Section("6.10.6.b"));
242                status = false;
243             }
244
245             if (!hasLegalRMIIIOPReturnType(method))
246             {
247                fireSpecViolationEvent(session, method, new Section("6.10.6.c"));
248                status = false;
249             }
250
251             if (!throwsRemoteException(method))
252             {
253                fireSpecViolationEvent(session, method, new Section("6.10.6.d"));
254                status = false;
255             }
256          }
257
258          /*
259           * A session bean's home interface MUST define one or more
260           * create(...) methods.
261           *
262           * Spec 6.10.6
263           */

264          if (!hasCreateMethod(home))
265          {
266             fireSpecViolationEvent(session, new Section("6.10.6.e"));
267             status = false;
268          }
269
270          /*
271           * Each create(...) method in the session bean's home interface MUST
272           * have a matching ejbCreate(...) method in the session bean's class.
273           *
274           * Each create(...) method in the session bean's home interface MUST
275           * have the same number and types of arguments to its matching
276           * ejbCreate(...) method.
277           *
278           * The return type for a create(...) method MUST be the session
279           * bean's remote interface type.
280           *
281           * All the exceptions defined in the throws clause of the matching
282           * ejbCreate(...) method of the enterprise bean class MUST be
283           * included in the throws clause of a matching create(...) method.
284           *
285           * The throws clause of a create(...) method MUST include the
286           * javax.ejb.CreateException.
287           *
288           * Spec 6.10.6
289           */

290          Iterator JavaDoc createMethods = getCreateMethods(home);
291          try
292          {
293             String JavaDoc beanClass = session.getEjbClass();
294             Class JavaDoc bean = classloader.loadClass(beanClass);
295
296             while (createMethods.hasNext())
297             {
298                Method JavaDoc create = (Method JavaDoc)createMethods.next();
299
300                if (!hasMatchingEJBCreate(bean, create))
301                {
302                   fireSpecViolationEvent(session, create, new Section("6.10.6.f"));
303                   status = false;
304                }
305
306                if (!hasRemoteReturnType(session, create))
307                {
308                   fireSpecViolationEvent(session, create, new Section("6.10.6.g"));
309                   status = false;
310                }
311
312                if (hasMatchingEJBCreate(bean, create))
313                {
314                   Method JavaDoc ejbCreate = getMatchingEJBCreate(bean, create);
315
316                   if (!hasMatchingExceptions(ejbCreate, create))
317                   {
318                      fireSpecViolationEvent(session, create, new Section("6.10.6.h"));
319                      status = false;
320                   }
321                }
322
323                if (!throwsCreateException(create))
324                {
325                   fireSpecViolationEvent(session, create, new Section("6.10.6.i"));
326                   status = false;
327                }
328             }
329          }
330          catch (ClassNotFoundException JavaDoc ignored)
331          {
332          }
333       }
334       catch (ClassNotFoundException JavaDoc e)
335       {
336          /*
337           * The bean provider MUST specify the fully-qualified name of the
338           * enterprise bean's home interface in the <home> element.
339           *
340           * Spec 16.2
341           */

342          fireSpecViolationEvent(session, new Section("16.2.c"));
343          status = false;
344       }
345
346       return status;
347    }
348
349 /*
350  *************************************************************************
351  *
352  * VERIFY SESSION BEAN REMOTE INTERFACE
353  *
354  *************************************************************************
355  */

356    private boolean verifySessionRemote(SessionMetaData session)
357    {
358       /*
359        * Indicates whether we issued warnings or not during verification.
360        * This boolean is returned to the caller.
361        */

362       boolean status = true;
363
364       String JavaDoc name = session.getRemote();
365       if (name == null)
366          return false;
367
368       try
369       {
370          Class JavaDoc remote = classloader.loadClass(name);
371
372          /*
373           * The remote interface MUST extend the javax.ejb.EJBObject
374           * interface.
375           *
376           * Spec 6.10.5
377           */

378          if (!hasEJBObjectInterface(remote))
379          {
380             fireSpecViolationEvent(session, new Section("6.10.5.a"));
381             status = false;
382          }
383
384          /*
385           * Method arguments defined in the remote interface MUST be
386           * of valid types for RMI/IIOP.
387           *
388           * Method return values defined in the remote interface MUST
389           * be of valid types for RMI/IIOP.
390           *
391           * Methods defined in the remote interface MUST include
392           * java.rmi.RemoteException in their throws clause.
393           *
394           * Spec 6.10.5
395           */

396          Iterator JavaDoc it = Arrays.asList(remote.getMethods()).iterator();
397          while (it.hasNext())
398          {
399             Method JavaDoc method = (Method JavaDoc)it.next();
400
401             if (!hasLegalRMIIIOPArguments(method))
402             {
403                fireSpecViolationEvent(session, method, new Section("6.10.5.b"));
404                status = false;
405             }
406
407             if (!hasLegalRMIIIOPReturnType(method))
408             {
409                fireSpecViolationEvent(session, method, new Section("6.10.5.c"));
410                status = false;
411             }
412
413             if (!throwsRemoteException(method))
414             {
415                fireSpecViolationEvent(session, method, new Section("6.10.5.d"));
416                status = false;
417             }
418          }
419
420          /*
421           * For each method defined in the remote interface, there MUST be
422           * a matching method in the session bean's class. The matching
423           * method MUST have:
424           *
425           * - the same name
426           * - the same number and types of arguments, and the same
427           * return type
428           * - All the exceptions defined in the throws clause of the
429           * matching method of the session bean class must be defined
430           * in the throws clause of the method of the remote interface
431           *
432           * Spec 6.10.5
433           */

434          String JavaDoc beanName = session.getEjbClass();
435          Class JavaDoc bean = classloader.loadClass(beanName);
436
437          Iterator JavaDoc iterator = Arrays.asList(remote.getDeclaredMethods()).iterator();
438          while (iterator.hasNext())
439          {
440             Method JavaDoc remoteMethod = (Method JavaDoc)iterator.next();
441
442             if (!hasMatchingMethod(bean, remoteMethod))
443             {
444                fireSpecViolationEvent(session, remoteMethod, new Section("6.10.5.e"));
445                status = false;
446             }
447
448             if (hasMatchingMethod(bean, remoteMethod))
449             {
450                try
451                {
452                   Method JavaDoc beanMethod = bean.getMethod(remoteMethod.getName(), remoteMethod.getParameterTypes());
453
454                   if (!hasMatchingReturnType(remoteMethod, beanMethod))
455                   {
456                      fireSpecViolationEvent(session, remoteMethod, new Section("6.10.5.f"));
457                      status = false;
458                   }
459
460                   if (!hasMatchingExceptions(beanMethod, remoteMethod))
461                   {
462                      fireSpecViolationEvent(session, remoteMethod, new Section("6.10.5.g"));
463                      status = false;
464                   }
465                }
466                catch (NoSuchMethodException JavaDoc ignored)
467                {
468                }
469             }
470          } // while
471
}
472       catch (ClassNotFoundException JavaDoc e)
473       {
474          /*
475           * The Bean Provider MUST specify the fully-qualified name of the
476           * enterprise bean's remote interface in the <remote> element.
477           *
478           * Spec 16.2
479           */

480          fireSpecViolationEvent(session, new Section("16.2.d"));
481          status = false;
482       }
483
484       return status;
485    }
486
487 /*
488  *************************************************************************
489  *
490  * VERIFY SESSION BEAN CLASS
491  *
492  *************************************************************************
493  */

494    private boolean verifySessionBean(SessionMetaData session)
495    {
496       boolean status = true;
497
498       String JavaDoc name = session.getEjbClass();
499
500       try
501       {
502          Class JavaDoc bean = classloader.loadClass(name);
503
504          /*
505           * A session bean MUST implement, directly or indirectly,
506           * javax.ejb.SessionBean interface.
507           *
508           * Spec 6.5.1
509           * Spec 6.10.2
510           */

511          if (!hasSessionBeanInterface(bean))
512          {
513             fireSpecViolationEvent(session, new Section("6.5.1"));
514             status = false;
515          }
516
517          /*
518           * Only a stateful container-managed transaction demarcation
519           * session bean MAY implement the SessionSynchronization interface.
520           *
521           * A stateless Session bean MUST NOT implement the
522           * SessionSynchronization interface.
523           *
524           * Spec 6.5.3
525           */

526          if (hasSessionSynchronizationInterface(bean))
527          {
528             if (session.isStateless())
529             {
530                fireSpecViolationEvent(session, new Section("6.5.3.a"));
531                status = false;
532             }
533
534             if (session.isBeanManagedTx())
535             {
536                fireSpecViolationEvent(session, new Section("6.5.3.b"));
537                status = false;
538             }
539          }
540
541          /*
542           * A session bean MUST implement AT LEAST one ejbCreate method.
543           *
544           * Spec 6.5.5
545           */

546          if (!hasEJBCreateMethod(bean, true))
547          {
548             fireSpecViolationEvent(session, new Section("6.5.5"));
549             status = false;
550          }
551
552          /*
553           * A session with bean-managed transaction demarcation CANNOT
554           * implement the SessionSynchronization interface.
555           *
556           * Spec 6.6.1 (table 2)
557           */

558          if (hasSessionSynchronizationInterface(bean)
559                  && session.isBeanManagedTx())
560          {
561             fireSpecViolationEvent(session, new Section("6.6.1"));
562             status = false;
563          }
564
565          /*
566           * The session bean class MUST be defined as public.
567           *
568           * Spec 6.10.2
569           */

570          if (!isPublic(bean))
571          {
572             fireSpecViolationEvent(session, new Section("6.10.2.a"));
573             status = false;
574          }
575
576          /*
577           * The session bean class MUST NOT be final.
578           *
579           * Spec 6.10.2
580           */

581          if (isFinal(bean))
582          {
583             fireSpecViolationEvent(session, new Section("6.10.2.b"));
584             status = false;
585          }
586
587          /*
588           * The session bean class MUST NOT be abstract.
589           *
590           * Spec 6.10.2
591           */

592          if (isAbstract(bean))
593          {
594             fireSpecViolationEvent(session, new Section("6.10.2.c"));
595             status = false;
596          }
597
598          /*
599           * The session bean class MUST have a public constructor that
600           * takes no arguments.
601           *
602           * Spec 6.10.2
603           */

604          if (!hasDefaultConstructor(bean))
605          {
606             fireSpecViolationEvent(session, new Section("6.10.2.d"));
607             status = false;
608          }
609
610          /*
611           * The session bean class MUST NOT define the finalize() method.
612           *
613           * Spec 6.10.2
614           */

615          if (hasFinalizer(bean))
616          {
617             fireSpecViolationEvent(session, new Section("6.10.2.e"));
618             status = false;
619          }
620
621          /*
622           * The ejbCreate(...) method signatures MUST follow these rules:
623           *
624           * - The method MUST be declared as public
625           * - The method MUST NOT be declared as final or static
626           * - The return type MUST be void
627           * - The method arguments MUST be legal types for RMI/IIOP
628           *
629           * Spec 6.10.3
630           */

631          if (hasEJBCreateMethod(bean, true))
632          {
633             Iterator JavaDoc it = getEJBCreateMethods(bean);
634             while (it.hasNext())
635             {
636                Method JavaDoc ejbCreate = (Method JavaDoc)it.next();
637
638                if (!isPublic(ejbCreate))
639                {
640                   fireSpecViolationEvent(session, ejbCreate, new Section("6.10.3.a"));
641                   status = false;
642                }
643
644                if ((isFinal(ejbCreate)) || (isStatic(ejbCreate)))
645                {
646                   fireSpecViolationEvent(session, ejbCreate, new Section("6.10.3.b"));
647                   status = false;
648                }
649
650                if (!hasVoidReturnType(ejbCreate))
651                {
652                   fireSpecViolationEvent(session, ejbCreate, new Section("6.10.3.c"));
653                   status = false;
654                }
655
656                if (!hasLegalRMIIIOPArguments(ejbCreate))
657                {
658                   fireSpecViolationEvent(session, ejbCreate, new Section("6.10.3.d"));
659                   status = false;
660                }
661             } // while
662
}
663       }
664       catch (ClassNotFoundException JavaDoc e)
665       {
666          /*
667           * The Bean Provider MUST specify the fully-qualified name of the
668           * Java class that implements the enterprise bean's business
669           * methods.
670           *
671           * Spec 16.2
672           */

673          fireSpecViolationEvent(session, new Section("16.2.b"));
674          status = false;
675       }
676
677       return status;
678    }
679
680
681 /*
682  *************************************************************************
683  *
684  * VERIFY ENTITY BEAN HOME INTERFACE
685  *
686  *************************************************************************
687  */

688
689    private boolean verifyEntityHome(EntityMetaData entity)
690    {
691       boolean status = true;
692
693       String JavaDoc name = entity.getHome();
694       if (name == null)
695          return false;
696
697       try
698       {
699          Class JavaDoc home = classloader.loadClass(name);
700
701          /*
702           * Entity bean's home interface MUST extend the javax.ejb.EJBHome
703           * interface.
704           *
705           * Spec 9.2.8
706           */

707          if (!hasEJBHomeInterface(home))
708          {
709             fireSpecViolationEvent(entity, new Section("9.2.8.a"));
710             status = false;
711          }
712
713          /*
714           * The methods defined in the entity bean's home interface MUST
715           * have valid RMI-IIOP argument types.
716           *
717           * The methods defined in the entity bean's home interface MUST
718           * have valid RMI-IIOP return types.
719           *
720           * The methods defined in the entity bean's home interface MUST
721           * have java.rmi.RemoteException in their throws clause.
722           *
723           * Spec 9.2.8
724           */

725          Iterator JavaDoc homeMethods = Arrays.asList(home.getMethods()).iterator();
726          while (homeMethods.hasNext())
727          {
728             Method JavaDoc method = (Method JavaDoc)homeMethods.next();
729
730             if (!hasLegalRMIIIOPArguments(method))
731             {
732                fireSpecViolationEvent(entity, method, new Section("9.2.8.b"));
733
734                status = false;
735             }
736
737             if (!hasLegalRMIIIOPReturnType(method))
738             {
739                fireSpecViolationEvent(entity, method, new Section("9.2.8.c"));
740                status = false;
741             }
742
743             if (!throwsRemoteException(method))
744             {
745                fireSpecViolationEvent(entity, method, new Section("9.2.8.d"));
746                status = false;
747             }
748          } // while
749

750          /*
751           * Each method defined in the entity bean's home interface must be
752           * one of the following:
753           *
754           * - a create method
755           * - a finder method
756           *
757           * Spec 9.2.8
758           */

759          homeMethods = Arrays.asList(home.getMethods()).iterator();
760          while (homeMethods.hasNext())
761          {
762             Method JavaDoc method = (Method JavaDoc)homeMethods.next();
763
764             // Do not check the methods of the javax.ejb.EJBHome interface
765
if (method.getDeclaringClass().getName().equals(EJB_HOME_INTERFACE))
766                continue;
767
768             if (!(isCreateMethod(method) || isFinderMethod(method)))
769             {
770                fireSpecViolationEvent(entity, method, new Section("9.2.8.e"));
771                status = false;
772             }
773          }
774
775          /*
776           * Each create(...) method in the entity bean's home interface MUST
777           * have a matching ejbCreate(...) method in the entity bean's class.
778           *
779           * Each create(...) method in the entity bean's home interface MUST
780           * have the same number and types of arguments to its matching
781           * ejbCreate(...) method.
782           *
783           * The return type for a create(...) method MUST be the entity
784           * bean's remote interface type.
785           *
786           * All the exceptions defined in the throws clause of the matching
787           * ejbCreate(...) and ejbPostCreate(...) methods of the enterprise
788           * bean class MUST be included in the throws clause of a matching
789           * create(...) method.
790           *
791           * The throws clause of a create(...) method MUST include the
792           * javax.ejb.CreateException.
793           *
794           * Spec 9.2.8
795           */

796
797          try
798          {
799             String JavaDoc beanClass = entity.getEjbClass();
800             Class JavaDoc bean = classloader.loadClass(beanClass);
801
802             Iterator JavaDoc createMethods = getCreateMethods(home);
803             while (createMethods.hasNext())
804             {
805                Method JavaDoc create = (Method JavaDoc)createMethods.next();
806
807                if (!hasMatchingEJBCreate(bean, create))
808                {
809                   fireSpecViolationEvent(entity, create, new Section("9.2.8.f"));
810                   status = false;
811                }
812
813                if (!hasRemoteReturnType(entity, create))
814                {
815                   fireSpecViolationEvent(entity, create, new Section("9.2.8.g"));
816                   status = false;
817                }
818
819                if (hasMatchingEJBCreate(bean, create)
820                        && hasMatchingEJBPostCreate(bean, create))
821                {
822                   Method JavaDoc ejbCreate = getMatchingEJBCreate(bean, create);
823                   Method JavaDoc ejbPostCreate = getMatchingEJBPostCreate(bean, create);
824
825                   if (!(hasMatchingExceptions(ejbCreate, create)
826                           && hasMatchingExceptions(ejbPostCreate, create)))
827                   {
828                      fireSpecViolationEvent(entity, create, new Section("9.2.8.h"));
829                      status = false;
830                   }
831                }
832
833                if (!throwsCreateException(create))
834                {
835                   fireSpecViolationEvent(entity, create, new Section("9.2.8.i"));
836                   status = false;
837                }
838             }
839          }
840          catch (ClassNotFoundException JavaDoc ignored)
841          {
842          }
843
844          /*
845           * Each finder method MUST match one of the ejbFind<METHOD> methods
846           * defined in the entity bean class.
847           *
848           * The matching ejbFind<METHOD> method MUST have the same number and
849           * types of arguments.
850           *
851           * The return type for a find<METHOD> method MUST be the entity
852           * bean's remote interface type (single-object finder) or a
853           * collection thereof (for a multi-object finder).
854           *
855           * All the exceptions defined in the throws clause of an ejbFind
856           * method of the entity bean class MUST be included in the throws
857           * clause of the matching find method of the home interface.
858           *
859           * The throws clause of a finder method MUST include the
860           * javax.ejb.FinderException.
861           *
862           * Spec 9.2.8
863           */

864          try
865          {
866             String JavaDoc beanClass = entity.getEjbClass();
867             Class JavaDoc bean = classloader.loadClass(beanClass);
868
869             Iterator JavaDoc finderMethods = getFinderMethods(home);
870             while (finderMethods.hasNext())
871             {
872                Method JavaDoc finder = (Method JavaDoc)finderMethods.next();
873
874                if ((entity.isBMP()) && (!hasMatchingEJBFind(bean, finder)))
875                {
876                   fireSpecViolationEvent(entity, finder, new Section("9.2.8.j"));
877                   status = false;
878            &nbs