cayenne-commits mailing list archives

Site index · List index
Message view « Date » · « Thread »
Top « Date » · « Thread »
From aadamc...@apache.org
Subject svn commit: r454601 - in /incubator/cayenne/sandbox/asm-enhancer/src: main/java/org/apache/cayenne/enhancer/ test/java/org/apache/cayenne/enhancer/
Date Tue, 10 Oct 2006 03:59:02 GMT
Author: aadamchik
Date: Mon Oct  9 20:59:01 2006
New Revision: 454601

URL: http://svn.apache.org/viewvc?view=rev&rev=454601
Log:
working simple properties interceptor

Added:
    incubator/cayenne/sandbox/asm-enhancer/src/main/java/org/apache/cayenne/enhancer/ClassVisitorHelper.java
      - copied, changed from r454593, incubator/cayenne/sandbox/asm-enhancer/src/main/java/org/apache/cayenne/enhancer/ClassBuilder.java
Removed:
    incubator/cayenne/sandbox/asm-enhancer/src/main/java/org/apache/cayenne/enhancer/ClassBuilder.java
Modified:
    incubator/cayenne/sandbox/asm-enhancer/src/main/java/org/apache/cayenne/enhancer/PersistentClassVisitor.java
    incubator/cayenne/sandbox/asm-enhancer/src/main/java/org/apache/cayenne/enhancer/PersistentGetterVisitor.java
    incubator/cayenne/sandbox/asm-enhancer/src/main/java/org/apache/cayenne/enhancer/PersistentSetterVisitor.java
    incubator/cayenne/sandbox/asm-enhancer/src/test/java/org/apache/cayenne/enhancer/CayenneEnhancerTest.java
    incubator/cayenne/sandbox/asm-enhancer/src/test/java/org/apache/cayenne/enhancer/EnhancingClassLoader.java
    incubator/cayenne/sandbox/asm-enhancer/src/test/java/org/apache/cayenne/enhancer/MockEnhancedPojo.java
    incubator/cayenne/sandbox/asm-enhancer/src/test/java/org/apache/cayenne/enhancer/MockObjectContext.java

Copied: incubator/cayenne/sandbox/asm-enhancer/src/main/java/org/apache/cayenne/enhancer/ClassVisitorHelper.java
(from r454593, incubator/cayenne/sandbox/asm-enhancer/src/main/java/org/apache/cayenne/enhancer/ClassBuilder.java)
URL: http://svn.apache.org/viewvc/incubator/cayenne/sandbox/asm-enhancer/src/main/java/org/apache/cayenne/enhancer/ClassVisitorHelper.java?view=diff&rev=454601&p1=incubator/cayenne/sandbox/asm-enhancer/src/main/java/org/apache/cayenne/enhancer/ClassBuilder.java&r1=454593&p2=incubator/cayenne/sandbox/asm-enhancer/src/main/java/org/apache/cayenne/enhancer/ClassVisitorHelper.java&r2=454601
==============================================================================
--- incubator/cayenne/sandbox/asm-enhancer/src/main/java/org/apache/cayenne/enhancer/ClassBuilder.java
(original)
+++ incubator/cayenne/sandbox/asm-enhancer/src/main/java/org/apache/cayenne/enhancer/ClassVisitorHelper.java
Mon Oct  9 20:59:01 2006
@@ -26,20 +26,29 @@
 import org.objectweb.asm.Type;
 
 /**
- * A builder that encapsulates common class enhancement operations.
+ * A helper for the ASM ClassVisitor that encapsulates common class enhancement
+ * operations.
  * 
  * @author Andrus Adamchik
  */
-class ClassBuilder {
+class ClassVisitorHelper {
 
     private String fieldPrefix = "$cay_";
     private ClassVisitor classVisitor;
     private Type currentClass;
 
-    ClassBuilder(ClassVisitor classVisitor) {
+    ClassVisitorHelper(ClassVisitor classVisitor) {
         this.classVisitor = classVisitor;
     }
 
+    Type getCurrentClass() {
+        return currentClass;
+    }
+
+    String getPropertyField(String propertyName) {
+        return fieldPrefix + propertyName;
+    }
+
     void reset(String className) {
         // assuming no primitives or arrays
         this.currentClass = Type.getType("L" + className + ";");
@@ -93,7 +102,7 @@
         mv.visitLabel(l0);
         mv.visitVarInsn(Opcodes.ALOAD, 0);
 
-        // TODO: other opcodes
+        // TODO: andrus, 10/9/2006 other opcodes
         if ("I".equals(asmType.getDescriptor())) {
             mv.visitVarInsn(Opcodes.ILOAD, 1);
         }
@@ -101,8 +110,11 @@
             mv.visitVarInsn(Opcodes.ALOAD, 1);
         }
 
-        mv.visitFieldInsn(Opcodes.PUTFIELD, currentClass.getInternalName(), fieldPrefix
-                + propertyName, asmType.getDescriptor());
+        mv.visitFieldInsn(
+                Opcodes.PUTFIELD,
+                currentClass.getInternalName(),
+                getPropertyField(propertyName),
+                asmType.getDescriptor());
         mv.visitInsn(Opcodes.RETURN);
         Label l1 = new Label();
         mv.visitLabel(l1);
@@ -126,10 +138,13 @@
         Label l0 = new Label();
         mv.visitLabel(l0);
         mv.visitVarInsn(Opcodes.ALOAD, 0);
-        mv.visitFieldInsn(Opcodes.GETFIELD, currentClass.getInternalName(), fieldPrefix
-                + propertyName, asmType.getDescriptor());
+        mv.visitFieldInsn(
+                Opcodes.GETFIELD,
+                currentClass.getInternalName(),
+                getPropertyField(propertyName),
+                asmType.getDescriptor());
 
-        // TODO: other return opcodes
+        // TODO: andrus, 10/9/2006 other return opcodes
         if ("I".equals(asmType.getDescriptor())) {
             mv.visitInsn(Opcodes.IRETURN);
         }
@@ -147,7 +162,7 @@
     private void createField(String propertyName, Type asmType, int access) {
         FieldVisitor fv = classVisitor.visitField(
                 access,
-                fieldPrefix + propertyName,
+                getPropertyField(propertyName),
                 asmType.getDescriptor(),
                 null,
                 null);

Modified: incubator/cayenne/sandbox/asm-enhancer/src/main/java/org/apache/cayenne/enhancer/PersistentClassVisitor.java
URL: http://svn.apache.org/viewvc/incubator/cayenne/sandbox/asm-enhancer/src/main/java/org/apache/cayenne/enhancer/PersistentClassVisitor.java?view=diff&rev=454601&r1=454600&r2=454601
==============================================================================
--- incubator/cayenne/sandbox/asm-enhancer/src/main/java/org/apache/cayenne/enhancer/PersistentClassVisitor.java
(original)
+++ incubator/cayenne/sandbox/asm-enhancer/src/main/java/org/apache/cayenne/enhancer/PersistentClassVisitor.java
Mon Oct  9 20:59:01 2006
@@ -35,12 +35,12 @@
 class PersistentClassVisitor extends ClassAdapter {
 
     private Collection<String> enhancedProperties;
-    private ClassBuilder builder;
+    private ClassVisitorHelper helper;
 
     PersistentClassVisitor(ClassVisitor visitor, Collection<String> enhancedProperties)
{
         super(visitor);
         this.enhancedProperties = enhancedProperties;
-        this.builder = new ClassBuilder(this);
+        this.helper = new ClassVisitorHelper(this);
     }
 
     /**
@@ -55,14 +55,14 @@
             String superName,
             String[] interfaces) {
 
-        builder.reset(name);
-        interfaces = builder.addInterface(interfaces, Persistent.class);
-        
+        helper.reset(name);
+        interfaces = helper.addInterface(interfaces, Persistent.class);
+
         super.visit(version, access, name, signature, superName, interfaces);
 
-        builder.createProperty(ObjectId.class, "objectId");
-        builder.createProperty(ObjectContext.class, "objectContext", true);
-        builder.createProperty(Integer.TYPE, "persistenceState");
+        helper.createProperty(ObjectId.class, "objectId");
+        helper.createProperty(ObjectContext.class, "objectContext", true);
+        helper.createProperty(Integer.TYPE, "persistenceState");
     }
 
     /**
@@ -81,15 +81,15 @@
         // TODO: andrus, 10/8/2006 - check method sig for real... just checking
         // the name is not enough
 
-        // String getProperty = EnhancerUtil.propertyNameForGetter(name);
-        // if (getProperty != null && enhancedProperties.contains(getProperty)) {
-        // return new PersistentGetterVisitor(mv, className, getProperty);
-        // }
-        //
-        // String setProperty = EnhancerUtil.propertyNameForSetter(name);
-        // if (setProperty != null && enhancedProperties.contains(setProperty)) {
-        // return new PersistentSetterVisitor(mv, className, setProperty);
-        // }
+        String getProperty = EnhancerUtil.propertyNameForGetter(name);
+        if (getProperty != null && enhancedProperties.contains(getProperty)) {
+            return new PersistentGetterVisitor(mv, helper, getProperty);
+        }
+
+        String setProperty = EnhancerUtil.propertyNameForSetter(name);
+        if (setProperty != null && enhancedProperties.contains(setProperty)) {
+            return new PersistentSetterVisitor(mv, helper, setProperty);
+        }
 
         return mv;
     }

Modified: incubator/cayenne/sandbox/asm-enhancer/src/main/java/org/apache/cayenne/enhancer/PersistentGetterVisitor.java
URL: http://svn.apache.org/viewvc/incubator/cayenne/sandbox/asm-enhancer/src/main/java/org/apache/cayenne/enhancer/PersistentGetterVisitor.java?view=diff&rev=454601&r1=454600&r2=454601
==============================================================================
--- incubator/cayenne/sandbox/asm-enhancer/src/main/java/org/apache/cayenne/enhancer/PersistentGetterVisitor.java
(original)
+++ incubator/cayenne/sandbox/asm-enhancer/src/main/java/org/apache/cayenne/enhancer/PersistentGetterVisitor.java
Mon Oct  9 20:59:01 2006
@@ -18,17 +18,22 @@
  ****************************************************************/
 package org.apache.cayenne.enhancer;
 
+import org.apache.cayenne.ObjectContext;
+import org.objectweb.asm.Label;
 import org.objectweb.asm.MethodAdapter;
 import org.objectweb.asm.MethodVisitor;
+import org.objectweb.asm.Opcodes;
+import org.objectweb.asm.Type;
 
 class PersistentGetterVisitor extends MethodAdapter {
 
-    private String className;
+    private ClassVisitorHelper helper;
     private String propertyName;
 
-    PersistentGetterVisitor(MethodVisitor mv, String className, String propertyName) {
+    PersistentGetterVisitor(MethodVisitor mv, ClassVisitorHelper helper,
+            String propertyName) {
         super(mv);
-        this.className = className;
+        this.helper = helper;
         this.propertyName = propertyName;
     }
 
@@ -36,20 +41,33 @@
     public void visitCode() {
         super.visitCode();
 
-        // mv.visitVarInsn(Opcodes.ALOAD, 0);
-        // mv.visitFieldInsn(Opcodes.GETFIELD, className,
-        // "$cayenne_persistenceDelegate",
-        // "Lorg/apache/cayenne/jpa/enhancer/PersistenceDelegate;");
-        // Label l1 = new Label();
-        // mv.visitJumpInsn(Opcodes.IFNULL, l1);
-        // mv.visitVarInsn(Opcodes.ALOAD, 0);
-        // mv.visitFieldInsn(Opcodes.GETFIELD, className,
-        // PojoAdapterFactory.PERSISTENCE_DELEGATE_FIELD,
-        // "Lorg/apache/cayenne/jpa/enhancer/PersistenceDelegate;");
-        // mv.visitLdcInsn(propertyName);
-        // mv.visitMethodInsn(Opcodes.INVOKEINTERFACE,
-        // "org/apache/cayenne/jpa/enhancer/PersistenceDelegate",
-        // "prepareForAccess", "(Ljava/lang/String;)V");
-        // mv.visitLabel(l1);
+        String field = helper.getPropertyField("objectContext");
+        Type objectContextType = Type.getType(ObjectContext.class);
+
+        mv.visitVarInsn(Opcodes.ALOAD, 0);
+        mv.visitFieldInsn(
+                Opcodes.GETFIELD,
+                helper.getCurrentClass().getInternalName(),
+                field,
+                objectContextType.getDescriptor());
+        Label l1 = new Label();
+        mv.visitJumpInsn(Opcodes.IFNULL, l1);
+        Label l2 = new Label();
+        mv.visitLabel(l2);
+        mv.visitLineNumber(42, l2);
+        mv.visitVarInsn(Opcodes.ALOAD, 0);
+        mv.visitFieldInsn(
+                Opcodes.GETFIELD,
+                helper.getCurrentClass().getInternalName(),
+                field,
+                objectContextType.getDescriptor());
+        mv.visitVarInsn(Opcodes.ALOAD, 0);
+        mv.visitLdcInsn(propertyName);
+        mv.visitMethodInsn(
+                Opcodes.INVOKEINTERFACE,
+                objectContextType.getInternalName(),
+                "prepareForAccess",
+                "(Lorg/apache/cayenne/Persistent;Ljava/lang/String;)V");
+        mv.visitLabel(l1);
     }
 }

Modified: incubator/cayenne/sandbox/asm-enhancer/src/main/java/org/apache/cayenne/enhancer/PersistentSetterVisitor.java
URL: http://svn.apache.org/viewvc/incubator/cayenne/sandbox/asm-enhancer/src/main/java/org/apache/cayenne/enhancer/PersistentSetterVisitor.java?view=diff&rev=454601&r1=454600&r2=454601
==============================================================================
--- incubator/cayenne/sandbox/asm-enhancer/src/main/java/org/apache/cayenne/enhancer/PersistentSetterVisitor.java
(original)
+++ incubator/cayenne/sandbox/asm-enhancer/src/main/java/org/apache/cayenne/enhancer/PersistentSetterVisitor.java
Mon Oct  9 20:59:01 2006
@@ -18,17 +18,22 @@
  ****************************************************************/
 package org.apache.cayenne.enhancer;
 
+import org.apache.cayenne.ObjectContext;
+import org.objectweb.asm.Label;
 import org.objectweb.asm.MethodAdapter;
 import org.objectweb.asm.MethodVisitor;
+import org.objectweb.asm.Opcodes;
+import org.objectweb.asm.Type;
 
 class PersistentSetterVisitor extends MethodAdapter {
 
-    private String className;
+    private ClassVisitorHelper helper;
     private String propertyName;
 
-    PersistentSetterVisitor(MethodVisitor mv, String className, String propertyName) {
+    PersistentSetterVisitor(MethodVisitor mv, ClassVisitorHelper helper,
+            String propertyName) {
         super(mv);
-        this.className = className;
+        this.helper = helper;
         this.propertyName = propertyName;
     }
 
@@ -36,20 +41,39 @@
     public void visitCode() {
         super.visitCode();
 
-        // mv.visitVarInsn(Opcodes.ALOAD, 0);
-        // mv.visitFieldInsn(Opcodes.GETFIELD, className,
-        // PojoAdapterFactory.PERSISTENCE_DELEGATE_FIELD,
-        // "Lorg/apache/cayenne/jpa/enhancer/PersistenceDelegate;");
-        // Label l1 = new Label();
-        // mv.visitJumpInsn(Opcodes.IFNULL, l1);
-        // mv.visitVarInsn(Opcodes.ALOAD, 0);
-        // mv.visitFieldInsn(Opcodes.GETFIELD, className,
-        // PojoAdapterFactory.PERSISTENCE_DELEGATE_FIELD,
-        // "Lorg/apache/cayenne/jpa/enhancer/PersistenceDelegate;");
-        // mv.visitLdcInsn(propertyName);
-        // mv.visitMethodInsn(Opcodes.INVOKEINTERFACE,
-        // "org/apache/cayenne/jpa/enhancer/PersistenceDelegate",
-        // "prepareForUpdate", "(Ljava/lang/String;)V");
-        // mv.visitLabel(l1);
+        String field = helper.getPropertyField("objectContext");
+        Type objectContextType = Type.getType(ObjectContext.class);
+
+        mv.visitVarInsn(Opcodes.ALOAD, 0);
+        mv.visitFieldInsn(
+                Opcodes.GETFIELD,
+                helper.getCurrentClass().getInternalName(),
+                field,
+                objectContextType.getDescriptor());
+        Label l1 = new Label();
+        mv.visitJumpInsn(Opcodes.IFNULL, l1);
+        mv.visitVarInsn(Opcodes.ALOAD, 0);
+        mv.visitFieldInsn(
+                Opcodes.GETFIELD,
+                helper.getCurrentClass().getInternalName(),
+                field,
+                objectContextType.getDescriptor());
+        mv.visitVarInsn(Opcodes.ALOAD, 0);
+        mv.visitLdcInsn("attribute1");
+        mv.visitVarInsn(Opcodes.ALOAD, 0);
+        mv.visitFieldInsn(
+                Opcodes.GETFIELD,
+                helper.getCurrentClass().getInternalName(),
+                propertyName,
+                "Ljava/lang/String;");
+        mv.visitVarInsn(Opcodes.ALOAD, 1);
+        mv
+                .visitMethodInsn(
+                        Opcodes.INVOKEINTERFACE,
+                        objectContextType.getInternalName(),
+                        "propertyChanged",
+                        "(Lorg/apache/cayenne/Persistent;Ljava/lang/String;Ljava/lang/Object;Ljava/lang/Object;)V");
+        mv.visitLabel(l1);
+
     }
 }

Modified: incubator/cayenne/sandbox/asm-enhancer/src/test/java/org/apache/cayenne/enhancer/CayenneEnhancerTest.java
URL: http://svn.apache.org/viewvc/incubator/cayenne/sandbox/asm-enhancer/src/test/java/org/apache/cayenne/enhancer/CayenneEnhancerTest.java?view=diff&rev=454601&r1=454600&r2=454601
==============================================================================
--- incubator/cayenne/sandbox/asm-enhancer/src/test/java/org/apache/cayenne/enhancer/CayenneEnhancerTest.java
(original)
+++ incubator/cayenne/sandbox/asm-enhancer/src/test/java/org/apache/cayenne/enhancer/CayenneEnhancerTest.java
Mon Oct  9 20:59:01 2006
@@ -117,4 +117,100 @@
         Object state = getPersistenceState.invoke(o, (Object[]) null);
         assertEquals(PersistenceState.DELETED, state);
     }
+
+    public void testGetterIntercepted() throws Exception {
+
+        Class e1Class = Class.forName(C1, true, loader);
+        assertNotNull(e1Class);
+        assertEquals(C1, e1Class.getName());
+
+        Object o = e1Class.newInstance();
+
+        // attempt calling on detached object - must not fail
+        Method getAttribute1 = e1Class.getDeclaredMethod("getAttribute1", (Class[]) null);
+        assertEquals(null, getAttribute1.invoke(o, (Object[]) null));
+
+        // now call on attached object
+
+        final Object[] prepared = new Object[2];
+        ObjectContext context = new MockObjectContext() {
+
+            @Override
+            public void prepareForAccess(Persistent object, String property) {
+                prepared[0] = object;
+                prepared[1] = property;
+            }
+        };
+
+        Method setObjectContext = e1Class.getDeclaredMethod(
+                "setObjectContext",
+                new Class[] {
+                    ObjectContext.class
+                });
+
+        setObjectContext.invoke(o, new Object[] {
+            context
+        });
+
+        assertEquals(null, getAttribute1.invoke(o, (Object[]) null));
+        assertSame(o, prepared[0]);
+        assertEquals("attribute1", prepared[1]);
+    }
+
+    public void testSetterIntercepted() throws Exception {
+
+        Class e1Class = Class.forName(C1, true, loader);
+        assertNotNull(e1Class);
+        assertEquals(C1, e1Class.getName());
+
+        Object o = e1Class.newInstance();
+
+        // attempt calling on detached object - must not fail
+        Method getAttribute1 = e1Class.getDeclaredMethod("getAttribute1", (Class[]) null);
+        Method setAttribute1 = e1Class.getDeclaredMethod("setAttribute1", new Class[] {
+            String.class
+        });
+
+        assertEquals(null, getAttribute1.invoke(o, (Object[]) null));
+        setAttribute1.invoke(o, new Object[] {
+            "x"
+        });
+        assertEquals("x", getAttribute1.invoke(o, (Object[]) null));
+
+        // now call on attached object
+        final Object[] change = new Object[4];
+        ObjectContext context = new MockObjectContext() {
+
+            @Override
+            public void propertyChanged(
+                    Persistent object,
+                    String property,
+                    Object oldValue,
+                    Object newValue) {
+                change[0] = object;
+                change[1] = property;
+                change[2] = oldValue;
+                change[3] = newValue;
+            }
+        };
+
+        Method setObjectContext = e1Class.getDeclaredMethod(
+                "setObjectContext",
+                new Class[] {
+                    ObjectContext.class
+                });
+
+        setObjectContext.invoke(o, new Object[] {
+            context
+        });
+
+        setAttribute1.invoke(o, new Object[] {
+                "y"
+            });
+        assertEquals("y", getAttribute1.invoke(o, (Object[]) null));
+        assertSame(o, change[0]);
+        assertEquals("attribute1", change[1]);
+        assertEquals("x", change[2]);
+        assertEquals("y", change[3]);
+    }
 }

Modified: incubator/cayenne/sandbox/asm-enhancer/src/test/java/org/apache/cayenne/enhancer/EnhancingClassLoader.java
URL: http://svn.apache.org/viewvc/incubator/cayenne/sandbox/asm-enhancer/src/test/java/org/apache/cayenne/enhancer/EnhancingClassLoader.java?view=diff&rev=454601&r1=454600&r2=454601
==============================================================================
--- incubator/cayenne/sandbox/asm-enhancer/src/test/java/org/apache/cayenne/enhancer/EnhancingClassLoader.java
(original)
+++ incubator/cayenne/sandbox/asm-enhancer/src/test/java/org/apache/cayenne/enhancer/EnhancingClassLoader.java
Mon Oct  9 20:59:01 2006
@@ -26,107 +26,111 @@
 import java.lang.instrument.IllegalClassFormatException;
 import java.security.SecureClassLoader;
 
-public class EnhancingClassLoader extends SecureClassLoader {
+class EnhancingClassLoader extends SecureClassLoader {
 
-	protected ClassFileTransformer transformer;
+    protected ClassFileTransformer transformer;
 
-	public EnhancingClassLoader(ClassFileTransformer transformer) {
-		super(Thread.currentThread().getContextClassLoader());
-		this.transformer = transformer;
-	}
-
-	/**
-	 * Returns true if the class does not need to be enhanced.
-	 */
-	protected boolean skipClassEnhancement(String className) {
-		return transformer == null;
-	}
-
-	@Override
-	protected synchronized Class<?> loadClass(String name, boolean resolve)
-			throws ClassNotFoundException {
-
-		if (skipClassEnhancement(name)) {
-			return super.loadClass(name, resolve);
-		}
-
-		Class c = findLoadedClass(name);
-
-		if (c == null) {
-			c = findClass(name);
-		}
-
-		if (resolve) {
-			resolveClass(c);
-		}
-
-		return c;
-	}
-
-	/**
-	 * If a class name is one of the managed classes, loads it
-	 */
-	@Override
-	protected Class<?> findClass(String name) throws ClassNotFoundException {
-		if (skipClassEnhancement(name)) {
-			return Class.forName(name, true, getParent());
-		} else {
-			return findEnhancedClass(name);
-		}
-	}
-
-	/**
-	 * Loads class bytes, and passes them through the registered
-	 * ClassTransformers.
-	 */
-	protected Class<?> findEnhancedClass(String name)
-			throws ClassNotFoundException {
-		String path = name.replace('.', '/') + ".class";
-
-		InputStream in = getResourceAsStream(path);
-		if (in == null) {
-			return Class.forName(name, true, getParent());
-		}
-
-		try {
-
-			ByteArrayOutputStream out = new ByteArrayOutputStream(1024);
-			byte[] buffer = new byte[1024];
-			int read;
-
-			while ((read = in.read(buffer, 0, 1024)) > 0) {
-				out.write(buffer, 0, read);
-			}
-
-			out.close();
-			byte[] classBytes = out.toByteArray();
-
-			byte[] bytes;
-			try {
-				bytes = transformer.transform(getParent(), name, null, null,
-						classBytes);
-			} catch (IllegalClassFormatException e) {
-				throw new ClassNotFoundException("Could not transform class '"
-						+ name + "' due to invalid format", e);
-			}
-
-			if (bytes != null) {
-				classBytes = bytes;
-			} else {
-				// if transformer didn't transform ... this is suboptimal as
-				// we've already read the bytes from classfile...
-				return Class.forName(name, true, getParent());
-			}
-
-			return defineClass(name, classBytes, 0, classBytes.length);
-		} catch (IOException e) {
-			throw new ClassNotFoundException(name, e);
-		} finally {
-			try {
-				in.close();
-			} catch (IOException e) {
-				// ignore close exceptions...
-			}
-		}
-	}
+    public EnhancingClassLoader(ClassFileTransformer transformer) {
+        super(Thread.currentThread().getContextClassLoader());
+        this.transformer = transformer;
+    }
+
+    /**
+     * Returns true if the class does not need to be enhanced.
+     */
+    protected boolean skipClassEnhancement(String className) {
+        return transformer == null;
+    }
+
+    @Override
+    protected synchronized Class<?> loadClass(String name, boolean resolve)
+            throws ClassNotFoundException {
+
+        if (skipClassEnhancement(name)) {
+            return super.loadClass(name, resolve);
+        }
+
+        Class c = findLoadedClass(name);
+
+        if (c == null) {
+            c = findClass(name);
+        }
+
+        if (resolve) {
+            resolveClass(c);
+        }
+
+        return c;
+    }
+
+    /**
+     * If a class name is one of the managed classes, loads it
+     */
+    @Override
+    protected Class<?> findClass(String name) throws ClassNotFoundException {
+        if (skipClassEnhancement(name)) {
+            return Class.forName(name, true, getParent());
+        }
+        else {
+            return findEnhancedClass(name);
+        }
+    }
+
+    /**
+     * Loads class bytes, and passes them through the registered ClassTransformers.
+     */
+    protected Class<?> findEnhancedClass(String name) throws ClassNotFoundException
{
+        String path = name.replace('.', '/') + ".class";
+
+        InputStream in = getResourceAsStream(path);
+        if (in == null) {
+            return Class.forName(name, true, getParent());
+        }
+
+        try {
+
+            ByteArrayOutputStream out = new ByteArrayOutputStream(1024);
+            byte[] buffer = new byte[1024];
+            int read;
+
+            while ((read = in.read(buffer, 0, 1024)) > 0) {
+                out.write(buffer, 0, read);
+            }
+
+            out.close();
+            byte[] classBytes = out.toByteArray();
+
+            byte[] bytes;
+            try {
+                bytes = transformer.transform(getParent(), name, null, null, classBytes);
+            }
+            catch (IllegalClassFormatException e) {
+                throw new ClassNotFoundException("Could not transform class '"
+                        + name
+                        + "' due to invalid format", e);
+            }
+
+            if (bytes != null) {
+                classBytes = bytes;
+            }
+            else {
+                // if transformer didn't transform ... this is suboptimal as
+                // we've already read the bytes from classfile...
+                return Class.forName(name, true, getParent());
+            }
+
+            return defineClass(name, classBytes, 0, classBytes.length);
+        }
+        catch (IOException e) {
+            throw new ClassNotFoundException(name, e);
+        }
+        finally {
+            try {
+                in.close();
+            }
+            catch (IOException e) {
+                // ignore close exceptions...
+            }
+        }
+    }
 }

Modified: incubator/cayenne/sandbox/asm-enhancer/src/test/java/org/apache/cayenne/enhancer/MockEnhancedPojo.java
URL: http://svn.apache.org/viewvc/incubator/cayenne/sandbox/asm-enhancer/src/test/java/org/apache/cayenne/enhancer/MockEnhancedPojo.java?view=diff&rev=454601&r1=454600&r2=454601
==============================================================================
--- incubator/cayenne/sandbox/asm-enhancer/src/test/java/org/apache/cayenne/enhancer/MockEnhancedPojo.java
(original)
+++ incubator/cayenne/sandbox/asm-enhancer/src/test/java/org/apache/cayenne/enhancer/MockEnhancedPojo.java
Mon Oct  9 20:59:01 2006
@@ -25,7 +25,8 @@
 
 /**
  * This class in combination with the ASM Eclipse plugin is used as a reference for
- * building parts of the ASM enhancer.
+ * building parts of the ASM enhancer. It demonstrates how a pojo should look like after
+ * the enhancement.
  * 
  * @author Andrus Adamchik
  */

Modified: incubator/cayenne/sandbox/asm-enhancer/src/test/java/org/apache/cayenne/enhancer/MockObjectContext.java
URL: http://svn.apache.org/viewvc/incubator/cayenne/sandbox/asm-enhancer/src/test/java/org/apache/cayenne/enhancer/MockObjectContext.java?view=diff&rev=454601&r1=454600&r2=454601
==============================================================================
--- incubator/cayenne/sandbox/asm-enhancer/src/test/java/org/apache/cayenne/enhancer/MockObjectContext.java
(original)
+++ incubator/cayenne/sandbox/asm-enhancer/src/test/java/org/apache/cayenne/enhancer/MockObjectContext.java
Mon Oct  9 20:59:01 2006
@@ -32,8 +32,6 @@
 import org.apache.cayenne.query.Query;
 
 public class MockObjectContext implements ObjectContext {
-    
-    protected boolean preparedForAccess;
 
     public void prepareForAccess(Persistent object, String property) {
     }



Mime
View raw message