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