KickJava   Java API By Example, From Geeks To Geeks.

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


1 /*
2 * JBoss, Home of Professional Open Source
3 * Copyright 2005, JBoss Inc., and individual contributors as indicated
4 * by the @authors tag. See the copyright.txt in the distribution for a
5 * full listing of individual contributors.
6 *
7 * This is free software; you can redistribute it and/or modify it
8 * under the terms of the GNU Lesser General Public License as
9 * published by the Free Software Foundation; either version 2.1 of
10 * the License, or (at your option) any later version.
11 *
12 * This software is distributed in the hope that it will be useful,
13 * but WITHOUT ANY WARRANTY; without even the implied warranty of
14 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
15 * Lesser General Public License for more details.
16 *
17 * You should have received a copy of the GNU Lesser General Public
18 * License along with this software; if not, write to the Free
19 * Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA
20 * 02110-1301 USA, or see the FSF site: http://www.fsf.org.
21 */

22 package org.jboss.verifier.strategy;
23
24 // $Id: EJBVerifier11.java 41248 2006-02-17 08:31:12Z starksm $
25

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

864          try
865          {
866             String JavaDoc beanClass = entity.getEjbClass();
867             Class JavaDoc bean = classloader.loadClass(beanClass);
868
869             Iterator JavaDoc finderMethods = getFinderMethods(home);
870             while (finderMethods.hasNext())
871             {
872                Method JavaDoc finder = (Method JavaDoc)finderMethods.next();
873
874                if ((entity.isBMP()) && (!hasMatchingEJBFind(bean, finder)))
875                {
876                   fireSpecViolationEvent(entity, finder, new Section("9.2.8.j"));
877                   status = false;
878                }
879
880                if (!(hasRemoteReturnType(entity, finder)
881                        || isMultiObjectFinder(finder)))
882                {
883                   fireSpecViolationEvent(entity, finder, new Section("9.2.8.k"));
884                   status = false;
885                }
886
887                if ((entity.isBMP()) && (hasMatchingEJBFind(bean, finder)))
888                {
889                   Method JavaDoc ejbFind = getMatchingEJBFind(bean, finder);
890                   if (!(hasMatchingExceptions(ejbFind, finder)))
891                   {
892                      fireSpecViolationEvent(entity, finder, new Section("9.2.8.l"));
893                      status = false;
894                   }
895                }
896
897                if (!throwsFinderException(finder))
898                {
899                   fireSpecViolationEvent(entity, finder, new Section("9.2.8.m"));
900                   status = false;
901                }
902             }
903          }
904          catch (ClassNotFoundException JavaDoc ignored)
905          {
906          }
907       }
908       catch (ClassNotFoundException JavaDoc e)
909       {
910          /*
911           * The bean provider MUST specify the fully-qualified name of the
912           * enterprise bean's home interface in the <home> element.
913           *
914           * Spec 16.2
915           */

916          fireSpecViolationEvent(entity, new Section("16.2.c"));
917          status = false;
918       }
919
920       return status;
921    }
922
923
924 /*
925  *************************************************************************
926  *
927  * VERIFY ENTITY BEAN REMOTE INTERFACE
928  *
929  *************************************************************************
930  */

931
932    private boolean verifyEntityRemote(EntityMetaData entity)
933    {
934       boolean status = true;
935
936       String JavaDoc name = entity.getRemote();
937       if (name == null)
938          return false;
939
940       try
941       {
942          Class JavaDoc remote = classloader.loadClass(name);
943
944          /*
945           * Entity bean's remote interface MUST extend
946           * the javax.ejb.EJBObject interface.
947           *
948           * Spec 9.2.7
949           */

950          if (!hasEJBObjectInterface(remote))
951          {
952             fireSpecViolationEvent(entity, new Section("9.2.7.a"));
953             status = false;
954          }
955
956          /*
957           * The methods defined in the entity bean's remote interface MUST
958           * have valid RMI-IIOP argument types.
959           *
960           * The methods defined in the entity bean's home interface MUST
961           * have valid RMI-IIOP return types.
962           *
963           * The methods defined in the entity bean's home interface MUST
964           * have java.rmi.RemoteException in their throws clause.
965           *
966           * Spec 9.2.7
967           */

968          Iterator JavaDoc remoteMethods = Arrays.asList(remote.getMethods()).iterator();
969          while (remoteMethods.hasNext())
970          {
971             Method JavaDoc method = (Method JavaDoc)remoteMethods.next();
972
973             if (!hasLegalRMIIIOPArguments(method))
974             {
975                fireSpecViolationEvent(entity, method, new Section("9.2.7.b"));
976                status = false;
977             }
978
979             if (!hasLegalRMIIIOPReturnType(method))
980             {
981                fireSpecViolationEvent(entity, method, new Section("9.2.7.c"));
982                status = false;
983             }
984
985             if (!hasLegalRMIIIOPExceptionTypes(method))
986             {
987                fireSpecViolationEvent(entity, method, new Section("9.2.7.h"));
988                status = false;
989             }
990
991             if (!throwsRemoteException(method))
992             {
993                fireSpecViolationEvent(entity, method, new Section("9.2.7.d"));
994                status = false;
995             }
996          } // while
997

998          /*
999           * For each method defined in the remote interface, there MUST be
1000          * a matching method in the entity bean's class. The matching
1001          * method MUST have:
1002          *
1003          * - The same name.
1004          * - The same number and types of its arguments.
1005          * - The same return type.
1006          * - All the exceptions defined in the throws clause of the
1007          * matching method of the enterprise Bean class must be
1008          * defined in the throws clause of the method of the remote
1009          * interface.
1010          *
1011          * Spec 9.2.7
1012          */

1013
1014         try
1015         {
1016            String JavaDoc beanClass = entity.getEjbClass();
1017            Class JavaDoc bean = classloader.loadClass(beanClass);
1018
1019            remoteMethods = Arrays.asList(remote.getMethods()).iterator();
1020            while (remoteMethods.hasNext())
1021            {
1022               Method JavaDoc method = (Method JavaDoc)remoteMethods.next();
1023
1024               // Do not check the methods of the javax.ejb.EJBObject interface
1025
if (method.getDeclaringClass().getName().equals(EJB_OBJECT_INTERFACE))
1026                  continue;
1027
1028               if (!hasMatchingMethod(bean, method))
1029               {
1030                  fireSpecViolationEvent(entity, method, new Section("9.2.7.e"));
1031                  status = false;
1032               }
1033
1034               if (hasMatchingMethod(bean, method))
1035               {
1036                  try
1037                  {
1038                     Method JavaDoc beanMethod = bean.getMethod(method.getName(), method.getParameterTypes());
1039
1040                     if (!hasMatchingReturnType(beanMethod, method))
1041                     {
1042                        fireSpecViolationEvent(entity, method, new Section("9.2.7.f"));
1043                        status = false;
1044                     }
1045
1046                     if (!hasMatchingExceptions(beanMethod, method))
1047                     {
1048                        fireSpecViolationEvent(entity, method, new Section("9.2.7.g"));
1049                        status = false;
1050                     }
1051                  }
1052                  catch (NoSuchMethodException JavaDoc ignored)
1053                  {
1054                  }
1055               }
1056            }
1057         }
1058         catch (ClassNotFoundException JavaDoc ignored)
1059         {
1060         }
1061      }
1062      catch (ClassNotFoundException JavaDoc e)
1063      {
1064         /*
1065          * The Bean Provider MUST specify the fully-qualified name of the
1066          * enterprise bean's remote interface in the <remote> element.
1067          *
1068          * Spec 16.2
1069          */

1070         fireSpecViolationEvent(entity, new Section("16.2.d"));
1071         status = false;
1072      }
1073
1074      return status;
1075   }
1076
1077/*
1078 *************************************************************************
1079 *
1080 * VERIFY ENTITY BEAN CLASS
1081 *
1082 *************************************************************************
1083 */

1084
1085   private boolean verifyEntityBean(EntityMetaData entity)
1086   {
1087      boolean status = true;
1088
1089      String JavaDoc name = entity.getEjbClass();
1090
1091      try
1092      {
1093         Class JavaDoc bean = classloader.loadClass(name);
1094
1095         /*
1096          * The enterprise bean class MUST implement, directly or
1097          * indirectly, the javax.ejb.EntityBean interface.
1098          *
1099          * Spec 9.2.2
1100          */

1101         if (!hasEntityBeanInterface(bean))
1102         {
1103            fireSpecViolationEvent(entity, new Section("9.2.2.a"));
1104            status = false;
1105         }
1106
1107         /*
1108          * The entity bean class MUST be defined as public.
1109          *
1110          * Spec 9.2.2
1111          */

1112         if (!isPublic(bean))
1113         {
1114            fireSpecViolationEvent(entity, new Section("9.2.2.b"));
1115            status = false;
1116         }
1117
1118         /*
1119          * The entity bean class MUST NOT be defined as abstract.
1120          *
1121          * Spec 9.2.2
1122          */

1123         if (isAbstract(bean))
1124         {
1125            fireSpecViolationEvent(entity, new Section("9.2.2.c"));
1126            status = false;
1127         }
1128
1129         /*
1130          * The entity bean class MUST NOT be defined as final.
1131          *
1132          * Spec 9.2.2
1133          */

1134         if (isFinal(bean))
1135         {
1136            fireSpecViolationEvent(entity, new Section("9.2.2.d"));
1137            status = false;
1138         }
1139
1140         /*
1141          * The entity bean class MUST define a public constructor that
1142          * takes no arguments
1143          *
1144          * Spec 9.2.2
1145          */

1146         if (!hasDefaultConstructor(bean))
1147         {
1148            fireSpecViolationEvent(entity, new Section("9.2.2.e"));
1149            status = false;
1150         }
1151
1152         /*
1153          * The entity bean class MUST NOT define the finalize() method.
1154          *
1155          * Spec 9.2.2
1156          */

1157         if (hasFinalizer(bean))
1158         {
1159            fireSpecViolationEvent(entity, new Section("9.2.2.f"));
1160            status = false;
1161         }
1162
1163         /*
1164          * The ejbCreate(...) method signatures MUST follow these rules:
1165          *
1166          * - The method MUST be declared as public
1167          * - The method MUST NOT be declared as final or static
1168          * - The return type MUST be the entity bean's primary key type
1169          * - The method arguments MUST be legal types for RMI/IIOP
1170          * - The method return value type MUST be legal type for RMI/IIOP
1171          *
1172          * Spec 9.2.3
1173          */

1174         if (hasEJBCreateMethod(bean, false))
1175         {
1176            Iterator JavaDoc it = getEJBCreateMethods(bean);
1177            while (it.hasNext())
1178            {
1179               Method JavaDoc ejbCreate = (Method JavaDoc)it.next();
1180
1181               if (!isPublic(ejbCreate))
1182               {
1183                  fireSpecViolationEvent(entity, ejbCreate, new Section("9.2.3.a"));
1184                  status = false;
1185               }
1186
1187               if ((isFinal(ejbCreate)) || (isStatic(ejbCreate)))
1188               {
1189                  fireSpecViolationEvent(entity, ejbCreate, new Section("9.2.3.b"));
1190                  status = false;
1191               }
1192
1193               if (!hasPrimaryKeyReturnType(entity, ejbCreate))
1194               {
1195                  fireSpecViolationEvent(entity, ejbCreate, new Section("9.2.3.c"));
1196                  status = false;
1197               }
1198
1199               if (!hasLegalRMIIIOPArguments(ejbCreate))
1200               {
1201                  fireSpecViolationEvent(entity, ejbCreate, new Section("9.2.3.d"));
1202                  status = false;
1203               }
1204
1205               if (!hasLegalRMIIIOPReturnType(ejbCreate))
1206               {
1207                  fireSpecViolationEvent(entity, ejbCreate, new Section("9.2.3.e"));
1208                  status = false;
1209               }
1210            }
1211         }
1212
1213         /*
1214          * For each ejbCreate(...) method, the entity bean class MUST
1215          * define a matching ejbPostCreate(...) method.
1216          *
1217          * The ejbPostCreate(...) method MUST follow these rules:
1218          *
1219          * - the method MUST be declared as public
1220          * - the method MUST NOT be declared as final or static
1221          * - the return type MUST be void
1222          * - the method arguments MUST be the same as the matching
1223          * ejbCreate(...) method
1224          *
1225          * Spec 9.2.4
1226          */

1227         if (hasEJBCreateMethod(bean, false))
1228         {
1229            Iterator JavaDoc it = getEJBCreateMethods(bean);
1230            while (it.hasNext())
1231            {
1232               Method JavaDoc ejbCreate = (Method JavaDoc)it.next();
1233
1234               if (!hasMatchingEJBPostCreate(bean, ejbCreate))
1235               {
1236                  fireSpecViolationEvent(entity, ejbCreate, new Section("9.2.4.a"));
1237                  status = false;
1238               }
1239
1240               if (hasMatchingEJBPostCreate(bean, ejbCreate))
1241               {
1242                  Method JavaDoc ejbPostCreate = getMatchingEJBPostCreate(bean, ejbCreate);
1243
1244                  if (!isPublic(ejbPostCreate))
1245                  {
1246                     fireSpecViolationEvent(entity, ejbPostCreate, new Section("9.2.4.b"));
1247                     status = false;
1248                  }
1249
1250                  if (isStatic(ejbPostCreate))
1251                  {
1252                     fireSpecViolationEvent(entity, ejbPostCreate, new Section("9.2.4.c"));
1253                     status = false;
1254                  }
1255
1256                  if (isFinal(ejbPostCreate))
1257                  {
1258                     fireSpecViolationEvent(entity, ejbPostCreate, new Section("9.2.4.d"));
1259                     status = false;
1260                  }
1261
1262                  if (!hasVoidReturnType(ejbPostCreate))
1263                  {
1264                     fireSpecViolationEvent(entity, ejbPostCreate, new Section("9.2.4.e"));
1265                     status = false;
1266                  }
1267               }
1268            }
1269         }
1270
1271         /*
1272          * Every entity bean MUST define the ejbFindByPrimaryKey method.
1273          *
1274          * The return type for the ejbFindByPrimaryKey method MUST be the
1275          * primary key type.
1276          *
1277          * The ejbFindByPrimaryKey method MUST be a single-object finder.
1278          *
1279          * Spec 9.2.5
1280          */

1281         if (entity.isBMP() && (!hasEJBFindByPrimaryKey(bean)))
1282         {
1283            fireSpecViolationEvent(entity, new Section("9.2.5.a"));
1284            status = false;
1285         }
1286
1287         if (hasEJBFindByPrimaryKey(bean))
1288         {
1289            Method JavaDoc ejbFindByPrimaryKey = getEJBFindByPrimaryKey(bean);
1290
1291            if (!hasPrimaryKeyReturnType(entity, ejbFindByPrimaryKey))
1292            {
1293               fireSpecViolationEvent(entity, ejbFindByPrimaryKey, new Section("9.2.5.b"));
1294               status = false;
1295            }
1296
1297            if (!isSingleObjectFinder(entity, ejbFindByPrimaryKey))
1298            {
1299               fireSpecViolationEvent(entity, ejbFindByPrimaryKey, new Section("9.2.5.c"));
1300               status = false;
1301            }
1302         }
1303
1304         /*
1305          * A finder method MUST be declared as public.
1306          *
1307          * A finder method MUST NOT be declared as static.
1308          *
1309          * A finder method MUST NOT be declared as final.
1310          *
1311          * The finder method argument types MUST be legal types
1312          * for RMI/IIOP
1313          *
1314          * The finder method return type MUST be either the entity bean's
1315          * primary key type, or java.lang.util.Enumeration interface or
1316          * java.lang.util.Collection interface.
1317          *
1318          * Spec 9.2.5
1319          */

1320         if (hasFinderMethod(bean))
1321         {
1322            Iterator JavaDoc it = getEJBFindMethods(bean);
1323            while (it.hasNext())
1324            {
1325               Method JavaDoc finder = (Method JavaDoc)it.next();
1326
1327               if (!isPublic(finder))
1328               {
1329                  fireSpecViolationEvent(entity, finder, new Section("9.2.5.d"));
1330                  status = false;
1331               }
1332
1333               if (isFinal(finder))
1334               {
1335                  fireSpecViolationEvent(entity, finder, new Section("9.2.5.e"));
1336                  status = false;
1337               }
1338
1339               if (isStatic(finder))
1340               {
1341                  fireSpecViolationEvent(entity, finder, new Section("9.2.5.f"));
1342                  status = false;
1343               }
1344
1345               if (!hasLegalRMIIIOPArguments(finder))
1346               {
1347                  fireSpecViolationEvent(entity, finder, new Section("9.2.5.g"));
1348                  status = false;
1349               }
1350
1351               if (!(isSingleObjectFinder(entity, finder)
1352                       || isMultiObjectFinder(finder)))
1353               {
1354                  fireSpecViolationEvent(entity, finder, new Section("9.2.5.h"));
1355                  status = false;
1356               }
1357            }
1358         }
1359      }
1360      catch (ClassNotFoundException JavaDoc e)
1361      {
1362         /*
1363          * The Bean Provider MUST specify the fully-qualified name of the
1364          * Java class that implements the enterprise bean's business
1365          * methods.
1366          *
1367          * Spec 16.2
1368          */

1369         fireSpecViolationEvent(entity, new Section("16.2.b"));
1370         status = false;
1371      }
1372
1373      return status;
1374   }
1375
1376   private boolean verifyPrimaryKey(EntityMetaData entity)
1377   {
1378      boolean status = true;
1379
1380      if (entity.getPrimaryKeyClass() == null
1381              || entity.getPrimaryKeyClass().length() == 0)
1382      {
1383         fireSpecViolationEvent(entity, new Section("16.5.a"));
1384         return false; // We can't get any further if there's no PK class specified!
1385
}
1386
1387      if (entity.getPrimKeyField() == null
1388              || entity.getPrimKeyField().length() == 0)
1389      {
1390         Class JavaDoc cls = null;
1391
1392         try
1393         {
1394            cls = classloader.loadClass(entity.getPrimaryKeyClass());
1395
1396            if (entity.isCMP())
1397            {
1398               if (!isPublic(cls))
1399               {
1400                  fireSpecViolationEvent(entity, new Section("9.4.7.2.a"));
1401                  status = false;
1402               }
1403
1404               if (!isAllFieldsPublic(cls))
1405               {
1406                  fireSpecViolationEvent(entity, new Section("9.4.7.2.b"));
1407                  status = false;
1408               }
1409
1410               if (!hasANonStaticField(cls))
1411               {
1412                  fireSpecViolationEvent(entity, new Section("9.4.7.2.c"));
1413                  status = false;
1414               }
1415            }
1416
1417            if (!cls.getName().equals("java.lang.Object"))
1418            {
1419               Object JavaDoc one, two;
1420               try
1421               {
1422                  one = cls.newInstance();
1423                  two = cls.newInstance();
1424                  try
1425                  {
1426                     if (!one.equals(two))
1427                     {
1428                        fireSpecViolationEvent(entity, new Section("9.2.9.b"));
1429                        status = false;
1430                     }
1431                  }
1432                  catch (NullPointerException JavaDoc e)
1433                  {
1434                  } // That's OK - the implementor expected the fields to have values
1435
try
1436                  {
1437                     if (one.hashCode() != two.hashCode())
1438                     {
1439                        fireSpecViolationEvent(entity, new Section("9.2.9.c"));
1440                        status = false;
1441                     }
1442                  }
1443                  catch (NullPointerException JavaDoc e)
1444                  {
1445                  } // That's OK - the implementor expected the fields to have values
1446
}
1447               catch (IllegalAccessException JavaDoc e)
1448               {
1449                  // [FIXME] The two error messages below are incorrect.
1450
// The RMI-IDL language mapping does not require
1451
// the value types to have a no args constructor.
1452
// [JPL]
1453
//
1454
//fireSpecViolationEvent(entity, new Section("9.2.9.a"));
1455
//status = false;
1456
}
1457               catch (InstantiationException JavaDoc e)
1458               {
1459                  //fireSpecViolationEvent(entity, new Section("9.2.9.a"));
1460
//status = false;
1461
}
1462            }
1463         }
1464         catch (ClassNotFoundException JavaDoc e)
1465         {
1466            fireSpecViolationEvent(entity, new Section("16.2.e"));
1467            status = false; // Can't do any other checks if the class is null!
1468
}
1469      }
1470      else
1471      {
1472         if (entity.isBMP())
1473         {
1474            fireSpecViolationEvent(entity, new Section("9.4.7.1.a"));
1475            status = false;
1476         }
1477
1478         try
1479         {
1480            Class JavaDoc fieldClass = classloader.loadClass(entity.getEjbClass());
1481            Field JavaDoc field = null;
1482            try
1483            {
1484               field = fieldClass.getField(entity.getPrimKeyField());
1485               if (!entity.getPrimaryKeyClass().equals(field.getType().getName()))
1486               {
1487                  fireSpecViolationEvent(entity, new Section("9.4.7.1.c"));
1488                  status = false;
1489               }
1490
1491               Iterator JavaDoc it = entity.getCMPFields();
1492               boolean found = false;
1493               while (it.hasNext())
1494               {
1495                  String JavaDoc fieldName = (String JavaDoc)it.next();
1496                  if (fieldName.equals(entity.getPrimKeyField()))
1497                  {
1498                     found = true;
1499                     break;
1500                  }
1501               }
1502
1503               if (!found)
1504               {
1505                  fireSpecViolationEvent(entity, new Section("9.4.7.1.d"));
1506                  status = false;
1507               }
1508            }
1509            catch (NoSuchFieldException JavaDoc e)
1510            {
1511               fireSpecViolationEvent(entity, new Section("9.4.7.1.b"));
1512               status = false;
1513            }
1514         }
1515         catch (ClassNotFoundException JavaDoc e)
1516         {
1517         } // reported elsewhere
1518
}
1519
1520      return status;
1521   }
1522
1523}
1524
1525/*
1526vim:ts=3:sw=3:et
1527*/

1528
Popular Tags