[jboss-svn-commits] JBL Code SVN: r6621 - in labs/jbossrules/trunk/drools-core/src: main/java/org/drools/base main/java/org/drools/reteoo main/java/org/drools/util/asm test/java/org/drools/base
jboss-svn-commits at lists.jboss.org
jboss-svn-commits at lists.jboss.org
Thu Oct 5 15:52:27 EDT 2006
Author: tirelli
Date: 2006-10-05 15:52:08 -0400 (Thu, 05 Oct 2006)
New Revision: 6621
Modified:
labs/jbossrules/trunk/drools-core/src/main/java/org/drools/base/ShadowProxy.java
labs/jbossrules/trunk/drools-core/src/main/java/org/drools/base/ShadowProxyFactory.java
labs/jbossrules/trunk/drools-core/src/main/java/org/drools/reteoo/ObjectTypeNode.java
labs/jbossrules/trunk/drools-core/src/main/java/org/drools/util/asm/ClassFieldInspector.java
labs/jbossrules/trunk/drools-core/src/test/java/org/drools/base/ShadowProxyFactoryTest.java
Log:
JBRULES-44:
* Proxying and delegating all methods now
* Unit test updated
Modified: labs/jbossrules/trunk/drools-core/src/main/java/org/drools/base/ShadowProxy.java
===================================================================
--- labs/jbossrules/trunk/drools-core/src/main/java/org/drools/base/ShadowProxy.java 2006-10-05 19:14:10 UTC (rev 6620)
+++ labs/jbossrules/trunk/drools-core/src/main/java/org/drools/base/ShadowProxy.java 2006-10-05 19:52:08 UTC (rev 6621)
@@ -21,6 +21,6 @@
*/
public interface ShadowProxy {
- public void resetProxy();
+ public void updateProxy();
}
Modified: labs/jbossrules/trunk/drools-core/src/main/java/org/drools/base/ShadowProxyFactory.java
===================================================================
--- labs/jbossrules/trunk/drools-core/src/main/java/org/drools/base/ShadowProxyFactory.java 2006-10-05 19:14:10 UTC (rev 6620)
+++ labs/jbossrules/trunk/drools-core/src/main/java/org/drools/base/ShadowProxyFactory.java 2006-10-05 19:52:08 UTC (rev 6621)
@@ -17,6 +17,8 @@
package org.drools.base;
import java.lang.reflect.Method;
+import java.lang.reflect.Modifier;
+import java.util.HashMap;
import java.util.Iterator;
import java.util.Map;
@@ -27,7 +29,6 @@
import org.drools.asm.MethodVisitor;
import org.drools.asm.Opcodes;
import org.drools.asm.Type;
-import org.drools.util.asm.ClassFieldInspector;
/**
* A factory for ShadowProxy classes
@@ -43,14 +44,16 @@
public static Class getProxy(final Class clazz) {
try {
- final ClassFieldInspector inspector = new ClassFieldInspector( clazz,
- false );
- final String className = Type.getInternalName( clazz ) + "ShadowProxy";
+ String className = null;
+ if( clazz.getPackage().getName().startsWith( "java." ) ||
+ clazz.getPackage().getName().startsWith( "javax." )) {
+ className = "org/drools/shadow/"+Type.getInternalName( clazz )+"ShadowProxy";
+ } else {
+ className = Type.getInternalName( clazz ) + "ShadowProxy";
+ }
// generating byte array to create target class
final byte[] bytes = dump( clazz,
- inspector,
- className,
- clazz.isInterface() );
+ className );
// use bytes to get a class
final ByteArrayClassLoader classLoader = new ByteArrayClassLoader( Thread.currentThread().getContextClassLoader() );
final Class newClass = classLoader.defineClass( className.replace( '/',
@@ -63,9 +66,7 @@
}
protected static byte[] dump(final Class clazz,
- final ClassFieldInspector inspector,
- final String className,
- final boolean isInterface) throws Exception {
+ final String className) throws Exception {
final ClassWriter cw = new ClassWriter( true );
@@ -76,31 +77,46 @@
buildField( DELEGATE_FIELD_NAME,
Type.getDescriptor( clazz ),
cw );
- Map fieldNames = inspector.getFieldNames();
- Map fieldTypes = inspector.getFieldTypes();
- Map fieldGetters = inspector.getGetterMethods();
- for ( Iterator it = fieldNames.keySet().iterator(); it.hasNext(); ) {
- String fieldName = (String) it.next();
- buildField( FIELD_NAME_PREFIX + fieldName,
- Type.getDescriptor( (Class) fieldTypes.get( fieldName ) ),
- cw );
- buildField( FIELD_NAME_PREFIX + fieldName + FIELD_SET_FLAG,
- Type.BOOLEAN_TYPE.getDescriptor(),
- cw );
- buildGetMethod( FIELD_NAME_PREFIX + fieldName,
- (Class) fieldTypes.get( fieldName ),
- FIELD_NAME_PREFIX + fieldName + FIELD_SET_FLAG,
- (Method) fieldGetters.get( fieldName ),
- className,
- clazz,
- cw );
+
+ Map fieldTypes = new HashMap();
+
+ Method[] methods = clazz.getMethods();
+ for ( int i = 0; i < methods.length; i++ ) {
+ if ( (! Modifier.isFinal( methods[i].getModifiers() )) &&
+ Modifier.isPublic( methods[i].getModifiers() )) {
+ if ( (!methods[i].getReturnType().equals( Void.TYPE )) && (methods[i].getParameterTypes().length == 0) ) {
+ String fieldName = methods[i].getName();
+
+ buildField( FIELD_NAME_PREFIX + fieldName,
+ Type.getDescriptor( methods[i].getReturnType() ),
+ cw );
+ fieldTypes.put( FIELD_NAME_PREFIX + fieldName,
+ methods[i].getReturnType() );
+
+ buildField( FIELD_NAME_PREFIX + fieldName + FIELD_SET_FLAG,
+ Type.BOOLEAN_TYPE.getDescriptor(),
+ cw );
+ buildGetMethod( FIELD_NAME_PREFIX + fieldName,
+ methods[i].getReturnType(),
+ FIELD_NAME_PREFIX + fieldName + FIELD_SET_FLAG,
+ methods[i],
+ className,
+ clazz,
+ cw );
+ } else {
+ buildDelegateMethod( methods[i],
+ clazz,
+ className,
+ cw );
+ }
+ }
}
buildConstructor( clazz,
className,
cw );
- buildResetProxyMethod( fieldTypes,
+ buildUpdateProxyMethod( fieldTypes,
className,
cw );
@@ -255,10 +271,7 @@
ClassWriter cw) {
// method signature
Class[] exceptionTypes = method.getExceptionTypes();
- String[] exceptions = new String[exceptionTypes.length];
- for ( int i = 0; i < exceptions.length; i++ ) {
- exceptions[i] = Type.getInternalName( exceptionTypes[i] );
- }
+ String[] exceptions = getExceptionArrayAsString( exceptionTypes );
MethodVisitor mv = cw.visitMethod( Opcodes.ACC_PUBLIC,
method.getName(),
Type.getMethodDescriptor( method ),
@@ -342,11 +355,11 @@
mv.visitEnd();
}
- protected static void buildResetProxyMethod(Map fieldTypes,
+ protected static void buildUpdateProxyMethod(Map fieldTypes,
String className,
ClassWriter cw) {
MethodVisitor mv = cw.visitMethod( Opcodes.ACC_PUBLIC,
- "resetProxy",
+ "updateProxy",
Type.getMethodDescriptor( Type.VOID_TYPE,
new Type[]{} ),
null,
@@ -356,7 +369,7 @@
mv.visitLabel( l0 );
for ( Iterator it = fieldTypes.entrySet().iterator(); it.hasNext(); ) {
Map.Entry entry = (Map.Entry) it.next();
- String fieldName = FIELD_NAME_PREFIX + entry.getKey();
+ String fieldName = (String) entry.getKey();
String fieldFlag = fieldName + FIELD_SET_FLAG;
Class fieldType = (Class) entry.getValue();
Label l1 = new Label();
@@ -406,15 +419,64 @@
mv.visitEnd();
}
- protected static void buildEqualsMethod(Class clazz,
- String className,
- ClassWriter cw) {
+ // protected static void buildEqualsMethod(Class clazz,
+ // String className,
+ // ClassWriter cw) {
+ // MethodVisitor mv = cw.visitMethod( Opcodes.ACC_PUBLIC,
+ // "equals",
+ // "(Ljava/lang/Object;)Z",
+ // null,
+ // null );
+ // mv.visitCode();
+ // Label l0 = new Label();
+ // mv.visitLabel( l0 );
+ // mv.visitVarInsn( Opcodes.ALOAD,
+ // 0 );
+ // mv.visitFieldInsn( Opcodes.GETFIELD,
+ // className,
+ // DELEGATE_FIELD_NAME,
+ // Type.getDescriptor( clazz ) );
+ // mv.visitVarInsn( Opcodes.ALOAD,
+ // 1 );
+ // mv.visitMethodInsn( Opcodes.INVOKEVIRTUAL,
+ // Type.getInternalName( clazz ),
+ // "equals",
+ // "(Ljava/lang/Object;)Z" );
+ // mv.visitInsn( Opcodes.IRETURN );
+ // Label l1 = new Label();
+ // mv.visitLabel( l1 );
+ // mv.visitLocalVariable( "this",
+ // "L"+className+";",
+ // null,
+ // l0,
+ // l1,
+ // 0 );
+ // mv.visitLocalVariable( "object",
+ // Type.getDescriptor( Object.class ),
+ // null,
+ // l0,
+ // l1,
+ // 1 );
+ // mv.visitMaxs( 0,
+ // 0 );
+ // mv.visitEnd();
+ // }
+
+ protected static void buildDelegateMethod(Method method,
+ Class clazz,
+ String className,
+ ClassWriter cw) {
+
+ // creating method visitor
+ String[] exceptions = getExceptionArrayAsString( method.getExceptionTypes() );
MethodVisitor mv = cw.visitMethod( Opcodes.ACC_PUBLIC,
- "equals",
- "(Ljava/lang/Object;)Z",
+ method.getName(),
+ Type.getMethodDescriptor( method ),
null,
- null );
+ exceptions );
mv.visitCode();
+
+ // return this.delegate.method(...);
Label l0 = new Label();
mv.visitLabel( l0 );
mv.visitVarInsn( Opcodes.ALOAD,
@@ -423,33 +485,51 @@
className,
DELEGATE_FIELD_NAME,
Type.getDescriptor( clazz ) );
- mv.visitVarInsn( Opcodes.ALOAD,
- 1 );
+
+ Class[] parameters = method.getParameterTypes();
+ for ( int i = 0; i < parameters.length; i++ ) {
+ mv.visitVarInsn( Type.getType( parameters[i] ).getOpcode( Opcodes.ILOAD ),
+ i + 1 );
+ }
mv.visitMethodInsn( Opcodes.INVOKEVIRTUAL,
Type.getInternalName( clazz ),
- "equals",
- "(Ljava/lang/Object;)Z" );
- mv.visitInsn( Opcodes.IRETURN );
+ method.getName(),
+ Type.getMethodDescriptor( method ) );
+ mv.visitInsn( Type.getType( method.getReturnType() ).getOpcode( Opcodes.IRETURN ) );
Label l1 = new Label();
mv.visitLabel( l1 );
mv.visitLocalVariable( "this",
- "L"+className+";",
+ "L" + className + ";",
null,
l0,
l1,
0 );
- mv.visitLocalVariable( "object",
- Type.getDescriptor( Object.class ),
- null,
- l0,
- l1,
- 1 );
+ for ( int i = 0; i < parameters.length; i++ ) {
+ mv.visitLocalVariable( "arg" + i,
+ Type.getDescriptor( parameters[i] ),
+ null,
+ l0,
+ l1,
+ i + 1 );
+ }
mv.visitMaxs( 0,
0 );
mv.visitEnd();
}
/**
+ * @param exceptionTypes
+ * @return
+ */
+ private static String[] getExceptionArrayAsString(Class[] exceptionTypes) {
+ String[] exceptions = new String[exceptionTypes.length];
+ for ( int i = 0; i < exceptions.length; i++ ) {
+ exceptions[i] = Type.getInternalName( exceptionTypes[i] );
+ }
+ return exceptions;
+ }
+
+ /**
* Simple classloader
* @author Michael Neale
*/
Modified: labs/jbossrules/trunk/drools-core/src/main/java/org/drools/reteoo/ObjectTypeNode.java
===================================================================
--- labs/jbossrules/trunk/drools-core/src/main/java/org/drools/reteoo/ObjectTypeNode.java 2006-10-05 19:14:10 UTC (rev 6620)
+++ labs/jbossrules/trunk/drools-core/src/main/java/org/drools/reteoo/ObjectTypeNode.java 2006-10-05 19:52:08 UTC (rev 6621)
@@ -17,12 +17,9 @@
*/
import java.io.Serializable;
-import java.util.ArrayList;
-import java.util.List;
import org.drools.RuleBaseConfiguration;
import org.drools.common.BaseNode;
-import org.drools.common.DefaultFactHandle;
import org.drools.common.InternalFactHandle;
import org.drools.common.InternalWorkingMemory;
import org.drools.common.NodeMemory;
@@ -31,8 +28,6 @@
import org.drools.spi.PropagationContext;
import org.drools.util.FactHashTable;
import org.drools.util.Iterator;
-import org.drools.util.ObjectHashMap;
-import org.drools.util.PrimitiveLongMap;
import org.drools.util.AbstractHashTable.FactEntry;
/**
@@ -140,6 +135,12 @@
final PropagationContext context,
final InternalWorkingMemory workingMemory) {
final FactHashTable memory = (FactHashTable) workingMemory.getNodeMemory( this );
+
+ // checks if shadow is enabled
+ if(this.objectType.isShadowEnabled()) {
+ // replaces the actual object by its shadow before propagating
+ handle.setObject( this.objectType.getShadow( handle.getObject() ) );
+ }
// we do not need to check if the fact exists already
memory.add( handle, false );
Modified: labs/jbossrules/trunk/drools-core/src/main/java/org/drools/util/asm/ClassFieldInspector.java
===================================================================
--- labs/jbossrules/trunk/drools-core/src/main/java/org/drools/util/asm/ClassFieldInspector.java 2006-10-05 19:14:10 UTC (rev 6620)
+++ labs/jbossrules/trunk/drools-core/src/main/java/org/drools/util/asm/ClassFieldInspector.java 2006-10-05 19:52:08 UTC (rev 6621)
@@ -34,6 +34,7 @@
import org.drools.asm.FieldVisitor;
import org.drools.asm.MethodVisitor;
import org.drools.asm.Opcodes;
+import org.drools.asm.tree.MethodNode;
/**
* Visit a POJO user class, and extract the property getter methods that are public, in the
@@ -160,11 +161,11 @@
final int fieldIndex = this.inspector.methods.size();
addToMapping( method,
fieldIndex );
- }
+ }
} catch ( final NoSuchMethodException e ) {
throw new IllegalStateException( "Error in getting field access method." );
}
- }
+ }
}
return null;
}
@@ -323,4 +324,5 @@
}
}
+
}
\ No newline at end of file
Modified: labs/jbossrules/trunk/drools-core/src/test/java/org/drools/base/ShadowProxyFactoryTest.java
===================================================================
--- labs/jbossrules/trunk/drools-core/src/test/java/org/drools/base/ShadowProxyFactoryTest.java 2006-10-05 19:14:10 UTC (rev 6620)
+++ labs/jbossrules/trunk/drools-core/src/test/java/org/drools/base/ShadowProxyFactoryTest.java 2006-10-05 19:52:08 UTC (rev 6621)
@@ -1,5 +1,8 @@
package org.drools.base;
+import java.util.ArrayList;
+import java.util.List;
+
import junit.framework.Assert;
import junit.framework.TestCase;
@@ -46,7 +49,7 @@
Assert.assertEquals( originalPrice, cheeseProxy.getPrice() );
// reseting proxy
- ((ShadowProxy) cheeseProxy).resetProxy();
+ ((ShadowProxy) cheeseProxy).updateProxy();
// now proxy see changes
Assert.assertEquals( actualType, cheese.getType() );
@@ -91,7 +94,7 @@
Assert.assertEquals( originalPrice, cheeseProxy.getPrice() );
// reseting proxy
- ((ShadowProxy) cheeseProxy).resetProxy();
+ ((ShadowProxy) cheeseProxy).updateProxy();
// now proxy see changes
Assert.assertEquals( actualType, cheese.getType() );
@@ -106,4 +109,21 @@
}
}
+ public void testProxyForAPIClass() {
+ try {
+ // creating original object
+ List list = new ArrayList();
+
+ // creating proxy
+ Class proxy = ShadowProxyFactory.getProxy( ArrayList.class );
+ List listProxy = (List) proxy.getConstructor( new Class[] { ArrayList.class } ).newInstance( new Object[] { list } );
+
+ // proxy is proxying the values
+ Assert.assertEquals( list, listProxy );
+
+ } catch ( Exception e ) {
+ fail("Error: "+e.getMessage());
+ }
+ }
+
}
More information about the jboss-svn-commits
mailing list