/************************************************************************************** * Copyright (c) Jonas Bon�r, Alexandre Vasseur. All rights reserved. * * http://aspectwerkz.codehaus.org * * ---------------------------------------------------------------------------------- * * The software in this package is published under the terms of the LGPL license * * a copy of which has been included with this distribution in the license.txt file. * **************************************************************************************/ package org.codehaus.aspectwerkz.proxy; import org.codehaus.aspectwerkz.DeploymentModel; import org.codehaus.aspectwerkz.definition.DefinitionParserHelper; import org.codehaus.aspectwerkz.definition.SystemDefinition; import org.codehaus.aspectwerkz.definition.SystemDefinitionContainer; import org.codehaus.aspectwerkz.intercept.AdvisableImpl; /** * Facade for Proxy service. Proxy are exposed to the weaver upon compilation, and can be made Advisable as well. * <p/> * We provide 2 proxy strategy: one by subclassing a non final concrete class, and thus having * the proxy delegate to the real implementation thru super.xxx(..) calls, and one by delegating to * N implementations of N interfaces. * <p/> * Proxy strategy provide a cache mechanism if ones wants to cache the compiled proxy. * <p/> * Pointcut to match delegating proxies should use a "+" as for regular subtype matching. * <p/> * Pointcut to match subclassing proxies don't need to use a "+" - precisely to avoid pointcut refactoring to match them. * * @author <a href="mailto:jboner@codehaus.org">Jonas Bon�r </a> * @author <a href="mailto:alex AT gnilux DOT com">Alexandre Vasseur</a> */ public class Proxy { /** * Compiles and returns a subclassing proxy class for the class specified. * * @param clazz the target class to make a proxy for * @param useCache true if a cached instance of the proxy classed should be used * @param makeAdvisable true if the proxy class should implement the <code>Advisable</code> interface, * e.g. be prepared for programmatic, runtime, per instance hot deployement of advice * @return the proxy class */ public static Class getProxyClassFor(final Class clazz, final boolean useCache, final boolean makeAdvisable) { return ProxySubclassingStrategy.getProxyClassFor(clazz, useCache, makeAdvisable); } /** * Creates a new subclassing proxy instance based for the class specified and instantiates it using its default no-argument * constructor. * <p/> * The proxy will be cached and non-advisable. * * @param clazz the target class to make a proxy for * @return the proxy instance */ public static Object newInstance(final Class clazz) { return ProxySubclassingStrategy.newInstance(clazz); } /** * Creates a new subclassing proxy instance for the class specified and instantiates it using the constructor matching * the argument type array specified. * <p/> * The proxy will be cached and non-advisable. * * @param clazz the target class to make a proxy for * @param argumentTypes the argument types matching the signature of the constructor to use when instantiating the proxy * @param argumentValues the argument values to use when instantiating the proxy * @return the proxy instance */ public static Object newInstance(final Class clazz, final Class[] argumentTypes, final Object[] argumentValues) { return ProxySubclassingStrategy.newInstance(clazz, argumentTypes, argumentValues); } /** * Creates a new subclassing proxy instance based for the class specified and instantiates it using its default no-argument * constructor. * * @param clazz the target class to make a proxy for * @param useCache true if a cached instance of the proxy classed should be used * @param makeAdvisable true if the proxy class should implement the <code>Advisable</code> interface, * e.g. be prepared for programmatic, runtime, per instance hot deployement of advice * @return the proxy instance */ public static Object newInstance(final Class clazz, final boolean useCache, final boolean makeAdvisable) { return ProxySubclassingStrategy.newInstance(clazz, useCache, makeAdvisable); } /** * Creates a new subclassing proxy instance for the class specified and instantiates it using the constructor matching * the argument type array specified. * * @param clazz the target class to make a proxy for * @param argumentTypes the argument types matching the signature of the constructor to use when instantiating the proxy * @param argumentValues the argument values to use when instantiating the proxy * @param useCache true if a cached instance of the proxy classed should be used * @param makeAdvisable true if the proxy class should implement the <code>Advisable</code> interface, * e.g. be prepared for programmatic, runtime, per instance hot deployement of advice * @return the proxy instance */ public static Object newInstance(final Class clazz, final Class[] argumentTypes, final Object[] argumentValues, final boolean useCache, final boolean makeAdvisable) { return ProxySubclassingStrategy.newInstance(clazz, argumentTypes, argumentValues, useCache, makeAdvisable); } ///////// -- other strategy /** * Compile or retrieve from cache a delegation proxy for the given interfaces. * * @param interfaces * @param useCache * @param makeAdvisable * @return */ public static Class getProxyClassFor(final Class[] interfaces, final boolean useCache, final boolean makeAdvisable) { return ProxyDelegationStrategy.getProxyClassFor(interfaces, useCache, makeAdvisable); } /** * Create a delegation proxy or retrieve it from cache and instantiate it, using the given implementations. * <p/> * Each implementation must implement the respective given interface. * * @param interfaces * @param implementations * @param useCache * @param makeAdvisable * @return */ public static Object newInstance(final Class[] interfaces, final Object[] implementations, final boolean useCache, final boolean makeAdvisable) { return ProxyDelegationStrategy.newInstance(interfaces, implementations, useCache, makeAdvisable); } /** * Enhances the proxy class with the Advisable mixin, to allow runtime per instance additions of * interceptors. Simply register in the system definition. * * @param proxyClassName * @param loader */ static void makeProxyAdvisable(final String proxyClassName, ClassLoader loader) { // changes occurs in the virtual definition only SystemDefinition definition = SystemDefinitionContainer.getVirtualDefinitionAt(loader); String withinPointcut = "within(" + proxyClassName.replace('/', '.') + ')'; definition.addMixinDefinition( DefinitionParserHelper.createAndAddMixinDefToSystemDef( AdvisableImpl.CLASS_INFO, withinPointcut, DeploymentModel.PER_INSTANCE, false, definition ) ); DefinitionParserHelper.createAndAddAdvisableDef( '(' + withinPointcut + " && execution(!static * *.*(..)))", definition ); } }