001: /*
002: * All content copyright (c) 2003-2006 Terracotta, Inc., except as may otherwise be noted in a separate copyright notice. All rights reserved.
003: */
004: package com.tc.object.config;
005:
006: import com.tc.aspectwerkz.DeploymentModel;
007: import com.tc.aspectwerkz.definition.deployer.AspectDefinitionBuilder;
008: import com.tc.aspectwerkz.definition.deployer.AspectModule;
009: import com.tc.aspectwerkz.definition.deployer.AspectModuleDeployer;
010:
011: /**
012: * Manages deployment of all AW aspects used to implement the Clustered Spring Runtime Container.
013: *
014: * @author Jonas Bonér
015: * @author Eugene Kuleshov
016: */
017: public class SpringAspectModule implements AspectModule {
018:
019: public void deploy(final AspectModuleDeployer deployer) {
020: buildDefinitionForBeanDefinitionProtocol(deployer);
021:
022: buildDefinitionForGetBeanProtocol(deployer);
023:
024: buildDefinitionForScopeProtocol(deployer);
025:
026: buildDefinitionForApplicationContextEventProtocol(deployer);
027:
028: buildDefinitionForAopProxyFactoryProtocol(deployer);
029:
030: // buildDefinitionForTransactionManagerProtocol(deployer);
031:
032: // buildDefinitionForConfigurableAnnotationProtocol(deployer);
033: }
034:
035: /**
036: * Handle ignored fields and other class metadata.
037: */
038: private void buildDefinitionForBeanDefinitionProtocol(
039: AspectModuleDeployer deployer) {
040: deployer
041: .addMixin(
042: "com.tcspring.DistributableBeanFactoryMixin",
043: DeploymentModel.PER_INSTANCE,
044: "within(org.springframework.beans.factory.support.AbstractBeanFactory)",
045: true);
046:
047: AspectDefinitionBuilder builder = deployer.newAspectBuilder(
048: "com.tcspring.BeanDefinitionProtocol",
049: DeploymentModel.PER_TARGET, null);
050:
051: // capture context parameters when BeanFactory is loaded by the
052: builder
053: .addAdvice(
054: "before",
055: "execution(int org.springframework.beans.factory.support.BeanDefinitionReader+.loadBeanDefinitions(..)) "
056: + "AND args(resource) AND target(reader)",
057: "captureIdentity(StaticJoinPoint jp, org.springframework.core.io.Resource resource, "
058: + "org.springframework.beans.factory.support.BeanDefinitionReader reader)");
059:
060: builder
061: .addAdvice(
062: "around",
063: "execution(* org.springframework.context.support.AbstractRefreshableApplicationContext+.loadBeanDefinitions(..)) "
064: + "AND args(beanFactory)",
065: "collectDefinitions(StaticJoinPoint jp, org.springframework.beans.factory.support.DefaultListableBeanFactory beanFactory)");
066:
067: builder
068: .addAdvice(
069: "after",
070: "execution(org.springframework.beans.factory.config.BeanDefinitionHolder.new(..)) AND target(holder)",
071: "saveBeanDefinition(StaticJoinPoint jp, org.springframework.beans.factory.config.BeanDefinitionHolder holder)");
072:
073: builder
074: .addAdvice(
075: "around",
076: "cflow(execution(* org.springframework.context.support.AbstractRefreshableApplicationContext+.loadBeanDefinitions(..))) "
077: + "AND withincode(* org.springframework.beans.factory.support.BeanDefinitionReaderUtils.createBeanDefinition(..)) "
078: + "AND call(* org.springframework.util.ClassUtils.forName(..)) "
079: + "AND args(className, loader)",
080: "disableClassForName(String className, java.lang.ClassLoader loader)");
081: }
082:
083: private void buildDefinitionForGetBeanProtocol(
084: AspectModuleDeployer deployer) {
085: AspectDefinitionBuilder builder = deployer.newAspectBuilder(
086: "com.tcspring.GetBeanProtocol",
087: DeploymentModel.PER_JVM, null);
088:
089: // This approach does not work because of Spring's handling of the circular dependencies
090: // builder.addAdvice("after",
091: // "execution(org.springframework.beans.factory.support.AbstractBeanFactory.new(..)) "
092: // + "AND this(factory)",
093: // "registerBeanPostProcessor(StaticJoinPoint jp, org.springframework.beans.factory.support.AbstractBeanFactory factory)");
094:
095: builder
096: .addAdvice(
097: "around",
098: "execution(* org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.createBean(String, ..)) "
099: + "AND args(beanName, ..) AND target(beanFactory)",
100: "beanNameCflow(StaticJoinPoint jp, String beanName,"
101: + "org.springframework.beans.factory.config.AutowireCapableBeanFactory beanFactory)");
102:
103: builder
104: .addAdvice(
105: "around",
106: "withincode(* org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.createBean(String, ..)) "
107: + "AND call(* org.springframework.beans.BeanWrapper+.getWrappedInstance()) "
108: + "AND this(beanFactory)",
109: "virtualizeSingletonBean(StaticJoinPoint jp, "
110: + "org.springframework.beans.factory.config.AutowireCapableBeanFactory beanFactory)");
111:
112: builder
113: .addAdvice(
114: "after",
115: "withincode(* org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.createBean(String, ..)) "
116: + "AND call(* org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.populateBean(..)) "
117: + "AND this(beanFactory) AND args(beanName, mergedBeanDefinition, instanceWrapper)",
118: "initializeSingletonBean(String beanName, "
119: + "org.springframework.beans.factory.support.RootBeanDefinition mergedBeanDefinition, "
120: + "org.springframework.beans.BeanWrapper instanceWrapper, "
121: + "org.springframework.beans.factory.config.AutowireCapableBeanFactory beanFactory)");
122: }
123:
124: private void buildDefinitionForScopeProtocol(
125: AspectModuleDeployer deployer) {
126: if (hasClass("org.springframework.beans.factory.config.Scope",
127: deployer)) {
128: deployer
129: .addMixin(
130: "com.tcspring.ScopeProtocol$DistributableBeanFactoryAwareMixin",
131: DeploymentModel.PER_INSTANCE,
132: "within(org.springframework.beans.factory.config.Scope+)",
133: true);
134:
135: AspectDefinitionBuilder builder = deployer
136: .newAspectBuilder("com.tcspring.ScopeProtocol",
137: DeploymentModel.PER_JVM, null);
138:
139: builder
140: .addAdvice(
141: "after",
142: "execution(* org.springframework.beans.factory.support.AbstractBeanFactory+.registerScope(String, org.springframework.beans.factory.config.Scope+)) "
143: + "AND target(beanFactory) AND args(scopeName, scope)",
144: "setDistributableBeanFactory(String scopeName, "
145: + "org.springframework.beans.factory.config.Scope scope, "
146: + "org.springframework.beans.factory.support.AbstractBeanFactory beanFactory)");
147:
148: builder
149: .addAdvice(
150: "around",
151: "withincode(* org.springframework.beans.factory.support.AbstractBeanFactory.getBean(String, ..)) "
152: + "AND call(* org.springframework.beans.factory.config.Scope+.get(String, ..)) "
153: + "AND target(s) AND args(beanName, ..)",
154: "virtualizeScopedBean(StaticJoinPoint jp, org.springframework.beans.factory.config.Scope s, String beanName)");
155:
156: builder
157: .addAdvice(
158: "around",
159: "withincode(* org.springframework.beans.factory.ObjectFactory+.getObject()) "
160: + "AND call(* org.springframework.beans.factory.config.Scope+.registerDestructionCallback(..)) "
161: + "AND target(scope) AND args(beanName, callback)",
162: "wrapDestructionCallback(StaticJoinPoint jp, String beanName, java.lang.Runnable callback, "
163: + "org.springframework.beans.factory.config.Scope scope)");
164:
165: builder
166: .addAdvice(
167: "around",
168: "withincode(* org.springframework.beans.factory.config.Scope+.get(..)) "
169: + "AND call(* org.springframework.web.context.request.RequestAttributes+.getAttribute(String, ..)) "
170: + "AND this(s) AND args(beanName, ..)",
171: "suspendRequestAttributeGet(StaticJoinPoint jp, org.springframework.beans.factory.config.Scope s, String beanName)");
172: builder
173: .addAdvice(
174: "around",
175: "withincode(* org.springframework.beans.factory.config.Scope+.get(..)) "
176: + "AND call(* org.springframework.web.context.request.RequestAttributes+.setAttribute(String, ..)) "
177: + "AND this(s) AND args(beanName, ..)",
178: "suspendRequestAttributeSet(StaticJoinPoint jp, org.springframework.beans.factory.config.Scope s, String beanName)");
179: }
180:
181: if (hasClass("javax.servlet.http.HttpSession", deployer)) {
182: AspectDefinitionBuilder sessionBuilder = deployer
183: .newAspectBuilder("com.tcspring.SessionProtocol",
184: DeploymentModel.PER_JVM, null);
185:
186: // XXX change to wrap call org.springframework.web.context.request.RequestAttributes+.getSessionId()
187: sessionBuilder
188: .addAdvice(
189: "around",
190: "cflow(execution(* org.springframework.web.context.request.SessionScope.getConversationId())) "
191: + "AND withincode(* org.springframework.web.context.request.ServletRequestAttributes.getSessionId()) "
192: + "AND call(* javax.servlet.http.HttpSession+.getId()) AND target(session)",
193: "clusterSessionId(StaticJoinPoint jp, javax.servlet.http.HttpSession session)");
194:
195: if (hasClass(
196: "javax.servlet.http.HttpSessionBindingListener",
197: deployer)) {
198: sessionBuilder
199: .addAdvice(
200: "around",
201: "execution(* org.springframework.web.context.request.ServletRequestAttributes.registerSessionDestructionCallback(..)) "
202: + "AND args(name, callback)",
203: "captureDestructionCallback(StaticJoinPoint jp, String name, java.lang.Runnable callback)");
204:
205: sessionBuilder
206: .addAdvice(
207: "around",
208: "withincode(* org.springframework.web.context.request.ServletRequestAttributes.registerSessionDestructionCallback(..)) "
209: + "AND call(* javax.servlet.http.HttpSession.setAttribute(..)) "
210: + "AND target(session) AND args(name, ..)",
211: "virtualizeSessionDestructionListener(StaticJoinPoint jp, String name, javax.servlet.http.HttpSession session)");
212: }
213: }
214: }
215:
216: private void buildDefinitionForApplicationContextEventProtocol(
217: final AspectModuleDeployer deployer) {
218: AspectDefinitionBuilder builder = deployer.newAspectBuilder(
219: "com.tcspring.ApplicationContextEventProtocol",
220: DeploymentModel.PER_JVM, null);
221:
222: builder
223: .addAdvice(
224: "before",
225: "withincode(* org.springframework.context.support.AbstractApplicationContext+.refresh()) "
226: + "AND call(* org.springframework.context.support.AbstractApplicationContext+.publishEvent(..)) "
227: + "AND target(ctx)",
228: "registerContext(StaticJoinPoint jp, org.springframework.context.support.AbstractApplicationContext ctx)");
229:
230: builder
231: .addAdvice(
232: "around",
233: "execution(void org.springframework.context.support.AbstractApplicationContext.publishEvent(..)) "
234: + "AND args(event) AND target(ctx)",
235: "interceptEvent(StaticJoinPoint jp, "
236: + "org.springframework.context.ApplicationEvent event, "
237: + "org.springframework.context.support.AbstractApplicationContext ctx)");
238: }
239:
240: private void buildDefinitionForAopProxyFactoryProtocol(
241: final AspectModuleDeployer deployer) {
242: if (hasClass(
243: "org.springframework.aop.framework.AopProxyFactory",
244: deployer)) {
245:
246: deployer
247: .addMixin(
248: "com.tcspring.AopProxyFactoryProtocol$BeanFactoryAwareMixin",
249: DeploymentModel.PER_INSTANCE,
250: "within(org.springframework.aop.framework.ProxyFactoryBean)",
251: true);
252:
253: AspectDefinitionBuilder builder = deployer
254: .newAspectBuilder(
255: "com.tcspring.AopProxyFactoryProtocol",
256: DeploymentModel.PER_JVM, null);
257:
258: // save a accessible copy of the BeanFactory
259: builder
260: .addAdvice(
261: "before",
262: "execution(void org.springframework.aop.framework.ProxyFactoryBean+.setBeanFactory(..)) "
263: + "AND args(beanFactory) AND this(bean)",
264: "saveBeanFactory(com.tcspring.BeanFactoryAware bean, "
265: + "org.springframework.beans.factory.BeanFactory beanFactory)");
266:
267: builder
268: .addAdvice(
269: "around",
270: "execution(* org.springframework.aop.framework.AopProxyFactory+.createAopProxy(..)) "
271: + "AND args(proxyFactory)",
272: "createAopProxy(StaticJoinPoint, org.springframework.aop.framework.AdvisedSupport proxyFactory)");
273: }
274: }
275:
276: private boolean hasClass(String name, AspectModuleDeployer deployer) {
277: return deployer.getClassLoader().getResource(
278: name.replace('.', '/') + ".class") != null;
279: }
280:
281: // private void buildDefinitionForConfigurableAnnotationProtocol(AspectModuleDeployer deployer) {
282: // try {
283: // AspectDefinitionBuilder builder =
284: // deployer.newAspectBuilder(
285: // "com.tcspring.ConfigurableAnnotationProtocol",
286: // DeploymentModel.PER_JVM, null);
287: //
288: // builder.addAdvice("afterReturning",
289: // "execution(*.new(..)) AND within(@Configurable *) AND this(beanInstance)",
290: // "afterBeanConstruction(Object beanInstance)");
291: //
292: // builder.addAdvice("around",
293: // "execution(* org.springframework.aop.config.SpringConfiguredBeanDefinitionParser.getBeanConfigurerClass())",
294: // "hijackBeanConfigurerClass(StaticJoinPoint jp)");
295: //
296: // } catch(Throwable t) {
297: // System.err.println("[AW::WARNING] unable to build aspect for @Configurable; " + t.toString()+"
298: // "+Thread.currentThread());
299: // }
300: // }
301:
302: // private void buildDefinitionForTransactionManagerProtocol(final AspectModuleDeployer deployer) {
303: // AspectDefinitionBuilder builder = deployer.newAspectBuilder("com.tcspring.TransactionManagerProtocol",
304: // DeploymentModel.PER_JVM, null);
305: //
306: // // hijack anything but NOT derivatives of the AbstractPlatformTransactionManager
307: //
308: // builder
309: // .addAdvice(
310: // "around",
311: // "execution(* org.springframework.transaction.PlatformTransactionManager+.getTransaction(..)) "
312: // + "AND !execution(* org.springframework.transaction.support.AbstractPlatformTransactionManager+.getTransaction(..))
313: // "
314: // + "AND target(manager)", "startTransaction(StaticJoinPoint jp, java.lang.Object manager)");
315: //
316: // builder
317: // .addAdvice(
318: // "around",
319: // "execution(* org.springframework.transaction.PlatformTransactionManager+.commit(..)) "
320: // + "AND !execution(* org.springframework.transaction.support.AbstractPlatformTransactionManager+.commit(..)) "
321: // + "AND target(manager)", "commitTransaction(StaticJoinPoint jp, java.lang.Object manager)");
322: //
323: // builder
324: // .addAdvice(
325: // "around",
326: // "execution(void org.springframework.transaction.PlatformTransactionManager+.rollback(..)) "
327: // + "AND !execution(* org.springframework.transaction.support.AbstractPlatformTransactionManager+.rollback(..)) "
328: // + "AND target(manager)", "rollbackTransaction(StaticJoinPoint jp, java.lang.Object manager)");
329: // }
330:
331: }
|