You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@openwebbeans.apache.org by st...@apache.org on 2012/12/30 18:52:57 UTC
svn commit: r1426968 - in /openwebbeans/trunk/webbeans-impl: ./
src/main/java/org/apache/webbeans/proxy/asm/
src/test/java/org/apache/webbeans/newtests/interceptors/factory/
src/test/java/org/apache/webbeans/newtests/interceptors/factory/beans/
Author: struberg
Date: Sun Dec 30 17:52:56 2012
New Revision: 1426968
URL: http://svn.apache.org/viewvc?rev=1426968&view=rev
Log:
OWB-344 start with an easy ASM proxy implementation
Added:
openwebbeans/trunk/webbeans-impl/src/main/java/org/apache/webbeans/proxy/asm/InterceptorDecoratorProxyFactory.java
openwebbeans/trunk/webbeans-impl/src/test/java/org/apache/webbeans/newtests/interceptors/factory/
openwebbeans/trunk/webbeans-impl/src/test/java/org/apache/webbeans/newtests/interceptors/factory/InterceptorDecoratorProxyFactoryTest.java
openwebbeans/trunk/webbeans-impl/src/test/java/org/apache/webbeans/newtests/interceptors/factory/beans/
openwebbeans/trunk/webbeans-impl/src/test/java/org/apache/webbeans/newtests/interceptors/factory/beans/ClassInterceptedClass.java
openwebbeans/trunk/webbeans-impl/src/test/java/org/apache/webbeans/newtests/interceptors/factory/beans/NonInterceptedClass.java
Modified:
openwebbeans/trunk/webbeans-impl/pom.xml
openwebbeans/trunk/webbeans-impl/src/main/java/org/apache/webbeans/proxy/asm/AsmProxyFactory.java
Modified: openwebbeans/trunk/webbeans-impl/pom.xml
URL: http://svn.apache.org/viewvc/openwebbeans/trunk/webbeans-impl/pom.xml?rev=1426968&r1=1426967&r2=1426968&view=diff
==============================================================================
--- openwebbeans/trunk/webbeans-impl/pom.xml (original)
+++ openwebbeans/trunk/webbeans-impl/pom.xml Sun Dec 30 17:52:56 2012
@@ -48,11 +48,19 @@
</dependency>
<dependency>
+ <groupId>org.ow2.asm</groupId>
+ <artifactId>asm-all</artifactId>
+ <version>4.1</version>
+ <optional>true</optional>
+ </dependency>
+<!-- TODO this is the old version
+ <dependency>
<groupId>asm</groupId>
<artifactId>asm</artifactId>
<version>3.3.1</version>
<optional>true</optional>
</dependency>
+-->
<dependency>
<groupId>org.apache.geronimo.specs</groupId>
Modified: openwebbeans/trunk/webbeans-impl/src/main/java/org/apache/webbeans/proxy/asm/AsmProxyFactory.java
URL: http://svn.apache.org/viewvc/openwebbeans/trunk/webbeans-impl/src/main/java/org/apache/webbeans/proxy/asm/AsmProxyFactory.java?rev=1426968&r1=1426967&r2=1426968&view=diff
==============================================================================
--- openwebbeans/trunk/webbeans-impl/src/main/java/org/apache/webbeans/proxy/asm/AsmProxyFactory.java (original)
+++ openwebbeans/trunk/webbeans-impl/src/main/java/org/apache/webbeans/proxy/asm/AsmProxyFactory.java Sun Dec 30 17:52:56 2012
@@ -48,8 +48,7 @@ import org.objectweb.asm.MethodVisitor;
import org.objectweb.asm.Opcodes;
import org.objectweb.asm.Type;
-public class AsmProxyFactory
- implements Opcodes
+public class AsmProxyFactory implements Opcodes
{
private static final AtomicInteger ID = new AtomicInteger(1);
Added: openwebbeans/trunk/webbeans-impl/src/main/java/org/apache/webbeans/proxy/asm/InterceptorDecoratorProxyFactory.java
URL: http://svn.apache.org/viewvc/openwebbeans/trunk/webbeans-impl/src/main/java/org/apache/webbeans/proxy/asm/InterceptorDecoratorProxyFactory.java?rev=1426968&view=auto
==============================================================================
--- openwebbeans/trunk/webbeans-impl/src/main/java/org/apache/webbeans/proxy/asm/InterceptorDecoratorProxyFactory.java (added)
+++ openwebbeans/trunk/webbeans-impl/src/main/java/org/apache/webbeans/proxy/asm/InterceptorDecoratorProxyFactory.java Sun Dec 30 17:52:56 2012
@@ -0,0 +1,165 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+package org.apache.webbeans.proxy.asm;
+
+
+import java.lang.reflect.Constructor;
+import java.lang.reflect.InvocationTargetException;
+import java.lang.reflect.Method;
+
+import org.apache.webbeans.proxy.ProxyGenerationException;
+import org.objectweb.asm.ClassWriter;
+import org.objectweb.asm.MethodVisitor;
+import org.objectweb.asm.Opcodes;
+import org.objectweb.asm.Type;
+
+
+/**
+ * WORK IN PROGRESS
+ *
+ * Generate a dynamic subclass which has exactly 1 delegation point instance
+ * which get's set in the Constructor of the proxy.
+ * Any non-intercepted or decorated method will get delegated natively,
+ * All intercepted and decorated methods will get invoked via an InvocationHandler chain.
+ *
+ * This factory will create and cache the proxy classes for a given type.
+ */
+public class InterceptorDecoratorProxyFactory
+{
+
+ /**
+ * Create a decorator and interceptor proxy for the given type.
+ *
+ * TODO: we also need to pass in the decorator and interceptor stack definition
+ * plus the list of methods which are intercepted
+ *
+ * TODO: create a way to access the internal delegation point for invoking private methods later.
+ *
+ * @param classLoader to use for creating the class in
+ * @param classToProxy
+ * @param <T>
+ * @return the proxy class
+ */
+ public synchronized <T> Class<T> createInterceptorDecoratorProxyClass(ClassLoader classLoader, Class<T> classToProxy)
+ {
+ String proxyName = classToProxy.getName() + "$OwbInterceptProxy";
+ String proxyClassFileName = proxyName.replace('.', '/');
+
+ try
+ {
+ final byte[] proxyBytes = generateProxy(classToProxy, proxyName, proxyClassFileName);
+ return defineAndLoadClass(classLoader, proxyName, proxyBytes);
+ }
+ catch (Exception e)
+ {
+ final InternalError internalError = new InternalError();
+ internalError.initCause(e);
+ throw internalError;
+ }
+ }
+
+
+ private byte[] generateProxy(Class<?> classToProxy, String proxyName, String proxyClassFileName)
+ throws ProxyGenerationException
+ {
+ ClassWriter cw = new ClassWriter(ClassWriter.COMPUTE_MAXS);
+ String classFileName = classToProxy.getName().replace('.', '/');
+
+ String[] interfaceNames = new String[0]; //X TODO there might be some more in the future
+
+ cw.visit(Opcodes.V1_5, Opcodes.ACC_PUBLIC + Opcodes.ACC_SUPER + Opcodes.ACC_SYNTHETIC, proxyClassFileName, null, classFileName, interfaceNames);
+ cw.visitSource(classFileName + ".java", null);
+
+ propagateDefaultConstructor(cw, classToProxy, classFileName);
+
+ //X TODO continue;
+
+ return cw.toByteArray();
+ }
+
+ private void propagateDefaultConstructor(ClassWriter cw, Class<?> classToProxy, String classFileName)
+ throws ProxyGenerationException
+ {
+ try
+ {
+ Constructor superDefaultCt = classToProxy.getConstructor(null);
+
+ final String descriptor = Type.getConstructorDescriptor(superDefaultCt);
+ final MethodVisitor mv = cw.visitMethod(Opcodes.ACC_PUBLIC, "<init>", descriptor, null, null);
+ mv.visitCode();
+ mv.visitVarInsn(Opcodes.ALOAD, 0);
+
+ mv.visitMethodInsn(Opcodes.INVOKESPECIAL, classFileName, "<init>", descriptor);
+ mv.visitInsn(Opcodes.RETURN);
+ mv.visitMaxs(-1, -1);
+ mv.visitEnd();
+ }
+ catch (NoSuchMethodException e)
+ {
+ throw new ProxyGenerationException(e);
+ }
+ }
+
+ /**
+ * The 'defineClass' method on the ClassLoader is protected, thus we need to invoke it via reflection.
+ * @return the Class which got loaded in the classloader
+ */
+ private <T> Class<T> defineAndLoadClass(ClassLoader classLoader, String proxyName, byte[] proxyBytes)
+ throws ProxyGenerationException
+ {
+ Class<?> clazz = classLoader.getClass();
+
+ Method defineClassMethod = null;
+ do
+ {
+ try
+ {
+ defineClassMethod = clazz.getDeclaredMethod("defineClass", String.class, byte[].class, int.class, int.class);
+ }
+ catch (NoSuchMethodException e)
+ {
+ // do nothing, we need to search the superclass
+ }
+
+ clazz = clazz.getSuperclass();
+ } while (defineClassMethod == null && clazz != Object.class);
+
+ if (defineClassMethod == null)
+ {
+ throw new ProxyGenerationException("could not find 'defineClass' method in the ClassLoader!");
+ }
+
+ defineClassMethod.setAccessible(true);
+ try
+ {
+ Class<T> definedClass = (Class<T>) defineClassMethod.invoke(classLoader, proxyName, proxyBytes, 0, proxyBytes.length);
+
+ return definedClass;
+ }
+ catch (IllegalAccessException e)
+ {
+ throw new ProxyGenerationException(e);
+ }
+ catch (InvocationTargetException e)
+ {
+ throw new ProxyGenerationException(e);
+ }
+ }
+
+}
Added: openwebbeans/trunk/webbeans-impl/src/test/java/org/apache/webbeans/newtests/interceptors/factory/InterceptorDecoratorProxyFactoryTest.java
URL: http://svn.apache.org/viewvc/openwebbeans/trunk/webbeans-impl/src/test/java/org/apache/webbeans/newtests/interceptors/factory/InterceptorDecoratorProxyFactoryTest.java?rev=1426968&view=auto
==============================================================================
--- openwebbeans/trunk/webbeans-impl/src/test/java/org/apache/webbeans/newtests/interceptors/factory/InterceptorDecoratorProxyFactoryTest.java (added)
+++ openwebbeans/trunk/webbeans-impl/src/test/java/org/apache/webbeans/newtests/interceptors/factory/InterceptorDecoratorProxyFactoryTest.java Sun Dec 30 17:52:56 2012
@@ -0,0 +1,52 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+package org.apache.webbeans.newtests.interceptors.factory;
+
+import org.apache.webbeans.newtests.interceptors.factory.beans.ClassInterceptedClass;
+import org.apache.webbeans.proxy.asm.InterceptorDecoratorProxyFactory;
+
+import org.junit.Assert;
+import org.junit.Test;
+
+
+/**
+ * Test the {@link org.apache.webbeans.proxy.asm.InterceptorDecoratorProxyFactory}
+ */
+public class InterceptorDecoratorProxyFactoryTest
+{
+
+ @Test
+ public void textSimpleProxyCreation() throws Exception
+ {
+ InterceptorDecoratorProxyFactory pf = new InterceptorDecoratorProxyFactory();
+
+ ClassLoader classLoader = this.getClass().getClassLoader();
+
+ Class<ClassInterceptedClass> proxyClass = pf.createInterceptorDecoratorProxyClass(classLoader, ClassInterceptedClass.class);
+ Assert.assertNotNull(proxyClass);
+
+ ClassInterceptedClass instance = proxyClass.newInstance();
+ Assert.assertNotNull(instance);
+ Assert.assertTrue(instance.defaultCtInvoked);
+
+ instance.setMeaningOfLife(42);
+
+ Assert.assertEquals(42, instance.getMeaningOfLife());
+ }
+}
Added: openwebbeans/trunk/webbeans-impl/src/test/java/org/apache/webbeans/newtests/interceptors/factory/beans/ClassInterceptedClass.java
URL: http://svn.apache.org/viewvc/openwebbeans/trunk/webbeans-impl/src/test/java/org/apache/webbeans/newtests/interceptors/factory/beans/ClassInterceptedClass.java?rev=1426968&view=auto
==============================================================================
--- openwebbeans/trunk/webbeans-impl/src/test/java/org/apache/webbeans/newtests/interceptors/factory/beans/ClassInterceptedClass.java (added)
+++ openwebbeans/trunk/webbeans-impl/src/test/java/org/apache/webbeans/newtests/interceptors/factory/beans/ClassInterceptedClass.java Sun Dec 30 17:52:56 2012
@@ -0,0 +1,47 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+package org.apache.webbeans.newtests.interceptors.factory.beans;
+
+import org.apache.webbeans.test.component.intercept.webbeans.bindings.Transactional;
+
+/**
+ * A simple class which is not intercepted
+ */
+@Transactional
+public class ClassInterceptedClass
+{
+ public boolean defaultCtInvoked = false;
+
+ private int meaningOfLife;
+
+ public ClassInterceptedClass()
+ {
+ defaultCtInvoked = true;
+ }
+
+ public int getMeaningOfLife()
+ {
+ return meaningOfLife;
+ }
+
+ public void setMeaningOfLife(int meaningOfLife)
+ {
+ this.meaningOfLife = meaningOfLife;
+ }
+}
Added: openwebbeans/trunk/webbeans-impl/src/test/java/org/apache/webbeans/newtests/interceptors/factory/beans/NonInterceptedClass.java
URL: http://svn.apache.org/viewvc/openwebbeans/trunk/webbeans-impl/src/test/java/org/apache/webbeans/newtests/interceptors/factory/beans/NonInterceptedClass.java?rev=1426968&view=auto
==============================================================================
--- openwebbeans/trunk/webbeans-impl/src/test/java/org/apache/webbeans/newtests/interceptors/factory/beans/NonInterceptedClass.java (added)
+++ openwebbeans/trunk/webbeans-impl/src/test/java/org/apache/webbeans/newtests/interceptors/factory/beans/NonInterceptedClass.java Sun Dec 30 17:52:56 2012
@@ -0,0 +1,30 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+package org.apache.webbeans.newtests.interceptors.factory.beans;
+
+/**
+ * A simple class which is not intercepted
+ */
+public class NonInterceptedClass
+{
+ public int getMeaningOfLife()
+ {
+ return 42;
+ }
+}