Author: rickmcguire
Date: Tue Jun 17 08:43:37 2008
New Revision: 668715

URL: http://svn.apache.org/viewvc?rev=668715&view=rev
Log:
Adding some commentary explaining what the different CMP2 generation pieces are 
doing. 


Modified:
    
openejb/trunk/openejb3/container/openejb-core/src/main/java/org/apache/openejb/core/cmp/cmp2/Cmp2Entity.java
    
openejb/trunk/openejb3/container/openejb-core/src/main/java/org/apache/openejb/core/cmp/cmp2/Cmp2Generator.java
    
openejb/trunk/openejb3/container/openejb-core/src/main/java/org/apache/openejb/core/cmp/cmp2/PostCreateGenerator.java

Modified: 
openejb/trunk/openejb3/container/openejb-core/src/main/java/org/apache/openejb/core/cmp/cmp2/Cmp2Entity.java
URL: 
http://svn.apache.org/viewvc/openejb/trunk/openejb3/container/openejb-core/src/main/java/org/apache/openejb/core/cmp/cmp2/Cmp2Entity.java?rev=668715&r1=668714&r2=668715&view=diff
==============================================================================
--- 
openejb/trunk/openejb3/container/openejb-core/src/main/java/org/apache/openejb/core/cmp/cmp2/Cmp2Entity.java
 (original)
+++ 
openejb/trunk/openejb3/container/openejb-core/src/main/java/org/apache/openejb/core/cmp/cmp2/Cmp2Entity.java
 Tue Jun 17 08:43:37 2008
@@ -17,9 +17,13 @@
  */
 package org.apache.openejb.core.cmp.cmp2;
 
-//
-// WARNING: Do not refactor this class.  It is used by the Cmp2Generator.
-//
+/**
+ * WARNING: Do not refactor this class.  It is used by the Cmp2Generator.
+ * 
+ * This interface defines a number of interfaces used by 
+ * the CMP2 container to manage the EJB.  The implementation 
+ * methods are generated by the Cmp2Generator class. 
+ */
 public interface Cmp2Entity {
     Object OpenEJB_getPrimaryKey();
 

Modified: 
openejb/trunk/openejb3/container/openejb-core/src/main/java/org/apache/openejb/core/cmp/cmp2/Cmp2Generator.java
URL: 
http://svn.apache.org/viewvc/openejb/trunk/openejb3/container/openejb-core/src/main/java/org/apache/openejb/core/cmp/cmp2/Cmp2Generator.java?rev=668715&r1=668714&r2=668715&view=diff
==============================================================================
--- 
openejb/trunk/openejb3/container/openejb-core/src/main/java/org/apache/openejb/core/cmp/cmp2/Cmp2Generator.java
 (original)
+++ 
openejb/trunk/openejb3/container/openejb-core/src/main/java/org/apache/openejb/core/cmp/cmp2/Cmp2Generator.java
 Tue Jun 17 08:43:37 2008
@@ -56,12 +56,38 @@
     private final Class beanClass;
     private final PostCreateGenerator postCreateGenerator;
 
+    /**
+     * Constructor for a Cmp2Generator.  This validates the
+     * initial EJB state information and prepares for the
+     * code generation process.
+     * 
+     * @param cmpImplClass
+     *                  The name of the implementation class we're generating.
+     * @param beanClass The bean implementation class that is our starting
+     *                  point for code generation.
+     * @param pkField   The name of the primary key field (optional if the
+     *                  primary key class is given).
+     * @param primKeyClass
+     *                  The optional primary key class for complex primary
+     *                  keys.
+     * @param cmpFields The list of fields that are managed using cmp.
+     */
     public Cmp2Generator(String cmpImplClass, Class beanClass, String pkField, 
Class<?> primKeyClass, String[] cmpFields) {
-        if (pkField == null && primKeyClass == null) throw new 
NullPointerException("Both pkField and primKeyClass are null");
+            
         beanClassName = Type.getInternalName(beanClass);
         implClassName = cmpImplClass.replace('.', '/');
+        
+        if (pkField == null && primKeyClass == null) {
+            throw new NullPointerException("Both pkField and primKeyClass are 
null for bean " + beanClassName);
+        }
+        
         this.primKeyClass = primKeyClass;
+        
 
+        // for each of the defined cmp fields, we need to locate the getter 
method 
+        // for the name and retrieve the type.  This a) verifies that we have 
at least 
+        // a getter defined and b) that we know the field return type.  The 
created CmpField 
+        // list will feed into the generation process. 
         for (String cmpFieldName : cmpFields) {
             String getterName = getterName(cmpFieldName);
             try {
@@ -74,6 +100,8 @@
             }
         }
 
+        // if a pkField is defined, it MUST be a CMP field.  Make sure it 
really exists 
+        // in the list we constructed above. 
         if (pkField != null) {
             this.pkField = this.cmpFields.get(pkField);
             if (this.pkField == null) {
@@ -83,6 +111,7 @@
             this.pkField = null;
         }
 
+        // build up the list of ejbSelectxxxx methods.  These will be 
generated automatically. 
         for (Method method : beanClass.getMethods()) {
             if (Modifier.isAbstract(method.getModifiers()) && 
method.getName().startsWith("ejbSelect")) {
                 addSelectMethod(method);
@@ -91,11 +120,22 @@
 
         this.beanClass = beanClass;
 
+        // The class writer will be used for all generator activies, while the 
+        // postCreateGenerator will be used to add the ejbPostCreatexxxx 
methods as a 
+        // last step. 
         cw = new ClassWriter(true);
-
         postCreateGenerator = new PostCreateGenerator(beanClass, cw);
     }
 
+    /**
+     * Add a field to the list of fields defined as CMR 
+     * fields.  Note that if the field is also defined 
+     * as a CMP field, it will be removed from the normal 
+     * CMP list. 
+     * 
+     * @param cmrField The new CMR field definition pulled from the
+     *                 EJB metadata.
+     */
     public void addCmrField(CmrField cmrField) {
         if (cmpFields.get(cmrField.getName()) != null) {
             cmpFields.remove(cmrField.getName());
@@ -103,11 +143,30 @@
         cmrFields.add(cmrField);
     }
 
+    /**
+     * Add a method to the list of ejbSelect methods that 
+     * need to be processed. 
+     * 
+     * @param selectMethod
+     *               The method that needs to be processed.
+     */
     public void addSelectMethod(Method selectMethod) {
         selectMethods.add(selectMethod);
     }
 
+    /**
+     * Perform the generation step for a CMP Entity Bean.  
+     * This uses the accumulated meta data and the 
+     * base bean class to generate a subclass with 
+     * the automatically generated bits of OpenEJB infrastructure
+     * hooks. 
+     * 
+     * @return The class file byte array to be used for defining this 
+     *         class.
+     */
     public byte[] generate() {
+        // generate the class as super class of the base bean class.  This 
class will also implment 
+        // EntityBean and Cmp2Entity. 
         cw.visit(V1_5, ACC_PUBLIC + ACC_SUPER, implClassName, null, 
beanClassName, new String[]{"org/apache/openejb/core/cmp/cmp2/Cmp2Entity", 
"javax/ejb/EntityBean"});
 
         // public static Object deploymentInfo;
@@ -127,17 +186,21 @@
             fv.visitEnd();
         }
 
+        // Generate the set of cmp fields as private attributes. 
         // private ${cmpField.type} ${cmpField.name};
         for (CmpField cmpField : cmpFields.values()) {
             createField(cmpField);
         }
 
+        // and create the corresponding CMR fields as well. 
         for (CmrField cmrField : cmrFields) {
             createCmrFields(cmrField);
         }
 
         createConstructor();
 
+        // now for each of the CMP fields, generate the getter and setter 
methods 
+        // from the abstract methods the bean author should have provided. 
         for (CmpField cmpField : cmpFields.values()) {
             // public ${cmpField.type} get${cmpField.name}() {
             //     return this.${cmpField.name};
@@ -150,25 +213,31 @@
             createSetter(cmpField);
         }
 
+        // and repeat this for the cmr fields. 
         for (CmrField cmrField : cmrFields) {
             createCmrGetter(cmrField);
             createCmrSetter(cmrField);
         }
 
+        
         createSimplePrimaryKeyGetter();
 
+        // add the set of OpenEJB container management methods. 
         createOpenEJB_isDeleted();
-
         createOpenEJB_deleted();
-
         createOpenEJB_addCmr();
-
         createOpenEJB_removeCmr();
 
+        // generate the select methods 
         for (Method selectMethod : selectMethods) {
             createSelectMethod(selectMethod);
         }
 
+        
+        // now automatically generate any of the ejb* methods.  According to 
the 
+        // spec, the bean author should be responsble for these, but since 
these 
+        // are frequently just nop stubs, we'll take responsibility for 
creating 
+        // empty ones in the generated superclass. 
         if (!hasMethod(beanClass, "ejbActivate")) createEjbActivate();
         if (!hasMethod(beanClass, "ejbPassivate")) createEjbPassivate();
         if (!hasMethod(beanClass, "ejbLoad")) createEjbLoad();
@@ -177,10 +246,12 @@
         if (!hasMethod(beanClass, "setEntityContext", EntityContext.class)) 
createSetEntityContext();
         if (!hasMethod(beanClass, "unsetEntityContext")) 
createUnsetEntityContext();
 
+        // add on any post-create methods that might be required. 
         postCreateGenerator.generate();
 
         cw.visitEnd();
-
+        // the class, in theory, is now complete.  Return in byte[] form so 
this can 
+        // be defined in the appropriate classloader instance. 
         return cw.toByteArray();
     }
 
@@ -222,7 +293,7 @@
         MethodVisitor mv = cw.visitMethod(ACC_PUBLIC, "OpenEJB_deleted", 
"()V", null, null);
         mv.visitCode();
 
-        // if (deleted) return;
+        /* if (deleted) return; */
         mv.visitVarInsn(ALOAD, 0);
         mv.visitFieldInsn(GETFIELD, implClassName, "deleted", "Z");
         Label notDeleted = new Label();
@@ -350,6 +421,12 @@
         mv.visitEnd();
     }
 
+    /**
+     * Add a CMP field to the class.  The field is created 
+     * with private scope. 
+     * 
+     * @param cmpField The Cmp field defined in the metadata.
+     */
     private void createField(CmpField cmpField) {
         FieldVisitor fv = cw.visitField(ACC_PRIVATE,
                 cmpField.getName(),
@@ -359,6 +436,17 @@
         fv.visitEnd();
     }
 
+    
+    /**
+     * Generate a concrete getter field for a CMP field.  
+     * At this point, we're just generating a simple 
+     * accessor for the field, given the type.  The 
+     * JPA engine when it makes this implementation class 
+     * a managed class define whatever additional logic 
+     * might be required. 
+     * 
+     * @param cmpField The CMP field backing this getter method.
+     */
     private void createGetter(CmpField cmpField) {
         String methodName = getterName(cmpField.getName());
         MethodVisitor mv = cw.visitMethod(ACC_PUBLIC, methodName, "()" + 
cmpField.getDescriptor(), null, null);
@@ -374,6 +462,17 @@
         return "get" + propertyName.substring(0, 1).toUpperCase() + 
propertyName.substring(1);
     }
 
+    
+    /**
+     * Generate a concrete setter field for a CMP field.  
+     * At this point, we're just generating a simple 
+     * accessor for the field, given the type.  The 
+     * JPA engine when it makes this implementation class 
+     * a managed class define whatever additional logic 
+     * might be required. 
+     * 
+     * @param cmpField The CMP field backing this setter method.
+     */
     private void createSetter(CmpField cmpField) {
         String methodName = setterName(cmpField.getName());
         MethodVisitor mv = cw.visitMethod(ACC_PUBLIC, methodName, "(" + 
cmpField.getDescriptor() + ")V", null, null);
@@ -390,9 +489,29 @@
         return "set" + propertyName.substring(0, 1).toUpperCase() + 
propertyName.substring(1);
     }
 
+    /**
+     * Create a simple internal method for obtaining the
+     * primary key.  There are 2 possibilities for handling 
+     * the primary key here: 
+     * 
+     * 1)  There is a defined primary key field.  The 
+     * contents of that field are returned. 
+     * 
+     * 2)  The primary key is provided by the container.  
+     * This is a long value stored in a private, generated 
+     * field.  This field is returned as a generated 
+     * wrappered Long. 
+     * 
+     * 3)  A primary key class has been provided.  An instance 
+     * of this class is instantiated, and code is generated 
+     * that will copy all of the CMP fields from the EJB 
+     * into the primary key instance. 
+     */
     private void createSimplePrimaryKeyGetter() {
         MethodVisitor mv = cw.visitMethod(ACC_PUBLIC, "OpenEJB_getPrimaryKey", 
"()Ljava/lang/Object;", null, null);
         mv.visitCode();
+        
+        // the primary key is identifed as a field.  We just return that value 
directly. 
         if (pkField != null) {
             // push the pk field
             mv.visitVarInsn(ALOAD, 0);
@@ -401,6 +520,9 @@
             // return the pk field (from the stack)
             mv.visitInsn(pkField.getType().getOpcode(IRETURN));
         } else if (Object.class.equals(primKeyClass)) {
+            // this is a container-generated primary key.  It's a long value 
stored in 
+            // a generated field.  We return that value, wrappered in a Long 
instance. 
+            
             // push the pk field
             mv.visitVarInsn(ALOAD, 0);
             mv.visitFieldInsn(GETFIELD, implClassName, UNKNOWN_PK_NAME, 
UNKNOWN_PK_TYPE.getDescriptor());
@@ -408,6 +530,9 @@
             // return the pk field (from the stack)
             mv.visitInsn(UNKNOWN_PK_TYPE.getOpcode(IRETURN));
         } else {
+            // We have a primary key class defined.  For every field that 
matches one of the 
+            // defined CMP fields, we generate code to copy that value into 
the corresponding 
+            // field of the primary key class. 
             String pkImplName = primKeyClass.getName().replace('.', '/');
 
             // new Pk();
@@ -448,6 +573,18 @@
         mv.visitEnd();
     }
 
+    /**
+     * Create the CMR fields defined for this object.  This 
+     * creates a pair of fields for each CMR field.  The 
+     * first field is the real field containing the object 
+     * data.  The second field will be an accessor object 
+     * that's instantiated when the fields are first 
+     * initialized.  The accessor field gets created with 
+     * the same name and "Cmr" concatenated to the end 
+     * of the field name. 
+     * 
+     * @param cmrField The CMR field descriptor.
+     */
     private void createCmrFields(CmrField cmrField) {
         FieldVisitor fv = cw.visitField(ACC_PRIVATE,
                 cmrField.getName(),
@@ -464,6 +601,17 @@
         fv.visitEnd();
     }
 
+    /**
+     * Initialize the CMR fields associated with a CMR 
+     * definition.  This initializes two fields per CMR 
+     * defined field:  1)  The CMR field itself (which might 
+     * be initialized to an instance of a defined type) and 2)
+     * the appropriate CMD accessor that handles the 
+     * different types of relationship. 
+     * 
+     * @param mv       The method context we're initializing in.
+     * @param cmrField The CMR field to process.
+     */
     private void initCmrFields(MethodVisitor mv, CmrField cmrField) {
         // this.${cmrField.name} = new ${cmrField.initialValueType}();
         Type initialValueType = cmrField.getInitialValueType();
@@ -512,8 +660,21 @@
                 cmrField.getAccessorDescriptor());
     }
 
+    /**
+     * Create a getter method for the CMR field.  This 
+     * will used the accessor object initialized into the 
+     * name + "Cmr" field that was already generated and 
+     * initialized at object creation.  The accessor 
+     * object manages the object relationship. 
+     * 
+     * @param cmrField The field we're generating.
+     */
     private void createCmrGetter(CmrField cmrField) {
-        if (cmrField.isSynthetic()) return;
+        // a synthentic method essentially means this is a relationship with 
+        // no back reference.  We don't generate a getter method for this 
+        if (cmrField.isSynthetic()) {
+            return;
+        }
 
         String methodName = getterName(cmrField.getName());
         MethodVisitor mv = cw.visitMethod(ACC_PUBLIC, methodName, "()" + 
cmrField.getProxyDescriptor(), null, null);
@@ -522,7 +683,13 @@
         mv.visitFieldInsn(GETFIELD, implClassName, cmrField.getName() + "Cmr", 
cmrField.getAccessorDescriptor());
         mv.visitVarInsn(ALOAD, 0);
         mv.visitFieldInsn(GETFIELD, implClassName, cmrField.getName(), 
cmrField.getDescriptor());
+        
+        // return this.${cmrField.name}Cmr.get(this.${cmdField.name});  
+        // this takes the value stored in the CMR field (which might be a 
single value or 
+        // a Set or Collection), and hands it to the appropriate accessor. 
         mv.visitMethodInsn(INVOKEVIRTUAL, cmrField.getAccessorInternalName(), 
"get", cmrField.getCmrStyle().getGetterDescriptor());
+        // if the style is a single value, then we're going to need to cast 
this 
+        // to the target class before returning.  
         if (cmrField.getCmrStyle() == CmrStyle.SINGLE) {
             mv.visitTypeInsn(CHECKCAST, 
cmrField.getProxyType().getInternalName());
         }
@@ -531,12 +698,27 @@
         mv.visitEnd();
     }
 
+    
+    /**
+     * Generate a setter method for a CMR field.  The 
+     * setter method will delegate the setting responsibility 
+     * to the accessor object store the associated Cmr field. 
+     * 
+     * @param cmrField The field we're generating the setter for.
+     */
     private void createCmrSetter(CmrField cmrField) {
-        if (cmrField.isSynthetic()) return;
+        // a synthentic method essentially means this is a relationship with 
+        // no back reference.  We don't generate a getter method for this 
+        if (cmrField.isSynthetic()) {
+            return;
+        }
 
         String methodName = setterName(cmrField.getName());
         MethodVisitor mv = cw.visitMethod(ACC_PUBLIC, methodName, "(" + 
cmrField.getProxyDescriptor() + ")V", null, null);
         mv.visitCode();
+        // if this is a Many relationship, the CMR field contains a Set value. 
 The accessor 
+        // will process the elements in the Set, removing any existing ones, 
and then populating 
+        // the Set with the new values from the new value source. 
         if (cmrField.getCmrStyle() != CmrStyle.SINGLE) {
             mv.visitVarInsn(ALOAD, 0);
             mv.visitFieldInsn(GETFIELD, implClassName, cmrField.getName() + 
"Cmr", cmrField.getAccessorDescriptor());
@@ -546,6 +728,9 @@
             mv.visitMethodInsn(INVOKEVIRTUAL, 
cmrField.getAccessorInternalName(), "set", 
cmrField.getCmrStyle().getSetterDescriptor());
             mv.visitInsn(RETURN);
         } else {
+            // this is a single value.  We pass the existing value and the old 
value to 
+            // the accessor, then must cast the accessor return value to the 
target type 
+            // so we can store it in the real CMR field. 
             mv.visitVarInsn(ALOAD, 0);
             mv.visitVarInsn(ALOAD, 0);
             mv.visitFieldInsn(GETFIELD, implClassName, cmrField.getName() + 
"Cmr", cmrField.getAccessorDescriptor());
@@ -561,7 +746,17 @@
         mv.visitEnd();
     }
 
+    /**
+     * Generate the OpenEJB_deleted() logic for a 
+     * CMR field.  This handles the cascade from the referencing    
+     * object to the CMR fields for the object.  This method generates the 
+     * CMR logic inline inside the object OpenEJB_deleted() method. 
+     * 
+     * @param mv       The method context we're operating within.
+     * @param cmrField The CMD field containing the deleted value.
+     */
     private void createOpenEJB_deleted(MethodVisitor mv, CmrField cmrField) {
+        // this.${cmrField.name}Cmr.deleted(this.${cmrField.name}); 
         mv.visitVarInsn(ALOAD, 0);
         mv.visitFieldInsn(GETFIELD, implClassName, cmrField.getName() + "Cmr", 
cmrField.getAccessorDescriptor());
         mv.visitVarInsn(ALOAD, 0);
@@ -569,6 +764,16 @@
         mv.visitMethodInsn(INVOKEVIRTUAL, cmrField.getAccessorInternalName(), 
"deleted", cmrField.getCmrStyle().getDeletedDescriptor());
     }
 
+    /**
+     * Generate the OpenEJB_addCmr logic for an individual 
+     * CMR field.  Each CMR field has a test against the 
+     * property name, which is passed to the wrappering 
+     * addCmr method.  This results in a series of 
+     * if blocks for each defined CMD property.  
+     * 
+     * @param mv       The method we're generating within.
+     * @param cmrField The CMR field definition.
+     */
     private void createOpenEJB_addCmr(MethodVisitor mv, CmrField cmrField) {
         // if (${cmrField.name}.equals(arg1))
         mv.visitLdcInsn(cmrField.getName());
@@ -578,6 +783,8 @@
         Label end = new Label();
         mv.visitJumpInsn(IFEQ, end);
 
+        // collection style relationship.  Generate the code to add this 
object to the 
+        // collection already anchored in the CMR field.  
         if (cmrField.getCmrStyle() != CmrStyle.SINGLE) {
             mv.visitVarInsn(ALOAD, 0);
             mv.visitFieldInsn(GETFIELD, implClassName, cmrField.getName(), 
cmrField.getDescriptor());
@@ -585,6 +792,7 @@
             mv.visitVarInsn(ALOAD, 3);
             Label fieldNotNull = new Label();
             mv.visitJumpInsn(IFNONNULL, fieldNotNull);
+            // lazy creation of the collection type if not already created. 
             mv.visitTypeInsn(NEW, 
cmrField.getInitialValueType().getInternalName());
             mv.visitInsn(DUP);
             mv.visitMethodInsn(INVOKESPECIAL, 
cmrField.getInitialValueType().getInternalName(), "<init>", "()V");
@@ -601,6 +809,8 @@
             mv.visitInsn(POP);
             mv.visitVarInsn(ALOAD, 0);
             mv.visitVarInsn(ALOAD, 3);
+            // unconditionally set the CMR field to the collection.  This is 
either the 
+            // original one on entry, or a new one for first access. 
             mv.visitFieldInsn(PUTFIELD, implClassName, cmrField.getName(), 
cmrField.getDescriptor());
 
             // return null;
@@ -642,6 +852,15 @@
 //        mv.visitMethodInsn(INVOKEVIRTUAL, "java/io/PrintStream", "println", 
"(Ljava/lang/Object;)V");
 //    }
 
+    
+    /**
+     * Emit the remove logic for an individual CMR field. 
+     * Like the addCmr logic, each field is guarded by an 
+     * if test on the property name.  
+     * 
+     * @param mv
+     * @param cmrField
+     */
     private void createOpenEJB_removeCmr(MethodVisitor mv, CmrField cmrField) {
         // if (${cmrField.name}.equals(arg1))
         mv.visitLdcInsn(cmrField.getName());
@@ -650,7 +869,8 @@
         // if not equal jump to end
         Label end = new Label();
         mv.visitJumpInsn(IFEQ, end);
-
+        
+        // collection valued CMR field.  Remove the object from the 
collection. 
         if (cmrField.getCmrStyle() != CmrStyle.SINGLE) {
             // ${cmrField.name}.remove(arg2)
             mv.visitVarInsn(ALOAD, 0);
@@ -665,6 +885,8 @@
             // return;
             mv.visitInsn(RETURN);
         } else {
+            // single valued, so just null out the field. 
+            
             // this.${cmrField.name} = null;
             mv.visitVarInsn(ALOAD, 0);
             mv.visitInsn(ACONST_NULL);
@@ -678,6 +900,13 @@
         mv.visitLabel(end);
     }
 
+    /**
+     * Generate a concrete implementation of an abstract 
+     * ejbSelectxxxx method. 
+     * 
+     * @param selectMethod
+     *               The abstract definition for the method we're generating.
+     */
     private void createSelectMethod(Method selectMethod) {
         Class<?> returnType = selectMethod.getReturnType(); 
         
@@ -806,15 +1035,47 @@
         }
 
     }
+    
+    
+    /**
+     * Helper class to handle common type conversions 
+     * in generated code. 
+     */
     private static class Convert {
+        /**
+         * Generate code to performing boxing of primitive types 
+         * into a wrapper class instance.  
+         * 
+         * @param mv     The method currently being emitted.
+         * @param from   The class we're converting from.
+         */
         public static void toObjectFrom(MethodVisitor mv, Class from) {
+            // we only handler boxing for the primitive types. 
             if (from.isPrimitive()) {
                 Convert conversion = getConversion(from);
-                if (conversion == null) throw new 
NullPointerException("conversion is null " + from.getName() + " " + 
from.isPrimitive());
+                // the only conversion that will be trouble here is void.  
+                if (conversion == null) 
+                {
+                    throw new NullPointerException("conversion is null " + 
from.getName() + " " + from.isPrimitive());
+                }
                 conversion.primitiveToObject(mv);
             }
         }
 
+        /**
+         * Handle a conversion from one object type to another.  If
+         * There are 3 possible conversions:
+         * 
+         * 1)  The to class is Object.  This can be handled
+         * without conversion.  This option is a NOP.
+         * 2)  The to class is a reference type (non-primitive).  This 
conversion
+         * is a cast operation (which might fail at run time).
+         * 3)  The to class is a primitive type.  This is
+         * an unboxing operation.
+         * 
+         * @param mv     The method currently being constructed.
+         * @param to     The target class for the conversion.
+         */
         public static void fromObjectTo(MethodVisitor mv, Class to) {
             if (to.equals(Object.class)) {
                 // direct assignment will work
@@ -822,7 +1083,10 @@
                 mv.visitTypeInsn(CHECKCAST, Type.getInternalName(to));
             } else {
                 Convert conversion = getConversion(to);
-                if (conversion == null) throw new 
NullPointerException("unsupported conversion for EJB select return type " + 
to.getName());
+                {
+                    if (conversion == null)
+                        throw new NullPointerException("unsupported conversion 
for EJB select return type " + to.getName());
+                }
                 conversion.objectToPrimitive(mv);
             }
         }

Modified: 
openejb/trunk/openejb3/container/openejb-core/src/main/java/org/apache/openejb/core/cmp/cmp2/PostCreateGenerator.java
URL: 
http://svn.apache.org/viewvc/openejb/trunk/openejb3/container/openejb-core/src/main/java/org/apache/openejb/core/cmp/cmp2/PostCreateGenerator.java?rev=668715&r1=668714&r2=668715&view=diff
==============================================================================
--- 
openejb/trunk/openejb3/container/openejb-core/src/main/java/org/apache/openejb/core/cmp/cmp2/PostCreateGenerator.java
 (original)
+++ 
openejb/trunk/openejb3/container/openejb-core/src/main/java/org/apache/openejb/core/cmp/cmp2/PostCreateGenerator.java
 Tue Jun 17 08:43:37 2008
@@ -25,31 +25,69 @@
 import java.lang.reflect.Modifier;
 
 /**
+ * Generate concrete implementations of EjbPostCreatexxx
+ * methods for a bean class. 
  * @version $Rev$ $Date$
  */
 public class PostCreateGenerator {
     private final Class beanClass;
     private final ClassWriter cw;
 
+    /**
+     * Constructor for a PostCreateGenerator.
+     * 
+     * @param beanClass The source EJB implementation class (the user
+     *                  provided class).
+     * @param cw        The ClassWriter instance used for constructing the
+     *                  instantiation class.  This has already gone through
+     *                  other generation steps, we're implementing additional
+     *                  stages of the process.
+     */
     public PostCreateGenerator(Class beanClass, ClassWriter cw) {
         this.beanClass = beanClass;
         this.cw = cw;
     }
 
+    
+    /**
+     * Generate the ejbPostCreatexxxx methods.  Inorder to 
+     * be considered for generation, there must A) be a 
+     * corresponding ejbCreatexxxx method and B) the 
+     * target method must either not exist or exist but be
+     * abstract.
+     */
     public void generate() {
+        // ok, scan the class for the ejbCreate methods and check to see if 
+        // we need to provide an ejbPostCreate implementation. 
         for (Method ejbCreate : beanClass.getMethods()) {
-
-            if (!ejbCreate.getName().startsWith("ejbCreate")) continue;
+            if (!ejbCreate.getName().startsWith("ejbCreate")) 
+            {
+                continue;
+            }
 
             StringBuilder ejbPostCreateName = new 
StringBuilder(ejbCreate.getName());
             ejbPostCreateName.replace(0, "ejbC".length(), "ejbPostC");
 
-            if (hasMethod(beanClass, ejbPostCreateName.toString(), 
ejbCreate.getParameterTypes())) continue;
-
+            // if there is a concrete method here, we just skip this. 
+            if (hasMethod(beanClass, ejbPostCreateName.toString(), 
ejbCreate.getParameterTypes())) {
+                continue;
+            }
+            // we need to generate this method 
             createEjbPostCreate(ejbPostCreateName.toString(), ejbCreate);
         }
     }
 
+    /**
+     * Test whether a class provides a concrete implementation 
+     * of a class with the given name and parameter types. 
+     * 
+     * @param beanClass The source implementation class.
+     * @param name      The required method name.
+     * @param args      The list of argument types.
+     * 
+     * @return true if the method exists and is NOT abstract.  Returns 
+     *         false if the method is not found or IS abstract.
+     */
     private boolean hasMethod(Class beanClass, String name, Class... args) {
         try {
             Method method = beanClass.getMethod(name, args);
@@ -59,6 +97,16 @@
         }
     }
 
+    /**
+     * Generate an ejbPostCreatexxxx method corresponding 
+     * to an ejbCreatexxxx method definition.  These provided 
+     * methods are just empty stubs. 
+     * 
+     * @param ejbPostCreateName
+     *                  The name we're creating under.
+     * @param ejbCreate The matching ejbCreate method.  The post create method
+     *                  will match this one in terms of method signature.
+     */
     public void createEjbPostCreate(String ejbPostCreateName, Method 
ejbCreate) {
         String methodDescriptor = Type.getMethodDescriptor(Type.VOID_TYPE, 
Type.getArgumentTypes(ejbCreate));
         MethodVisitor mv = cw.visitMethod(Opcodes.ACC_PUBLIC, 
ejbPostCreateName, methodDescriptor, null, null);


Reply via email to