KickJava   Java API By Example, From Geeks To Geeks.

Java > Open Source Codes > org > nanocontainer > aop > defaults > AopNodeBuilderDecorationDelegate


1 /*****************************************************************************
2  * Copyright (C) NanoContainer Organization. All rights reserved. *
3  * ------------------------------------------------------------------------- *
4  * The software in this package is published under the terms of the BSD *
5  * style license a copy of which has been included with this distribution in *
6  * the LICENSE.txt file. *
7  * *
8  * Original code by James Strachan *
9  *****************************************************************************/

10
11 package org.nanocontainer.aop.defaults;
12
13 import dynaop.Aspects;
14 import dynaop.Pointcuts;
15 import dynaop.ProxyFactory;
16 import org.aopalliance.intercept.MethodInterceptor;
17 import org.nanocontainer.aop.AspectablePicoContainer;
18 import org.nanocontainer.aop.AspectsApplicator;
19 import org.nanocontainer.aop.AspectsContainer;
20 import org.nanocontainer.aop.AspectsManager;
21 import org.nanocontainer.aop.ClassPointcut;
22 import org.nanocontainer.aop.ComponentPointcut;
23 import org.nanocontainer.aop.MethodPointcut;
24 import org.nanocontainer.aop.dynaop.InstanceMixinFactory;
25 import org.nanocontainer.script.NodeBuilderDecorationDelegate;
26 import org.nanocontainer.script.NanoContainerMarkupException;
27 import org.picocontainer.MutablePicoContainer;
28 import org.picocontainer.defaults.ComponentAdapterFactory;
29
30 import java.util.List JavaDoc;
31 import java.util.Map JavaDoc;
32
33 /**
34  * @author Aslak Hellesøy
35  * @author Paul Hammant
36  * @version $Revision: 3144 $
37  */

38 public class AopNodeBuilderDecorationDelegate implements NodeBuilderDecorationDelegate {
39
40     private final AspectsManager aspectsManager;
41     private Object JavaDoc currentKey;
42     private AspectablePicoContainer currentPico;
43     private ClassPointcut currentClassCut;
44     private MethodPointcut currentMethodCut;
45
46     public AopNodeBuilderDecorationDelegate(AspectsManager aspectsManager) {
47         this.aspectsManager = aspectsManager;
48     }
49
50     public ComponentAdapterFactory decorate(ComponentAdapterFactory componentAdapterFactory, Map JavaDoc attributes) {
51         AspectsComponentAdapterFactory aspectsComponentAdapterFactory = createAdapterFactory(aspectsManager, componentAdapterFactory);
52         return aspectsComponentAdapterFactory;
53     }
54
55     public MutablePicoContainer decorate(MutablePicoContainer picoContainer) {
56         currentPico = mixinAspectablePicoContainer(aspectsManager, picoContainer);
57         return currentPico;
58     }
59
60     public Object JavaDoc createNode(Object JavaDoc name, Map JavaDoc attributes, Object JavaDoc parentElement) {
61         if (name.equals("aspect")) {
62             return createAspectNode(attributes, name);
63         } else if (name.equals("pointcut")) {
64             return createPointcutNode(attributes, name);
65         } else {
66             throw new NanoContainerMarkupException("Don't know how to create a '" + name + "' child of a '" + parentElement.toString() + "' element");
67         }
68     }
69
70     private Object JavaDoc createPointcutNode(Map JavaDoc attributes, Object JavaDoc name) {
71         currentClassCut = (ClassPointcut) attributes.remove("classCut");
72         currentMethodCut = (MethodPointcut) attributes.remove("methodCut");
73         return name;
74     }
75
76     private Object JavaDoc createAspectNode(Map JavaDoc attributes, Object JavaDoc name) {
77         ClassPointcut classCut = (ClassPointcut) attributes.remove("classCut");
78         if(classCut != null) {
79             currentClassCut = classCut;
80         }
81         MethodPointcut methodCut = (MethodPointcut) attributes.remove("methodCut");
82         if(methodCut != null) {
83             currentMethodCut = methodCut;
84         }
85
86         MethodInterceptor interceptor = (MethodInterceptor) attributes.remove("interceptor");
87         Object JavaDoc interceptorKey = attributes.remove("interceptorKey");
88         Class JavaDoc mixinClass = (Class JavaDoc) attributes.remove("mixinClass");
89         List JavaDoc mixinInterfaces = (List JavaDoc) attributes.remove("mixinInterfaces");
90
91         ComponentPointcut componentCut = (ComponentPointcut) attributes.remove("componentCut");
92         if (componentCut == null && currentKey != null) {
93             componentCut = currentPico.getPointcutsFactory().component(currentKey);
94         }
95
96         if (interceptor != null || interceptorKey != null) {
97             registerInterceptor(currentPico, currentClassCut, componentCut, currentMethodCut, interceptor, interceptorKey);
98         } else if (mixinClass != null) {
99             registerMixin(currentPico, currentClassCut, componentCut, toClassArray(mixinInterfaces), mixinClass);
100         } else {
101             throw new NanoContainerMarkupException("No advice specified - must specify one of interceptor, interceptorKey, mixinClass, or mixinKey");
102         }
103
104         return name;
105     }
106
107
108     private AspectsComponentAdapterFactory createAdapterFactory(AspectsApplicator aspectsApplicator,
109                                                                 ComponentAdapterFactory delegateAdapterFactory) {
110         if (delegateAdapterFactory != null) {
111             return new AspectsComponentAdapterFactory(aspectsApplicator, delegateAdapterFactory);
112         } else {
113             return new AspectsComponentAdapterFactory(aspectsApplicator);
114         }
115     }
116
117     private AspectablePicoContainer mixinAspectablePicoContainer(AspectsManager aspectsManager,
118                                                                  MutablePicoContainer pico) {
119         Aspects aspects = new Aspects();
120         aspects.mixin(Pointcuts.ALL_CLASSES, new Class JavaDoc[]{AspectsContainer.class}, new InstanceMixinFactory(aspectsManager));
121         aspects.interfaces(Pointcuts.ALL_CLASSES, new Class JavaDoc[]{AspectablePicoContainer.class});
122         return (AspectablePicoContainer) ProxyFactory.getInstance(aspects).wrap(pico);
123     }
124
125     private void registerInterceptor(AspectablePicoContainer pico, ClassPointcut classCut,
126                                      ComponentPointcut componentCut, MethodPointcut methodCut, MethodInterceptor interceptor,
127                                      Object JavaDoc interceptorKey) {
128         // precondition:
129
if (interceptor == null && interceptorKey == null) {
130             throw new RuntimeException JavaDoc("assertion failed -- non-null interceptor or interceptorKey expected");
131         }
132
133         // validate script:
134
if (classCut == null && componentCut == null) {
135             throw new NanoContainerMarkupException("currentClassCut or componentCut required for interceptor advice");
136         }
137         if (methodCut == null) {
138             throw new NanoContainerMarkupException("currentMethodCut required for interceptor advice");
139         }
140
141         if (classCut != null) {
142             if (interceptor != null) {
143                 pico.registerInterceptor(classCut, methodCut, interceptor);
144             } else {
145                 pico.registerInterceptor(classCut, methodCut, interceptorKey);
146             }
147         } else {
148             if (interceptor != null) {
149                 pico.registerInterceptor(componentCut, methodCut, interceptor);
150             } else {
151                 pico.registerInterceptor(componentCut, methodCut, interceptorKey);
152             }
153         }
154     }
155
156     private void registerMixin(AspectablePicoContainer pico, ClassPointcut classCut, ComponentPointcut componentCut,
157                                Class JavaDoc[] mixinInterfaces, Class JavaDoc mixinClass) {
158         // precondition:
159
if (mixinClass == null) {
160             throw new RuntimeException JavaDoc("assertion failed -- mixinClass required");
161         }
162
163         // validate script:
164
if (classCut == null && componentCut == null) {
165             throw new NanoContainerMarkupException("currentClassCut or componentCut required for mixin advice");
166         }
167
168         if (classCut != null) {
169             if (mixinInterfaces != null) {
170                 pico.registerMixin(classCut, mixinInterfaces, mixinClass);
171             } else {
172                 pico.registerMixin(classCut, mixinClass);
173             }
174         } else {
175             if (mixinInterfaces != null) {
176                 pico.registerMixin(componentCut, mixinInterfaces, mixinClass);
177             } else {
178                 pico.registerMixin(componentCut, mixinClass);
179             }
180         }
181     }
182
183     private Class JavaDoc[] toClassArray(List JavaDoc l) {
184         if (l == null) {
185             return null;
186         }
187         return (Class JavaDoc[]) l.toArray(new Class JavaDoc[l.size()]);
188     }
189
190     public void rememberComponentKey(Map JavaDoc attributes) {
191         Object JavaDoc key = attributes.get("key");
192         Object JavaDoc clazz = attributes.get("class");
193         if (key != null) {
194             currentKey = key;
195         } else {
196             currentKey = clazz;
197         }
198     }
199 }
200
Popular Tags