KickJava   Java API By Example, From Geeks To Geeks.

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


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: EJBVerifier21.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 JavaDoc;
34 import java.util.Arrays JavaDoc;
35 import java.util.Iterator JavaDoc;
36
37 /**
38  * EJB 2.1 bean verifier.
39  *
40  * @author <a HREF="mailto:christoph.jung@infor.de">Christoph G. Jung</a>
41  * @author Thomas.Diesler@jboss.org
42  *
43  * @version $Revision: 41248 $
44  * @since 02.12.2003
45  */

46
47 public class EJBVerifier21 extends AbstractEJB2xVerifier
48 {
49    // provide logging
50
private static Logger log = Logger.getLogger(EJBVerifier21.class);
51
52    /*
53     * Constructor
54     */

55    public EJBVerifier21(VerificationContext context)
56    {
57       super(context);
58    }
59
60    public String JavaDoc getMessageBundle()
61    {
62       return "EJB21Messages.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 serviceEndpointExists = false;
74       boolean verified = false;
75
76       if (!verifyBean(session))
77          return;
78
79       verified = verifySessionBean(session);
80
81       if (hasRemoteInterfaces(session))
82       {
83          // Check remote interfaces
84
localOrRemoteExists = true;
85          verified = verified && verifySessionRemote(session);
86          verified = verified && verifySessionHome(session);
87       }
88
89       if (hasLocalInterfaces(session))
90       {
91          // Check local interfaces
92
localOrRemoteExists = true;
93          verified = verified && verifySessionLocal(session);
94          verified = verified && verifySessionLocalHome(session);
95       }
96
97       if (hasServiceEndpointInterfaces(session))
98       {
99          // Check local interfaces
100
serviceEndpointExists = true;
101          verified = verified && verifyServiceEndpoint(session);
102       }
103
104       // The session bean MUST implement either a remote home and
105
// remote, or local home and local interface, or the service endpoint
106
// interface. It MAY implement a
107
// remote home, remote, local home, local interface or service endpoint
108
// interface
109
//
110
// Spec 7.11.1
111
//
112
if (!localOrRemoteExists && !serviceEndpointExists)
113       {
114          fireSpecViolationEvent(session, new Section("7.11.1"));
115          verified = false;
116       }
117
118       if (verified)
119       {
120          // All OK; full steam ahead
121
fireBeanVerifiedEvent(session);
122       }
123    }
124
125    public void checkEntity(EntityMetaData entity)
126    {
127       if (entity.isCMP1x())
128       {
129          cmp1XVerifier.checkEntity(entity);
130       }
131       else
132       {
133          checkBmpOrCmp2Entity(entity);
134       }
135    }
136
137    public void checkMessageBean(MessageDrivenMetaData mdb)
138    {
139       boolean beanVerified = false;
140
141       if (!verifyBean(mdb))
142          return;
143
144       beanVerified = verifyMessageDrivenBean(mdb);
145
146       if (beanVerified)
147       {
148          // OK, we're done
149
fireBeanVerifiedEvent(mdb);
150       }
151    }
152
153    private void checkBmpOrCmp2Entity(EntityMetaData entity)
154    {
155       boolean localOrRemoteExists = false;
156       boolean verified = false;
157
158       if (!verifyBean(entity))
159          return;
160
161       if (entity.isCMP())
162       {
163          verified = verifyCMPEntityBean(entity);
164       }
165       else if (entity.isBMP())
166       {
167          verified = verifyBMPEntityBean(entity);
168       }
169
170       if (hasRemoteInterfaces(entity))
171       {
172          // Check remote interfaces
173
localOrRemoteExists = true;
174          verified = verified && verifyEntityRemote(entity);
175          verified = verified && verifyEntityHome(entity);
176       }
177
178       if (hasLocalInterfaces(entity))
179       {
180          // Check local interfaces
181
localOrRemoteExists = true;
182          verified = verified && verifyEntityLocal(entity);
183          verified = verified && verifyEntityLocalHome(entity);
184       }
185
186       verified = verified && verifyPrimaryKey(entity);
187
188       if (!localOrRemoteExists)
189       {
190          // The entity bean MUST implement either a remote home and
191
// remote, or local home and local interface. It MAY implement
192
// a remote home, remote, local home or local interface.
193
//
194
// Spec 10.6.1 (CMP) / 12.2.1 (BMP)
195
//
196
if (entity.isCMP())
197          {
198             fireSpecViolationEvent(entity, new Section("10.6.1"));
199             verified = false;
200          }
201          else
202          {
203             fireSpecViolationEvent(entity, new Section("12.2.1"));
204             verified = false;
205          }
206       }
207
208       if (verified)
209       {
210          fireBeanVerifiedEvent(entity);
211       }
212    }
213
214    /**
215     * Try to load the beans class declared in the &lt;ejb-class&gt;
216     * element.
217     *
218     * @return <code>true</code> if everything went alright
219     */

220    protected boolean verifyBean(BeanMetaData theBean)
221    {
222       String JavaDoc beanName = theBean.getEjbClass();
223
224       if (beanName == null)
225          return false;
226
227       try
228       {
229          bean = classloader.loadClass(beanName);
230          return true;
231       }
232       catch (ClassNotFoundException JavaDoc cnfe)
233       {
234          fireSpecViolationEvent(theBean, new Section("22.2.b",
235                  "Class not found on '" + beanName + "': " + cnfe.getMessage()));
236          return false;
237       }
238    }
239
240    /**
241     * Check whether the bean has declared local interfaces and whether
242     * we can load the defined classes
243     *
244     * @return <code>true</code> if everything went alright
245     */

246    protected boolean hasRemoteInterfaces(BeanMetaData bean)
247    {
248       boolean status = true;
249       String JavaDoc homeName = bean.getHome();
250       String JavaDoc remoteName = bean.getRemote();
251
252       if (homeName == null || remoteName == null)
253          return false;
254
255       // Verify the <home> class
256
try
257       {
258          home = classloader.loadClass(homeName);
259       }
260       catch (ClassNotFoundException JavaDoc cnfe)
261       {
262          fireSpecViolationEvent(bean, new Section("22.2.c",
263                  "Class not found on '" + homeName + "': " + cnfe.getMessage()));
264          status = false;
265       }
266
267       // Verify the <remote> class
268
try
269       {
270          remote = classloader.loadClass(remoteName);
271       }
272       catch (ClassNotFoundException JavaDoc cnfe)
273       {
274          fireSpecViolationEvent(bean, new Section("22.2.d",
275                  "Class not found on '" + remoteName + "': " + cnfe.getMessage()));
276          status = false;
277       }
278
279       return status;
280    }
281
282    /**
283     * Check whether the bean has declared local interfaces and whether
284     * we can load the defined classes
285     *
286     * @return <code>true</code> if everything went alright
287     */

288    protected boolean hasLocalInterfaces(BeanMetaData bean)
289    {
290       boolean status = true;
291       String JavaDoc localHomeName = bean.getLocalHome();
292       String JavaDoc localName = bean.getLocal();
293
294       if (localHomeName == null || localName == null)
295          return false;
296
297       // Verify the <local-home> class
298
try
299       {
300          localHome = classloader.loadClass(localHomeName);
301       }
302       catch (ClassNotFoundException JavaDoc cnfe)
303       {
304          fireSpecViolationEvent(bean, new Section("22.2.e",
305                  "Class not found on '" + localHomeName + "': " +
306                  cnfe.getMessage()));
307          status = false;
308       }
309
310       try
311       {
312          local = classloader.loadClass(localName);
313       }
314       catch (ClassNotFoundException JavaDoc cnfe)
315       {
316          fireSpecViolationEvent(bean, new Section("22.2.f",
317                  "Class not found on '" + localName + "': " + cnfe.getMessage()));
318          status = false;
319       }
320
321       return status;
322    }
323
324    /**
325     * Verifies the session bean remote home interface against the EJB 2.1
326     * specification.
327     *
328     * @param session XML metadata of the session bean
329     */

330    protected boolean verifySessionHome(SessionMetaData session)
331    {
332       boolean status = true;
333
334       // The home interface of a stateless session bean MUST have one
335
// create() method that takes no arguments.
336
//
337
// The create() method MUST return the session bean's remote
338
// interface.
339
//
340
// There CAN NOT be other create() methods in the home interface.
341
//
342
// Spec 7.11.6
343
//
344
if (session.isStateless())
345       {
346          if (!hasDefaultCreateMethod(home))
347          {
348             fireSpecViolationEvent(session, new Section("7.11.6.d2"));
349             status = false;
350          }
351          else
352          {
353             Method JavaDoc create = getDefaultCreateMethod(home);
354
355             if (hasMoreThanOneCreateMethods(home))
356             {
357                fireSpecViolationEvent(session, new Section("7.11.6.d2"));
358                status = false;
359             }
360          }
361       }
362
363       // The session bean's home interface MUST extend the
364
// javax.ejb.EJBHome interface.
365
//
366
// Spec 7.11.6
367
//
368
if (!hasEJBHomeInterface(home))
369       {
370          fireSpecViolationEvent(session, new Section("7.11.6.a"));
371          status = false;
372       }
373
374       // Method arguments defined in the home interface MUST be
375
// of valid types for RMI/IIOP.
376
//
377
// Method return values defined in the home interface MUST
378
// be of valid types for RMI/IIOP.
379
//
380
// Methods defined in the home interface MUST include
381
// java.rmi.RemoteException in their throws clause.
382
//
383
// Spec 7.11.6
384
///
385
Iterator JavaDoc it = Arrays.asList(home.getMethods()).iterator();
386       while (it.hasNext())
387       {
388          Method JavaDoc method = (Method JavaDoc)it.next();
389
390          if (!hasLegalRMIIIOPArguments(method))
391          {
392             fireSpecViolationEvent(session, method, new Section("7.11.6.b1"));
393             status = false;
394          }
395
396          if (!hasLegalRMIIIOPReturnType(method))
397          {
398             fireSpecViolationEvent(session, method, new Section("7.11.6.b2"));
399             status = false;
400          }
401
402          if (!throwsRemoteException(method))
403          {
404             fireSpecViolationEvent(session, method, new Section("7.11.6.b3"));
405             status = false;
406          }
407       }
408
409       // A session bean's home interface MUST define one or more
410
// create(...) methods.
411
//
412
// Spec 7.11.6
413
//
414
if (!hasCreateMethod(home))
415       {
416          fireSpecViolationEvent(session, new Section("7.11.6.d1"));
417          status = false;
418       }
419
420       // Each create(...) method in the session bean's home interface
421
// MUST have a matching ejbCreate(...) method in the session
422
// bean's class.
423
//
424
// Each create(...) method in the session bean's home interface
425
// MUST have the same number and types of arguments to its
426
// matching ejbCreate(...) method.
427
//
428
// The return type for a create(...) method MUST be the session
429
// bean's remote interface type.
430
//
431
// All the exceptions defined in the throws clause of the matching
432
// ejbCreate(...) method of the enterprise bean class MUST be
433
// included in the throws clause of a matching create(...) method.
434
//
435
// The throws clause of a create(...) method MUST include the
436
// javax.ejb.CreateException.
437
//
438
// Spec 7.11.6
439
//
440
Iterator JavaDoc createMethods = getCreateMethods(home);
441       while (createMethods.hasNext())
442       {
443          Method JavaDoc create = (Method JavaDoc)createMethods.next();
444
445          if (!hasMatchingEJBCreate(bean, create))
446          {
447             fireSpecViolationEvent(session, create, new Section("7.11.6.e"));
448             status = false;
449          }
450
451          if (!hasRemoteReturnType(session, create))
452          {
453             fireSpecViolationEvent(session, create, new Section("7.11.6.f"));
454             status = false;
455          }
456
457          if (hasMatchingEJBCreate(bean, create))
458          {
459             Method JavaDoc ejbCreate = getMatchingEJBCreate(bean, create);
460             if (!hasMatchingExceptions(ejbCreate, create))
461             {
462                fireSpecViolationEvent(session, create,
463                        new Section("7.11.6.g"));
464                status = false;
465             }
466          }
467
468          if (!throwsCreateException(create))
469          {
470             fireSpecViolationEvent(session, create, new Section("7.11.6.h"));
471             status = false;
472          }
473       }
474
475       return status;
476    }
477
478    /**
479     * Verifies the session bean local home interface against the EJB 2.1
480     * specification.
481     *
482     * @param session parsed metadata of the session bean
483     */

484    protected boolean verifySessionLocalHome(SessionMetaData session)
485    {
486       boolean status = true;
487
488       // The local home interface of a stateless session bean MUST have
489
// one create() method that takes no arguments.
490
//
491
// There CAN NOT be other create() methods in the home interface.
492
//
493
// Spec 7.11.8
494
//
495
if (session.isStateless())
496       {
497          if (!hasDefaultCreateMethod(localHome))
498          {
499             fireSpecViolationEvent(session, new Section("7.11.8.d2"));
500             status = false;
501          }
502          else
503          {
504             Method JavaDoc create = getDefaultCreateMethod(localHome);
505
506             if (hasMoreThanOneCreateMethods(localHome))
507             {
508                fireSpecViolationEvent(session, new Section("7.11.8.d2"));
509                status = false;
510             }
511          }
512       }
513
514       // The session bean's home interface MUST extend the
515
// javax.ejb.EJBLocalHome interface.
516
//
517
// Spec 7.11.8
518
//
519
if (!hasEJBLocalHomeInterface(localHome))
520       {
521          fireSpecViolationEvent(session, new Section("7.11.8.a"));
522          status = false;
523       }
524
525       // Methods defined in the local home interface MUST NOT include
526
// java.rmi.RemoteException in their throws clause.
527
//
528
// Spec 7.11.8
529
//
530
Iterator JavaDoc it = Arrays.asList(localHome.getMethods()).iterator();
531       while (it.hasNext())
532       {
533          Method JavaDoc method = (Method JavaDoc)it.next();
534
535          if (throwsRemoteException(method))
536          {
537             fireSpecViolationEvent(session, method, new Section("7.11.8.b"));
538             status = false;
539          }
540       }
541
542       // A session bean's home interface MUST define one or more
543
// create(...) methods.
544
//
545
// Spec 7.11.8
546
//
547
if (!hasCreateMethod(localHome))
548       {
549          fireSpecViolationEvent(session, new Section("7.11.8.d1"));
550          status = false;
551       }
552
553       // Each create(...) method in the session bean's local home
554
// interface MUST have a matching ejbCreate(...) method in the
555
// session bean's class.
556
//
557
// Each create(...) method in the session bean's home interface
558
// MUST have the same number and types of arguments to its
559
// matching ejbCreate(...) method.
560
//
561
// The return type for a create(...) method MUST be the session
562
// bean's local interface type.
563
//
564
// All the exceptions defined in the throws clause of the matching
565
// ejbCreate(...) method of the enterprise bean class MUST be
566
// included in the throws clause of a matching create(...) method.
567
//
568
// The throws clause of a create(...) method MUST include the
569
// javax.ejb.CreateException.
570
//
571
// Spec 7.11.8
572
//
573
Iterator JavaDoc createMethods = getCreateMethods(localHome);
574       while (createMethods.hasNext())
575       {
576          Method JavaDoc create = (Method JavaDoc)createMethods.next();
577
578          if (!hasMatchingEJBCreate(bean, create))
579          {
580             fireSpecViolationEvent(session, create,
581                     new Section("7.11.8.e"));
582             status = false;
583          }
584
585          if (!hasLocalReturnType(session, create))
586          {
587             fireSpecViolationEvent(session, create,
588                     new Section("7.11.8.f"));
589             status = false;
590          }
591
592          if (hasMatchingEJBCreate(bean, create))
593          {
594             Method JavaDoc ejbCreate = getMatchingEJBCreate(bean, create);
595             if (!hasMatchingExceptions(ejbCreate, create))
596             {
597                fireSpecViolationEvent(session, create,
598                        new Section("7.11.8.g"));
599             }
600          }
601
602          if (!throwsCreateException(create))
603          {
604             fireSpecViolationEvent(session, create,
605                     new Section("7.11.8.h"));
606             status = false;
607          }
608       }
609
610       return status;
611    }
612
613    /*
614     * Verify Session Bean Remote Interface
615     */

616    protected boolean verifySessionRemote(SessionMetaData session)
617    {
618       boolean status = true;
619
620       // The remote interface MUST extend the javax.ejb.EJBObject
621
// interface.
622
//
623
// Spec 7.11.5
624
//
625
if (!hasEJBObjectInterface(remote))
626       {
627          fireSpecViolationEvent(session, new Section("7.11.5.a"));
628          status = false;
629       }
630
631       // Method arguments defined in the remote interface MUST be
632
// of valid types for RMI/IIOP.
633
//
634
// Method return values defined in the remote interface MUST
635
// be of valid types for RMI/IIOP.
636
//
637
// Methods defined in the remote interface MUST include
638
// java.rmi.RemoteException in their throws clause.
639
//
640
// Spec 7.11.5
641
//
642
Iterator JavaDoc it = Arrays.asList(remote.getMethods()).iterator();
643       while (it.hasNext())
644       {
645          Method JavaDoc method = (Method JavaDoc)it.next();
646
647          if (!hasLegalRMIIIOPArguments(method))
648          {
649             fireSpecViolationEvent(session, method, new Section("7.11.5.b1"));
650             status = false;
651          }
652
653          if (!hasLegalRMIIIOPReturnType(method))
654          {
655             fireSpecViolationEvent(session, method, new Section("7.11.5.b2"));
656             status = false;
657          }
658
659          if (!throwsRemoteException(method))
660          {
661             fireSpecViolationEvent(session, method, new Section("7.11.5.b3"));
662             status = false;
663          }
664       }
665
666       // For each method defined in the remote interface, there MUST be
667
// a matching method in the session bean's class. The matching
668
// method MUST have:
669
//
670
// - the same name
671
// - the same number and types of arguments, and the same
672
// return type
673
// - All the exceptions defined in the throws clause of the
674
// matching method of the session bean class must be defined
675
// in the throws clause of the method of the remote interface
676
//
677
// Spec 7.11.5
678
//
679
it = Arrays.asList(remote.getDeclaredMethods()).iterator();
680       while (it.hasNext())
681       {
682          Method JavaDoc remoteMethod = (Method JavaDoc)it.next();
683
684          if (!hasMatchingMethod(bean, remoteMethod))
685          {
686             fireSpecViolationEvent(session, remoteMethod,
687                     new Section("7.11.5.d1"));
688
689             status = false;
690          }
691
692          if (hasMatchingMethod(bean, remoteMethod))
693          {
694             try
695             {
696                Method JavaDoc beanMethod = bean.getMethod(remoteMethod.getName(),
697                        remoteMethod.getParameterTypes());
698
699                if (!hasMatchingReturnType(remoteMethod, beanMethod))
700                {
701                   fireSpecViolationEvent(session, remoteMethod,
702                           new Section("7.11.5.d2"));
703                   status = false;
704                }
705
706                if (!hasMatchingExceptions(beanMethod, remoteMethod))
707                {
708                   fireSpecViolationEvent(session, remoteMethod,
709                           new Section("7.11.5.d3"));
710                   status = false;
711                }
712             }
713             catch (NoSuchMethodException JavaDoc ignored)
714             {
715             }
716          }
717       }
718
719       return status;
720    }
721
722    /*
723     * Verify Session Bean Local Interface
724     */

725    protected boolean verifySessionLocal(SessionMetaData session)
726    {
727       boolean status = true;
728
729       // The local interface MUST extend the javax.ejb.EJBLocalObject
730
// interface.
731
//
732
// Spec 7.11.7
733
//
734
if (!hasEJBLocalObjectInterface(local))
735       {
736          fireSpecViolationEvent(session, new Section("7.11.7.a"));
737          status = false;
738       }
739
740       // Methods defined in the local interface MUST NOT include
741
// java.rmi.RemoteException in their throws clause.
742
//
743
// Spec 7.11.7
744
//
745
Iterator JavaDoc it = Arrays.asList(local.getMethods()).iterator();
746       while (it.hasNext())
747       {
748          Method JavaDoc method = (Method JavaDoc)it.next();
749          if (throwsRemoteException(method))
750          {
751             fireSpecViolationEvent(session, method, new Section("7.11.7.b"));
752             status = false;
753          }
754       }
755
756       // For each method defined in the local interface, there MUST be
757
// a matching method in the session bean's class. The matching
758
// method MUST have:
759
//
760
// - the same name
761
// - the same number and types of arguments, and the same
762
// return type
763
// - All the exceptions defined in the throws clause of the
764
// matching method of the session bean class must be defined
765
// in the throws clause of the method of the remote interface
766
//
767
// Spec 7.11.7
768
//
769
it = Arrays.asList(local.getDeclaredMethods()).iterator();
770       while (it.hasNext())
771       {
772          Method JavaDoc localMethod = (Method JavaDoc)it.next();
773
774          if (!hasMatchingMethod(bean, localMethod))
775          {
776             fireSpecViolationEvent(session, localMethod,
777                     new Section("7.11.7.d1"));
778             status = false;
779          }
780
781          if (hasMatchingMethod(bean, localMethod))
782          {
783             try
784             {
785                Method JavaDoc beanMethod = bean.getMethod(localMethod.getName(),
786                        localMethod.getParameterTypes());
787
788                if (!hasMatchingReturnType(localMethod, beanMethod))
789                {
790                   fireSpecViolationEvent(session, localMethod,
791                           new Section("7.11.7.d2"));
792                   status = false;
793                }
794
795                if (!hasMatchingExceptions(beanMethod, localMethod))
796                {
797                   fireSpecViolationEvent(session, localMethod,
798                           new Section("7.11.7.d3"));
799                   status = false;
800                }
801             }
802             catch (NoSuchMethodException JavaDoc ignored)
803             {
804             }
805          }
806       }
807
808       return status;
809    }
810
811    /*
812     * Verify Session Bean
813     */

814    protected boolean verifySessionBean(SessionMetaData session)
815    {
816       boolean status = true;
817
818       // A session bean MUST implement, directly or indirectly,
819
// javax.ejb.SessionBean interface.
820
//
821
// Spec 7.11.2
822
//
823
if (!hasSessionBeanInterface(bean))
824       {
825          fireSpecViolationEvent(session, new Section("7.11.2.a"));
826          status = false;
827       }
828
829       // Only a stateful container-managed transaction demarcation
830
// session bean MAY implement the SessionSynchronization
831
// interface.
832
//
833
// A stateless Session bean MUST NOT implement the
834
// SessionSynchronization interface.
835
//
836
// Spec 7.5.3
837
//
838
if (hasSessionSynchronizationInterface(bean))
839       {
840          if (session.isStateless())
841          {
842             fireSpecViolationEvent(session, new Section("7.5.3.a"));
843             status = false;
844          }
845
846          if (session.isBeanManagedTx())
847          {
848             fireSpecViolationEvent(session, new Section("7.5.3.b"));
849             status = false;
850          }
851       }
852
853       //
854
// A session bean MUST implement AT LEAST one ejbCreate method.
855
//
856
// Spec 7.11.3
857
//
858
if (!hasEJBCreateMethod(bean, true))
859       {
860          fireSpecViolationEvent(session, new Section("7.11.3"));
861          status = false;
862       }
863
864       // A session with bean-managed transaction demarcation CANNOT
865
// implement the SessionSynchronization interface.
866
//
867
// Spec 7.6.1 (table 2)
868
//
869
if (hasSessionSynchronizationInterface(bean)
870               && session.isBeanManagedTx())
871       {
872          fireSpecViolationEvent(session, new Section("7.6.1"));
873          status = false;
874       }
875
876       // The session bean class MUST be defined as public.
877
//
878
// Spec 7.11.2
879
//
880
if (!isPublic(bean))
881       {
882          fireSpecViolationEvent(session, new Section("7.11.2.b1"));
883          status = false;
884       }
885
886       // The session bean class MUST NOT be final.
887
//
888
// Spec 7.11.2
889
//
890
if (isFinal(bean))
891       {
892          fireSpecViolationEvent(session, new Section("7.11.2.b2"));
893          status = false;
894       }
895
896       // The session bean class MUST NOT be abstract.
897
//
898
// Spec 7.11.2
899
//
900
if (isAbstract(bean))
901       {
902          fireSpecViolationEvent(session, new Section("7.11.2.b3"));
903          status = false;
904       }
905
906       // The session bean class MUST have a public constructor that
907
// takes no arguments.
908
//
909
// Spec 7.11.2
910
//
911
if (!hasDefaultConstructor(bean))
912       {
913          fireSpecViolationEvent(session, new Section("7.11.2.c"));
914          status = false;
915       }
916
917       // The session bean class MUST NOT define the finalize() method.
918
//
919
// Spec 7.11.2
920
//
921
if (hasFinalizer(bean))
922       {
923          fireSpecViolationEvent(session, new Section("7.11.2.d"));
924          status = false;
925       }
926
927       // The ejbCreate(...) method signatures MUST follow these rules:
928
//
929
// - The method name MUST have ejbCreate as its prefix
930
// - The method MUST be declared as public
931
// - The method MUST NOT be declared as final or static
932
// - The return type MUST be void
933
// - The method arguments MUST be legal types for RMI/IIOP
934
// - The method SHOULD not throw a java.rmi.RemoteException
935
// (NOTE we don't test for this as it's not a MUST)
936
//
937
// Spec 7.11.3
938
//
939
if (hasEJBCreateMethod(bean, true))
940       {
941          Iterator JavaDoc it = getEJBCreateMethods(bean);
942          while (it.hasNext())
943          {
944             Method JavaDoc ejbCreate = (Method JavaDoc)it.next();
945
946             if (!isPublic(ejbCreate))
947             {
948                fireSpecViolationEvent(session, ejbCreate,
949                        new Section("7.11.3.b"));
950                status = false;
951             }
952
953             if ((isFinal(ejbCreate)) || (isStatic(ejbCreate)))
954             {
955                fireSpecViolationEvent(session, ejbCreate,
956                        new Section("7.11.3.c"));
957                status = false;
958             }
959
960             if (!hasVoidReturnType(ejbCreate))
961             {
962                fireSpecViolationEvent(session, ejbCreate,
963                        new Section("7.11.3.d"));
964                status = false;
965             }
966
967             if (!hasLegalRMIIIOPArguments(ejbCreate))
968             {
969                fireSpecViolationEvent(session, ejbCreate,
970                        new Section("7.11.3.e"));
971                status = false;
972             }
973          }
974       }
975
976       return status;
977    }
978
979    /*
980     * Verify Entity Bean Home Interface
981     */

982    private boolean verifyEntityHome(EntityMetaData entity)
983    {
984       boolean status = true;
985
986       // Entity bean's home interface MUST extend the javax.ejb.EJBHome
987
// interface.
988
//
989
// Spec 12.2.9
990
//
991
if (!hasEJBHomeInterface(home))
992       {
993          fireSpecViolationEvent(entity, new Section("12.2.9.a"));
994          status = false;
995       }
996
997       // The methods defined in the entity bean's home interface MUST
998
// have valid RMI-IIOP argument types.
999
//
1000
// The methods defined in the entity bean's home interface MUST
1001
// have valid RMI-IIOP return types.
1002
//
1003
// The methods defined in the entity bean's home interface MUST
1004
// have java.rmi.RemoteException in their throws clause.
1005
//
1006
// Spec 12.2.9
1007
//
1008
Iterator JavaDoc methods = Arrays.asList(home.getMethods()).iterator();
1009      while (methods.hasNext())
1010      {
1011         Method JavaDoc method = (Method JavaDoc)methods.next();
1012
1013         if (!hasLegalRMIIIOPArguments(method))
1014         {
1015            fireSpecViolationEvent(entity, method,
1016                    new Section("12.2.9.b1"));
1017            status = false;
1018         }
1019
1020         if (!hasLegalRMIIIOPReturnType(method))
1021         {
1022            fireSpecViolationEvent(entity, method,
1023                    new Section("12.2.9.b2"));
1024            status = false;
1025         }
1026
1027         if (!throwsRemoteException(method))
1028         {
1029            fireSpecViolationEvent(entity, method,
1030                    new Section("12.2.9.b3"));
1031            status = false;
1032         }
1033      }
1034
1035      // Each method defined in the entity bean's home interface must be
1036
// one of the following:
1037
//
1038
// - a create method
1039
// - a finder method
1040
// - a home method
1041
//
1042
// Spec 12.2.9
1043
//
1044
methods = Arrays.asList(home.getMethods()).iterator();
1045      while (methods.hasNext())
1046      {
1047         Method JavaDoc method = (Method JavaDoc)methods.next();
1048
1049         // Do not check the methods of the javax.ejb.EJBHome interface
1050
if (method.getDeclaringClass().getName().equals(EJB_HOME_INTERFACE))
1051            continue;
1052
1053         if (isCreateMethod(method))
1054         {
1055            // Each create(...) method in the entity bean's home
1056
// interface MUST have a matching ejbCreate(...) method in
1057
// the entity bean's class.
1058
//
1059
// Each create(...) method in the entity bean's home
1060
// interface MUST have the same number and types of
1061
// arguments to its matching ejbCreate(...) method.
1062
//
1063
// The return type for a create(...) method MUST be the
1064
// entity bean's remote interface type.
1065
//
1066
// All the exceptions defined in the throws clause of the
1067
// matching ejbCreate(...) and ejbPostCreate(...) methods of
1068
// the enterprise bean class MUST be included in the throws
1069
// clause of a matching create(...) method.
1070
//
1071
// The throws clause of a create(...) method MUST include
1072
// the javax.ejb.CreateException.
1073
//
1074
// Spec 12.2.9
1075
//
1076
if (!hasMatchingEJBCreate(bean, method))
1077            {
1078               fireSpecViolationEvent(entity, method, new Section("12.2.9.d"));
1079               status = false;
1080            }
1081
1082            if (!hasRemoteReturnType(entity, method))
1083            {
1084               fireSpecViolationEvent(entity, method, new Section("12.2.9.e"));
1085               status = false;
1086            }
1087
1088            if (hasMatchingEJBCreate(bean, method)
1089                    && hasMatchingEJBPostCreate(bean, method))
1090            {
1091               Method JavaDoc ejbCreate = getMatchingEJBCreate(bean, method);
1092               Method JavaDoc ejbPostCreate = getMatchingEJBPostCreate(bean, method);
1093
1094               if (!(hasMatchingExceptions(ejbCreate, method)
1095                       && hasMatchingExceptions(ejbPostCreate, method)))
1096               {
1097                  fireSpecViolationEvent(entity, method,
1098                          new Section("12.2.9.f"));
1099               }
1100            }
1101
1102            if (!throwsCreateException(method))
1103            {
1104               fireSpecViolationEvent(entity, method, new Section("12.2.9.g"));
1105               status = false;
1106            }
1107         }
1108         else if (isFinderMethod(method))
1109         {
1110            // Each finder method MUST match one of the ejbFind<METHOD>
1111
// methods defined in the entity bean class.
1112
//
1113
// The matching ejbFind<METHOD> method MUST have the same
1114
// number and types of arguments.
1115
//
1116
// The return type for a find<METHOD> method MUST be the
1117
// entity bean's remote interface type (single-object
1118
// finder) or a collection thereof (for a multi-object
1119
// finder).
1120
//
1121
// All the exceptions defined in the throws clause of an
1122
// ejbFind method of the entity bean class MUST be included
1123
// in the throws clause of the matching find method of the
1124
// home interface.
1125
//
1126
// The throws clause of a finder method MUST include the
1127
// javax.ejb.FinderException.
1128
//
1129
// Spec 12.2.9
1130
//
1131
if (entity.isBMP())
1132            { // Check for BMP violations
1133
if ((!hasMatchingEJBFind(bean, method)))
1134               {
1135                  fireSpecViolationEvent(entity, method,
1136                          new Section("12.2.9.h"));
1137                  status = false;
1138               }
1139
1140               if (!(hasRemoteReturnType(entity, method)
1141                       || isMultiObjectFinder(method)))
1142               {
1143                  fireSpecViolationEvent(entity, method,
1144                          new Section("12.2.9.j"));
1145                  status = false;
1146               }
1147
1148               if ((hasMatchingEJBFind(bean, method)))
1149               {
1150                  Method JavaDoc ejbFind = getMatchingEJBFind(bean, method);
1151                  if (!(hasMatchingExceptions(ejbFind, method)))
1152                  {
1153                     fireSpecViolationEvent(entity, method,
1154                             new Section("12.2.9.k"));
1155                     status = false;
1156                  }
1157               }
1158
1159               if (!throwsFinderException(method))
1160               {
1161                  fireSpecViolationEvent(entity, method,
1162                          new Section("12.2.9.l"));
1163                  status = false;
1164               }
1165            } // if( entity.isBMP() )
1166

1167            if (entity.isCMP())
1168            {
1169
1170               if (!(hasRemoteReturnType(entity, method)
1171                       || isMultiObjectFinder(method)))
1172               {
1173                  fireSpecViolationEvent(entity, method,
1174                          new Section("10.6.10.a"));
1175                  status = false;
1176               }
1177
1178               if (!throwsFinderException(method))
1179               {
1180                  fireSpecViolationEvent(entity, method,
1181                          new Section("10.6.10.b"));
1182                  status = false;
1183               }
1184
1185               // For every finder method there must be a matching
1186
// <query> element defined in the deployment descriptor
1187
// with the exception of findByPrimaryKey
1188
//
1189
// JBoss Extension: 'findAll' is _also_ ignored.
1190
//
1191
if (!method.getName().equals("findByPrimaryKey")
1192                       && !method.getName().equals("findAll")
1193                       && !hasMatchingQuery(method, entity))
1194               {
1195                  fireSpecViolationEvent(entity, method,
1196                          new Section("10.5.6"));
1197                  status = false;
1198               }
1199            } // if( entity.isCMP() )
1200
}
1201         else // Neither Create nor Finder method
1202
{
1203            // Each home method MUST match a method defined in the
1204
// entity bean class.
1205
//
1206
// The matching ejbHome<METHOD> method MUST have the same
1207
// number and types of arguments, and a matching return
1208
// type.
1209
//
1210
// Spec 12.2.9
1211
//
1212
if (!hasMatchingEJBHome(bean, method))
1213            {
1214               fireSpecViolationEvent(entity, method,
1215                       new Section("12.2.9.m"));
1216               status = false;
1217            }
1218         }
1219      } // while( methods.hasNext() )
1220

1221
1222      return status;
1223   }
1224
1225   /*
1226    * Verify Entity Bean Local Home Interface
1227    */

1228   private boolean verifyEntityLocalHome(EntityMetaData entity)
1229   {
1230      boolean status = true;
1231
1232      // Entity bean's local home interface MUST extend the
1233
// javax.ejb.EJBLocalHome interface.
1234
//
1235
// Spec 12.2.11
1236
//
1237
if (!hasEJBLocalHomeInterface(localHome))
1238      {
1239         fireSpecViolationEvent(entity, new Section("12.2.11.a"));
1240         status = false;
1241      }
1242
1243      // The methods defined in the entity bean's home interface MUST
1244
// NOT have java.rmi.RemoteException in their throws clause.
1245
//
1246
// Spec 12.2.11
1247
//
1248
Iterator JavaDoc homeMethods = Arrays.asList(localHome.getMethods()).iterator();
1249      while (homeMethods.hasNext())
1250      {
1251         Method JavaDoc method = (Method JavaDoc)homeMethods.next();
1252
1253         if (throwsRemoteException(method))
1254         {
1255            fireSpecViolationEvent(entity, method, new Section("12.2.11.b"));
1256            status = false;
1257         }
1258      }
1259
1260      // Each method defined in the entity bean's local home interface
1261
// must be one of the following:
1262
//
1263
// - a create method
1264
// - a finder method
1265
// - a home method
1266
//
1267
// Spec 12.2.11
1268
//
1269
homeMethods = Arrays.asList(localHome.getMethods()).iterator();
1270      while (homeMethods.hasNext())
1271      {
1272         Method JavaDoc method = (Method JavaDoc)homeMethods.next();
1273
1274         // Do not check the methods of the javax.ejb.EJBLocalHome interface
1275
if (method.getDeclaringClass().getName().equals(EJB_LOCAL_HOME_INTERFACE))
1276            continue;
1277
1278         if (isCreateMethod(method))
1279         {
1280            // Each create(...) method in the entity bean's local home
1281
// interface MUST have a matching ejbCreate(...) method in
1282
// the entity bean's class.
1283
//
1284
// Each create(...) method in the entity bean's local home
1285
// interface MUST have the same number and types of
1286
// arguments to its matching ejbCreate(...) method.
1287
//
1288
// The return type for a create(...) method MUST be the
1289
// entity bean's local interface type.
1290
//
1291
// All the exceptions defined in the throws clause of the
1292
// matching ejbCreate(...) and ejbPostCreate(...) methods of
1293
// the enterprise bean class MUST be included in the throws
1294
// clause of a matching create(...) method.
1295
//
1296
// The throws clause of a create(...) method MUST include
1297
// the javax.ejb.CreateException.
1298
//
1299
// Spec 12.2.11
1300
//
1301
if (!hasMatchingEJBCreate(bean, method))
1302            {
1303               fireSpecViolationEvent(entity, method,
1304                       new Section("12.2.11.e"));
1305               status = false;
1306            }
1307
1308            if (!hasLocalReturnType(entity, method))
1309            {
1310               fireSpecViolationEvent(entity, method,
1311                       new Section("12.2.11.f"));
1312               status = false;
1313            }
1314
1315            if (hasMatchingEJBCreate(bean, method)
1316                    && hasMatchingEJBPostCreate(bean, method))
1317            {
1318               Method JavaDoc ejbCreate = getMatchingEJBCreate(bean, method);
1319               Method JavaDoc ejbPostCreate = getMatchingEJBPostCreate(bean, method);
1320
1321               if (!(hasMatchingExceptions(ejbCreate, method)
1322                       && hasMatchingExceptions(ejbPostCreate, method)))
1323               {
1324                  fireSpecViolationEvent(entity, method,
1325                          new Section("12.2.11.g"));
1326               }
1327            }
1328
1329            if (!throwsCreateException(method))
1330            {
1331               fireSpecViolationEvent(entity, method,
1332                       new Section("12.2.11.h"));
1333               status = false;
1334            }
1335         }
1336         else if (isFinderMethod(method))
1337         {
1338            // Each finder method MUST match one of the ejbFind<METHOD>
1339
// methods defined in the entity bean class.
1340
//
1341
// The matching ejbFind<METHOD> method MUST have the same
1342
// number and types of arguments.
1343
//
1344
// The return type for a find<METHOD> method MUST be the
1345
// entity bean's local interface type (single-object finder)
1346
// or a collection thereof (for a multi-object finder).
1347
//
1348
// All the exceptions defined in the throws clause of an
1349
// ejbFind method of the entity bean class MUST be included
1350
// in the throws clause of the matching find method of the
1351
// home interface.
1352
//
1353
// The throws clause of a finder method MUST include the
1354
// javax.ejb.FinderException.
1355
//
1356
// Spec 12.2.11
1357
//
1358
if (!(hasLocalReturnType(entity, method)
1359                    || isMultiObjectFinder(method)))
1360            {
1361               fireSpecViolationEvent(entity, method,
1362                       new Section("12.2.11.j"));
1363               status = false;
1364            }
1365
1366            if (!throwsFinderException(method))
1367            {
1368               fireSpecViolationEvent(entity, method,
1369                       new Section("12.2.11.k"));
1370               status = false;
1371            }
1372
1373            if (entity.isCMP())
1374            {
1375               // The entity bean class does not implement the finder
1376
// methods. The implementation of the finder methods are
1377
// provided by the Container
1378
//
1379
// Spec 10.6.2
1380
//
1381
if (hasMatchingEJBFind(bean, method))
1382               {
1383                  fireSpecViolationEvent(entity, method,
1384                          new Section("10.6.2.j"));
1385                  status = false;
1386               }
1387
1388               // For every finder method there must be a matching
1389
// <query> element defined in the deployment descriptor
1390
// with the exception of findByPrimaryKey
1391
//
1392
// JBoss Extension: 'findAll' is _also_ ignored.
1393
//
1394
// Spec 10.5.6
1395
//
1396
if (!method.getName().equals("findByPrimaryKey")
1397                       && !method.getName().equals("findAll")
1398                       && !hasMatchingQuery(method, entity))
1399               {
1400                  fireSpecViolationEvent(entity, method,
1401                          new Section("10.5.6"));
1402                  status = false;
1403               }
1404            }
1405
1406            if (entity.isBMP())
1407            {
1408               if (!hasMatchingEJBFind(bean, method))
1409               {
1410                  fireSpecViolationEvent(entity, method,
1411                          new Section("12.2.11.i"));
1412                  status = false;
1413               }
1414               else
1415               {
1416                  Method JavaDoc ejbFind = getMatchingEJBFind(bean, method);
1417
1418                  if (!(hasMatchingExceptions(ejbFind, method)))
1419                  {
1420                     fireSpecViolationEvent(entity, method,
1421                             new Section("12.2.11.l"));
1422                  }
1423               }
1424            }
1425         }
1426         else
1427         {
1428            // Each home method MUST match a method defined in the
1429
// entity bean class.
1430
//
1431
// The matching ejbHome<METHOD> method MUST have the same
1432
// number and types of arguments, and a matching return
1433
// type.
1434
//
1435
// Spec 12.2.9
1436
//
1437
if (!hasMatchingEJBHome(bean, method))
1438            {
1439               fireSpecViolationEvent(entity, method,
1440                       new Section("12.2.11.m"));
1441               status = false;
1442            }
1443         }
1444      } // while( homeMethods.hasNext() )
1445

1446      return status;
1447   }
1448
1449   /*
1450    * Verify Entity Bean Local Interface
1451    */

1452   private boolean verifyEntityLocal(EntityMetaData entity)
1453   {
1454      boolean status = true;
1455
1456      // Entity bean's local interface MUST extend
1457
// the javax.ejb.EJBLocalObject interface.
1458
//
1459
// Spec 12.2.10
1460
//
1461
if (!hasEJBLocalObjectInterface(local))
1462      {
1463         fireSpecViolationEvent(entity, new Section("12.2.10.a"));
1464         status = false;
1465      }
1466
1467      // The methods defined in the entity bean's local interface MUST
1468
// NOT have java.rmi.RemoteException in their throws clause.
1469
//
1470
// Spec 12.2.10
1471
//
1472
Iterator JavaDoc localMethods = Arrays.asList(local.getMethods()).iterator();
1473      while (localMethods.hasNext())
1474      {
1475         Method JavaDoc method = (Method JavaDoc)localMethods.next();
1476
1477         if (throwsRemoteException(method))
1478         {
1479            fireSpecViolationEvent(entity, method, new Section("12.2.10.b"));
1480            status = false;
1481         }
1482      }
1483
1484      // For each method defined in the local interface, there MUST be
1485
// a matching method in the entity bean's class. The matching
1486
// method MUST have:
1487
//
1488
// - The same name.
1489
// - The same number and types of its arguments.
1490
// - The same return type.
1491
// - All the exceptions defined in the throws clause of the
1492
// matching method of the enterprise Bean class must be
1493
// defined in the throws clause of the method of the local
1494
// interface.
1495
//
1496
// Spec 12.2.10
1497
//
1498
localMethods = Arrays.asList(local.getMethods()).iterator();
1499      while (localMethods.hasNext())
1500      {
1501         Method JavaDoc method = (Method JavaDoc)localMethods.next();
1502
1503         // Do not check the methods of the javax.ejb.EJBLocalObject
1504
// interface
1505
if (method.getDeclaringClass().getName().equals(EJB_LOCAL_OBJECT_INTERFACE))
1506            continue;
1507
1508         if (!hasMatchingMethod(bean, method))
1509         {
1510            fireSpecViolationEvent(entity, method, new Section("12.2.10.c"));
1511            status = false;
1512         }
1513
1514         if (hasMatchingMethod(bean, method))
1515         {
1516            try
1517            {
1518               Method JavaDoc beanMethod = bean.getMethod(method.getName(),
1519                       method.getParameterTypes());
1520
1521               if (!hasMatchingReturnType(beanMethod, method))
1522               {
1523                  fireSpecViolationEvent(entity, method,
1524                          new Section("12.2.10.d"));
1525                  status = false;
1526               }
1527
1528               if (!hasMatchingExceptions(beanMethod, method))
1529               {
1530                  fireSpecViolationEvent(entity, method,
1531                          new Section("12.2.10.e"));
1532
1533                  status = false;
1534               }
1535            }
1536            catch (NoSuchMethodException JavaDoc ignored)
1537            {
1538            }
1539         }
1540      }
1541
1542      return status;
1543   }
1544
1545   /*
1546    * Verify Entity Bean Remote Interface
1547    */

1548   private boolean verifyEntityRemote(EntityMetaData entity)
1549   {
1550      boolean status = true;
1551
1552      // Entity bean's remote interface MUST extend
1553
// the javax.ejb.EJBObject interface.
1554
//
1555
// Spec 9.2.7
1556
//
1557
if (!hasEJBObjectInterface(remote))
1558      {
1559         fireSpecViolationEvent(entity, new Section("9.2.7.a"));
1560         status = false;
1561      }
1562
1563      // The methods defined in the entity bean's remote interface MUST
1564
// have valid RMI-IIOP argument types.
1565
//
1566
// The methods defined in the entity bean's home interface MUST
1567
// have valid RMI-IIOP return types.
1568
//
1569
// The methods defined in the entity bean's home interface MUST
1570
// have java.rmi.RemoteException in their throws clause.
1571
//
1572
// Spec 9.2.7
1573
//
1574
Iterator JavaDoc it = Arrays.asList(remote.getMethods()).iterator();
1575      while (it.hasNext())
1576      {
1577         Method JavaDoc method = (Method JavaDoc)it.next();
1578
1579         if (!hasLegalRMIIIOPArguments(method))
1580         {
1581            fireSpecViolationEvent(entity, method, new Section("9.2.7.b"));
1582            status = false;
1583         }
1584
1585         if (!hasLegalRMIIIOPReturnType(method))
1586         {
1587            fireSpecViolationEvent(entity, method, new Section("9.2.7.c"));
1588            status = false;
1589         }
1590
1591         if (!hasLegalRMIIIOPExceptionTypes(method))
1592         {
1593            fireSpecViolationEvent(entity, method, new Section("9.2.7.h"));
1594            status = false;
1595         }
1596
1597         if (!throwsRemoteException(method))
1598         {
1599            fireSpecViolationEvent(entity, method, new Section("9.2.7.d"));
1600            status = false;
1601         }
1602      }
1603
1604      // For each method defined in the remote interface, there MUST be
1605
// a matching method in the entity bean's class. The matching
1606
// method MUST have:
1607
//
1608
// - The same name.
1609
// - The same number and types of its arguments.
1610
// - The same return type.
1611
// - All the exceptions defined in the throws clause of the
1612
// matching method of the enterprise Bean class must be
1613
// defined in the throws clause of the method of the remote
1614
// interface.
1615
//
1616
// Spec 9.2.7
1617
//
1618
it = Arrays.asList(remote.getMethods()).iterator();
1619      while (it.hasNext())
1620      {
1621         Method JavaDoc method = (Method JavaDoc)it.next();
1622
1623         // Do not check the methods of the javax.ejb.EJBObject interface
1624
if (method.getDeclaringClass().getName().equals(EJB_OBJECT_INTERFACE))
1625            continue;
1626
1627         if (!hasMatchingMethod(bean, method))
1628         {
1629            fireSpecViolationEvent(entity, method, new Section("9.2.7.e"));
1630            status = false;
1631         }
1632
1633         if (hasMatchingMethod(bean, method))
1634         {
1635            try
1636            {
1637               Method JavaDoc beanMethod = bean.getMethod(method.getName(),
1638                       method.getParameterTypes());
1639
1640               if (!hasMatchingReturnType(beanMethod, method))
1641               {
1642                  fireSpecViolationEvent(entity, method,
1643                          new Section("9.2.7.f"));
1644                  status = false;
1645               }
1646
1647               if (!hasMatchingExceptions(beanMethod, method))
1648               {
1649                  fireSpecViolationEvent(entity, method,
1650                          new Section("9.2.7.g"));
1651                  status = false;
1652               }
1653            }
1654            catch (NoSuchMethodException JavaDoc ignored)
1655            {
1656            }
1657         }
1658      }
1659
1660      return status;
1661   }
1662
1663   /*
1664    * Verify Entity Bean Class
1665    */

1666   private boolean verifyCMPEntityBean(EntityMetaData entity)
1667   {
1668      boolean status = true;
1669
1670      // The enterprise bean class MUST implement, directly or
1671
// indirectly, the javax.ejb.EntityBean interface.
1672
//
1673
// Spec 10.6.2
1674
//
1675
if (!hasEntityBeanInterface(bean))
1676      {
1677         fireSpecViolationEvent(entity, new Section("10.6.2.a"));
1678         status = false;
1679      }
1680
1681      // The entity bean class MUST be defined as public and abstract.
1682
//
1683
// Spec 10.6.2
1684
//
1685
if (!isPublic(bean) || !isAbstract(bean))
1686      {
1687         fireSpecViolationEvent(entity, new Section("10.6.2.b"));
1688         status = false;
1689      }
1690
1691      // The entity bean class MUST define a public constructor that
1692
// takes no arguments
1693
//
1694
// Spec 10.6.2
1695
//
1696
if (!hasDefaultConstructor(bean))
1697      {
1698         fireSpecViolationEvent(entity, new Section("10.6.2.c"));
1699         status = false;
1700      }
1701
1702      // The entity bean class MUST NOT define the finalize() method.
1703
//
1704
// Spec 10.6.2
1705
//
1706
if (hasFinalizer(bean))
1707      {
1708         fireSpecViolationEvent(entity, new Section("10.6.2.d"));
1709         status = false;
1710      }
1711
1712      // The ejbCreate(...) method signatures MUST follow these rules:
1713
//
1714
// - The method MUST be declared as public
1715
// - The method MUST NOT be declared as final or static
1716
// - The return type MUST be the entity bean's primary key type
1717
// --- Only if method is on remote home ---
1718
// - The method arguments MUST be legal types for RMI/IIOP
1719
// - The method return value type MUST be legal type for RMI/IIOP
1720
// --- End of only if method is on remote home ---
1721
// - The method must define the javax.ejb.CreateException
1722
//
1723
// Spec 10.6.4
1724
//
1725
if (hasEJBCreateMethod(bean, false))
1726      {
1727         Iterator JavaDoc it = getEJBCreateMethods(bean);
1728         while (it.hasNext())
1729         {
1730            Method JavaDoc ejbCreate = (Method JavaDoc)it.next();
1731            if (!isPublic(ejbCreate))
1732            {
1733               fireSpecViolationEvent(entity, ejbCreate,
1734                       new Section("10.6.4.b"));
1735               status = false;
1736            }
1737
1738            if ((isFinal(ejbCreate)) || (isStatic(ejbCreate)))
1739            {
1740               fireSpecViolationEvent(entity, ejbCreate,
1741                       new Section("10.6.4.c"));
1742               status = false;
1743            }
1744
1745            if (!hasPrimaryKeyReturnType(entity, ejbCreate))
1746            {
1747               fireSpecViolationEvent(entity, ejbCreate,
1748                       new Section("10.6.4.d"));
1749               status = false;
1750            }
1751
1752            /* FIXME
1753             * This is only true if the method is on the remote home
1754             * interface
1755             if (!hasLegalRMIIIOPArguments(ejbCreate)) {
1756             fireSpecViolationEvent(entity, ejbCreate, new Section("10.6.4.d"));
1757             status = false;
1758             }
1759
1760             if (!hasLegalRMIIIOPReturnType(ejbCreate)) {
1761             fireSpecViolationEvent(entity, ejbCreate, new Section("10.5.4.f"));
1762             status = false;
1763             }
1764             */

1765
1766            if (!throwsCreateException(ejbCreate))
1767            {
1768               fireSpecViolationEvent(entity, ejbCreate,
1769                       new Section("10.6.4.g"));
1770               status = false;
1771            }
1772         }
1773      }
1774
1775      // For each ejbCreate(...) method, the entity bean class MUST
1776
// define a matching ejbPostCreate(...) method.
1777
//
1778
// The ejbPostCreate(...) method MUST follow these rules:
1779
//
1780
// - the method MUST be declared as public
1781
// - the method MUST NOT be declared as final or static
1782
// - the return type MUST be void
1783
// - the method arguments MUST be the same as the matching
1784
// ejbCreate(...) method
1785
//
1786
// Spec 10.6.5
1787
//
1788
if (hasEJBCreateMethod(bean, false))
1789      {
1790         Iterator JavaDoc it = getEJBCreateMethods(bean);
1791
1792         while (it.hasNext())
1793         {
1794            Method JavaDoc ejbCreate = (Method JavaDoc)it.next();
1795
1796            if (!hasMatchingEJBPostCreate(bean, ejbCreate))
1797            {
1798               fireSpecViolationEvent(entity, ejbCreate,
1799                       new Section("10.6.5.a"));
1800               status = false;
1801            }
1802
1803            if (hasMatchingEJBPostCreate(bean, ejbCreate))
1804            {
1805               Method JavaDoc ejbPostCreate = getMatchingEJBPostCreate(bean,
1806                       ejbCreate);
1807
1808               if (!isPublic(ejbPostCreate))
1809               {
1810                  fireSpecViolationEvent(entity, ejbPostCreate,
1811                          new Section("10.6.5.b"));
1812                  status = false;
1813               }
1814
1815               if (isStatic(ejbPostCreate))
1816               {
1817                  fireSpecViolationEvent(entity, ejbPostCreate,
1818                          new Section("10.6.5.c"));
1819                  status = false;
1820               }
1821
1822               if (isFinal(ejbPostCreate))
1823               {
1824                  fireSpecViolationEvent(entity, ejbPostCreate,
1825                          new Section("10.6.5.d"));
1826                  status = false;
1827               }
1828
1829               if (!hasVoidReturnType(ejbPostCreate))
1830               {
1831                  fireSpecViolationEvent(entity, ejbPostCreate,
1832                          new Section("10.6.5.e"));
1833                  status = false;
1834               }
1835            }
1836         }
1837      }
1838
1839      // The ejbHome(...) method signatures MUST follow these rules:
1840
//
1841
// - The method name MUST have ejbHome as its prefix.
1842
// - The method MUST be declared as public
1843
// - The method MUST NOT be declared as static.
1844
// - The method MUST NOT define the java.rmi.RemoteException
1845
//
1846
// Spec 10.6.6
1847
//
1848
Iterator JavaDoc it = getEjbHomeMethods(bean);
1849      while (it.hasNext())
1850      {
1851         Method JavaDoc ejbHome = (Method JavaDoc)it.next();
1852         if (!isPublic(ejbHome))
1853         {
1854            fireSpecViolationEvent(entity, ejbHome, new Section("10.6.6.a"));
1855            status = false;
1856         }
1857
1858         if (isStatic(ejbHome))
1859         {
1860            fireSpecViolationEvent(entity, ejbHome, new Section("10.6.6.b"));
1861            status = false;
1862         }
1863
1864         if (throwsRemoteException(ejbHome))
1865         {
1866            fireSpecViolationEvent(entity, ejbHome, new Section("10.6.6.c"));
1867            status = false;
1868         }
1869      }
1870
1871      // The CMP entity bean MUST implement get and set accessor methods for
1872
// each field within the abstract persistance schema.
1873
//
1874
// Spec 10.6.2
1875
//
1876
it = entity.getCMPFields();
1877      while (it.hasNext())
1878      {
1879         String JavaDoc fieldName = (String JavaDoc)it.next();
1880         String JavaDoc getName = "get" + fieldName.substring(0, 1).toUpperCase() +
1881                 fieldName.substring(1);
1882         Class JavaDoc fieldType = null;
1883
1884         try
1885         {
1886            Method JavaDoc m = bean.getMethod(getName, new Class JavaDoc[0]);
1887            fieldType = m.getReturnType();
1888
1889            // The getter must not return 'void' according to the JavaBeans
1890
// Spec
1891
if (fieldType == Void.TYPE)
1892            {
1893               fireSpecViolationEvent(entity,
1894                       new Section("jb.7.1.b", "Field: " + fieldName));
1895            }
1896         }
1897         catch (NoSuchMethodException JavaDoc nsme)
1898         {
1899            fireSpecViolationEvent(entity,
1900                    new Section("10.6.2.g", "Field: " + fieldName));
1901            status = false;
1902         }
1903
1904         String JavaDoc setName = "set" + fieldName.substring(0, 1).toUpperCase() +
1905                 fieldName.substring(1);
1906         Class JavaDoc[] args = new Class JavaDoc[1];
1907         args[0] = fieldType;
1908
1909         try
1910         {
1911            Method JavaDoc m = bean.getMethod(setName, args);
1912            fieldType = m.getReturnType();
1913
1914            // According to the JavaBeans Spec, a setter method must
1915
// return 'void'
1916
if (fieldType != Void.TYPE)
1917            {
1918               fireSpecViolationEvent(entity,
1919                       new Section("jb.7.1.a", "Field: " + fieldName));
1920            }
1921         }
1922         catch (NoSuchMethodException JavaDoc nsme)
1923         {
1924            // Try with java.util.Collection
1925
//
1926
// FIXME: This should only be tried for CMR methods; a CMP
1927
// setter cannot accept a Collection!
1928
try
1929            {
1930               args[0] = classloader.loadClass("java.util.Collection");
1931               Method JavaDoc m = bean.getMethod(setName, args);
1932            }
1933            catch (NoSuchMethodException JavaDoc nsme2)
1934            {
1935               fireSpecViolationEvent(entity,
1936                       new Section("10.6.2.h", "Field: " + fieldName));
1937               status = false;
1938            }
1939            catch (ClassNotFoundException JavaDoc cnfe)
1940            {
1941               // Something is really broken
1942
}
1943         }
1944      }
1945
1946      // The ejbSelect(...) method signatures MUST follow these rules:
1947
//
1948
// - The method name MUST have ejbSelect as its prefix.
1949
// - The method MUST be declared as public
1950
// - The method MUST be declared as abstract.
1951
// - The method MUST define the javax.ejb.FinderException
1952
//
1953
// Spec 10.6.7
1954
//
1955
it = getEjbSelectMethods(bean);
1956      while (it.hasNext())
1957      {
1958         Method JavaDoc ejbSelect = (Method JavaDoc)it.next();
1959
1960         if (!isPublic(ejbSelect))
1961         {
1962            fireSpecViolationEvent(entity, ejbSelect, new Section("10.6.7.a"));
1963            status = false;
1964         }
1965
1966         if (!isAbstract(ejbSelect))
1967         {
1968            fireSpecViolationEvent(entity, ejbSelect, new Section("10.6.7.b"));
1969            status = false;
1970         }
1971
1972         if (!throwsFinderException(ejbSelect))
1973         {
1974            fireSpecViolationEvent(entity, ejbSelect, new Section("10.6.7.c"));
1975            status = false;
1976         }
1977
1978         if (!hasMatchingQuery(ejbSelect, entity))
1979         {
1980            fireSpecViolationEvent(entity, ejbSelect, new Section("10.5.7"));
1981            status = false;
1982         }
1983      }
1984
1985      // A CMP Entity Bean must not define Finder methods.
1986
//
1987
// Spec 10.6.2
1988
//
1989
if (hasFinderMethod(bean))
1990      {
1991         fireSpecViolationEvent(entity, new Section("10.6.2.i"));
1992         status = false;
1993      }
1994
1995      return status;
1996   }
1997
1998   /*
1999    * Verify BMP Entity Class
2000    */

2001   private boolean verifyBMPEntityBean(EntityMetaData entity)
2002   {
2003      boolean status = true;
2004
2005      // The enterprise bean class MUST implement, directly or
2006
// indirectly, the javax.ejb.EntityBean interface.
2007
//
2008
// Spec 12.2.2
2009
//
2010
if (!hasEntityBeanInterface(bean))
2011      {
2012         fireSpecViolationEvent(entity, new Section("12.2.2.a"));
2013         status = false;
2014      }
2015
2016      // The entity bean class MUST be defined as public and NOT abstract.
2017
//
2018
// Spec 12.2.2
2019
//
2020
if (!isPublic(bean) || isAbstract(bean))
2021      {
2022         fireSpecViolationEvent(entity, new Section("12.2.2.b"));
2023         status = false;
2024      }
2025
2026      // The entity bean class MUST NOT be defined as final.
2027
//
2028
// Spec 12.2.2
2029
//
2030
if (isFinal(bean))
2031      {
2032         fireSpecViolationEvent(entity, new Section("12.2.2.c"));
2033         status = false;
2034      }
2035
2036      // The entity bean class MUST define a public constructor that
2037
// takes no arguments
2038
//
2039
// Spec 12.2.2
2040
//
2041
if (!hasDefaultConstructor(bean))
2042      {
2043         fireSpecViolationEvent(entity, new Section("12.2.2.d"));
2044         status = false;
2045      }
2046
2047      // The entity bean class MUST NOT define the finalize() method.
2048
//
2049
// Spec 12.2.2
2050
//
2051
if (hasFinalizer(bean))
2052      {
2053         fireSpecViolationEvent(entity, new Section("12.2.2.e"));
2054         status = false;
2055      }
2056
2057      // The ejbCreate(...) method signatures MUST follow these rules:
2058
//
2059
// - The method MUST be declared as public
2060
// - The method MUST NOT be declared as final or static
2061
// - The return type MUST be the entity bean's primary key type
2062
// --- If the method is on the remote home interface ---
2063
// - The method arguments MUST be legal types for RMI/IIOP
2064
// - The method return value type MUST be legal type for RMI/IIOP
2065
// --- End if the method is on the remote home interface ---
2066
//
2067
// Spec 12.2.3
2068
//
2069
if (hasEJBCreateMethod(bean, false))
2070      {
2071         Iterator JavaDoc it = getEJBCreateMethods(bean);
2072         while (it.hasNext())
2073         {
2074            Method JavaDoc ejbCreate = (Method JavaDoc)it.next();
2075            if (!isPublic(ejbCreate))
2076            {
2077               fireSpecViolationEvent(entity, ejbCreate,
2078                       new Section("12.2.3.a"));
2079               status = false;
2080            }
2081
2082            if ((isFinal(ejbCreate)) || (isStatic(ejbCreate)))
2083            {
2084               fireSpecViolationEvent(entity, ejbCreate,
2085                       new Section("12.2.3.b"));
2086               status = false;
2087            }
2088
2089            if (!hasPrimaryKeyReturnType(entity, ejbCreate))
2090            {
2091               fireSpecViolationEvent(entity, ejbCreate,
2092                       new Section("12.2.3.c"));
2093               status = false;
2094            }
2095
2096            /* FIXME
2097             * This code needs to only be invoked if the method is on the
2098             * remote home.
2099             if (!hasLegalRMIIIOPArguments(ejbCreate)) {
2100             fireSpecViolationEvent(entity, ejbCreate, new Section("9.2.3.d"));
2101             status = false;
2102             }
2103             if (!hasLegalRMIIIOPReturnType(ejbCreate)) {
2104             fireSpecViolationEvent(entity, ejbCreate, new Section("9.2.3.e"));
2105             status = false;
2106             }
2107            */

2108         }
2109      }
2110
2111      // For each ejbCreate(...) method, the entity bean class MUST
2112
// define a matching ejbPostCreate(...) method.
2113
//
2114
// The ejbPostCreate(...) method MUST follow these rules:
2115
//
2116
// - the method MUST be declared as public
2117
// - the method MUST NOT be declared as final or static
2118
// - the return type MUST be void
2119
// - the method arguments MUST be the same as the matching
2120
// ejbCreate(...) method
2121
//
2122
// Spec 12.2.4
2123
//
2124
if (hasEJBCreateMethod(bean, false))
2125      {
2126         Iterator JavaDoc it = getEJBCreateMethods(bean);
2127         while (it.hasNext())
2128         {
2129            Method JavaDoc ejbCreate = (Method JavaDoc)it.next();
2130
2131            if (!hasMatchingEJBPostCreate(bean, ejbCreate))
2132            {
2133               fireSpecViolationEvent(entity, ejbCreate,
2134                       new Section("12.2.4.a"));
2135               status = false;
2136            }
2137
2138            if (hasMatchingEJBPostCreate(bean, ejbCreate))
2139            {
2140               Method JavaDoc ejbPostCreate = getMatchingEJBPostCreate(bean,
2141                       ejbCreate);
2142
2143               if (!isPublic(ejbPostCreate))
2144               {
2145                  fireSpecViolationEvent(entity, ejbPostCreate,
2146                          new Section("12.2.4.b"));
2147                  status = false;
2148               }
2149
2150               if (isStatic(ejbPostCreate) || isFinal(ejbPostCreate))
2151               {
2152                  fireSpecViolationEvent(entity, ejbPostCreate,
2153                          new Section("12.2.4.c"));
2154                  status = false;
2155               }
2156
2157               if (!hasVoidReturnType(ejbPostCreate))
2158               {
2159                  fireSpecViolationEvent(entity, ejbPostCreate,
2160                          new Section("12.2.4.d"));
2161                  status = false;
2162               }
2163            }
2164         }
2165      }
2166
2167      // Every entity bean MUST define the ejbFindByPrimaryKey method.
2168
//
2169
// The return type for the ejbFindByPrimaryKey method MUST be the
2170
// primary key type.
2171
//
2172
// The ejbFindByPrimaryKey method MUST be a single-object finder.
2173
//
2174
// Spec 12.2.5
2175
//
2176
if (!hasEJBFindByPrimaryKey(bean))
2177      {
2178         fireSpecViolationEvent(entity, new Section("12.2.5.e"));
2179         status = false;
2180      }
2181
2182      if (hasEJBFindByPrimaryKey(bean))
2183      {
2184         Method JavaDoc ejbFindByPrimaryKey = getEJBFindByPrimaryKey(bean);
2185
2186         if (!hasPrimaryKeyReturnType(entity, ejbFindByPrimaryKey))
2187         {
2188            fireSpecViolationEvent(entity, ejbFindByPrimaryKey,
2189                    new Section("12.2.5.e1"));
2190            status = false;
2191         }
2192
2193         if (!isSingleObjectFinder(entity, ejbFindByPrimaryKey))
2194         {
2195            fireSpecViolationEvent(entity, ejbFindByPrimaryKey,
2196                    new Section("12.2.5.e2"));
2197            status = false;
2198         }
2199      }
2200
2201      // A finder method MUST be declared as public.
2202
//
2203
// A finder method MUST NOT be declared as static.
2204
//
2205
// A finder method MUST NOT be declared as final.
2206
//
2207
// The finder method argument types MUST be legal types for
2208
// RMI/IIOP
2209
//
2210
// The finder method return type MUST be either the entity bean's
2211
// primary key type, or java.lang.util.Enumeration interface or
2212
// java.lang.util.Collection interface.
2213
//
2214
// Spec 12.2.5
2215
//
2216
if (hasFinderMethod(bean))
2217      {
2218         Iterator JavaDoc it = getEJBFindMethods(bean);
2219         while (it.hasNext())
2220         {
2221            Method JavaDoc finder = (Method JavaDoc)it.next();
2222
2223            if (!isPublic(finder))
2224            {
2225               fireSpecViolationEvent(entity, finder, new Section("12.2.5.a"));
2226               status = false;
2227            }
2228
2229            if (isFinal(finder) || isStatic(finder))
2230            {
2231               fireSpecViolationEvent(entity, finder, new Section("12.2.5.b"));
2232               status = false;
2233            }
2234
2235            /** FIXME
2236             * this path should only get invoked if the finder is on the
2237             * remote interface.
2238             if (!hasLegalRMIIIOPArguments(finder)) {
2239             fireSpecViolationEvent(entity, finder, new Section("12.2.5.c"));
2240             status = false;
2241             }
2242             */

2243
2244            if (!(isSingleObjectFinder(entity, finder)
2245                    || isMultiObjectFinder(finder)))
2246            {
2247               fireSpecViolationEvent(entity, finder, new Section("12.2.5.d"));
2248               status = false;
2249            }
2250         }
2251      }
2252
2253      // The ejbHome(...) method signatures MUST follow these rules:
2254
//
2255
// - The method name MUST have ejbHome as its prefix.
2256
// - The method MUST be declared as public
2257
// - The method MUST NOT be declared as static.
2258
// - The method MUST NOT define the java.rmi.RemoteException
2259
//
2260
// Spec 10.6.6
2261
//
2262
Iterator JavaDoc it = getEjbHomeMethods(bean);
2263      while (it.hasNext())
2264      {
2265         Method JavaDoc ejbHome = (Method JavaDoc)it.next();
2266
2267         if (!isPublic(ejbHome))
2268         {
2269            fireSpecViolationEvent(entity, ejbHome, new Section("10.6.6.a"));
2270            status = false;
2271         }
2272
2273         if (isStatic(ejbHome))
2274         {
2275            fireSpecViolationEvent(entity, ejbHome, new Section("10.6.6.b"));
2276            status = false;
2277         }
2278
2279         if (throwsRemoteException(ejbHome))
2280         {
2281            fireSpecViolationEvent(entity, ejbHome, new Section("10.6.6.c"));
2282            status = false;
2283         }
2284      }
2285
2286      return status;
2287   }
2288
2289   /*
2290    * Verify Primary Key
2291    */

2292   private boolean verifyPrimaryKey(EntityMetaData entity)
2293   {
2294      boolean status = true;
2295      boolean cmp = entity.isCMP();
2296
2297      if (entity.getPrimaryKeyClass() == null
2298              || entity.getPrimaryKeyClass().length() == 0)
2299      {
2300         if (cmp)
2301            fireSpecViolationEvent(entity, new Section("10.6.1.a"));
2302         else
2303            fireSpecViolationEvent(entity, new Section("12.2.1.a"));
2304
2305         // We can't get any further if there's no PK class specified!
2306
return false;
2307      }
2308
2309      // FIXME - Still missing the bits from 10.8.2 for CMP primary
2310
// keys. Primarily the class must be public, all fields in the
2311
// class must be public and the fields must also be a subset of
2312
// the CMP fields within the bean.
2313
//
2314
Class JavaDoc cls = null;
2315      try
2316      {
2317         cls = classloader.loadClass(entity.getPrimaryKeyClass());
2318      }
2319      catch (ClassNotFoundException JavaDoc e)
2320      {
2321         if (cmp)
2322            fireSpecViolationEvent(entity, new Section("10.6.13.a"));
2323         else
2324            fireSpecViolationEvent(entity, new Section("12.2.12.a"));
2325
2326         // Can't do any other checks if the class is null!
2327
return false;
2328      }
2329
2330      // The primary key type must be a valid type in RMI-IIOP.
2331
//
2332
// Spec 10.6.13 & 12.2.12
2333
//
2334
if (!isRMIIDLValueType(cls))
2335      {
2336         if (cmp)
2337            fireSpecViolationEvent(entity, new Section("10.6.13.b"));
2338         else
2339            fireSpecViolationEvent(entity, new Section("12.2.12.b"));
2340         status = false;
2341      }
2342
2343      // No primary key field specified, just a primary key class.
2344
if (entity.getPrimKeyField() == null ||
2345              entity.getPrimKeyField().length() == 0)
2346      {
2347         // This is a check for some interesting implementation of
2348
// equals() and hashCode(). I am not sure how well it works in
2349
// the end.
2350
//
2351
if (!cls.getName().equals("java.lang.Object"))
2352         {
2353            Object JavaDoc one, two;
2354
2355            try
2356            {
2357               one = cls.newInstance();
2358               two = cls.newInstance();
2359               try
2360               {
2361                  if (!one.equals(two))
2362                  {
2363                     if (cmp)
2364                     {
2365                        // fireSpecViolationEvent(entity, new Section("10.6.13.c"));
2366
log.warn("Default instances of primary key: " + cls
2367                                + " do not equate, check your equals method");
2368                     }
2369                     else
2370                     {
2371                        //fireSpecViolationEvent(entity, new Section("12.2.12.c"));
2372
log.warn("Default instances of primary key: " + cls
2373                                + " do not equate, check your equals method");
2374                     }
2375                     status = true;
2376                  }
2377               }
2378               catch (NullPointerException JavaDoc e)
2379               {
2380                  // That's OK - the implementor expected the fields to
2381
// have values
2382
}
2383
2384               try
2385               {
2386                  if (one.hashCode() != two.hashCode())
2387                  {
2388                     if (cmp)
2389                     {
2390                        //fireSpecViolationEvent(entity, new Section("10.6.13.d"));
2391
log.warn("Default instances of primary key: " + cls
2392                                + " do not have the same hash, check your hashCode method");
2393                     }
2394                     else
2395                     {
2396                        //fireSpecViolationEvent(entity, new Section("12.2.12.d"));
2397
log.warn("Default instances of primary key: " + cls
2398                                + " do not have the same hash, check your hashCode method");
2399                     }
2400                     status = true;
2401                  }
2402               }
2403               catch (NullPointerException JavaDoc e)
2404               {
2405                  // That's OK - the implementor expected the fields to have values
2406
}
2407            }
2408            catch (IllegalAccessException JavaDoc e)
2409            {
2410               // If CMP primary key class MUST have a public
2411
// constructor with no parameters. 10.8.2.a
2412
///
2413
if (cmp)
2414               {
2415                  fireSpecViolationEvent(entity, new Section("10.8.2.a"));
2416                  status = false;
2417               }
2418            }
2419            catch (InstantiationException JavaDoc e)
2420            {
2421               //Not sure what condition this is at the moment - JMW
2422
//fireSpecViolationEvent(entity, new Section("9.2.9.a"));
2423
//status = false;
2424
}
2425         }
2426      }
2427      else
2428      {
2429         // BMP Beans MUST not include the primkey-field element in
2430
// their deployment descriptor. Deployment descriptor comment
2431
//
2432
if (entity.isBMP())
2433         {
2434            fireSpecViolationEvent(entity, new Section("dd.a"));
2435            status = false;
2436         }
2437
2438         // The primary keyfield MUST be a CMP field within the
2439
// entity bean.
2440
//
2441
// Spec 10.8.1
2442
//
2443
boolean found = false;
2444         Iterator JavaDoc it = entity.getCMPFields();
2445         while (it.hasNext())
2446         {
2447            String JavaDoc fieldName = (String JavaDoc)it.next();
2448            if (fieldName.equals(entity.getPrimKeyField()))
2449            {
2450               found = true;
2451               break;
2452            }
2453         }
2454
2455         if (!found)
2456         {
2457            status = false;
2458            fireSpecViolationEvent(entity, new Section("10.8.1.b"));
2459         }
2460
2461         try
2462         {
2463            // The class of the primary key field MUST match the
2464
// primary key class specified for the entity bean. We
2465
// figure out the class of this field by getting the
2466
// return type of the get<FieldName> accessor method.
2467
//
2468
// Spec 10.8.1
2469
//
2470
String JavaDoc pkField = entity.getPrimKeyField();
2471            String JavaDoc methodName = "get" +
2472                    pkField.substring(0, 1).toUpperCase() + pkField.substring(1);
2473
2474            Method JavaDoc method = bean.getMethod(methodName, new Class JavaDoc[0]);
2475            if (!entity.getPrimaryKeyClass().equals(method.getReturnType().getName())
2476            )
2477            {
2478               status = false;
2479               fireSpecViolationEvent(entity, new Section("10.8.1.a"));
2480            }
2481
2482         }
2483         catch (NoSuchMethodException JavaDoc e)
2484         {
2485            // The primary keyfield MUST be a CMP field within the
2486
// entity bean.
2487
//
2488
// Spec 10.8.1
2489
//
2490
status = false;
2491            fireSpecViolationEvent(entity, new Section("10.8.1.b"));
2492         }
2493      }
2494
2495      return status;
2496   }
2497
2498   /*
2499    * Verify Message Driven Bean
2500    */

2501   protected boolean verifyMessageDrivenBean(MessageDrivenMetaData mdBean)
2502   {
2503      boolean status = true;
2504
2505      // A message driven bean MUST implement, directly or indirectly,
2506
// javax.ejb.MessageDrivenBean interface.
2507
//
2508
// Spec 15.7.2
2509
//
2510
if (!hasMessageDrivenBeanInterface(bean))
2511      {
2512         fireSpecViolationEvent(mdBean, new Section("15.7.2.a"));
2513         status = false;
2514      }
2515
2516      // The class must implement, directly or indirectly, the message listener interface required by the messaging
2517
// type that it supports. In the case of JMS, this is the javax.jms.MessageListener interface.
2518
//
2519
// Spec 15.7.2
2520
//
2521
if (!isAssignableFrom(mdBean.getMessagingType(), bean))
2522      {
2523         fireSpecViolationEvent(mdBean, new Section("15.7.2.b"));
2524         status = false;
2525      }
2526
2527      // The message driven bean class MUST be defined as public.
2528
//
2529
// Spec 15.7.2
2530
//
2531
if (!isPublic(bean))
2532      {
2533         fireSpecViolationEvent(mdBean, new Section("15.7.2.c1"));
2534         status = false;
2535      }
2536
2537      // The message driven bean class MUST NOT be final.
2538
//
2539
// Spec 15.7.2
2540
//
2541
if (isFinal(bean))
2542      {
2543         fireSpecViolationEvent(mdBean, new Section("15.7.2.c2"));
2544         status = false;
2545      }
2546
2547      // The message driven bean class MUST NOT be abstract.
2548
//
2549
// Spec 15.7.2
2550
//
2551
if (isAbstract(bean))
2552      {
2553         fireSpecViolationEvent(mdBean, new Section("15.7.2.c3"));
2554         status = false;
2555      }
2556
2557      // The message driven bean class MUST have a public constructor that
2558
// takes no arguments.
2559
//
2560
// Spec 15.7.2
2561
//
2562
if (!hasDefaultConstructor(bean))
2563      {
2564         fireSpecViolationEvent(mdBean, new Section("15.7.2.d"));
2565         status = false;
2566      }
2567
2568      // The message driven bean class MUST NOT define the finalize() method.
2569
//
2570
// Spec 15.7.2
2571
//
2572
if (hasFinalizer(bean))
2573      {
2574         fireSpecViolationEvent(mdBean, new Section("15.7.2.e"));
2575         status = false;
2576      }
2577
2578      // A message driven bean MUST implement the ejbCreate() method.
2579
// The ejbCreate() method signature MUST follow these rules:
2580
//
2581
// - The method name MUST be ejbCreate
2582
// - The method MUST be declared as public
2583
// - The method MUST NOT be declared as final or static
2584
// - The return type MUST be void
2585
// - The method arguments MUST have no arguments.
2586
// - The method MUST NOT define any application exceptions.
2587
//
2588
// Spec 15.7.2, 3
2589
//
2590
if (hasEJBCreateMethod(bean, false))
2591      {
2592         Iterator JavaDoc it = getEJBCreateMethods(bean);
2593         Method JavaDoc ejbCreate = (Method JavaDoc)it.next();
2594
2595         if (!isPublic(ejbCreate))
2596         {
2597            fireSpecViolationEvent(mdBean, ejbCreate, new Section("15.7.3.b"));
2598            status = false;
2599         }
2600
2601         if ((isFinal(ejbCreate)) || (isStatic(ejbCreate)))
2602         {
2603            fireSpecViolationEvent(mdBean, ejbCreate, new Section("15.7.3.c"));
2604            status = false;
2605         }
2606
2607         if (!hasVoidReturnType(ejbCreate))
2608         {
2609            fireSpecViolationEvent(mdBean, ejbCreate, new Section("15.7.3.d"));
2610            status = false;
2611         }
2612
2613         if (!hasNoArguments(ejbCreate))
2614         {
2615            fireSpecViolationEvent(mdBean, ejbCreate, new Section("15.7.3.e"));
2616            status = false;
2617         }
2618
2619         if (!throwsNoException(ejbCreate))
2620         {
2621            fireSpecViolationEvent(mdBean, ejbCreate, new Section("15.7.3.f"));
2622            status = false;
2623         }
2624
2625         if (it.hasNext())
2626         {
2627            fireSpecViolationEvent(mdBean, new Section("15.7.3.a"));
2628            status = false;
2629         }
2630      }
2631      else
2632      {
2633         fireSpecViolationEvent(mdBean, new Section("15.7.3.a"));
2634         status = false;
2635      }
2636
2637      // The message-driven bean class must define the message listener methods. The signature of a message
2638
// listener method must follow these rules:
2639
//
2640
// - The method MUST be declared as public
2641
// - The method MUST NOT be declared as final or static
2642
//
2643
// Spec 15.7.4
2644
//
2645

2646      Class JavaDoc messageListener = null;
2647      try
2648      {
2649         messageListener = classloader.loadClass(mdBean.getMessagingType());
2650      }
2651      catch (ClassNotFoundException JavaDoc cnfe)
2652      {
2653         fireSpecViolationEvent(mdBean,
2654                 new Section("15.7.2.b",
2655                         "Class not found on '" + mdBean.getMessagingType() + "': " + cnfe.getMessage()));
2656         status = false;
2657
2658      }
2659
2660      if (messageListener != null)
2661      {
2662         Method JavaDoc[] methods = bean.getMethods();
2663         for (int i = 0; i < methods.length; ++i)
2664         {
2665            if (methods[i].getDeclaringClass().equals(messageListener))
2666            {
2667               if (!isPublic(methods[i]))
2668               {
2669                  fireSpecViolationEvent(mdBean, methods[i], new Section("15.7.4.b"));
2670                  status = false;
2671               }
2672
2673               if ((isFinal(methods[i])) || (isStatic(methods[i])))
2674               {
2675                  fireSpecViolationEvent(mdBean, methods[i], new Section("15.7.4.c"));
2676                  status = false;
2677               }
2678            }
2679         }
2680      }
2681
2682      // A message driven bean MUST implement the ejbRemove() method.
2683
// The ejbRemove() method signature MUST follow these rules:
2684
//
2685
// - The method name MUST be ejbRemove
2686
// - The method MUST be declared as public
2687
// - The method MUST NOT be declared as final or static
2688
// - The return type MUST be void
2689
// - The method MUST have no arguments.
2690
// - The method MUST NOT define any application exceptions.
2691
//
2692
// Spec 15.7.5
2693
//
2694
if (hasEJBRemoveMethod(bean))
2695      {
2696         Iterator JavaDoc it = getEJBRemoveMethods(bean);
2697         Method JavaDoc ejbRemove = (Method JavaDoc)it.next();
2698
2699         if (!isPublic(ejbRemove))
2700         {
2701            fireSpecViolationEvent(mdBean, ejbRemove, new Section("15.7.5.b"));
2702            status = false;
2703         }
2704
2705         if ((isFinal(ejbRemove)) || (isStatic(ejbRemove)))
2706         {
2707            fireSpecViolationEvent(mdBean, ejbRemove, new Section("15.7.5.c"));
2708            status = false;
2709         }
2710
2711         if (!hasVoidReturnType(ejbRemove))
2712         {
2713            fireSpecViolationEvent(mdBean, ejbRemove, new Section("15.7.5.d"));
2714            status = false;
2715         }
2716
2717         if (!hasNoArguments(ejbRemove))
2718         {
2719            fireSpecViolationEvent(mdBean, ejbRemove, new Section("15.7.5.e"));
2720            status = false;
2721         }
2722
2723         if (!throwsNoException(ejbRemove))
2724         {
2725            fireSpecViolationEvent(mdBean, ejbRemove, new Section("15.7.5.f"));
2726            status = false;
2727         }
2728
2729         if (it.hasNext())
2730         {
2731            fireSpecViolationEvent(mdBean, new Section("15.7.5.a"));
2732            status = false;
2733         }
2734      }
2735      else
2736      {
2737         fireSpecViolationEvent(mdBean, new Section("15.7.5.a"));
2738         status = false;
2739      }
2740
2741      return status;
2742   }
2743
2744   /**
2745    * Verify Session Bean Service Endpoint
2746    * @param session
2747    * @return
2748    */

2749   protected boolean verifyServiceEndpoint(SessionMetaData session)
2750   {
2751      boolean status = true;
2752
2753      // The service endpoint interface MUST extend the java.rmi.Remote
2754
// interface.
2755
//
2756
// Spec 7.11.9
2757
//
2758
if (!hasRemoteInterface(serviceEndpointInterface))
2759      {
2760         fireSpecViolationEvent(session, new Section("7.11.9.a"));
2761         status = false;
2762      }
2763
2764      // Method arguments defined in the service-endpoint interface MUST be
2765
// of valid types for RMI/JAXRPC.
2766
//
2767
// Method return values defined in the remote interface MUST
2768
// be of valid types for RMI/JAXRPC.
2769
//
2770
// Methods defined in the remote interface MUST include
2771
// java.rmi.RemoteException in their throws clause.
2772
//
2773
// Spec 7.11.9
2774
//
2775
Iterator JavaDoc it = Arrays.asList(serviceEndpointInterface.getMethods()).iterator();
2776      while (it.hasNext())
2777      {
2778         Method JavaDoc method = (Method JavaDoc)it.next();
2779
2780         if (!hasLegalJAXRPCArguments(method))
2781         {
2782            fireSpecViolationEvent(session, method, new Section("7.11.9.b1"));
2783            status = false;
2784         }
2785
2786         if (!hasLegalJAXRPCReturnType(method))
2787         {
2788            fireSpecViolationEvent(session, method, new Section("7.11.9.b2"));
2789            status = false;
2790         }
2791
2792         if (!throwsRemoteException(method))
2793         {
2794            fireSpecViolationEvent(session, method, new Section("7.11.9.b3"));
2795            status = false;
2796         }
2797      }
2798
2799      // For each method defined in the web service interface, there MUST be
2800
// a matching method in the session bean's class. The matching
2801
// method MUST have:
2802
//
2803
// - the same name
2804
// - the same number and types of arguments, and the same
2805
// return type
2806
// - All the exceptions defined in the throws clause of the
2807
// matching method of the session bean class must be defined
2808
// in the throws clause of the method of the remote interface
2809
//
2810
// Spec 7.11.5
2811
//
2812
it = Arrays.asList(serviceEndpointInterface.getDeclaredMethods()).iterator();
2813      while (it.hasNext())
2814      {
2815         Method JavaDoc seiMethod = (Method JavaDoc)it.next();
2816
2817         if (!hasMatchingMethod(bean, seiMethod))
2818         {
2819            fireSpecViolationEvent(session, seiMethod, new Section("7.11.9.c"));
2820            status = false;
2821         }
2822         else
2823         {
2824            try
2825            {
2826               Method JavaDoc beanMethod = bean.getMethod(seiMethod.getName(), seiMethod.getParameterTypes());
2827               if (!hasMatchingReturnType(seiMethod, beanMethod))
2828               {
2829                  fireSpecViolationEvent(session, seiMethod, new Section("7.11.9.c1"));
2830                  status = false;
2831               }
2832
2833               if (!hasMatchingExceptions(beanMethod, seiMethod))
2834               {
2835                  fireSpecViolationEvent(session, seiMethod, new Section("7.11.59.c2"));
2836                  status = false;
2837               }
2838            }
2839            catch (NoSuchMethodException JavaDoc ignored)
2840            {
2841            }
2842         }
2843      }
2844
2845      return status;
2846   }
2847
2848   /**
2849    * @param method
2850    * @return
2851    */

2852   protected boolean hasLegalJAXRPCReturnType(Method JavaDoc method)
2853   {
2854      return isJAXRPCType(method.getReturnType());
2855   }
2856
2857   /**
2858    * @param class1
2859    * @return
2860    */

2861   protected boolean isJAXRPCType(Class JavaDoc class1)
2862   {
2863      // TODO this should be implemented along the jaxrpc spec
2864
return isRMIIDLValueType(class1);
2865   }
2866
2867   /**
2868    * @param method
2869    * @return
2870    */

2871   protected boolean hasLegalJAXRPCArguments(Method JavaDoc method)
2872   {
2873      Class JavaDoc[] params = method.getParameterTypes();
2874
2875      for (int i = 0; i < params.length; ++i)
2876      {
2877         if (!isJAXRPCType(params[i]))
2878            return false;
2879      }
2880
2881      return true;
2882   }
2883
2884   /**
2885    * Check whether the bean has declared service endpoint interfaces and whether
2886    * we can load the defined classes
2887    * @param bean
2888    * @return <code>true</code> if everything went alright
2889    */

2890   protected boolean hasServiceEndpointInterfaces(SessionMetaData bean)
2891   {
2892      boolean status = true;
2893      String JavaDoc seiName = bean.getServiceEndpoint();
2894
2895      if (seiName == null)
2896         return false;
2897
2898      // Verify the <service-endpoint> class
2899
try
2900      {
2901         serviceEndpointInterface = classloader.loadClass(seiName);
2902      }
2903      catch (ClassNotFoundException JavaDoc cnfe)
2904      {
2905         fireSpecViolationEvent(bean,
2906                 new Section("23.2", "Class not found on '" + seiName + "': " + cnfe.getMessage()));
2907         status = false;
2908      }
2909
2910      return status;
2911   }
2912
2913}
2914
Popular Tags