1 5 package com.tcspring; 6 7 import org.aopalliance.aop.Advice; 8 import org.aopalliance.intercept.MethodInterceptor; 9 import org.apache.commons.logging.Log; 10 import org.apache.commons.logging.LogFactory; 11 import org.springframework.aop.Advisor; 12 import org.springframework.aop.AfterReturningAdvice; 13 import org.springframework.aop.IntroductionInterceptor; 14 import org.springframework.aop.MethodBeforeAdvice; 15 import org.springframework.aop.MethodMatcher; 16 import org.springframework.aop.Pointcut; 17 import org.springframework.aop.PointcutAdvisor; 18 import org.springframework.aop.ThrowsAdvice; 19 import org.springframework.aop.framework.AdvisedSupport; 20 import org.springframework.aop.framework.AopConfigException; 21 import org.springframework.aop.framework.AopProxy; 22 import org.springframework.aop.framework.ProxyFactoryBean; 23 import org.springframework.beans.factory.BeanFactory; 24 25 import com.tc.aspectwerkz.DeploymentModel; 26 import com.tc.aspectwerkz.aspect.container.AspectFactoryManager; 27 import com.tc.aspectwerkz.definition.AspectDefinition; 28 import com.tc.aspectwerkz.definition.DocumentParser; 29 import com.tc.aspectwerkz.definition.SystemDefinition; 30 import com.tc.aspectwerkz.definition.SystemDefinitionContainer; 31 import com.tc.aspectwerkz.definition.deployer.AspectDefinitionBuilder; 32 import com.tc.aspectwerkz.exception.WrappedRuntimeException; 33 import com.tc.aspectwerkz.proxy.Proxy; 34 import com.tc.aspectwerkz.proxy.ProxyDelegationStrategy; 35 import com.tc.aspectwerkz.proxy.ProxySubclassingStrategy; 36 import com.tc.aspectwerkz.proxy.Uuid; 37 import com.tc.aspectwerkz.reflect.MethodInfo; 38 import com.tc.aspectwerkz.reflect.impl.java.JavaClassInfo; 39 import com.tc.aspectwerkz.transform.TransformationConstants; 40 import com.tc.aspectwerkz.util.UuidGenerator; 41 42 import java.lang.reflect.Field ; 43 import java.lang.reflect.Method ; 44 import java.util.HashSet ; 45 import java.util.Set ; 46 47 53 public class FastAopProxy implements AopProxy { 54 private final transient Log logger = LogFactory.getLog(getClass()); 55 56 private static final boolean USE_CACHE = false; 57 private static final boolean MAKE_ADVISABLE = false; 58 59 private static final String SPRING_ASPECT_CONTAINER = SpringAspectContainer.class.getName(); 60 61 private static final MethodInfo s_methodBeforeAdviceMethodInfo = JavaClassInfo 62 .getClassInfo(MethodBeforeAdvice.class) 63 .getMethods()[0]; 64 private static final MethodInfo s_methodInterceptorMethodInfo = JavaClassInfo 65 .getClassInfo(MethodInterceptor.class) 66 .getMethods()[0]; 67 private static final MethodInfo s_afterReturningAdviceMethodInfo = JavaClassInfo 68 .getClassInfo(AfterReturningAdvice.class) 69 .getMethods()[0]; 70 71 private static final String s_throwsAdviceMethodName = "afterThrowing"; 72 73 private final ProxyFactoryBean m_proxyFactory; 74 private final SystemDefinition m_systemDef; 75 private final ClassLoader m_loader; 76 private final Class m_targetClass; 77 private final String m_proxyName; 78 private final boolean m_isSubclassingProxy; 79 private final BeanFactory m_beanFactory; 80 81 83 public FastAopProxy(final ProxyFactoryBean proxyFactory) throws AopConfigException { 84 if (proxyFactory == null) { throw new AopConfigException("Cannot create AopProxy with null ProxyConfig"); } 85 if (proxyFactory.getAdvisors().length == 0 && proxyFactory.getTargetSource() == AdvisedSupport.EMPTY_TARGET_SOURCE) { throw new AopConfigException( 86 "Cannot create AopProxy with no advisors and no target source"); } 87 if (proxyFactory.getTargetSource().getTargetClass() == null) { throw new AopConfigException( 88 "Either an interface or a target is required for proxy creation"); } 89 90 logger.info("Creating FastProxy for " + proxyFactory.getTargetSource().getTargetClass().getName()); 93 94 m_proxyFactory = proxyFactory; 95 m_targetClass = m_proxyFactory.getTargetSource().getTargetClass(); 96 m_loader = m_targetClass.getClassLoader(); 97 m_isSubclassingProxy = m_proxyFactory.isProxyTargetClass() || m_proxyFactory.getProxiedInterfaces().length == 0; 98 m_proxyName = getProxyName(); 99 m_systemDef = new SystemDefinition(m_proxyName + UuidGenerator.generate(m_proxyName)); 100 101 try { 102 m_beanFactory = ((BeanFactoryAware) proxyFactory).tc$getBeanFactory(); 103 } catch (Exception e) { 104 throw new WrappedRuntimeException(e); 105 } 106 107 prepareSystemDefinition(); 108 parseSpringDefinition(); 109 } 110 111 private String getProxyName() { 112 return m_targetClass.getName().replace('.', '/') 113 + (m_isSubclassingProxy ? ProxySubclassingStrategy.PROXY_SUFFIX : ProxyDelegationStrategy.PROXY_SUFFIX) 114 + Long.toString(Uuid.newUuid()); 115 } 116 117 public Object getProxy() { 118 return getProxy(null); 119 } 120 121 public Object getProxy(final ClassLoader classLoader) { 122 final Object target; 123 try { 124 target = m_proxyFactory.getTargetSource().getTarget(); 125 } catch (Exception e) { 126 throw new AopConfigException("ProxyFactory is not correctly initialized - target is NULL", e); 127 } 128 129 if (m_isSubclassingProxy) { 130 return Proxy.newInstance(target.getClass(), USE_CACHE, MAKE_ADVISABLE, m_systemDef); 132 } else { 133 final Class [] interfaces = m_proxyFactory.getProxiedInterfaces(); 135 final Object [] implementations = new Object [interfaces.length]; 136 for (int i = 0; i < implementations.length; i++) { 137 implementations[i] = target; 138 } 139 return Proxy.newInstance(interfaces, implementations, USE_CACHE, MAKE_ADVISABLE, m_systemDef); 140 } 141 } 142 143 private void prepareSystemDefinition() { 144 DocumentParser.addVirtualAspect(m_systemDef); 145 if (!SystemDefinitionContainer.s_classLoaderSystemDefinitions.containsKey(m_loader)) { 146 SystemDefinitionContainer.s_classLoaderSystemDefinitions.put(m_loader, new HashSet ()); 147 } 148 ((Set ) SystemDefinitionContainer.s_classLoaderSystemDefinitions.get(m_loader)).add(m_systemDef); 149 } 150 151 private void parseSpringDefinition() { 152 Advisor[] advisors = m_proxyFactory.getAdvisors(); 153 154 for (int i = 0; i < advisors.length; i++) { 156 Advisor advisor = advisors[i]; 157 if (advisor instanceof PointcutAdvisor) { 158 PointcutAdvisor pointcutAdvisor = (PointcutAdvisor) advisor; 159 160 final Advice aspect = pointcutAdvisor.getAdvice(); 161 if (aspect instanceof IntroductionInterceptor) { throw new IllegalStateException ( 163 "IntroductionInterceptor is currently not supported by FastProxy"); } 164 if (aspect instanceof ThrowsAdvice) { throw new IllegalStateException ( 166 "ThrowsAdvice is currently not supported by FastProxy"); } 167 168 final Class aspectClass = aspect.getClass(); 169 final Pointcut pointcut = pointcutAdvisor.getPointcut(); 170 if (!pointcut.getClassFilter().matches(m_targetClass)) { 171 continue; 172 } 173 174 final StringBuffer pcd = new StringBuffer (); 176 MethodMatcher methodMatcher = pointcut.getMethodMatcher(); 177 Method [] methods = m_targetClass.getDeclaredMethods(); 178 boolean hasAtLeastOneMatch = false; 179 for (int j = 0; j < methods.length; j++) { 180 Method method = methods[j]; 181 if (methodMatcher.matches(method, m_targetClass)) { 182 buildPointcutForMethod(pcd, method); 183 hasAtLeastOneMatch = true; 184 } 185 } 186 if (hasAtLeastOneMatch) { 187 int length = pcd.length(); 188 pcd.delete(length - 3, length); 189 } else { 190 continue; 191 } 192 193 final AspectDefinition aspectDef = buildAspectDefinition(aspect, aspectClass, pcd.toString()); 195 196 initializeAspectFactory(aspect, aspectDef); 197 } else { 198 throw new IllegalStateException ("introductions (mixins) are currently not supported"); 199 } 200 } 201 } 202 203 private void buildPointcutForMethod(final StringBuffer pcd, final Method method) { 204 pcd.append("execution("); 205 pcd.append(method.getReturnType().getName()); 206 pcd.append(" "); 207 pcd.append(m_targetClass.getName()); 208 pcd.append("."); 209 pcd.append(method.getName()); 210 pcd.append("("); 211 pcd.append(".."); 212 pcd.append(")) || "); 213 } 214 215 private AspectDefinition buildAspectDefinition(final Advice aspect, final Class aspectClass, final String pcd) { 216 AspectDefinitionBuilder builder = new AspectDefinitionBuilder(aspectClass.getName(), DeploymentModel.PER_JVM, 217 SPRING_ASPECT_CONTAINER, m_systemDef, m_loader); 218 219 if (aspect instanceof MethodBeforeAdvice) { 220 builder.addAdvice("before", pcd.toString(), s_methodBeforeAdviceMethodInfo.getName()); 221 } else if (aspect instanceof MethodInterceptor) { 222 builder.addAdvice("around", pcd.toString(), s_methodInterceptorMethodInfo.getName()); 223 } else if (aspect instanceof AfterReturningAdvice) { 224 builder 225 .addAdvice("after returning(java.lang.Object)", pcd.toString(), s_afterReturningAdviceMethodInfo.getName()); 226 } else if (aspect instanceof ThrowsAdvice) { 227 builder.addAdvice("after throwing(java.lang.Throwable+)", pcd.toString(), s_throwsAdviceMethodName); 228 } 229 builder.build(); 230 231 final AspectDefinition aspectDef = builder.getAspectDefinition(); 232 aspectDef.addParameter(SpringAspectContainer.BEAN_FACTORY_KEY, m_beanFactory); 233 m_systemDef.addAspect(aspectDef); 234 return aspectDef; 235 } 236 237 241 private String createAspectFactory(final AspectDefinition aspectDef) { 242 String aspectFactoryClassName = AspectFactoryManager.getAspectFactoryClassName(aspectDef.getClassName(), aspectDef 243 .getQualifiedName()); 244 String aspectFactoryJavaName = aspectFactoryClassName.replace('/', '.'); 245 AspectFactoryManager.loadAspectFactory(aspectFactoryClassName, m_proxyName, aspectDef.getClassName().replace('.', 246 '/'), 247 aspectDef.getQualifiedName(), null, null, m_loader, DeploymentModel.PER_JVM 248 .toString()); 249 return aspectFactoryJavaName; 250 } 251 252 256 private void initializeAspectFactory(final Advice aspect, final AspectDefinition aspectDef) { 257 final String factoryName = createAspectFactory(aspectDef); 259 try { 260 Class factory = m_loader.loadClass(factoryName); 261 Field aspectField = factory.getDeclaredField(TransformationConstants.FACTORY_SINGLE_ASPECT_FIELD_NAME); 262 aspectField.set(null, aspect); 263 } catch (Exception e) { 264 throw new WrappedRuntimeException(e); 265 } 266 } 267 } 268 | Popular Tags |