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();
}
}