Docjar: A Java Source and Docuemnt Enginecom.*    java.*    javax.*    org.*    all    new    plug-in

Quick Search    Search Deep

Source code: org/mobicents/slee/container/deployment/SbbVerifier.java


1   /***************************************************
2    *                                                 *
3    *  Mobicents: The Open Source JSLEE Platform      *
4    *                                                 *
5    *  Distributable under LGPL license.              *
6    *  See terms of license at gnu.org.               *
7    *                                                 *
8    ***************************************************/
9   /*
10   * SbbVerifier.java
11   * 
12   * Created on Jul 26, 2004
13   *
14   */
15  package org.mobicents.slee.container.deployment;
16  
17  import java.io.IOException;
18  import java.io.InputStream;
19  import java.util.HashSet;
20  import java.util.Iterator;
21  import java.util.Map;
22  import java.util.Set;
23  
24  import javassist.ClassPool;
25  import javassist.CtClass;
26  import javassist.CtField;
27  import javassist.CtMethod;
28  import javassist.Modifier;
29  import javassist.NotFoundException;
30  
31  import javax.slee.ActivityContextInterface;
32  import javax.slee.Sbb;
33  import javax.slee.management.SbbDescriptor;
34  
35  import org.jboss.logging.Logger;
36  import org.mobicents.slee.container.SleeContainer;
37  import org.mobicents.slee.container.management.CMPField;
38  import org.mobicents.slee.container.management.ComponentKey;
39  import org.mobicents.slee.container.management.DeployableUnitIDImpl;
40  import org.mobicents.slee.container.management.EventTypeDescriptorImpl;
41  import org.mobicents.slee.container.management.EventTypeIDImpl;
42  import org.mobicents.slee.container.management.GetChildRelationMethod;
43  import org.mobicents.slee.container.management.ProfileCMPMethod;
44  import org.mobicents.slee.container.management.SbbDescriptorImpl;
45  import org.mobicents.slee.container.management.SbbEventEntry;
46  
47  /**
48   * Verify that a sbb abstract class provided by a sbb developer is following a set of constraints.
49   * <BR>This verifier checks that the sbb developer developed the Sbb Abstract class
50   * following the slee specification requirements.<BR>
51   * <BR>It verifies also that the Sbb Abstract class and the definitions provided 
52   * by the sbb developer in the deployment descriptor are matching<BR> 
53   * It verifies also the sbb concrete class generated by the slee runtime to check
54   * the generated byte code integrity.
55   * 
56   * @author DERUELLE Jean <a href="mailto:jean.deruelle@gmail.com">jean.deruelle@gmail.com</a>
57   *
58   */
59  public class SbbVerifier {
60      public final static String DEPLOYMENT_PATH = SleeContainer.DEPLOY_PATH;
61      
62      
63      /**
64       * the set of constraints defined by the slee specification
65       * on a sbb abstract class
66       */
67      //private List constraints=null;
68      /**
69       * deployment descriptor used to verified that the Sbb Abstract class and 
70       * the definitions in the deployment descriptor are matching 
71       */
72      private SbbDescriptorImpl sbbDeploymentDescriptor=null;
73      /**
74       * Path where to find the classes 
75       */
76      private static String deployPath=null;
77      
78      
79      /**
80       * Pool to generate or read classes with javassist
81       */
82      private ClassPool pool = null;
83      /**
84       * Logger to logg information
85       */
86      private static Logger logger=null;
87  
88  
89      private String errorString;
90      
91      private static boolean firstTime = true;
92  
93  
94      /** the class holder for javax.slee.Sbb */
95      private CtClass sbbAbstractClass;
96      
97      static{        
98          logger = Logger.getLogger(SbbVerifier.class);
99          
100     }
101     
102     /**
103      * 
104      */
105     public SbbVerifier(SbbDescriptor sbbDescriptor) {   
106         
107         sbbDeploymentDescriptor=(SbbDescriptorImpl)sbbDescriptor;
108         pool=((DeployableUnitIDImpl) (sbbDescriptor
109                 .getDeployableUnit())).getDUDeployer().getClassPool();
110         try {
111             sbbAbstractClass = pool.get(Sbb.class.getName());
112         } catch (NotFoundException e) {
113             String s = "Cannot find class ! while verifying ";
114             logger.fatal(e);
115             throw new RuntimeException (s,e);
116         }
117     }
118     
119     /**
120      * Verify that a sbb abstract class provided by a sbb developer is following 
121      * a set of constraints.
122      * @param sbbAbstractClassName name of the sbb abstract class provided by the user
123      * @return true is the sbb abstract class is safe
124      */
125     public boolean verifySbbAbstractClass(String sbbAbstractClassName, SleeContainer serviceContainer){
126        
127         try{
128             
129             // FIXME: this is obsolete, we don't want the class to be defined before it is inspected and enhanced
130             // logger.info("Verifying "+ profileTransientStateClass(sbbAbstractClassName).getName());
131             // CtClass ctClass=pool.get(sbbAbstractClassName);
132 
133             /*
134              * Load the abstract class definition in memory, but do not make it visible via the classloader yet 
135              */
136             logger.info("Verifying "+ sbbAbstractClassName);
137             ClassLoader cl = (ClassLoader)Thread.currentThread().getContextClassLoader();
138             String classRsrcName = sbbAbstractClassName.replace('.', '/') + ".class";
139             InputStream sbbAbstractClassIS = cl.getResourceAsStream(classRsrcName);
140             CtClass ctClass = pool.makeClass(sbbAbstractClassIS);
141 
142           if(!checkSbbAbstractClassConstraints(ctClass)){
143               logger.error("SbbAbstractClass Constraints were not successfully verified");
144               return false;
145           }              
146           if(!checkSbbAgainstDeploymentDescriptor(ctClass)){
147               logger.error("Sbb and deployment descriptor are not matching");
148               return false;          
149           }
150           if ( ! this.checkEventHandlerMethods(ctClass,serviceContainer)){
151               logger.error("EventHandler Methods were not successfully verified");
152               return false;
153           }
154         }
155         catch(IOException ioe){
156             logger.info("Sbb Abstract Class validation failed for: " + sbbAbstractClassName, ioe);
157             return false;
158         }
159         logger.info(sbbAbstractClassName+" is safe");
160         return true;
161     }
162     
163     /**
164      * Verify the sbb concrete class generated by the slee runtime to check
165      * the generated byte code integrity.
166      * @param sbbConcreteClassName name of the sbb abstract class provided by the user
167      * @return true is the sbb concrete class is safe
168      */
169     public boolean verifySbbConcreteClass(String sbbConcreteClassName){
170         return false;
171     }
172     
173     /**
174      * Check the constraints defined by the slee specification final release 1.0
175      * on an Sbb Abstract Class : 
176      * The class must implement, directly or indirectly, the javax.slee.Sbb interface.
177      *  · The class must be defined as public and must be abstract.
178      *  · The class must not define the finalize method
179      *  · The SBB Developer must provide a public constructor that takes no arguments.
180      * @param sbbAbstractClass class, provided by the sbb developer, to check
181      * @return true if the class is safe
182      */
183     protected boolean checkSbbAbstractClassConstraints(CtClass sbbAbstractClass){
184         int modifiers=sbbAbstractClass.getModifiers();
185         //check that the class modifiers contain abstratc and public
186         if(!Modifier.isAbstract(modifiers) || !Modifier.isPublic(modifiers)){
187             logger.error("The class is nor abstract neither public");
188             return false;
189         }
190         //check that the finalize method is not present in the class
191         CtMethod[] methods=sbbAbstractClass.getDeclaredMethods();
192         if(methods!=null){
193             for(int i=0;i<methods.length;i++){
194                 CtMethod method = methods[i];
195                 if(method.getName().equalsIgnoreCase("finalize")){
196                     logger.error("finalize method is present in the sbb abstract class "+
197                             sbbAbstractClass.getName());
198                     return false;
199                 }
200                 if ( methods[i].getName().startsWith("ejb") ) {
201                     logger.debug("invalid method name detected " + methods[i].getName());
202                     return false;
203             }
204                
205                 if ( methods[i].getName().startsWith("sbb") ) {
206                     if ( logger.isDebugEnabled())
207                         logger.debug("checking method " + methods[i].getName());
208                     CtMethod[] abstractClassMethods = this.sbbAbstractClass.getDeclaredMethods();
209                     int k;
210                     for ( k = 0; k < abstractClassMethods.length; k ++ ) {
211                         CtMethod ctMethod = abstractClassMethods[k];
212                         if ( ctMethod.getName().equals(methods[i].getName())) break;
213         }
214                     // Not an abstract method so it is invalid.
215                     if ( k == abstractClassMethods.length) {
216                         logger.error("invalid method name determined " + methods[i].getName());
217                         return false;
218                     }
219                 }
220             }
221         }
222         else{
223             logger.error("there is no abstract methods inthis abstract Class : "+sbbAbstractClass.getName());
224             return false;
225         }
226         //check that the method implements the Sbb class either directly or by inheritance
227         try{
228             boolean implementSbbLinkFound=false;            
229             implementSbbLinkFound=
230                 checkInterfaces(sbbAbstractClass.getInterfaces(),"javax.slee.Sbb");
231             CtClass superClass=sbbAbstractClass.getSuperclass();            
232             while(superClass!=null && !implementSbbLinkFound){
233                 if(superClass.getName().equalsIgnoreCase("javax.slee.Sbb"))
234                     implementSbbLinkFound=true;
235                 else{
236                     implementSbbLinkFound=
237                         checkInterfaces(superClass.getInterfaces(),"javax.slee.Sbb");
238                     superClass=superClass.getSuperclass();
239                 }
240             }
241             if(!implementSbbLinkFound){
242                 logger.error("sbb abstract class "+
243                         sbbAbstractClass.getName()+" doesn't implements the javax.slee.Sbb class either directly or by inheritance");
244                 return false;
245             }
246         }
247         catch(NotFoundException nfe){
248             nfe.printStackTrace();
249             return false;
250         }
251         //check that the class has a public constructor without any arguments        
252         /**CtConstructor[] constructors=sbbAbstractClass.getConstructors();
253         boolean defaultConstructorFound=false;
254         if(constructors!=null){            
255             try{
256               for(int i=0;i<constructors.length;i++){
257                   constructors[i].getParameterTypes();                
258               }
259             }
260             catch(NotFoundException nfe){
261                 defaultConstructorFound=true;
262             }
263         }
264         else
265             return false;
266         
267         if(!defaultConstructorFound)
268             return false;**/
269         //check that the field names do not start with sbb or ejb
270         CtField[] ctFields=sbbAbstractClass.getFields();
271         for(int i=0;i<ctFields.length;i++){
272             if(ctFields[i].getName().startsWith("sbb") ||
273                ctFields[i].getName().startsWith("ejb")){
274                 logger.error("the sbb abstract class "+
275                         sbbAbstractClass.getName()+" has a field starting with sbb or ejb: "+
276                         ctFields[i].getName());                
277                 return false;
278             }
279         }
280         
281        
282         
283         
284         
285         return true;
286     }
287     
288     /**
289      * Check if among the interfaces one is the class searched
290      * @param interfaces the interfaces
291      * @param interfaceSearched the interface to look for
292      * return true if among the interfaces one is the class searched
293      */
294     private boolean checkInterfaces(CtClass[] interfaces,String interfaceSearched) {        
295         if(interfaces==null){
296             logger.debug("no interfaces");
297             return false;
298         }
299         for(int i=0;i<interfaces.length;i++){
300             if(interfaces[i].getName().equalsIgnoreCase(interfaceSearched)){
301                 return true;
302             }
303         }
304         logger.debug("interfaces are zero length");
305         return false;    
306     }
307 
308     /**
309      * Check that the sbb abstract class correclty implements what is defined
310      * in the deployment descriptor
311      * For each method defined by the SBB Developer, there must be a matching method in
312      * the SBB abstract class. The matching method must have:
313      *     o The same name.
314      *      o The same number of arguments, and same argument and return types.
315      *      o The same set of exceptions in the throws clause.
316      * param sbbAbstractClass the sbb abstract class to check
317      * @return true if the sbb abstract class correclty implements what is defined
318      * in the deployment descriptor
319      */
320     protected boolean checkSbbAgainstDeploymentDescriptor(CtClass sbbAbstractClass){
321         logger.debug("checkSbbAgainstDeploymentDescriptor started");
322         Map abstractMethods=ClassUtils.getAbstractMethodsFromClass(sbbAbstractClass);
323         Map superClassesAbstractMethods = ClassUtils.getSuperClassesAbstractMethodsFromClass(sbbAbstractClass);
324         logger.debug("checkSbbAgainstDeploymentDescriptor abstract methods retrieved");
325         //Check CMP fields
326         CMPField[] cmpFields=
327             sbbDeploymentDescriptor.getCMPFields();
328         logger.debug("checkSbbAgainstDeploymentDescriptor CMP Fields retrieved ");
329         if(cmpFields!=null){
330             if(!checkCMPFieldsAgainstDeploymentDescripor(abstractMethods,cmpFields,sbbAbstractClass)
331                 && !checkCMPFieldsAgainstDeploymentDescripor(superClassesAbstractMethods,cmpFields,sbbAbstractClass)){
332                 logger.error("CMP fields are not safe");
333                 return false;
334             }
335         }        
336         logger.debug("checkSbbAgainstDeploymentDescriptor CMP Fields ok");
337         //Check the presence of the get child relation methods
338         GetChildRelationMethod[] getChildRelationMethods=
339             sbbDeploymentDescriptor.getChildRelationMethods();
340         if(getChildRelationMethods!=null){            
341             for(int i=0;i<getChildRelationMethods.length;i++){
342               String methodName=getChildRelationMethods[i].getMethodName();
343               CtMethod getChildRelationMethod=(CtMethod)abstractMethods.get(methodName);
344               if(getChildRelationMethod==null){
345                   getChildRelationMethod = (CtMethod)superClassesAbstractMethods.get(methodName);
346                   if(getChildRelationMethod==null){
347                     
348                   logger.error("integrity compromised on sbbAbstractClass "+
349                           sbbAbstractClass.getName()+" GetChildRelationMethod "+
350                           methodName+" defined in the descriptor is missing");
351                   return false;
352                   }
353               }
354               //The method has been verified so it is removed from the abstract method map
355               abstractMethods.remove(methodName);
356             }
357         }        
358         logger.debug("get child relation methods ok");
359         
360         if (!checkProfileCMPMethods(sbbAbstractClass, abstractMethods, superClassesAbstractMethods))
361             return false;
362         
363         //Check the presence of the activity context interface narrow method
364         Class activityContextInterface=
365             sbbDeploymentDescriptor.getActivityContextInterface();        
366         if(activityContextInterface!=null){            
367             String activityContextInterfaceName=activityContextInterface.getName();
368             logger.debug(activityContextInterface.getName());
369             CtMethod narrowMethod=(CtMethod)abstractMethods.get("asSbbActivityContextInterface");
370             if(narrowMethod==null){
371               narrowMethod =(CtMethod)superClassesAbstractMethods.get("asSbbActivityContextInterface");
372               if(narrowMethod==null){
373                 logger.error("integrity compromised on sbbAbstractClass "+
374                         sbbAbstractClass.getName()+
375                         " narrow method asSbbActivityContextInterface with the return type"+
376                         activityContextInterfaceName+" defined in the descriptor is missing");
377                 return false;
378               }
379             }
380             try {
381                 if(!narrowMethod.getReturnType().getName().equals(activityContextInterfaceName)){
382                     logger.error("integrity compromised on sbbAbstractClass "+
383                             sbbAbstractClass.getName()+
384                             " narrow method asSbbActivityContextInterface with the return type"+
385                             activityContextInterfaceName+" has in the abstract method a return type different "+
386                             narrowMethod.getReturnType().getName());
387                     return false;
388                 }
389             } catch (NotFoundException e) {
390                 logger.error("integrity compromised on sbbAbstractClass "+
391                         sbbAbstractClass.getName()+
392                         " narrow method asSbbActivityContextInterface with the return type"+
393                         activityContextInterfaceName+" has a no return type");
394             }
395             //The method has been verified so it is removed from the abstract method map
396             abstractMethods.remove("asSbbActivityContextInterface");
397         }
398         logger.debug("asSbbActivityContextInterface ok");
399         //Check the presence of fire Event methods
400         //FIXME need to do more checking on the fire event methods
401         HashSet sbbEventEntries=
402             sbbDeploymentDescriptor.getSbbEventEntries();
403         
404         if(sbbEventEntries!=null){            
405             Iterator it=sbbEventEntries.iterator();
406             //firedEvents
407             while(it.hasNext()){
408                 SbbEventEntry sbbEventEntry=(SbbEventEntry)it.next();
409                 String methodName="fire"+sbbEventEntry.getEventName();                
410                 CtMethod fireEventMethod=(CtMethod)abstractMethods.get(methodName);            
411                 if(fireEventMethod!=null){
412                     //The method has been verified so it is removed from the abstract method map
413                   abstractMethods.remove(methodName);
414                     /*logger.error("integrity compromised on sbbAbstractClass "+
415                           sbbAbstractClass.getName()+" ProfileCMPMethod "+
416                           methodName+" defined in the descriptor is missing");
417                   return false;*/
418               }              
419           }
420         }        
421         logger.debug("sbbEventEntries ok");
422         //TODO check the other methods declared in the descriptor
423         //sbb local interface 
424         //Usage parameter method is generated by us. 
425         CtMethod getDefaultSbbUsageParameterSetMethod = (CtMethod)abstractMethods.get("getDefaultSbbUsageParameterSet");
426         if ( getDefaultSbbUsageParameterSetMethod != null ) {
427             logger.debug("getDefaultUsageParameterSet abstract method found in the SBB.");
428             String usageParameterInterfaceName = this.sbbDeploymentDescriptor.getUsageParametersInterface();
429             if (usageParameterInterfaceName == null){
430                 logger.error("No Usage parameter found in the descriptor corresponding to the getDefaultSbbUsageParameterSet defined in the SBB!");
431                 return false;
432             }
433             
434             try {
435                 String returnType = getDefaultSbbUsageParameterSetMethod.getReturnType().getName();
436                 logger.debug("RETURN TYPE: " + returnType + " INTERFACE NAME: " + usageParameterInterfaceName);
437                 if (returnType.compareTo(usageParameterInterfaceName) != 0) {
438                     logger.error("The return type of getDefaultSbbUsageParameterSet defined in the SBB does not match the interface name in the descriptor!");
439                     return false;
440                 }
441             } catch (NotFoundException e) {
442                 // TODO Auto-generated catch block
443                 e.printStackTrace();
444             }
445             
446             CtClass[] params = null ;
447             try {
448                 params = getDefaultSbbUsageParameterSetMethod.getParameterTypes();
449             } catch (NotFoundException ex ) {
450                
451             }
452             if (params != null && params.length != 0  ) {
453                 logger.error("Unexpected parameter found" + params[0].getName());
454                 return false;
455             }
456             abstractMethods.remove("getDefaultSbbUsageParameterSet"); 
457         }
458         logger.debug("getDefaultSbbUsageParameterSet ok");
459         //Named Usage Parameter method is generated by us.
460         CtMethod getSbbUsageParameterSet = (CtMethod) abstractMethods.get("getSbbUsageParameterSet");
461         if ( getSbbUsageParameterSet != null ) {
462             CtClass[] params = null;
463             try {
464                 params = getSbbUsageParameterSet.getParameterTypes();
465                 if ( params.length != 1 ){
466                     logger.error("too many args!");
467                     return false;
468                 } 
469                 if ( ! (params[0].getName().equals(String.class.getName()))) {
470                     logger.error("Arg type must be String!");
471                     return false;
472                 }
473             }catch (NotFoundException ex) {
474                 logger.error("Expected parameter not found");
475                 return false;
476             }
477             abstractMethods.remove("getSbbUsageParameterSet");
478         }
479         logger.debug("getSbbUsageParameterSet ok");
480         //Check if some methods have not been verfied
481         Iterator  it=abstractMethods.keySet().iterator();              
482         while(it.hasNext()){
483             logger.error("abstract method left: "+ it.next());
484             
485         }
486         if(abstractMethods.size()!=0){
487             logger.error("Some methods have not been verified against the sbb descriptor" +
488                 ", maybe these methods have not been described in the descriptor and so are not allowed");
489             return false;
490         }
491         abstractMethods=null;
492         logger.debug("SbbAbstractClass "+sbbAbstractClass.getName()+" follows the descriptor");
493         return true;
494     }
495     /**
496      * @param sbbAbstractClass
497      * @param abstractMethods
498      * @param superClassesAbstractMethods
499      * @return
500      */
501     private boolean checkProfileCMPMethods(CtClass sbbAbstractClass, Map abstractMethods, Map superClassesAbstractMethods) {
502         //Check the presence of the profile CMP methods
503         ProfileCMPMethod[] profileCMPMethods=
504             sbbDeploymentDescriptor.getProfileCMPMethods();
505         if(profileCMPMethods!=null){            
506           for(int i=0;i<profileCMPMethods.length;i++){
507               String methodName=profileCMPMethods[i].getProfileCMPMethod();
508               CtMethod profileCMPMethod=(CtMethod)abstractMethods.get(methodName);
509               if(profileCMPMethod==null){
510                   profileCMPMethod = (CtMethod)superClassesAbstractMethods.get(methodName);
511                 if(profileCMPMethod == null){
512                   logger.error("integrity compromised on sbbAbstractClass "+
513                           sbbAbstractClass.getName()+" ProfileCMPMethod "+
514                           methodName+" defined in the descriptor is missing");
515                   return false;
516                 }
517               }
518               else{
519                   if(profileCMPMethod.getName().startsWith("sbb") ||
520                      profileCMPMethod.getName().startsWith("ejb")){
521                       logger.error("integrity compromised on sbbAbstractClass "+
522                             sbbAbstractClass.getName()+" ProfileCMPMethod "+
523                             methodName+" should not starts with sbb or ejb in its name");
524                     return false;
525                   }
526                   CtClass[] parameters;
527                     try {
528                         parameters = profileCMPMethod.getParameterTypes();                        
529                         if(parameters.length!=1){
530                             logger.error("integrity compromised on sbbAbstractClass "+
531                                 sbbAbstractClass.getName()+" ProfileCMPMethod "+
532                                 methodName+" should have one and only argument " +
533                                 "of type javax.slee.profile.ProfileID");
534                             return false;
535                       }
536                         else{                            
537                             if(!parameters[0].getName().equals("javax.slee.profile.ProfileID")){
538                                 logger.error("integrity compromised on sbbAbstractClass "+
539                                     sbbAbstractClass.getName()+" ProfileCMPMethod "+
540                                     methodName+" should have one and only argument " +
541                                     "of type javax.slee.profile.ProfileID");
542                                 return false;
543                             }
544                         }                            
545                     } catch (NotFoundException e) {                                                
546                         logger.error("integrity compromised on sbbAbstractClass "+
547                             sbbAbstractClass.getName()+" ProfileCMPMethod "+
548                             methodName+" should have one argument of type javax.slee.profile.ProfileID");
549                     return false;
550                     }
551                     try {
552                         CtClass[] exceptions= profileCMPMethod.getExceptionTypes();
553                         if(exceptions.length<2){                            
554                             logger.error("integrity compromised on sbbAbstractClass "+
555                                 sbbAbstractClass.getName()+" ProfileCMPMethod "+
556                                 methodName+" should have both exceptions " +
557                                 "of type javax.slee.profile.UnrecognizedProfileNameException and "+
558                                 "javax.slee.profile.UnrecognizedProfileTableNameException declared thrown");
559                             return false;
560                       }
561                         else{
562                             boolean profileNameExceptionThrown=false;
563                             boolean profileTableNameExceptionThrown=false;
564                             int j=0;
565                             while(j<exceptions.length && 
566                                     (!profileNameExceptionThrown || !profileTableNameExceptionThrown)){
567                                 if(exceptions[j].getName().equals(
568                                         "javax.slee.profile.UnrecognizedProfileNameException"))
569                                     profileNameExceptionThrown=true;
570                                 if(exceptions[j].getName().equals(
571                                         "javax.slee.profile.UnrecognizedProfileNameException"))
572                                     profileTableNameExceptionThrown=true;
573                                 j++;
574                             }
575                             if(!profileNameExceptionThrown){
576                                 logger.error("integrity compromised on sbbAbstractClass "+
577                                     sbbAbstractClass.getName()+" ProfileCMPMethod "+
578                                     methodName+" should have this exception " +
579                                     "of type javax.slee.profile.UnrecognizedProfileNameException "+
580                                     "declared thrown");
581                             return false;
582                             }
583                             if(!profileTableNameExceptionThrown){
584                                 logger.error("integrity compromised on sbbAbstractClass "+
585                                     sbbAbstractClass.getName()+" ProfileCMPMethod "+
586                                     methodName+" should have this exception " +
587                                     "of type javax.slee.profile.UnrecognizedProfileTableNameException "+
588                                     "declared thrown");
589                             return false;
590                             }    
591                         }                            
592                     } catch (NotFoundException e) {                                                
593                         logger.error("integrity compromised on sbbAbstractClass "+
594                             sbbAbstractClass.getName()+" ProfileCMPMethod "+
595                             methodName+" should have both exceptions " +
596                             "of type javax.slee.profile.UnrecognizedProfileNameException and "+
597                             "javax.slee.profile.UnrecognizedProfileTableNameException declared thrown");
598                     return false;
599                     }
600                     ComponentKey componentKey=profileCMPMethods[i].getProfileSpecKey();
601                     //TODO check that the return type is equals to the profileCMP interface
602                     //specified in the profile descriptor deployment
603               }
604               //The method has been verified so it is removed from the abstract method map
605               abstractMethods.remove(methodName);
606           }
607         }        
608         logger.debug("profiles CMP methods ok");
609         return true;
610     }
611 
612     /**
613      * Check that for the CMP fields defined in the sbbDeployment descriptor
614      * there is at least one accessor.
615      * If the CMP field has a getter :
616      *     the getter should have a return type
617      *     the getter should not have any parameters
618      * If the CMP field has a setter :
619      *     the getter should not have a return type
620      *     the getter should have one parameter 
621      * @param abstractMethods the abstract Method of the abstract class
622      * @param cmpFields the CMP Fields to check
623      * @param sbbAbstractClass the sbb abstract class 
624      * @return true if the CMP fields follow the constraints false otherwise
625      */
626     private boolean checkCMPFieldsAgainstDeploymentDescripor(Map abstractMethods,CMPField[] cmpFields,CtClass sbbAbstractClass) {               
627         for(int i=0;i<cmpFields.length;i++){
628             String fieldName=cmpFields[i].getFieldName();
629             //Set the first char of the accessor to UpperCase to follow the javabean requirements
630             fieldName=fieldName.substring(0,1).toUpperCase()+fieldName.substring(1);
631             CtMethod setterAccessor=(CtMethod)abstractMethods.get("set"+fieldName);
632             CtMethod getterAccessor=(CtMethod)abstractMethods.get("get"+fieldName);
633             //check that the CMP field has at least one accessor
634             if(setterAccessor==null && getterAccessor==null){
635                 logger.error("integrity compromised on sbbAbstractClass "+
636                         sbbAbstractClass.getName()+" on CMP Field "+fieldName+
637                         " => accessor missing");
638                 return false;
639             }
640             if(getterAccessor!=null){
641                 //check that the getter accessor has a return type
642                 try{
643                     CtClass returnType=getterAccessor.getReturnType();
644                     if(returnType.getName().equalsIgnoreCase("void")){
645                         logger.error("integrity compromised on sbbAbstractClass "+
646                                 sbbAbstractClass.getName()+" on CMP Field "+fieldName+
647                                 " => getter accessor has no return type");
648                         return false;
649                     }
650                 }
651                 catch(NotFoundException nfe){
652                     logger.error("integrity compromised on sbbAbstractClass "+
653                             sbbAbstractClass.getName()+" on CMP Field "+fieldName+
654                             " => getter accessor has no return type");
655                     return false;
656                 }
657                 //check that the getter accessor has no parameters
658                 try{
659                     CtClass[] parameterTypes=getterAccessor.getParameterTypes();
660                     if(parameterTypes!=null && parameterTypes.length>0){
661                         logger.error("integrity compromised on sbbAbstractClass "+
662                                 sbbAbstractClass.getName()+" on CMP Field "+fieldName+
663                                 " => getter accessor has some parameters");
664                         return false;
665                     }
666                 }
667                 catch(NotFoundException nfe){}
668                 //The method has been verified so it is removed from the abstract method map
669                 abstractMethods.remove(getterAccessor.getName());
670             }
671             if(setterAccessor!=null){
672                 //check that the setter accessor has no return type
673                 try{
674                     CtClass returnType=setterAccessor.getReturnType();
675                     if(!returnType.getName().equalsIgnoreCase("void")){
676                         logger.error("integrity compromised on sbbAbstractClass "+
677                                 sbbAbstractClass.getName()+" on CMP Field "+fieldName+
678                                 " => setter accessor has a return type "+returnType.getName());
679                         return false;
680                     }
681                 }
682                 catch(NotFoundException nfe){}
683                 //check that the setter accessor has one parameter
684                 try{
685                     CtClass[] parameterTypes=setterAccessor.getParameterTypes();
686                     if(parameterTypes.length!=1){
687                         logger.error("integrity compromised on sbbAbstractClass "+
688                                 sbbAbstractClass.getName()+" on CMP Field "+fieldName+
689                                 " => setter accessor has the wrong number of parameters");
690                         return false;
691                     }
692                 }
693                 catch(NotFoundException nfe){
694                     logger.error("integrity compromised on sbbAbstractClass "+
695                             sbbAbstractClass.getName()+" on CMP Field "+fieldName+
696                             " => setter accessor has no parameters");
697                     return false;
698                 }
699                 
700                 try {
701                   //check that getter return type == setter parameter type == xml type
702                   CtClass getterReturnType = getterAccessor.getReturnType();
703                   CtClass[] setterParamTypes = setterAccessor.getParameterTypes();
704                  
705                 CtClass setterParamType = setterParamTypes[0];
706                 if (!getterReturnType.equals(setterParamType)) {
707                   logger.error("integrity compromised on sbbAbstractClass "+
708                           sbbAbstractClass.getName()+" on CMP Field "+fieldName+
709                           " => getter return type is not same as setter parameter type");
710                   return false;
711                 }
712                 
713                 if (cmpFields[i].getSbbComponentKey() != null) {
714                   
715                   try {
716                     //Then the getter return type, setter param type should be SbbLocalObject
717                     logger.debug("Getter return type is: " + getterReturnType.getName());
718 
719                     //FIXME - This is a bit slow
720                     
721                     Class cl = Thread.currentThread().getContextClassLoader().loadClass(getterReturnType.getName());                                  
722                     Class sbbLOClass = Thread.currentThread().getContextClassLoader().
723                                       loadClass("javax.slee.SbbLocalObject");
724                                                                                                          
725                     if (!sbbLOClass.isAssignableFrom(cl)) {
726                       logger.error("integrity compromised on sbbAbstractClass "+
727                                   sbbAbstractClass.getName()+" on CMP Field "+fieldName+
728                                   " => getter and setter types for an sbb ref must be SbbLocalObject");
729                           return false;
730                     }
731                   } catch (Exception e) {
732                     logger.error("Failed check ref param", e);
733                     return false;
734                   }
735                 }                
736                 }
737                 catch(NotFoundException nfe){
738                     logger.error("integrity compromised on sbbAbstractClass "+
739                             sbbAbstractClass.getName()+" on CMP Field "+fieldName+
740                             " => getter/setter accessor has no parameters/return type");
741                     return false;
742                 }
743                 
744                 //The method has been verified so it is removed from the abstract method map
745                 abstractMethods.remove(setterAccessor.getName());
746             }
747         }
748         return true;
749     }
750     
751     /**
752      * Check the event handler method signatures. The SBB developer must implement these. These must
753      * be recognized events in the slee else the Sbb is not valid.
754      * 
755      * @param sbbAbstractClass -- The abstract class to check.
756      * @param serviceContainer -- service container in which the event descriptors are installed.
757      */
758     private boolean checkEventHandlerMethods
759       (CtClass sbbAbstractClass, SleeContainer serviceContainer) {
760         
761         HashSet sbbEventEntries = this.sbbDeploymentDescriptor.getSbbEventEntries();
762         
763         for ( Iterator it = sbbEventEntries.iterator(); it.hasNext();  ) {
764             SbbEventEntry sbbEventEntry = (SbbEventEntry) it.next();
765             String eventName = sbbEventEntry.getEventName();
766             // Dont need a method for FIRED only methods.
767             if ( sbbEventEntry.getEventDirection() == SbbEventEntry.FIRED ) continue;
768            
769             ComponentKey ckey = sbbEventEntry.getEventTypeRefKey();
770             EventTypeIDImpl eventTypeID = serviceContainer.getEventType(ckey);
771             // Make sure that the slee knows about this event.
772             if ( eventTypeID == null){
773                 logger.debug("event type id "+ eventName +" is unknown to the SLEE!");
774                 return false;
775             }
776             String methodName = "on"+sbbEventEntry.getEventName();
777             EventTypeDescriptorImpl eventTypeDesc = serviceContainer.getEventDescriptor(eventTypeID);
778             String eventClass = eventTypeDesc.getEventClassName();
779             // Check if we have a method of the required name.
780             Set methodSet  = ClassUtils.getPublicMethods(sbbAbstractClass);
781             //CtMethod[] methods  = sbbAbstractClass.getMethods();
782             
783             CtMethod[] methods = new CtMethod[methodSet.size()]; 
784             methodSet.toArray(methods);
785             
786             int i ;
787             for (  i = 0; i < methods.length; i ++ ) {
788                 if (methods[i].getName().equals(methodName)) break;
789             }
790             
791             if ( i == methods.length ){
792                 logger.debug("no methods to check against "+ methodName);
793                 return false;
794             }
795             try {
796                 if ( ((CtMethod) methods[i]).getReturnType() !=  CtClass.voidType ) {
797                     this.errorString = "event handler must have void return type";
798                     logger.debug(errorString);
799                     return false;
800                 }
801                 CtClass[] parameters =  ((CtMethod) methods[i]).getParameterTypes();
802                 if ( parameters.length != 2 ) {
803                     this.errorString = "bad method signature ( wrong number of params!)";
804                     logger.debug(errorString);
805                     return false;
806                 }
807                 CtClass param = parameters[0];
808                
809                 if ( ! param.getName().equals(eventClass) ) {
810                     this.errorString = "bad event handler method signature expected " + eventClass;
811                     logger.debug( errorString );
812                     return false;
813                 }
814                 param = parameters[1];
815                
816               
817                 if ( !param.getName().equals(ActivityContextInterface.class.getName())) {
818                     this.errorString = "bad event handler method signature expected " + ActivityContextInterface.class.getName() ;
819                     logger.debug( errorString );
820                     return false;
821                 }
822             } catch  ( Exception ex ) {
823                 ex.printStackTrace();
824             }
825             logger.debug("found an event handler " + ((CtMethod)methods[i]).getName());
826         }
827         return true;
828         
829     }
830 }