Return-Path: X-Original-To: apmail-deltaspike-commits-archive@www.apache.org Delivered-To: apmail-deltaspike-commits-archive@www.apache.org Received: from mail.apache.org (hermes.apache.org [140.211.11.3]) by minotaur.apache.org (Postfix) with SMTP id 4A65310214 for ; Thu, 26 Feb 2015 18:21:38 +0000 (UTC) Received: (qmail 37346 invoked by uid 500); 26 Feb 2015 18:21:28 -0000 Delivered-To: apmail-deltaspike-commits-archive@deltaspike.apache.org Received: (qmail 37307 invoked by uid 500); 26 Feb 2015 18:21:28 -0000 Mailing-List: contact commits-help@deltaspike.apache.org; run by ezmlm Precedence: bulk List-Help: List-Unsubscribe: List-Post: List-Id: Reply-To: dev@deltaspike.apache.org Delivered-To: mailing list commits@deltaspike.apache.org Received: (qmail 37229 invoked by uid 99); 26 Feb 2015 18:21:28 -0000 Received: from git1-us-west.apache.org (HELO git1-us-west.apache.org) (140.211.11.23) by apache.org (qpsmtpd/0.29) with ESMTP; Thu, 26 Feb 2015 18:21:28 +0000 Received: by git1-us-west.apache.org (ASF Mail Server at git1-us-west.apache.org, from userid 33) id 73676E0B3E; Thu, 26 Feb 2015 18:21:28 +0000 (UTC) Content-Type: text/plain; charset="us-ascii" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit From: tandraschko@apache.org To: commits@deltaspike.apache.org Date: Thu, 26 Feb 2015 18:21:30 -0000 Message-Id: <782a43e5c9b74999921f7be82e452bde@git.apache.org> In-Reply-To: <4b7caf97c4c4402285d967e5dcde9504@git.apache.org> References: <4b7caf97c4c4402285d967e5dcde9504@git.apache.org> X-Mailer: ASF-Git Admin Mailer Subject: [3/3] deltaspike git commit: DELTASPIKE-823 Removed SPI in favor of manual interceptor implemention DELTASPIKE-823 Removed SPI in favor of manual interceptor implemention Project: http://git-wip-us.apache.org/repos/asf/deltaspike/repo Commit: http://git-wip-us.apache.org/repos/asf/deltaspike/commit/e90019fd Tree: http://git-wip-us.apache.org/repos/asf/deltaspike/tree/e90019fd Diff: http://git-wip-us.apache.org/repos/asf/deltaspike/diff/e90019fd Branch: refs/heads/master Commit: e90019fd902d8218fcb9df0f6c4ee5fc385f748c Parents: 3d457b2 Author: Thomas Andraschko Authored: Thu Feb 26 19:21:17 2015 +0100 Committer: Thomas Andraschko Committed: Thu Feb 26 19:21:17 2015 +0100 ---------------------------------------------------------------------- .../spi/AbstractPartialBeanProvider.java | 43 -- .../partialbean/spi/PartialBeanBuilder.java | 68 ---- .../partialbean/spi/PartialBeanDescriptor.java | 96 ----- .../partialbean/spi/PartialBeanProvider.java | 36 -- .../impl/ASMProxyClassGenerator.java | 354 ---------------- .../impl/PartialBeanBindingExtension.java | 97 +---- .../partialbean/impl/PartialBeanDescriptor.java | 96 +++++ .../partialbean/impl/PartialBeanLifecycle.java | 8 +- .../partialbean/impl/PartialBeanProxy.java | 28 -- .../impl/PartialBeanProxyFactory.java | 210 ---------- .../interception/ManualInvocationContext.java | 194 +++++++++ .../interception/ManualInvocationHandler.java | 107 +++++ ...nualInvocationThrowableWrapperException.java | 31 ++ .../ProceedOriginalMethodException.java | 30 ++ .../impl/proxy/AsmProxyClassGenerator.java | 403 +++++++++++++++++++ .../impl/proxy/PartialBeanProxy.java | 28 ++ .../impl/proxy/PartialBeanProxyFactory.java | 218 ++++++++++ .../partialbean/shared/CustomInterceptor.java | 5 +- .../shared/CustomInterceptorImpl.java | 22 +- .../shared/CustomInterceptorState.java | 37 ++ .../core/api/partialbean/uc001/PartialBean.java | 58 +-- .../PartialBeanAsInterfaceEarFileTest.java | 86 ++-- .../uc001/PartialBeanAsInterfaceTest.java | 80 ++-- .../uc001/TestPartialBeanHandler.java | 127 +++--- .../core/api/partialbean/uc002/PartialBean.java | 112 +++--- .../uc002/PartialBeanAsAbstractClassTest.java | 146 +++---- .../core/api/partialbean/uc003/PartialBean.java | 93 ++--- ...lBeanAsAbstractClassWithInterceptorTest.java | 100 ----- .../api/partialbean/uc003/PartialBeanTest.java | 70 ++++ .../api/partialbean/uc003/SuperInterface.java | 24 ++ .../api/partialbean/uc003/SuperInterface2.java | 24 ++ .../uc003/TestPartialBeanHandler.java | 128 +++--- .../api/partialbean/uc004/AbstractSuper.java | 48 +-- .../uc004/ApplicationScopedPartialBean.java | 74 ++-- .../api/partialbean/uc004/SuperInterface.java | 48 +-- .../api/partialbean/uc005/AbstractSuper.java | 48 +-- .../uc005/ApplicationScopedPartialBean.java | 74 ++-- .../uc005/ScopedPartialBeanTest.java | 166 ++++---- .../api/partialbean/uc005/SuperInterface.java | 48 +-- .../api/partialbean/uc006/AbstractSuper.java | 62 +-- .../partialbean/uc006/AbstractSuperSuper.java | 50 +-- .../uc006/ApplicationScopedPartialBean.java | 72 ++-- .../uc006/ScopedPartialBeanTest.java | 150 +++---- .../uc006/TestPartialBeanHandler.java | 126 +++--- .../uc007/MethodLevelInterceptorTest.java | 101 +++++ .../core/api/partialbean/uc007/PartialBean.java | 102 ++--- ...lBeanAsAbstractClassWithInterceptorTest.java | 86 ---- .../uc007/TestPartialBeanHandler.java | 101 ++--- .../uc007/TestPartialBeanProvider.java | 31 -- .../uc008/ClassLevelInterceptorTest.java | 103 +++++ .../core/api/partialbean/uc008/PartialBean.java | 66 +-- .../api/partialbean/uc008/PartialBeanTest.java | 70 ---- .../api/partialbean/uc008/SuperInterface.java | 24 -- .../api/partialbean/uc008/SuperInterface2.java | 24 -- .../uc008/TestPartialBeanHandler.java | 99 ++--- 55 files changed, 2506 insertions(+), 2426 deletions(-) ---------------------------------------------------------------------- http://git-wip-us.apache.org/repos/asf/deltaspike/blob/e90019fd/deltaspike/modules/partial-bean/api/src/main/java/org/apache/deltaspike/partialbean/spi/AbstractPartialBeanProvider.java ---------------------------------------------------------------------- diff --git a/deltaspike/modules/partial-bean/api/src/main/java/org/apache/deltaspike/partialbean/spi/AbstractPartialBeanProvider.java b/deltaspike/modules/partial-bean/api/src/main/java/org/apache/deltaspike/partialbean/spi/AbstractPartialBeanProvider.java deleted file mode 100644 index 71800cb..0000000 --- a/deltaspike/modules/partial-bean/api/src/main/java/org/apache/deltaspike/partialbean/spi/AbstractPartialBeanProvider.java +++ /dev/null @@ -1,43 +0,0 @@ -/* - * 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.deltaspike.partialbean.spi; - -import java.util.ArrayList; -import java.util.List; - -public abstract class AbstractPartialBeanProvider implements PartialBeanProvider -{ - private final ArrayList descriptors = new ArrayList(); - - @Override - public List get() - { - return descriptors; - } - - protected void add(PartialBeanDescriptor partialBeanDescriptor) - { - descriptors.add(partialBeanDescriptor); - } - - protected void add(PartialBeanBuilder partialBeanBuilder) - { - descriptors.add(partialBeanBuilder.create()); - } -} http://git-wip-us.apache.org/repos/asf/deltaspike/blob/e90019fd/deltaspike/modules/partial-bean/api/src/main/java/org/apache/deltaspike/partialbean/spi/PartialBeanBuilder.java ---------------------------------------------------------------------- diff --git a/deltaspike/modules/partial-bean/api/src/main/java/org/apache/deltaspike/partialbean/spi/PartialBeanBuilder.java b/deltaspike/modules/partial-bean/api/src/main/java/org/apache/deltaspike/partialbean/spi/PartialBeanBuilder.java deleted file mode 100644 index dda52b8..0000000 --- a/deltaspike/modules/partial-bean/api/src/main/java/org/apache/deltaspike/partialbean/spi/PartialBeanBuilder.java +++ /dev/null @@ -1,68 +0,0 @@ -/* - * 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.deltaspike.partialbean.spi; - -import java.lang.annotation.Annotation; -import java.lang.reflect.InvocationHandler; -import java.util.ArrayList; -import java.util.Arrays; - -public class PartialBeanBuilder -{ - private final Class binding; - private final Class handler; - private final ArrayList> classes; - - public PartialBeanBuilder(Class bindingClass, Class handlerClass) - { - this.binding = bindingClass; - this.handler = handlerClass; - - this.classes = new ArrayList>(); - } - - public PartialBeanBuilder(Class bindingClass, Class handlerClass, - Class... classes) - { - this.binding = bindingClass; - this.handler = handlerClass; - - this.classes = new ArrayList>(); - this.classes.addAll(Arrays.asList(classes)); - } - - public PartialBeanBuilder addClass(Class classToAdd) - { - classes.add(classToAdd); - - return this; - } - - public PartialBeanBuilder addClasses(Class... classesToAdd) - { - classes.addAll(Arrays.asList(classesToAdd)); - - return this; - } - - public PartialBeanDescriptor create() - { - return new PartialBeanDescriptor(binding, handler, classes); - } -} http://git-wip-us.apache.org/repos/asf/deltaspike/blob/e90019fd/deltaspike/modules/partial-bean/api/src/main/java/org/apache/deltaspike/partialbean/spi/PartialBeanDescriptor.java ---------------------------------------------------------------------- diff --git a/deltaspike/modules/partial-bean/api/src/main/java/org/apache/deltaspike/partialbean/spi/PartialBeanDescriptor.java b/deltaspike/modules/partial-bean/api/src/main/java/org/apache/deltaspike/partialbean/spi/PartialBeanDescriptor.java deleted file mode 100644 index 19e9f37..0000000 --- a/deltaspike/modules/partial-bean/api/src/main/java/org/apache/deltaspike/partialbean/spi/PartialBeanDescriptor.java +++ /dev/null @@ -1,96 +0,0 @@ -/* - * 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.deltaspike.partialbean.spi; - -import java.lang.annotation.Annotation; -import java.lang.reflect.InvocationHandler; -import java.util.ArrayList; -import java.util.Arrays; -import java.util.List; - -public class PartialBeanDescriptor -{ - private Class binding; - private Class handler; - private List> classes; - - public PartialBeanDescriptor(Class binding) - { - this.binding = binding; - } - - public PartialBeanDescriptor(Class binding, - Class handler) - { - this.binding = binding; - this.handler = handler; - } - - public PartialBeanDescriptor(Class binding, - Class handler, - Class... classes) - { - this.binding = binding; - this.handler = handler; - this.classes = new ArrayList>(); - if (classes.length > 0) - { - this.classes.addAll(Arrays.asList(classes)); - } - } - - public PartialBeanDescriptor(Class binding, - Class handler, - List> classes) - { - this.binding = binding; - this.handler = handler; - this.classes = classes; - } - - public Class getBinding() - { - return binding; - } - - public void setBinding(Class binding) - { - this.binding = binding; - } - - public Class getHandler() - { - return handler; - } - - public void setHandler(Class handler) - { - this.handler = handler; - } - - public List> getClasses() - { - return classes; - } - - public void setClasses(List> classes) - { - this.classes = classes; - } -} http://git-wip-us.apache.org/repos/asf/deltaspike/blob/e90019fd/deltaspike/modules/partial-bean/api/src/main/java/org/apache/deltaspike/partialbean/spi/PartialBeanProvider.java ---------------------------------------------------------------------- diff --git a/deltaspike/modules/partial-bean/api/src/main/java/org/apache/deltaspike/partialbean/spi/PartialBeanProvider.java b/deltaspike/modules/partial-bean/api/src/main/java/org/apache/deltaspike/partialbean/spi/PartialBeanProvider.java deleted file mode 100644 index 04ffc76..0000000 --- a/deltaspike/modules/partial-bean/api/src/main/java/org/apache/deltaspike/partialbean/spi/PartialBeanProvider.java +++ /dev/null @@ -1,36 +0,0 @@ -/* - * 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.deltaspike.partialbean.spi; - -import java.util.List; -import org.apache.deltaspike.core.spi.activation.Deactivatable; - -/** - * The PartialBeanProvider allows to register a partial bean in BeforeBeanDiscovery as a completely new AnnotatedType, - * to enable interceptors on the provided partial beans. - * - * Partial beans which will be collected later in ProcessAnnotatedType can't be intercepted. - * - * If other/new partial beans will be found later via ProcessAnnotatedType, they will be merged with the early provided - * partial beans from the PartialBeanProvider's. - */ -public interface PartialBeanProvider extends Deactivatable -{ - List get(); -} http://git-wip-us.apache.org/repos/asf/deltaspike/blob/e90019fd/deltaspike/modules/partial-bean/impl/src/main/java/org/apache/deltaspike/partialbean/impl/ASMProxyClassGenerator.java ---------------------------------------------------------------------- diff --git a/deltaspike/modules/partial-bean/impl/src/main/java/org/apache/deltaspike/partialbean/impl/ASMProxyClassGenerator.java b/deltaspike/modules/partial-bean/impl/src/main/java/org/apache/deltaspike/partialbean/impl/ASMProxyClassGenerator.java deleted file mode 100644 index f8292dd..0000000 --- a/deltaspike/modules/partial-bean/impl/src/main/java/org/apache/deltaspike/partialbean/impl/ASMProxyClassGenerator.java +++ /dev/null @@ -1,354 +0,0 @@ -/* - * 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.deltaspike.partialbean.impl; - -import java.lang.annotation.Annotation; -import java.lang.reflect.InvocationHandler; -import java.lang.reflect.UndeclaredThrowableException; -import java.util.Arrays; -import javax.enterprise.inject.Typed; -import javax.inject.Inject; -import org.objectweb.asm.ClassWriter; -import org.objectweb.asm.Label; -import org.objectweb.asm.Opcodes; -import org.objectweb.asm.Type; -import org.objectweb.asm.commons.GeneratorAdapter; -import org.objectweb.asm.commons.Method; - -@Typed -public abstract class ASMProxyClassGenerator -{ - private static final String FIELDNAME_HANDLER = "__handler"; - - private static final Type TYPE_CLASS = Type.getType(Class.class); - private static final Type TYPE_OBJECT = Type.getType(Object.class); - - private ASMProxyClassGenerator() - { - // prevent instantiation - } - - public static Class generateProxyClass(ClassLoader classLoader, - Class targetClass, - Class invocationHandlerClass, - String suffix, - java.lang.reflect.Method[] methodsToProxy) - { - String proxyName = targetClass.getCanonicalName() + suffix; - String classFileName = proxyName.replace('.', '/'); - - byte[] proxyBytes = generateProxyClassBytes(targetClass, invocationHandlerClass, - classFileName, methodsToProxy); - Class proxyClass = (Class) loadClass(classLoader, proxyName, proxyBytes); - - return proxyClass; - } - - private static byte[] generateProxyClassBytes(Class targetClass, - Class invocationHandlerClass, - String proxyName, - java.lang.reflect.Method[] methods) - { - Class superClass = targetClass; - String[] interfaces = new String[] { }; - - if (targetClass.isInterface()) - { - superClass = Object.class; - interfaces = new String[] { Type.getInternalName(targetClass) }; - } - - // add PartialBeanProxy as interface - interfaces = Arrays.copyOf(interfaces, interfaces.length + 1); - interfaces[interfaces.length - 1] = Type.getInternalName(PartialBeanProxy.class); - - Type superType = Type.getType(superClass); - Type proxyType = Type.getObjectType(proxyName); - Type invocationHandlerType = Type.getType(invocationHandlerClass); - - ClassWriter cw = new ClassWriter(ClassWriter.COMPUTE_MAXS); - cw.visit(Opcodes.V1_6, Opcodes.ACC_PUBLIC + Opcodes.ACC_SUPER, proxyType.getInternalName(), null, - superType.getInternalName(), interfaces); - - // copy annotations - for (Annotation annotation : targetClass.getDeclaredAnnotations()) - { - cw.visitAnnotation(Type.getDescriptor(annotation.annotationType()), true).visitEnd(); - } - - addInvocationHandlerField(cw, invocationHandlerType); - addDefaultConstructor(cw, proxyType, superType); - addPartialBeanProxyMethods(cw, proxyType, invocationHandlerType); - - for (java.lang.reflect.Method method : methods) - { - overwriteMethod(cw, method, proxyType, invocationHandlerType); - } - - return cw.toByteArray(); - } - - private static void addInvocationHandlerField(ClassWriter cw, Type invocationHandlerType) - { - // generates the following: - // @Inject private MyPartialBeanInvocationHandler __handler; - cw.visitField(Opcodes.ACC_PRIVATE, FIELDNAME_HANDLER, invocationHandlerType.getDescriptor(),null, null) - .visitAnnotation(Type.getDescriptor(Inject.class), true) - .visitEnd(); - } - - private static void addDefaultConstructor(ClassWriter cw, Type proxyType, Type superType) - { - GeneratorAdapter mg = new GeneratorAdapter(Opcodes.ACC_PUBLIC, - new Method("", Type.VOID_TYPE, new Type[]{ }), - null, - null, - cw); - - mg.visitCode(); - - // invoke super constructor - mg.loadThis(); - mg.invokeConstructor(superType, Method.getMethod("void ()")); - - mg.returnValue(); - mg.endMethod(); - mg.visitEnd(); - } - - private static void addPartialBeanProxyMethods(ClassWriter cw, Type proxyType, Type invocationHandlerType) - { - try - { - // implement #setHandler - Method asmMethod = - Method.getMethod(PartialBeanProxy.class.getDeclaredMethod("setHandler", InvocationHandler.class)); - GeneratorAdapter mg = new GeneratorAdapter(Opcodes.ACC_PUBLIC, asmMethod, null, null, cw); - - mg.visitCode(); - - mg.visitVarInsn(Opcodes.ALOAD, 0); - mg.visitVarInsn(Opcodes.ALOAD, 1); - mg.visitTypeInsn(Opcodes.CHECKCAST, invocationHandlerType.getInternalName()); - mg.visitFieldInsn(Opcodes.PUTFIELD, proxyType.getInternalName(), FIELDNAME_HANDLER, - invocationHandlerType.getDescriptor()); - - mg.visitInsn(Opcodes.RETURN); - mg.visitMaxs(2, 1); - mg.visitEnd(); - - - // implement #getHandler - asmMethod = Method.getMethod(PartialBeanProxy.class.getDeclaredMethod("getHandler")); - mg = new GeneratorAdapter(Opcodes.ACC_PUBLIC, asmMethod, null, null, cw); - - mg.visitCode(); - - mg.visitVarInsn(Opcodes.ALOAD, 0); - mg.visitFieldInsn(Opcodes.GETFIELD, proxyType.getInternalName(), FIELDNAME_HANDLER, - invocationHandlerType.getDescriptor()); - - mg.visitInsn(Opcodes.ARETURN); - mg.visitMaxs(2, 1); - mg.visitEnd(); - } - catch (NoSuchMethodException e) - { - throw new IllegalStateException("Unable to implement " + PartialBeanProxy.class.getName(), e); - } - } - - private static void overwriteMethod(ClassWriter cw, java.lang.reflect.Method method, Type proxyType, - Type invocationHandlerType) - { - Type methodType = Type.getType(method); - Type[] exceptionTypes = getTypes(method.getExceptionTypes()); - - // push the method definition - int modifiers = (Opcodes.ACC_PUBLIC | Opcodes.ACC_PROTECTED) & method.getModifiers(); - Method asmMethod = Method.getMethod(method); - GeneratorAdapter mg = new GeneratorAdapter(modifiers, asmMethod, null, exceptionTypes, cw); - - // copy annotations - for (Annotation annotation : method.getDeclaredAnnotations()) - { - mg.visitAnnotation(Type.getDescriptor(annotation.annotationType()), true).visitEnd(); - } - - mg.visitCode(); - - Label tryBlockStart = exceptionTypes.length > 0 ? mg.mark() : null; - - mg.push(Type.getType(method.getDeclaringClass())); - - // the following code generates the bytecode for this line of Java: - // Method method = .class.getMethod("add", new Class[] { }); - // get the method name to invoke, and push to stack - mg.push(method.getName()); - - // create the Class[] - mg.push(methodType.getArgumentTypes().length); - mg.newArray(TYPE_CLASS); - - // push parameters into array - for (int i = 0; i < methodType.getArgumentTypes().length; i++) - { - // keep copy of array on stack - mg.dup(); - - // push index onto stack - mg.push(i); - mg.push(methodType.getArgumentTypes()[i]); - mg.arrayStore(TYPE_CLASS); - } - - // invoke getMethod() with the method name and the array of types - mg.invokeVirtual(TYPE_CLASS, Method.getMethod("java.lang.reflect.Method getDeclaredMethod(String, Class[])")); - - // the following code generates bytecode equivalent to: - // return - // (() invoker.invoke(this, method, new Object[] { Value()]; - mg.loadThis(); - - mg.getField(proxyType, FIELDNAME_HANDLER, invocationHandlerType); - // put below method: - mg.swap(); - - // we want to pass "this" in as the first parameter - mg.loadThis(); - // put below method: - mg.swap(); - - // need to construct the array of objects passed in - // create the Object[] - mg.push(methodType.getArgumentTypes().length); - mg.newArray(TYPE_OBJECT); - - // push parameters into array - for (int i = 0; i < methodType.getArgumentTypes().length; i++) - { - // keep copy of array on stack - mg.dup(); - - // push index onto stack - mg.push(i); - - mg.loadArg(i); - mg.valueOf(methodType.getArgumentTypes()[i]); - mg.arrayStore(TYPE_OBJECT); - } - - // invoke the InvocationHandler - mg.invokeVirtual(invocationHandlerType, - Method.getMethod("Object invoke(Object, java.lang.reflect.Method, Object[])")); - - // cast the result - mg.unbox(methodType.getReturnType()); - - Label tryBlockEnd = exceptionTypes.length > 0 ? mg.mark() : null; - - // push return - mg.returnValue(); - - // build try/catch - if (exceptionTypes.length > 0) - { - Label rethrow = mg.mark(); - mg.visitVarInsn(Opcodes.ASTORE, 1); - mg.visitVarInsn(Opcodes.ALOAD, 1); - mg.visitInsn(Opcodes.ATHROW); - - // catch declared exceptions and rethrow it... - for (Type exceptionType : exceptionTypes) - { - mg.visitTryCatchBlock(tryBlockStart, tryBlockEnd, rethrow, exceptionType.getInternalName()); - } - - // catch Throwable and wrap it with a UndeclaredThrowableException - Type uteType = Type.getType(UndeclaredThrowableException.class); - rethrow = mg.mark(); - mg.visitVarInsn(Opcodes.ASTORE, 1); - mg.newInstance(uteType); - mg.dup(); - mg.visitVarInsn(Opcodes.ALOAD, 1); - mg.invokeConstructor(uteType, - Method.getMethod("void (java.lang.Throwable)")); - mg.visitInsn(Opcodes.ATHROW); - - mg.visitTryCatchBlock(tryBlockStart, tryBlockEnd, rethrow, Type.getInternalName(Throwable.class)); - - mg.endMethod(); - } - - // finish the method - mg.endMethod(); - mg.visitMaxs(10, 10); - mg.visitEnd(); - } - - - private static Type[] getTypes(Class... src) - { - Type[] result = new Type[src.length]; - for (int i = 0; i < result.length; i++) - { - result[i] = Type.getType(src[i]); - } - return result; - } - - /** - * Adapted from http://asm.ow2.org/doc/faq.html#Q5 - * - * @param b - * - * @return Class - */ - private static Class loadClass(ClassLoader loader, String className, byte[] b) - { - // override classDefine (as it is protected) and define the class. - try - { - java.lang.reflect.Method method = ClassLoader.class.getDeclaredMethod( - "defineClass", String.class, byte[].class, int.class, int.class); - - // protected method invocation - boolean accessible = method.isAccessible(); - if (!accessible) - { - method.setAccessible(true); - } - try - { - return (Class) method.invoke(loader, className, b, Integer.valueOf(0), Integer.valueOf(b.length)); - } - finally - { - if (!accessible) - { - method.setAccessible(false); - } - } - } - catch (Exception e) - { - throw e instanceof RuntimeException ? ((RuntimeException) e) : new RuntimeException(e); - } - } -} http://git-wip-us.apache.org/repos/asf/deltaspike/blob/e90019fd/deltaspike/modules/partial-bean/impl/src/main/java/org/apache/deltaspike/partialbean/impl/PartialBeanBindingExtension.java ---------------------------------------------------------------------- diff --git a/deltaspike/modules/partial-bean/impl/src/main/java/org/apache/deltaspike/partialbean/impl/PartialBeanBindingExtension.java b/deltaspike/modules/partial-bean/impl/src/main/java/org/apache/deltaspike/partialbean/impl/PartialBeanBindingExtension.java index 19b7b86..4eff57f 100644 --- a/deltaspike/modules/partial-bean/impl/src/main/java/org/apache/deltaspike/partialbean/impl/PartialBeanBindingExtension.java +++ b/deltaspike/modules/partial-bean/impl/src/main/java/org/apache/deltaspike/partialbean/impl/PartialBeanBindingExtension.java @@ -18,6 +18,7 @@ */ package org.apache.deltaspike.partialbean.impl; +import org.apache.deltaspike.partialbean.impl.proxy.PartialBeanProxyFactory; import java.lang.annotation.Annotation; import java.lang.reflect.InvocationHandler; import java.lang.reflect.Modifier; @@ -35,12 +36,9 @@ import javax.enterprise.inject.spi.Extension; import javax.enterprise.inject.spi.ProcessAnnotatedType; import org.apache.deltaspike.core.spi.activation.Deactivatable; import org.apache.deltaspike.core.util.ClassDeactivationUtils; -import org.apache.deltaspike.core.util.ServiceUtils; import org.apache.deltaspike.core.util.bean.BeanBuilder; import org.apache.deltaspike.core.util.metadata.builder.AnnotatedTypeBuilder; import org.apache.deltaspike.partialbean.api.PartialBeanBinding; -import org.apache.deltaspike.partialbean.spi.PartialBeanDescriptor; -import org.apache.deltaspike.partialbean.spi.PartialBeanProvider; public class PartialBeanBindingExtension implements Extension, Deactivatable { @@ -53,85 +51,7 @@ public class PartialBeanBindingExtension implements Extension, Deactivatable protected void init(@Observes BeforeBeanDiscovery beforeBeanDiscovery) { - this.isActivated = ClassDeactivationUtils.isActivated(getClass()); - - if (!this.isActivated) - { - return; - } - - List providers = ServiceUtils.loadServiceImplementations(PartialBeanProvider.class); - for (PartialBeanProvider provider : providers) - { - for (PartialBeanDescriptor descriptor : provider.get()) - { - if (descriptors.containsKey(descriptor.getBinding())) - { - PartialBeanDescriptor existingDescriptor = descriptors.get(descriptor.getBinding()); - - // check if multiple handlers are defined for the same binding - if ((descriptor.getHandler() != null - && descriptor.getHandler().equals(existingDescriptor.getHandler())) - || (existingDescriptor.getHandler() != null - && existingDescriptor.getHandler().equals(descriptor.getHandler()))) - { - this.definitionError = new IllegalStateException("Multiple handlers found for " - + descriptor.getBinding().getName() + " (" - + descriptor.getHandler().getName() + " and " - + existingDescriptor.getHandler().getName() + ")"); - return; - } - - if (existingDescriptor.getClasses() == null) - { - existingDescriptor.setClasses(new ArrayList>()); - } - - // merge bean classes - if (descriptor.getClasses() != null && descriptor.getClasses().size() > 0) - { - existingDescriptor.getClasses().addAll(descriptor.getClasses()); - } - } - else - { - descriptors.put(descriptor.getBinding(), descriptor); - } - } - } - - // loop early partial beans and register them via a new annotated type for the proxy - // this enables interceptors on the early provided partial beans - for (Map.Entry, PartialBeanDescriptor> entry : this.descriptors.entrySet()) - { - PartialBeanDescriptor descriptor = entry.getValue(); - if (descriptor.getClasses() != null) - { - for (Class partialBeanClass : descriptor.getClasses()) - { - // skip - if (alreadyProxied.contains(partialBeanClass)) - { - continue; - } - - // handler currently not defined - skip early partial bean process - // later if the handler is still null, we will throw a definition error - if (descriptor.getHandler() == null) - { - continue; - } - - Class partialBeanProxyClass = - PartialBeanProxyFactory.getProxyClass(partialBeanClass, descriptor.getHandler()); - AnnotatedType annotatedType = - new AnnotatedTypeBuilder().readFromType(partialBeanProxyClass).create(); - beforeBeanDiscovery.addAnnotatedType(annotatedType); - - alreadyProxied.add(partialBeanClass); - } - } - } + this.isActivated = ClassDeactivationUtils.isActivated(getClass()); } public void findInvocationHandlerBindings(@Observes ProcessAnnotatedType pat, BeanManager beanManager) @@ -160,12 +80,6 @@ public class PartialBeanBindingExtension implements Extension, Deactivatable { pat.veto(); - // skip already proxied beans - if (alreadyProxied.contains(beanClass)) - { - return; - } - PartialBeanDescriptor descriptor = descriptors.get(bindingClass); if (descriptor == null) @@ -236,17 +150,10 @@ public class PartialBeanBindingExtension implements Extension, Deactivatable { for (Class partialBeanClass : descriptor.getClasses()) { - // skip already/early proxied beans - if (alreadyProxied.contains(partialBeanClass)) - { - continue; - } - Bean partialBean = createPartialBean(partialBeanClass, descriptor, afterBeanDiscovery, beanManager); if (partialBean != null) { afterBeanDiscovery.addBean(partialBean); - alreadyProxied.add(partialBeanClass); } } } http://git-wip-us.apache.org/repos/asf/deltaspike/blob/e90019fd/deltaspike/modules/partial-bean/impl/src/main/java/org/apache/deltaspike/partialbean/impl/PartialBeanDescriptor.java ---------------------------------------------------------------------- diff --git a/deltaspike/modules/partial-bean/impl/src/main/java/org/apache/deltaspike/partialbean/impl/PartialBeanDescriptor.java b/deltaspike/modules/partial-bean/impl/src/main/java/org/apache/deltaspike/partialbean/impl/PartialBeanDescriptor.java new file mode 100644 index 0000000..02bb098 --- /dev/null +++ b/deltaspike/modules/partial-bean/impl/src/main/java/org/apache/deltaspike/partialbean/impl/PartialBeanDescriptor.java @@ -0,0 +1,96 @@ +/* + * 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.deltaspike.partialbean.impl; + +import java.lang.annotation.Annotation; +import java.lang.reflect.InvocationHandler; +import java.util.ArrayList; +import java.util.Arrays; +import java.util.List; + +public class PartialBeanDescriptor +{ + private Class binding; + private Class handler; + private List> classes; + + public PartialBeanDescriptor(Class binding) + { + this.binding = binding; + } + + public PartialBeanDescriptor(Class binding, + Class handler) + { + this.binding = binding; + this.handler = handler; + } + + public PartialBeanDescriptor(Class binding, + Class handler, + Class... classes) + { + this.binding = binding; + this.handler = handler; + this.classes = new ArrayList>(); + if (classes.length > 0) + { + this.classes.addAll(Arrays.asList(classes)); + } + } + + public PartialBeanDescriptor(Class binding, + Class handler, + List> classes) + { + this.binding = binding; + this.handler = handler; + this.classes = classes; + } + + public Class getBinding() + { + return binding; + } + + public void setBinding(Class binding) + { + this.binding = binding; + } + + public Class getHandler() + { + return handler; + } + + public void setHandler(Class handler) + { + this.handler = handler; + } + + public List> getClasses() + { + return classes; + } + + public void setClasses(List> classes) + { + this.classes = classes; + } +} http://git-wip-us.apache.org/repos/asf/deltaspike/blob/e90019fd/deltaspike/modules/partial-bean/impl/src/main/java/org/apache/deltaspike/partialbean/impl/PartialBeanLifecycle.java ---------------------------------------------------------------------- diff --git a/deltaspike/modules/partial-bean/impl/src/main/java/org/apache/deltaspike/partialbean/impl/PartialBeanLifecycle.java b/deltaspike/modules/partial-bean/impl/src/main/java/org/apache/deltaspike/partialbean/impl/PartialBeanLifecycle.java index 9d2a229..dc05a02 100644 --- a/deltaspike/modules/partial-bean/impl/src/main/java/org/apache/deltaspike/partialbean/impl/PartialBeanLifecycle.java +++ b/deltaspike/modules/partial-bean/impl/src/main/java/org/apache/deltaspike/partialbean/impl/PartialBeanLifecycle.java @@ -18,6 +18,8 @@ */ package org.apache.deltaspike.partialbean.impl; +import org.apache.deltaspike.partialbean.impl.proxy.PartialBeanProxyFactory; +import org.apache.deltaspike.partialbean.impl.proxy.PartialBeanProxy; import org.apache.deltaspike.core.util.ExceptionUtils; import org.apache.deltaspike.core.util.metadata.builder.ContextualLifecycle; @@ -63,8 +65,7 @@ class PartialBeanLifecycle implements Contextual { T instance = proxyClass.newInstance(); - // only required here, for early partial beans, the handler will be injected and handled by CDI - ((PartialBeanProxy) instance).setHandler(createHandlerInstance()); + ((PartialBeanProxy) instance).setRedirectInvocationHandler(createHandlerInstance()); if (this.injectionTarget != null) { @@ -130,7 +131,7 @@ class PartialBeanLifecycle implements Contextual CreationalContext creationalContext = beanManager.createCreationalContext(handlerBean); H handlerInstance = (H) beanManager.getReference(handlerBean, this.handlerClass, creationalContext); - + if (handlerBean.getScope().equals(Dependent.class)) { this.creationalContextOfDependentHandler = creationalContext; @@ -139,4 +140,3 @@ class PartialBeanLifecycle implements Contextual return handlerInstance; } } - http://git-wip-us.apache.org/repos/asf/deltaspike/blob/e90019fd/deltaspike/modules/partial-bean/impl/src/main/java/org/apache/deltaspike/partialbean/impl/PartialBeanProxy.java ---------------------------------------------------------------------- diff --git a/deltaspike/modules/partial-bean/impl/src/main/java/org/apache/deltaspike/partialbean/impl/PartialBeanProxy.java b/deltaspike/modules/partial-bean/impl/src/main/java/org/apache/deltaspike/partialbean/impl/PartialBeanProxy.java deleted file mode 100644 index e7ddbf2..0000000 --- a/deltaspike/modules/partial-bean/impl/src/main/java/org/apache/deltaspike/partialbean/impl/PartialBeanProxy.java +++ /dev/null @@ -1,28 +0,0 @@ -/* - * 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.deltaspike.partialbean.impl; - -import java.lang.reflect.InvocationHandler; - -public interface PartialBeanProxy -{ - void setHandler(InvocationHandler handler); - - InvocationHandler getHandler(); -} http://git-wip-us.apache.org/repos/asf/deltaspike/blob/e90019fd/deltaspike/modules/partial-bean/impl/src/main/java/org/apache/deltaspike/partialbean/impl/PartialBeanProxyFactory.java ---------------------------------------------------------------------- diff --git a/deltaspike/modules/partial-bean/impl/src/main/java/org/apache/deltaspike/partialbean/impl/PartialBeanProxyFactory.java b/deltaspike/modules/partial-bean/impl/src/main/java/org/apache/deltaspike/partialbean/impl/PartialBeanProxyFactory.java deleted file mode 100644 index f52f7c4..0000000 --- a/deltaspike/modules/partial-bean/impl/src/main/java/org/apache/deltaspike/partialbean/impl/PartialBeanProxyFactory.java +++ /dev/null @@ -1,210 +0,0 @@ -/* - * 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.deltaspike.partialbean.impl; - -import java.lang.reflect.InvocationHandler; -import java.lang.reflect.Method; -import java.lang.reflect.Modifier; -import java.util.ArrayList; -import java.util.Arrays; -import java.util.Iterator; -import java.util.List; -import javax.enterprise.inject.Typed; -import org.apache.deltaspike.core.util.ClassUtils; - -@Typed -public abstract class PartialBeanProxyFactory -{ - private static final String CLASSNAME_SUFFIX = "$$DSPartialBeanProxy"; - - private PartialBeanProxyFactory() - { - // prevent instantiation - } - - public static Class getProxyClass(Class targetClass, - Class invocationHandlerClass) - { - Class proxyClass = ClassUtils.tryToLoadClassForName(constructProxyClassName(targetClass), targetClass); - if (proxyClass == null) - { - proxyClass = createProxyClass(targetClass.getClassLoader(), targetClass, invocationHandlerClass); - } - - return proxyClass; - } - - private static synchronized Class createProxyClass(ClassLoader classLoader, Class targetClass, - Class invocationHandlerClass) - { - Class proxyClass = ClassUtils.tryToLoadClassForName(constructProxyClassName(targetClass), targetClass); - if (proxyClass == null) - { - proxyClass = ASMProxyClassGenerator.generateProxyClass(classLoader, - targetClass, - invocationHandlerClass, - CLASSNAME_SUFFIX, - findNotImplementedMethods(targetClass)); - } - - return proxyClass; - } - - private static String constructProxyClassName(Class clazz) - { - return clazz.getCanonicalName() + CLASSNAME_SUFFIX; - } - - /** - * Checks if the given class is partial bean proxy class. - * - * @param clazz - * @return - */ - public static boolean isProxyClass(Class clazz) - { - return clazz.getName().endsWith(CLASSNAME_SUFFIX); - } - - /** - * Collects all abstract methods which needs to be proxied from the given class and super classes... - * - * @param clazz The clazz which will be proxied. - * @return All abstract methods. - */ - private static Method[] findNotImplementedMethods(Class clazz) - { - List methods = new ArrayList(); - for (Method method : clazz.getDeclaredMethods()) - { - if (!containsMethodWithSameSignature(method, methods)) - { - methods.add(method); - } - } - for (Method method : clazz.getMethods()) - { - if (!containsMethodWithSameSignature(method, methods)) - { - methods.add(method); - } - } - - // collect methods from abstract super classes... - Class currentSuperClass = clazz.getSuperclass(); - while (currentSuperClass != null) - { - if (Modifier.isAbstract(currentSuperClass.getModifiers())) - { - for (Method method : currentSuperClass.getDeclaredMethods()) - { - if (!containsMethodWithSameSignature(method, methods)) - { - methods.add(method); - } - } - for (Method method : currentSuperClass.getMethods()) - { - if (!containsMethodWithSameSignature(method, methods)) - { - methods.add(method); - } - } - } - currentSuperClass = currentSuperClass.getSuperclass(); - } - - // sort out invalid methods - Iterator it = methods.iterator(); - while (it.hasNext()) - { - Method method = it.next(); - - if (method.isBridge()) - { - // we have no interest in generics bridge methods - it.remove(); - } - - if (!Modifier.isAbstract(method.getModifiers())) - { - it.remove(); - } - - if ("finalize".equals(method.getName())) - { - // we do not proxy finalize() - it.remove(); - } - } - - // sort out somewhere implemented abstract methods - Class currentClass = clazz; - while (currentClass != null) - { - Iterator methodIterator = methods.iterator(); - while (methodIterator.hasNext()) - { - Method method = methodIterator.next(); - try - { - Method foundMethod = currentClass.getMethod(method.getName(), method.getParameterTypes()); - // if method is implementent in the current class -> remove it - if (foundMethod != null && !Modifier.isAbstract(foundMethod.getModifiers())) - { - methodIterator.remove(); - } - } - catch (Exception e) - { - // ignore... - } - } - - currentClass = currentClass.getSuperclass(); - } - - return methods.toArray(new Method[methods.size()]); - } - - private static boolean containsMethodWithSameSignature(Method method, List methods) - { - if (methods.contains(method)) - { - return true; - } - - for (Method currentMethod : methods) - { - if (hasSameSignature(currentMethod, method)) - { - return true; - } - } - - return false; - } - - private static boolean hasSameSignature(Method a, Method b) - { - return a.getName().equals(b.getName()) - && a.getReturnType().equals(b.getReturnType()) - && Arrays.equals(a.getParameterTypes(), b.getParameterTypes()); - } -} http://git-wip-us.apache.org/repos/asf/deltaspike/blob/e90019fd/deltaspike/modules/partial-bean/impl/src/main/java/org/apache/deltaspike/partialbean/impl/interception/ManualInvocationContext.java ---------------------------------------------------------------------- diff --git a/deltaspike/modules/partial-bean/impl/src/main/java/org/apache/deltaspike/partialbean/impl/interception/ManualInvocationContext.java b/deltaspike/modules/partial-bean/impl/src/main/java/org/apache/deltaspike/partialbean/impl/interception/ManualInvocationContext.java new file mode 100644 index 0000000..dee3751 --- /dev/null +++ b/deltaspike/modules/partial-bean/impl/src/main/java/org/apache/deltaspike/partialbean/impl/interception/ManualInvocationContext.java @@ -0,0 +1,194 @@ +/* + * 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.deltaspike.partialbean.impl.interception; + +import java.lang.reflect.Constructor; +import java.lang.reflect.Method; +import java.util.HashMap; +import java.util.List; +import java.util.Map; +import javax.enterprise.context.spi.CreationalContext; +import javax.enterprise.inject.Typed; +import javax.enterprise.inject.spi.InterceptionType; +import javax.enterprise.inject.spi.Interceptor; +import javax.interceptor.InvocationContext; +import org.apache.deltaspike.core.api.provider.BeanManagerProvider; + +@Typed +public class ManualInvocationContext implements InvocationContext +{ + protected List> interceptors; + protected int interceptorIndex; + protected T target; + protected Method method; + protected Object[] parameters; + protected Map contextData; + protected Object timer; + protected ManualInvocationHandler manualInvocationHandler; + + public ManualInvocationContext(ManualInvocationHandler manualInvocationHandler, + List> interceptors, T target, Method method, Object[] parameters, Object timer) + { + this.manualInvocationHandler = manualInvocationHandler; + this.interceptors = interceptors; + this.target = target; + this.method = method; + this.parameters = parameters; + this.timer = timer; + + this.interceptorIndex = 0; + } + + @Override + public Object getTarget() + { + return target; + } + + @Override + public Method getMethod() + { + return method; + } + + @Override + public Object[] getParameters() + { + return parameters; + } + + @Override + public void setParameters(Object[] os) + { + parameters = os; + } + + @Override + public Map getContextData() + { + if (contextData == null) + { + contextData = new HashMap(); + } + return contextData; + } + + @Override + public Object proceed() throws Exception + { + if (interceptors.size() > interceptorIndex) + { + Interceptor interceptor = null; + CreationalContext creationalContext = null; + H interceptorInstance = null; + + try + { + interceptor = + interceptors.get(interceptorIndex++); + creationalContext = + BeanManagerProvider.getInstance().getBeanManager().createCreationalContext(interceptor); + interceptorInstance = + interceptor.create(creationalContext); + + Object value = interceptor.intercept(InterceptionType.AROUND_INVOKE, interceptorInstance, this); + return value; + } + catch (Exception e) + { + ProceedOriginalMethodException proceedOriginalMethodException = + extractProceedOriginalMethodException(e); + if (proceedOriginalMethodException != null) + { + try + { + return manualInvocationHandler.proceedOriginal(target, method, parameters); + } + catch (Throwable t) + { + // wrap it to rethrow the original Throwable later + throw new ManualInvocationThrowableWrapperException(t); + } + } + + throw e; + } + finally + { + if (creationalContext != null) + { + if (interceptorInstance != null && interceptor != null) + { + interceptor.destroy(interceptorInstance, creationalContext); + } + + creationalContext.release(); + } + } + } + + // all interceptors handled without return a value + try + { + Object value = manualInvocationHandler.proceedOriginal(target, method, parameters); + return value; + } + catch (Exception e) + { + throw e; + } + catch (Throwable t) + { + // wrap it to rethrow the original Throwable later + throw new ManualInvocationThrowableWrapperException(t); + } + } + + protected ProceedOriginalMethodException extractProceedOriginalMethodException(Throwable throwable) + { + if (throwable instanceof ProceedOriginalMethodException) + { + return (ProceedOriginalMethodException) throwable; + } + + while (throwable.getCause() != null) + { + throwable = throwable.getCause(); + if (throwable instanceof ProceedOriginalMethodException) + { + return (ProceedOriginalMethodException) throwable; + } + } + + return null; + } + + @Override + public Object getTimer() + { + return timer; + } + + // @Override + // CDI 1.1 compatibility + public Constructor getConstructor() + { + return null; + } +} http://git-wip-us.apache.org/repos/asf/deltaspike/blob/e90019fd/deltaspike/modules/partial-bean/impl/src/main/java/org/apache/deltaspike/partialbean/impl/interception/ManualInvocationHandler.java ---------------------------------------------------------------------- diff --git a/deltaspike/modules/partial-bean/impl/src/main/java/org/apache/deltaspike/partialbean/impl/interception/ManualInvocationHandler.java b/deltaspike/modules/partial-bean/impl/src/main/java/org/apache/deltaspike/partialbean/impl/interception/ManualInvocationHandler.java new file mode 100644 index 0000000..78776b0 --- /dev/null +++ b/deltaspike/modules/partial-bean/impl/src/main/java/org/apache/deltaspike/partialbean/impl/interception/ManualInvocationHandler.java @@ -0,0 +1,107 @@ +/* + * 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.deltaspike.partialbean.impl.interception; + +import java.lang.annotation.Annotation; +import java.lang.reflect.InvocationHandler; +import java.lang.reflect.Method; +import java.util.ArrayList; +import java.util.List; +import javax.enterprise.inject.Typed; +import javax.enterprise.inject.spi.BeanManager; +import javax.enterprise.inject.spi.InterceptionType; +import javax.enterprise.inject.spi.Interceptor; +import javax.interceptor.InterceptorBinding; +import org.apache.deltaspike.core.api.provider.BeanManagerProvider; + +@Typed +public class ManualInvocationHandler implements InvocationHandler +{ + private static final ManualInvocationHandler INSTANCE = new ManualInvocationHandler(); + + public static Object staticInvoke(T proxy, Method method, Object[] parameters) throws Throwable + { + return INSTANCE.invoke(proxy, method, parameters); + } + + @Override + public Object invoke(Object proxy, Method method, Object[] parameters) throws Throwable + { + List> interceptors = resolveInterceptors(proxy, method); + if (interceptors != null && interceptors.size() > 0) + { + try + { + ManualInvocationContext invocationContext = + new ManualInvocationContext(this, interceptors, proxy, method, parameters, null); + return invocationContext.proceed(); + } + catch (ManualInvocationThrowableWrapperException e) + { + // unwrap + throw e.getCause(); + } + } + + return proceedOriginal(proxy, method, parameters); + } + + protected Object proceedOriginal(Object proxy, Method method, Object[] parameters) throws Throwable + { + throw new ProceedOriginalMethodException(); + } + + protected List> resolveInterceptors(Object instance, Method method) + { + Annotation[] interceptorBindings = extractInterceptorBindings(instance, method); + if (interceptorBindings.length > 0) + { + BeanManager beanManager = BeanManagerProvider.getInstance().getBeanManager(); + return beanManager.resolveInterceptors(InterceptionType.AROUND_INVOKE, + interceptorBindings); + } + + return null; + } + + protected Annotation[] extractInterceptorBindings(Object instance, Method method) + { + ArrayList bindings = new ArrayList(); + + for (Annotation annotation : instance.getClass().getDeclaredAnnotations()) + { + if (annotation.annotationType().isAnnotationPresent(InterceptorBinding.class) + && !bindings.contains(annotation)) + { + bindings.add(annotation); + } + } + + for (Annotation annotation : method.getDeclaredAnnotations()) + { + if (annotation.annotationType().isAnnotationPresent(InterceptorBinding.class) + && !bindings.contains(annotation)) + { + bindings.add(annotation); + } + } + + return bindings.toArray(new Annotation[bindings.size()]); + } +} http://git-wip-us.apache.org/repos/asf/deltaspike/blob/e90019fd/deltaspike/modules/partial-bean/impl/src/main/java/org/apache/deltaspike/partialbean/impl/interception/ManualInvocationThrowableWrapperException.java ---------------------------------------------------------------------- diff --git a/deltaspike/modules/partial-bean/impl/src/main/java/org/apache/deltaspike/partialbean/impl/interception/ManualInvocationThrowableWrapperException.java b/deltaspike/modules/partial-bean/impl/src/main/java/org/apache/deltaspike/partialbean/impl/interception/ManualInvocationThrowableWrapperException.java new file mode 100644 index 0000000..1b28b2b --- /dev/null +++ b/deltaspike/modules/partial-bean/impl/src/main/java/org/apache/deltaspike/partialbean/impl/interception/ManualInvocationThrowableWrapperException.java @@ -0,0 +1,31 @@ +/* + * 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.deltaspike.partialbean.impl.interception; + +/** + * Wrapper for {@link Throwable}s because the highest exception of + * {@link javax.interceptor.InvocationContext#proceed()} is a {@link Exception}. + */ +public class ManualInvocationThrowableWrapperException extends RuntimeException +{ + public ManualInvocationThrowableWrapperException(Throwable e) + { + super(e); + } +} http://git-wip-us.apache.org/repos/asf/deltaspike/blob/e90019fd/deltaspike/modules/partial-bean/impl/src/main/java/org/apache/deltaspike/partialbean/impl/interception/ProceedOriginalMethodException.java ---------------------------------------------------------------------- diff --git a/deltaspike/modules/partial-bean/impl/src/main/java/org/apache/deltaspike/partialbean/impl/interception/ProceedOriginalMethodException.java b/deltaspike/modules/partial-bean/impl/src/main/java/org/apache/deltaspike/partialbean/impl/interception/ProceedOriginalMethodException.java new file mode 100644 index 0000000..40021e2 --- /dev/null +++ b/deltaspike/modules/partial-bean/impl/src/main/java/org/apache/deltaspike/partialbean/impl/interception/ProceedOriginalMethodException.java @@ -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.deltaspike.partialbean.impl.interception; + +import java.io.Serializable; + +/** + * Exception which will be throewd by the {@link ManualInvocationContext} if all interecptors + * are successfully handled and the original method should be called. + */ +public class ProceedOriginalMethodException extends RuntimeException implements Serializable +{ + +} \ No newline at end of file http://git-wip-us.apache.org/repos/asf/deltaspike/blob/e90019fd/deltaspike/modules/partial-bean/impl/src/main/java/org/apache/deltaspike/partialbean/impl/proxy/AsmProxyClassGenerator.java ---------------------------------------------------------------------- diff --git a/deltaspike/modules/partial-bean/impl/src/main/java/org/apache/deltaspike/partialbean/impl/proxy/AsmProxyClassGenerator.java b/deltaspike/modules/partial-bean/impl/src/main/java/org/apache/deltaspike/partialbean/impl/proxy/AsmProxyClassGenerator.java new file mode 100644 index 0000000..96ce418 --- /dev/null +++ b/deltaspike/modules/partial-bean/impl/src/main/java/org/apache/deltaspike/partialbean/impl/proxy/AsmProxyClassGenerator.java @@ -0,0 +1,403 @@ +/* + * 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.deltaspike.partialbean.impl.proxy; + +import java.lang.annotation.Annotation; +import java.lang.reflect.InvocationHandler; +import java.lang.reflect.UndeclaredThrowableException; +import java.util.Arrays; +import javax.enterprise.inject.Typed; +import org.apache.deltaspike.partialbean.impl.interception.ManualInvocationHandler; +import org.apache.deltaspike.partialbean.impl.interception.ProceedOriginalMethodException; +import org.objectweb.asm.ClassWriter; +import org.objectweb.asm.Label; +import org.objectweb.asm.Opcodes; +import org.objectweb.asm.Type; +import org.objectweb.asm.commons.GeneratorAdapter; +import org.objectweb.asm.commons.Method; + +@Typed +public abstract class AsmProxyClassGenerator +{ + private static final String FIELDNAME_HANDLER = "__handler"; + + private static final Type TYPE_CLASS = Type.getType(Class.class); + private static final Type TYPE_OBJECT = Type.getType(Object.class); + + private AsmProxyClassGenerator() + { + // prevent instantiation + } + + public static Class generateProxyClass(ClassLoader classLoader, + Class targetClass, + Class invocationHandlerClass, + String suffix, + java.lang.reflect.Method[] redirectMethods, + java.lang.reflect.Method[] interceptionMethods) + { + String proxyName = targetClass.getCanonicalName() + suffix; + String classFileName = proxyName.replace('.', '/'); + + byte[] proxyBytes = generateProxyClassBytes(targetClass, invocationHandlerClass, + classFileName, redirectMethods, interceptionMethods); + Class proxyClass = (Class) loadClass(classLoader, proxyName, proxyBytes); + + return proxyClass; + } + + private static byte[] generateProxyClassBytes(Class targetClass, + Class invocationHandlerClass, + String proxyName, + java.lang.reflect.Method[] redirectMethods, + java.lang.reflect.Method[] interceptionMethods) + { + Class superClass = targetClass; + String[] interfaces = new String[] { }; + + if (targetClass.isInterface()) + { + superClass = Object.class; + interfaces = new String[] { Type.getInternalName(targetClass) }; + } + + // add PartialBeanProxy as interface + interfaces = Arrays.copyOf(interfaces, interfaces.length + 1); + interfaces[interfaces.length - 1] = Type.getInternalName(PartialBeanProxy.class); + + Type superType = Type.getType(superClass); + Type proxyType = Type.getObjectType(proxyName); + Type invocationHandlerType = Type.getType(invocationHandlerClass); + + ClassWriter cw = new ClassWriter(ClassWriter.COMPUTE_MAXS); + cw.visit(Opcodes.V1_6, Opcodes.ACC_PUBLIC + Opcodes.ACC_SUPER, proxyType.getInternalName(), null, + superType.getInternalName(), interfaces); + + // copy annotations + for (Annotation annotation : targetClass.getDeclaredAnnotations()) + { + cw.visitAnnotation(Type.getDescriptor(annotation.annotationType()), true).visitEnd(); + } + + defineInvocationHandlerField(cw, invocationHandlerType); + defineConstructor(cw, proxyType, superType); + definePartialBeanProxyMethods(cw, proxyType, invocationHandlerType); + + for (java.lang.reflect.Method method : redirectMethods) + { + defineMethod(cw, method, proxyType, invocationHandlerType, superType, true); + } + + for (java.lang.reflect.Method method : interceptionMethods) + { + defineMethod(cw, method, proxyType, invocationHandlerType, superType, false); + } + + return cw.toByteArray(); + } + + private static void defineInvocationHandlerField(ClassWriter cw, Type invocationHandlerType) + { + // generates + // private MyPartialBeanInvocationHandler __handler; + cw.visitField(Opcodes.ACC_PRIVATE, FIELDNAME_HANDLER, invocationHandlerType.getDescriptor(), null, null) + .visitEnd(); + } + + private static void defineConstructor(ClassWriter cw, Type proxyType, Type superType) + { + GeneratorAdapter mg = new GeneratorAdapter(Opcodes.ACC_PUBLIC, + new Method("", Type.VOID_TYPE, new Type[]{ }), + null, + null, + cw); + + mg.visitCode(); + + // invoke super constructor + mg.loadThis(); + mg.invokeConstructor(superType, Method.getMethod("void ()")); + mg.returnValue(); + mg.endMethod(); + + mg.visitEnd(); + } + + private static void definePartialBeanProxyMethods(ClassWriter cw, Type proxyType, Type invocationHandlerType) + { + try + { + // implement #setRedirectInvocationHandler + Method asmMethod = Method.getMethod( + PartialBeanProxy.class.getDeclaredMethod("setRedirectInvocationHandler", + InvocationHandler.class)); + GeneratorAdapter mg = new GeneratorAdapter(Opcodes.ACC_PUBLIC, asmMethod, null, null, cw); + + mg.visitCode(); + + mg.loadThis(); + mg.loadArg(0); + mg.checkCast(invocationHandlerType); + mg.putField(proxyType, FIELDNAME_HANDLER, invocationHandlerType); + mg.returnValue(); + + mg.visitMaxs(2, 1); + mg.visitEnd(); + + + // implement #getRedirectInvocationHandler + asmMethod = Method.getMethod(PartialBeanProxy.class.getDeclaredMethod("getRedirectInvocationHandler")); + mg = new GeneratorAdapter(Opcodes.ACC_PUBLIC, asmMethod, null, null, cw); + + mg.visitCode(); + + mg.loadThis(); + mg.getField(proxyType, FIELDNAME_HANDLER, invocationHandlerType); + mg.returnValue(); + + mg.visitMaxs(2, 1); + mg.visitEnd(); + } + catch (NoSuchMethodException e) + { + throw new IllegalStateException("Unable to implement " + PartialBeanProxy.class.getName(), e); + } + } + + private static void defineMethod(ClassWriter cw, java.lang.reflect.Method method, Type proxyType, + Type invocationHandlerType, Type superType, boolean callInvocationHandler) + { + Type methodType = Type.getType(method); + Type[] exceptionTypes = getTypes(method.getExceptionTypes()); + + // push the method definition + int modifiers = (Opcodes.ACC_PUBLIC | Opcodes.ACC_PROTECTED) & method.getModifiers(); + Method asmMethod = Method.getMethod(method); + GeneratorAdapter mg = new GeneratorAdapter(modifiers, asmMethod, null, exceptionTypes, cw); + + // copy annotations + for (Annotation annotation : method.getDeclaredAnnotations()) + { + mg.visitAnnotation(Type.getDescriptor(annotation.annotationType()), true).visitEnd(); + } + + mg.visitCode(); + + Label tryBlockStart = mg.mark(); + + mg.loadThis(); + loadCurrentMethod(mg, method, methodType); + loadArguments(mg, method, methodType); + + // invoke our ProxyInvocationHandler + mg.invokeStatic(Type.getType(ManualInvocationHandler.class), + Method.getMethod("Object staticInvoke(Object, java.lang.reflect.Method, Object[])")); + + // cast the result + mg.unbox(methodType.getReturnType()); + + Label tryBlockEnd = mg.mark(); + + // push return + mg.returnValue(); + + boolean throwableCatched = false; + + // catch ProceedOriginalRuntimeException + Label proceedOriginal = mg.mark(); + if (callInvocationHandler) + { + mg.loadThis(); + mg.getField(proxyType, FIELDNAME_HANDLER, invocationHandlerType); + mg.loadThis(); + loadCurrentMethod(mg, method, methodType); + loadArguments(mg, method, methodType); + mg.invokeVirtual(invocationHandlerType, + Method.getMethod("Object invoke(Object, java.lang.reflect.Method, Object[])")); + mg.unbox(methodType.getReturnType()); + mg.returnValue(); + } + else + { + mg.loadThis(); + mg.loadArgs(); + mg.visitMethodInsn(Opcodes.INVOKESPECIAL, + superType.getInternalName(), + method.getName(), + Type.getMethodDescriptor(method), + false); + mg.returnValue(); + } + mg.visitTryCatchBlock(tryBlockStart, tryBlockEnd, proceedOriginal, + Type.getInternalName(ProceedOriginalMethodException.class)); + + // catch declared exceptions + if (exceptionTypes.length > 0) + { + Label rethrow = mg.mark(); + mg.visitVarInsn(Opcodes.ASTORE, 1); + mg.visitVarInsn(Opcodes.ALOAD, 1); + mg.throwException(); + + // catch declared exceptions and rethrow it... + for (Type exceptionType : exceptionTypes) + { + if (exceptionType.getClassName().equals(Throwable.class.getName())) + { + throwableCatched = true; + } + mg.visitTryCatchBlock(tryBlockStart, tryBlockEnd, rethrow, exceptionType.getInternalName()); + } + } + + if (!throwableCatched) + { + // catch Throwable and wrap it with a UndeclaredThrowableException + Type uteType = Type.getType(UndeclaredThrowableException.class); + Label wrapAndRethrow = mg.mark(); + + mg.visitVarInsn(Opcodes.ASTORE, 1); + mg.newInstance(uteType); + mg.dup(); + mg.visitVarInsn(Opcodes.ALOAD, 1); + mg.invokeConstructor(uteType, + Method.getMethod("void (java.lang.Throwable)")); + mg.throwException(); + + mg.visitTryCatchBlock(tryBlockStart, tryBlockEnd, wrapAndRethrow, Type.getInternalName(Throwable.class)); + } + + // finish the method + mg.endMethod(); + mg.visitMaxs(10, 10); + mg.visitEnd(); + } + + /** + * Generates: + *
+     * Method method =
+     *      method.getDeclaringClass().getMethod("methodName", new Class[] { args... });
+     * 
+ * @param mg + * @param method + * @param methodType + */ + private static void loadCurrentMethod(GeneratorAdapter mg, java.lang.reflect.Method method, Type methodType) + { + mg.push(Type.getType(method.getDeclaringClass())); + mg.push(method.getName()); + + // create the Class[] + mg.push(methodType.getArgumentTypes().length); + mg.newArray(TYPE_CLASS); + + // push parameters into array + for (int i = 0; i < methodType.getArgumentTypes().length; i++) + { + // keep copy of array on stack + mg.dup(); + + // push index onto stack + mg.push(i); + mg.push(methodType.getArgumentTypes()[i]); + mg.arrayStore(TYPE_CLASS); + } + + // invoke getMethod() with the method name and the array of types + mg.invokeVirtual(TYPE_CLASS, Method.getMethod("java.lang.reflect.Method getDeclaredMethod(String, Class[])")); + } + + /** + * Defines a new Object[] and push all method argmuments into the array. + * + * @param mg + * @param method + * @param methodType + */ + private static void loadArguments(GeneratorAdapter mg, java.lang.reflect.Method method, Type methodType) + { + // create the Object[] + mg.push(methodType.getArgumentTypes().length); + mg.newArray(TYPE_OBJECT); + + // push parameters into array + for (int i = 0; i < methodType.getArgumentTypes().length; i++) + { + // keep copy of array on stack + mg.dup(); + + // push index onto stack + mg.push(i); + + mg.loadArg(i); + mg.valueOf(methodType.getArgumentTypes()[i]); + mg.arrayStore(TYPE_OBJECT); + } + } + + private static Type[] getTypes(Class... src) + { + Type[] result = new Type[src.length]; + for (int i = 0; i < result.length; i++) + { + result[i] = Type.getType(src[i]); + } + return result; + } + + /** + * Adapted from http://asm.ow2.org/doc/faq.html#Q5 + * + * @param b + * + * @return Class + */ + private static Class loadClass(ClassLoader loader, String className, byte[] b) + { + // override classDefine (as it is protected) and define the class. + try + { + java.lang.reflect.Method method = ClassLoader.class.getDeclaredMethod( + "defineClass", String.class, byte[].class, int.class, int.class); + + // protected method invocation + boolean accessible = method.isAccessible(); + if (!accessible) + { + method.setAccessible(true); + } + try + { + return (Class) method.invoke(loader, className, b, Integer.valueOf(0), Integer.valueOf(b.length)); + } + finally + { + if (!accessible) + { + method.setAccessible(false); + } + } + } + catch (Exception e) + { + throw e instanceof RuntimeException ? ((RuntimeException) e) : new RuntimeException(e); + } + } +} http://git-wip-us.apache.org/repos/asf/deltaspike/blob/e90019fd/deltaspike/modules/partial-bean/impl/src/main/java/org/apache/deltaspike/partialbean/impl/proxy/PartialBeanProxy.java ---------------------------------------------------------------------- diff --git a/deltaspike/modules/partial-bean/impl/src/main/java/org/apache/deltaspike/partialbean/impl/proxy/PartialBeanProxy.java b/deltaspike/modules/partial-bean/impl/src/main/java/org/apache/deltaspike/partialbean/impl/proxy/PartialBeanProxy.java new file mode 100644 index 0000000..9ec50c5 --- /dev/null +++ b/deltaspike/modules/partial-bean/impl/src/main/java/org/apache/deltaspike/partialbean/impl/proxy/PartialBeanProxy.java @@ -0,0 +1,28 @@ +/* + * 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.deltaspike.partialbean.impl.proxy; + +import java.lang.reflect.InvocationHandler; + +public interface PartialBeanProxy +{ + void setRedirectInvocationHandler(InvocationHandler redirectInvocationHandler); + + InvocationHandler getRedirectInvocationHandler(); +} \ No newline at end of file