From: <ad...@jb...> - 2005-09-29 20:53:43
|
I had a look at what it would take to write a "Proxy" advisor similar to what is done for the current proxy containers in org.jboss.proxy I came up with a simple (and incomplete) version that is based on the ClassContainer. One of the issues I came across was you cannot add per instance advices unless the target has an instance advisor, which is something that I could easily work around by allowing the advisor to be an instance advisor as well with the following code change in the PerInstanceAdvice/Interceptor | if (targetObject == null) return invocation.invokeNext(); // static method call or static field call | | InstanceAdvisor instanceAdvisor = null; | + if (targetObject instanceof Advised) | + { | Advised advised = (Advised) targetObject; | instanceAdvisor = advised._getInstanceAdvisor(); | + } | + else | + { | + Advisor advisor = invocation.getAdvisor(); | + if (advisor == null || advisor instanceof InstanceAdvisor == false) | + return invocation.invokeNext(); | | + instanceAdvisor = (InstanceAdvisor) advisor; | + } | | Here is the prototype. Most of it is copied from the instance advisor code, some of it overrides the Advisor code to allow the proxy to implement interfaces that are neither introduced or mixed in on the target class/object. | /* | * JBoss, the OpenSource J2EE webOS | * | * Distributable under LGPL license. | * See terms of license at gnu.org. | */ | package org.jboss.aop.container; | | import java.lang.reflect.Constructor; | import java.lang.reflect.InvocationHandler; | import java.lang.reflect.Method; | import java.lang.reflect.Proxy; | import java.util.Iterator; | import java.util.Map; | import java.util.Set; | import java.util.WeakHashMap; | | import org.jboss.aop.AspectManager; | import org.jboss.aop.ClassContainer; | import org.jboss.aop.Domain; | import org.jboss.aop.InstanceAdvisor; | import org.jboss.aop.MethodJoinPoint; | import org.jboss.aop.advice.AspectDefinition; | import org.jboss.aop.advice.Interceptor; | import org.jboss.aop.joinpoint.Joinpoint; | import org.jboss.aop.joinpoint.MethodInvocation; | import org.jboss.aop.metadata.SimpleMetaData; | import org.jboss.aop.util.MethodHashing; | | import EDU.oswego.cs.dl.util.concurrent.ConcurrentReaderHashMap; | | /** | * A ProxyAdvisor. | * | * @author <a href="ad...@jb...">Adrian Brock</a> | * @version $Revision: 1.1 $ | */ | public class ProxyAdvisor extends ClassContainer implements InstanceAdvisor | { | /** The interfaces */ | protected Class[] interfaces; | | /** The target */ | protected Object target; | | /** All methods */ | protected Method[] allMethods; | | /** The instance aspects */ | protected transient WeakHashMap instanceAspects; | | /** The joinpoint aspects */ | protected transient WeakHashMap joinpointAspects; | | /** The invocatin handler */ | protected InvocationHandler handler = new ProxyAdvisorInvocationHandler(); | | /** | * Create an advised proxy | * | * @param target the target | * @return the advised proxy | */ | public static Object createAdvisedProxy(Object target) | { | if (target == null) | throw new IllegalArgumentException("No target"); | return createAdvisedProxy(target.getClass().getClassLoader(), target); | } | | /** | * Create an advised proxy | * | * @param cl the classloader | * @param target the target | * @return the advised proxy | */ | public static Object createAdvisedProxy(ClassLoader cl, Object target) | { | if (target == null) | throw new IllegalArgumentException("No target"); | return createAdvisedProxy(cl, target.getClass().getInterfaces(), target); | } | | /** | * Create an advised proxy | * | * @param cl the classloader | * @param interfaces the interfaces | * @param target the target | * @return the advised proxy | */ | public static Object createAdvisedProxy(ClassLoader cl, Class[] interfaces, Object target) | { | AspectManager manager = AspectManager.instance(); | return createAdvisedProxy(cl, interfaces, target, manager); | } | | /** | * Create an advised proxy | * | * @param cl the classloader | * @param interfaces the interfaces | * @param target the target | * @param manager the aspect manager | * @return the advised proxy | */ | public static Object createAdvisedProxy(ClassLoader cl, Class[] interfaces, Object target, AspectManager manager) | { | if (target == null) | throw new IllegalArgumentException("Null target"); | ProxyAdvisor advisor = new ProxyAdvisor(manager, interfaces, target); | return Proxy.newProxyInstance(cl, interfaces, advisor.handler); | } | | /** | * Create a new ProxyAdvisor. | * | * @param manager the aspect manager | * @param interfaces the interfaces | * @param target the target | */ | protected ProxyAdvisor(AspectManager manager, Class[] interfaces, Object target) | { | super("ProxyAdvisor", manager); | this.interfaces = interfaces; | this.target = target; | initializeClassContainer(); | initializeInstanceAspects(); | initializeJoinpointAspects(); | } | | public Method[] getAllMethods() | { | return allMethods; | } | | protected void createMethodMap() | { | try | { | if (interfaces != null) | { | for (int i = 0; i < interfaces.length; ++i) | { | Class intf = interfaces; | Method[] declaredMethods = intf.getMethods(); | for (int j = 0; j < declaredMethods.length; j++) | { | long hash = MethodHashing.methodHash(declaredMethods[j]); | advisedMethods.put(hash, declaredMethods[j]); | } | } | Object[] values = advisedMethods.getValues(); | allMethods = new Method[values.length]; | System.arraycopy(values, 0, allMethods, 0, values.length); | } | } | catch (Exception e) | { | throw new RuntimeException("Unexpected error", e); | } | } | | protected void createConstructorTables() | { | constructors = new Constructor[0]; | } | | public void appendInterceptor(int index, Interceptor interceptor) | { | throw new org.jboss.util.NotImplementedException("FIXME NYI appendInterceptor"); | } | | public void appendInterceptor(Interceptor interceptor) | { | throw new org.jboss.util.NotImplementedException("FIXME NYI appendInterceptor"); | } | | public void appendInterceptorStack(String stackName) | { | throw new org.jboss.util.NotImplementedException("FIXME NYI appendInterceptorStack"); | } | | public Domain getDomain() | { | throw new RuntimeException("getDomain() is only available when you use weaving with generated advisors"); | } | | public Interceptor[] getInterceptors() | { | throw new org.jboss.util.NotImplementedException("FIXME NYI getInterceptors"); | } | | public Interceptor[] getInterceptors(Interceptor[] baseChain) | { | throw new org.jboss.util.NotImplementedException("FIXME NYI getInterceptors"); | } | | public SimpleMetaData getMetaData() | { | throw new org.jboss.util.NotImplementedException("FIXME NYI getMetaData"); | } | | public Object getPerInstanceAspect(AspectDefinition def) | { | Object aspect = instanceAspects.get(def); | if (aspect == null) | { | synchronized (this) // doublecheck, but I don't want to synchronize everywhere and dynamic aspects are rare | { | aspect = instanceAspects.get(def); | if (aspect != null) return aspect; | getPerInstanceAspectDefinitions().add(def); | aspect = def.getFactory().createPerInstance(null, null); | WeakHashMap copy = new WeakHashMap(instanceAspects); | copy.put(def, aspect); | instanceAspects = copy; | } | } | return aspect; | } | | public Object getPerInstanceAspect(String aspectName) | { | throw new org.jboss.util.NotImplementedException("FIXME NYI getPerInstanceAspect"); | } | | public Object getPerInstanceJoinpointAspect(Joinpoint joinpoint, AspectDefinition def) | { | throw new org.jboss.util.NotImplementedException("FIXME NYI getPerInstanceJoinpointAspect"); | } | | public boolean hasInterceptors() | { | throw new org.jboss.util.NotImplementedException("FIXME NYI hasInterceptors"); | } | | public void insertInterceptor(int index, Interceptor interceptor) | { | throw new org.jboss.util.NotImplementedException("FIXME NYI insertInterceptor"); | } | | public void insertInterceptor(Interceptor interceptor) | { | throw new org.jboss.util.NotImplementedException("FIXME NYI insertInterceptor"); | } | | public void insertInterceptorStack(String stackName) | { | throw new org.jboss.util.NotImplementedException("FIXME NYI insertInterceptorStack"); | } | | public void removeInterceptor(String name) | { | throw new org.jboss.util.NotImplementedException("FIXME NYI removeInterceptor"); | } | | public void removeInterceptorStack(String name) | { | throw new org.jboss.util.NotImplementedException("FIXME NYI removeInterceptorStack"); | } | | protected synchronized void initializeInstanceAspects() | { | Set defs = getPerInstanceAspectDefinitions(); | if (defs.size() > 0) | { | instanceAspects = new WeakHashMap(); | Iterator it = defs.iterator(); | while (it.hasNext()) | { | AspectDefinition def = (AspectDefinition) it.next(); | Object aspect = def.getFactory().createPerInstance(this, this); | instanceAspects.put(def, aspect); | } | } | | } | | private synchronized void initializeJoinpointAspects() | { | Map jpAspects = getPerInstanceJoinpointAspectDefinitions(); | if (jpAspects.size() > 0) | { | joinpointAspects = new WeakHashMap(); | Iterator it = jpAspects.keySet().iterator(); | while (it.hasNext()) | { | AspectDefinition def = (AspectDefinition) it.next(); | ConcurrentReaderHashMap joins = new ConcurrentReaderHashMap(); | joinpointAspects.put(def, joins); | Set joinpoints = (Set) jpAspects.get(def); | Iterator jps = joinpoints.iterator(); | while (jps.hasNext()) | { | Object joinpoint = jps.next(); | joins.put(joinpoint, def.getFactory().createPerJoinpoint(this, this, (Joinpoint) joinpoint)); | } | } | } | } | | /** | * A ProxyAdvisorInvocationHandler. | */ | private class ProxyAdvisorInvocationHandler implements InvocationHandler | { | public Object invoke(Object proxy, Method method, Object[] args) throws Throwable | { | long hash = MethodHashing.calculateHash(method); | MethodJoinPoint joinPoint = (MethodJoinPoint) methodInterceptors.get(hash); | Interceptor[] interceptors = null; | if (joinPoint != null) | interceptors = joinPoint.interceptors; | else if (Object.class != method.getDeclaringClass()) | throw new IllegalArgumentException("Unknown method " + method); | MethodInvocation mi = new MethodInvocation(interceptors, hash, method, method, null); | mi.setTargetObject(target); | mi.setArguments(args); | mi.setAdvisor(ProxyAdvisor.this); | return mi.invokeNext(); | } | } | } | You can then use it like the following: | MessageEndpointFactory implementation: | | public MessageEndpoint createEndpoint(XAResource resource) throws UnavailableException | { | if (target == null) | throw new IllegalStateException("Null target"); | if (manager == null) | throw new IllegalStateException("Null manager"); | if (messageListener == null) | throw new IllegalStateException("Null messageListener"); | | ClassLoader cl = Thread.currentThread().getContextClassLoader(); | Class[] interfaces = new Class[] { messageListener, MessageEndpoint.class }; | return (MessageEndpoint) ProxyAdvisor.createAdvisedProxy(cl, interfaces, target, manager); | } | View the original post : http://www.jboss.com/index.html?module=bb&op=viewtopic&p=3898050#3898050 Reply to the post : http://www.jboss.com/index.html?module=bb&op=posting&mode=reply&p=3898050 |