Author: rickmcguire
Date: Mon Jun 16 06:08:29 2008
New Revision: 668149

URL: http://svn.apache.org/viewvc?rev=668149&view=rev
Log:
OPENEJB-820 Eliminate dynamic return type processing in generated select 
methods.


Modified:
    
openejb/trunk/openejb3/container/openejb-core/src/main/java/org/apache/openejb/core/cmp/CmpContainer.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/EjbSelect.java

Modified: 
openejb/trunk/openejb3/container/openejb-core/src/main/java/org/apache/openejb/core/cmp/CmpContainer.java
URL: 
http://svn.apache.org/viewvc/openejb/trunk/openejb3/container/openejb-core/src/main/java/org/apache/openejb/core/cmp/CmpContainer.java?rev=668149&r1=668148&r2=668149&view=diff
==============================================================================
--- 
openejb/trunk/openejb3/container/openejb-core/src/main/java/org/apache/openejb/core/cmp/CmpContainer.java
 (original)
+++ 
openejb/trunk/openejb3/container/openejb-core/src/main/java/org/apache/openejb/core/cmp/CmpContainer.java
 Mon Jun 16 06:08:29 2008
@@ -745,7 +745,7 @@
         String signature = deploymentInfo.getAbstractSchemaName() + "." + 
methodSignature;
 
         try {
-            // exectue the select query
+            // execute the select query
             Collection<Object> results = cmpEngine.queryBeans(deploymentInfo, 
signature, args);
 
             //
@@ -801,7 +801,7 @@
                 throw new ObjectNotFoundException();
             }
 
-            // return the single item.... multpile return values was handled 
in for loop above
+            // return the single item.... multiple return values was handled 
in for loop above
             Object returnValue = proxies.iterator().next();
             return returnValue;
         } catch (RuntimeException e) {

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=668149&r1=668148&r2=668149&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
 Mon Jun 16 06:08:29 2008
@@ -17,6 +17,18 @@
  */
 package org.apache.openejb.core.cmp.cmp2;
 
+import java.lang.reflect.Field;
+import java.lang.reflect.Method;
+import java.lang.reflect.Modifier;
+import java.util.ArrayList;
+import java.util.Collection;
+import java.util.HashMap;
+import java.util.LinkedHashMap;
+import java.util.List;
+import java.util.Map;
+
+import javax.ejb.EntityContext;
+
 import org.objectweb.asm.ClassWriter;
 import org.objectweb.asm.FieldVisitor;
 import org.objectweb.asm.Label;
@@ -24,28 +36,14 @@
 import org.objectweb.asm.Opcodes;
 import org.objectweb.asm.Type;
 
-import javax.ejb.EntityContext;
-import java.lang.reflect.Method;
-import java.lang.reflect.Field;
-import java.lang.reflect.Modifier;
-import java.util.LinkedHashMap;
-import java.util.Map;
-import java.util.List;
-import java.util.ArrayList;
-import java.util.HashMap;
-import java.util.Collection;
-
+/**
+ * Code generate for CMP level 2 beans.  This will 
+ * generate the concrete class used to instantiate 
+ * the bean instance. 
+ */
 public class Cmp2Generator implements Opcodes {
     private static final String UNKNOWN_PK_NAME = "OpenEJB_pk";
     private static final Type UNKNOWN_PK_TYPE = Type.getType(Long.class);
-    private static final Method EJB_SELECT_EXECUTE;
-    static {
-        try {
-            EJB_SELECT_EXECUTE = EjbSelect.class.getMethod("execute", 
Object.class, String.class, String.class, Object[].class);
-        } catch (NoSuchMethodException e) {
-            throw new RuntimeException(e);
-        }
-    }
 
     private final String implClassName;
     private final String beanClassName;
@@ -681,6 +679,10 @@
     }
 
     private void createSelectMethod(Method selectMethod) {
+        Class<?> returnType = selectMethod.getReturnType(); 
+        
+        Method executeMethod = EjbSelect.getSelectMethod(returnType); 
+        
         MethodVisitor mv = cw.visitMethod(ACC_PUBLIC, selectMethod.getName(), 
Type.getMethodDescriptor(selectMethod), null, getExceptionTypes(selectMethod));
         mv.visitCode();
 
@@ -690,8 +692,11 @@
         // push method signature
         mv.visitLdcInsn(getSelectMethodSignature(selectMethod));
 
-        // push return type
-        mv.visitLdcInsn(selectMethod.getReturnType().getName());
+        // push return type, but only if the executeMethod is not going to be 
for void or 
+        // one of the primitives. 
+        if (!returnType.isPrimitive()) {
+            mv.visitLdcInsn(returnType.getName());
+        }
 
         // new Object[]
         mv.visitIntInsn(BIPUSH, selectMethod.getParameterTypes().length);
@@ -719,20 +724,28 @@
             }
         }
 
-        // EjbSelect.execute(deploymentInfo, signature, args[]);
+        // EjbSelect.execute_xxxx(deploymentInfo, signature, [returnType.] 
args[]);
         mv.visitMethodInsn(INVOKESTATIC,
-                Type.getInternalName(EJB_SELECT_EXECUTE.getDeclaringClass()),
-                EJB_SELECT_EXECUTE.getName(),
-                Type.getMethodDescriptor(EJB_SELECT_EXECUTE));
-
-        if (!Void.TYPE.equals(selectMethod.getReturnType())) {
-            // convert return type
-            Convert.fromObjectTo(mv, selectMethod.getReturnType());
-
-            // return value;
+                Type.getInternalName(executeMethod.getDeclaringClass()),
+                executeMethod.getName(),
+                Type.getMethodDescriptor(executeMethod));
+
+        // if this is a void type, we just return.  Otherwise, the return type 
+        // needs to match the type returned from the method call 
+        if (!Void.TYPE.equals(returnType)) {
+            // if this is a non-primitive return type, then the returned 
+            // object will need to be cast to the appropriate return type for 
+            // the verifier.  The primitive types all have the proper type on 
the 
+            // stack already 
+            if (!returnType.isPrimitive()) {
+                // convert return type
+                Convert.fromObjectTo(mv, returnType);
+            }
+            
+            // And generate the appropriate return for the type 
             mv.visitInsn(Type.getReturnType(selectMethod).getOpcode(IRETURN));
         } else {
-            // return; 
+            // void return is just a RETURN. 
             mv.visitInsn(RETURN);
         }
 

Modified: 
openejb/trunk/openejb3/container/openejb-core/src/main/java/org/apache/openejb/core/cmp/cmp2/EjbSelect.java
URL: 
http://svn.apache.org/viewvc/openejb/trunk/openejb3/container/openejb-core/src/main/java/org/apache/openejb/core/cmp/cmp2/EjbSelect.java?rev=668149&r1=668148&r2=668149&view=diff
==============================================================================
--- 
openejb/trunk/openejb3/container/openejb-core/src/main/java/org/apache/openejb/core/cmp/cmp2/EjbSelect.java
 (original)
+++ 
openejb/trunk/openejb3/container/openejb-core/src/main/java/org/apache/openejb/core/cmp/cmp2/EjbSelect.java
 Mon Jun 16 06:08:29 2008
@@ -17,17 +17,87 @@
  */
 package org.apache.openejb.core.cmp.cmp2;
 
+import java.lang.reflect.Method;
+import java.util.HashMap; 
+import java.util.Map; 
+
+import javax.ejb.FinderException;
+
 import org.apache.openejb.Container;
 import org.apache.openejb.DeploymentInfo;
 import org.apache.openejb.core.cmp.CmpContainer;
 
-import javax.ejb.FinderException;
-
 /**
  * DO NOT REFACTOR THIS CLASS.  This class is referenced directly by generated 
code.
+ * 
+ * The execute_xxxx() methods below are used for executing the meat of the 
generated 
+ * ejbSelectxxxx methods.  Primitive types convert and return the return type 
directly and the   
+ * generated method will give the correct return instruction.  Reference types 
are resolved using 
+ * the execute_Object() method, and the generated code is responsible for 
casting the return value 
+ * to the proper return type. 
  */
 public class EjbSelect {
-    public static Object execute(Object di, String methodSignature, String 
returnType, Object... args) throws FinderException {
+    // our table of select methods for quick lookup 
+    static private HashMap<Class<?>, Method> selectMethods = new 
HashMap<Class<?>, Method>(); 
+    static {
+        try {
+            selectMethods.put(Object.class, 
EjbSelect.class.getMethod("execute_Object", Object.class, String.class, 
String.class, Object[].class));
+            selectMethods.put(Void.TYPE, 
EjbSelect.class.getMethod("execute_void", Object.class, String.class, 
Object[].class));
+            selectMethods.put(Boolean.TYPE, 
EjbSelect.class.getMethod("execute_boolean", Object.class, String.class, 
Object[].class));
+            selectMethods.put(Byte.TYPE, 
EjbSelect.class.getMethod("execute_byte", Object.class, String.class, 
Object[].class));
+            selectMethods.put(Character.TYPE, 
EjbSelect.class.getMethod("execute_char", Object.class, String.class, 
Object[].class));
+            selectMethods.put(Short.TYPE, 
EjbSelect.class.getMethod("execute_short", Object.class, String.class, 
Object[].class));
+            selectMethods.put(Integer.TYPE, 
EjbSelect.class.getMethod("execute_int", Object.class, String.class, 
Object[].class));
+            selectMethods.put(Long.TYPE, 
EjbSelect.class.getMethod("execute_long", Object.class, String.class, 
Object[].class));
+            selectMethods.put(Float.TYPE, 
EjbSelect.class.getMethod("execute_float", Object.class, String.class, 
Object[].class));
+            selectMethods.put(Double.TYPE, 
EjbSelect.class.getMethod("execute_double", Object.class, String.class, 
Object[].class));
+        } catch (NoSuchMethodException e) {
+            throw new RuntimeException(e);
+        }
+    }
+    
+    
+    /**
+     * Retrieve the execution stub for the specified 
+     * return type.  If this is one of the primitive types, 
+     * the stub will directly return the primitive value. 
+     * All reference types get mapped to the generic Object 
+     * return type, so they'll need to be cast to the 
+     * appropriate class by the generated wrapper method. 
+     * 
+     * @param returnType The class of the return type.
+     * 
+     * @return The method to be used to process the method invocation. 
+     */
+    public static Method getSelectMethod(Class<?> returnType) 
+    {
+        // perform a lookup on the return type.  If it is not found directly 
in the 
+        // mapping table, this is some sort of reference type.  
+        Method method = selectMethods.get(returnType); 
+        if (method == null) {
+            return selectMethods.get(Object.class); 
+        }
+        
+        return method; 
+    }
+    
+    
+    /**
+     * Perform a select operation when the return value is 
+     * a void.  This one is slightly different from the 
+     * rest, as the container operation performed is an 
+     * update() rather than a select() because there's 
+     * no value to return. 
+     * 
+     * @param di     The ejb object we're executing on behalf of.
+     * @param methodSignature
+     *               The signature of the selectxxxx method being invoked.
+     * @param args   The arguments to the select.  These need to match
+     *               the method signature.
+     * 
+     * @exception FinderException
+     */
+    public static void execute_void(Object di, String methodSignature, 
Object... args) throws FinderException {
         DeploymentInfo deploymentInfo = (DeploymentInfo) di;
         Container container = deploymentInfo.getContainer();
         if (!(container instanceof CmpContainer)) {
@@ -35,32 +105,138 @@
         }
         CmpContainer cmpContainer = (CmpContainer) container;
         
-        // if the return type is void, assume we have an update query
-        if ("void".equals(returnType)) {
-            int result = cmpContainer.update(deploymentInfo, methodSignature, 
args);
-            return result;
+        cmpContainer.update(deploymentInfo, methodSignature, args);
+    }
+    
+    
+    /**
+     * The single execution stub for all non-primitive 
+     * select operations.  This method has an additional 
+     * returnType parameter used to instantiate the return 
+     * value. 
+     * 
+     * @param di         The EJB object we're operating against.
+     * @param methodSignature
+     *                   The signature of the ejbSelectxxxx method.
+     * @param returnType The return type signature of the method.
+     * @param args       The select arguments.
+     * 
+     * @return An object of the specified type...which might be 
+     *         one of the collection types.
+     * @exception FinderException
+     */
+    public static Object execute_Object(Object di, String methodSignature, 
String returnType, Object... args) throws FinderException {
+        DeploymentInfo deploymentInfo = (DeploymentInfo) di;
+        Container container = deploymentInfo.getContainer();
+        if (!(container instanceof CmpContainer)) {
+            throw new FinderException("Deployment is not connected to a 
CmpContainer " + deploymentInfo.getDeploymentID());
         }
-
-        Object result = cmpContainer.select(deploymentInfo, methodSignature, 
returnType, args);
-        if (result instanceof Number) {
-            Number number = (Number) result;
-            if ("char".equals(returnType) || 
Character.class.getName().equals(returnType)) {
-                result = new Character((char) number.intValue());
-            } else if ("byte".equals(returnType) || 
Byte.class.getName().equals(returnType)) {
-                result = number.byteValue();
-            } else if ("short".equals(returnType) || 
Short.class.getName().equals(returnType)) {
-                result = number.shortValue();
-            } else if ("int".equals(returnType) || 
Integer.class.getName().equals(returnType)) {
-                result = number.intValue();
-            } else if ("long".equals(returnType) || 
Long.class.getName().equals(returnType)) {
-                result = number.longValue();
-            } else if ("float".equals(returnType) || 
Float.class.getName().equals(returnType)) {
-                result = number.floatValue();
-            } else if ("double".equals(returnType) || 
Double.class.getName().equals(returnType)) {
-                result = number.doubleValue();
-            }
+        CmpContainer cmpContainer = (CmpContainer) container;
+        
+        return cmpContainer.select(deploymentInfo, methodSignature, 
returnType, args);
+    }
+    
+    
+    public static char execute_char(Object di, String methodSignature, 
Object... args) throws FinderException {
+        DeploymentInfo deploymentInfo = (DeploymentInfo) di;
+        Container container = deploymentInfo.getContainer();
+        if (!(container instanceof CmpContainer)) {
+            throw new FinderException("Deployment is not connected to a 
CmpContainer " + deploymentInfo.getDeploymentID());
         }
-
-        return result;
+        CmpContainer cmpContainer = (CmpContainer) container;
+        
+        Character result = (Character)cmpContainer.select(deploymentInfo, 
methodSignature, "char", args);
+        return result.charValue(); 
+    }
+    
+    
+    public static byte execute_byte(Object di, String methodSignature, 
Object... args) throws FinderException {
+        DeploymentInfo deploymentInfo = (DeploymentInfo) di;
+        Container container = deploymentInfo.getContainer();
+        if (!(container instanceof CmpContainer)) {
+            throw new FinderException("Deployment is not connected to a 
CmpContainer " + deploymentInfo.getDeploymentID());
+        }
+        CmpContainer cmpContainer = (CmpContainer) container;
+        
+        Number result = (Number)cmpContainer.select(deploymentInfo, 
methodSignature, "byte", args);
+        return result.byteValue(); 
+    }
+    
+    
+    public static boolean execute_boolean(Object di, String methodSignature, 
Object... args) throws FinderException {
+        DeploymentInfo deploymentInfo = (DeploymentInfo) di;
+        Container container = deploymentInfo.getContainer();
+        if (!(container instanceof CmpContainer)) {
+            throw new FinderException("Deployment is not connected to a 
CmpContainer " + deploymentInfo.getDeploymentID());
+        }
+        CmpContainer cmpContainer = (CmpContainer) container;
+        
+        Boolean result = (Boolean)cmpContainer.select(deploymentInfo, 
methodSignature, "byte", args);
+        return result.booleanValue(); 
+    }
+    
+    
+    public static short execute_short(Object di, String methodSignature, 
Object... args) throws FinderException {
+        DeploymentInfo deploymentInfo = (DeploymentInfo) di;
+        Container container = deploymentInfo.getContainer();
+        if (!(container instanceof CmpContainer)) {
+            throw new FinderException("Deployment is not connected to a 
CmpContainer " + deploymentInfo.getDeploymentID());
+        }
+        CmpContainer cmpContainer = (CmpContainer) container;
+        
+        Number result = (Number)cmpContainer.select(deploymentInfo, 
methodSignature, "short", args);
+        return result.shortValue(); 
+    }
+    
+    
+    public static int execute_int(Object di, String methodSignature, Object... 
args) throws FinderException {
+        DeploymentInfo deploymentInfo = (DeploymentInfo) di;
+        Container container = deploymentInfo.getContainer();
+        if (!(container instanceof CmpContainer)) {
+            throw new FinderException("Deployment is not connected to a 
CmpContainer " + deploymentInfo.getDeploymentID());
+        }
+        CmpContainer cmpContainer = (CmpContainer) container;
+        
+        Number result = (Number)cmpContainer.select(deploymentInfo, 
methodSignature, "int", args);
+        return result.intValue(); 
+    }
+    
+    
+    public static long execute_long(Object di, String methodSignature, 
Object... args) throws FinderException {
+        DeploymentInfo deploymentInfo = (DeploymentInfo) di;
+        Container container = deploymentInfo.getContainer();
+        if (!(container instanceof CmpContainer)) {
+            throw new FinderException("Deployment is not connected to a 
CmpContainer " + deploymentInfo.getDeploymentID());
+        }
+        CmpContainer cmpContainer = (CmpContainer) container;
+        
+        Number result = (Number)cmpContainer.select(deploymentInfo, 
methodSignature, "long", args);
+        return result.longValue(); 
+    }
+    
+    
+    public static float execute_float(Object di, String methodSignature, 
Object... args) throws FinderException {
+        DeploymentInfo deploymentInfo = (DeploymentInfo) di;
+        Container container = deploymentInfo.getContainer();
+        if (!(container instanceof CmpContainer)) {
+            throw new FinderException("Deployment is not connected to a 
CmpContainer " + deploymentInfo.getDeploymentID());
+        }
+        CmpContainer cmpContainer = (CmpContainer) container;
+        
+        Number result = (Number)cmpContainer.select(deploymentInfo, 
methodSignature, "float", args);
+        return result.floatValue(); 
+    }
+    
+    
+    public static double execute_double(Object di, String methodSignature, 
Object... args) throws FinderException {
+        DeploymentInfo deploymentInfo = (DeploymentInfo) di;
+        Container container = deploymentInfo.getContainer();
+        if (!(container instanceof CmpContainer)) {
+            throw new FinderException("Deployment is not connected to a 
CmpContainer " + deploymentInfo.getDeploymentID());
+        }
+        CmpContainer cmpContainer = (CmpContainer) container;
+        
+        Number result = (Number)cmpContainer.select(deploymentInfo, 
methodSignature, "double", args);
+        return result.doubleValue(); 
     }
 }


Reply via email to