[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