KickJava   Java API By Example, From Geeks To Geeks.

Java > Open Source Codes > com > tc > aspectwerkz > aspect > management > Aspects


1 /*
2  * All content copyright (c) 2003-2006 Terracotta, Inc., except as may otherwise be noted in a separate copyright notice. All rights reserved.
3  */

4 package com.tc.aspectwerkz.aspect.management;
5
6
7 import com.tc.aspectwerkz.DeploymentModel;
8 import com.tc.aspectwerkz.aspect.container.AspectFactoryManager;
9 import com.tc.aspectwerkz.definition.AspectDefinition;
10 import com.tc.aspectwerkz.definition.SystemDefinition;
11 import com.tc.aspectwerkz.definition.SystemDefinitionContainer;
12 import com.tc.aspectwerkz.util.ContextClassLoader;
13
14 import java.util.*;
15 import java.lang.reflect.Method JavaDoc;
16
17 /**
18  * Manages the aspects.
19  * <p/>
20  * Each Aspect qName has a generated factory (one factory per aspect qName) on which we invoke reflectively
21  * the aspectOf and alike. Those are user exposed method. The weaved code does not use those.
22  *
23  * @author <a HREF="mailto:jboner@codehaus.org">Jonas Bonér </a>
24  * @author <a HREF="mailto:alex AT gnilux DOT com">Alexandre Vasseur</a>
25  */

26 public class Aspects {
27
28   /**
29    * Returns the aspect container class for the given aspect class qName.
30    * The qName is returned since we may have only the aspect class name upon lookup
31    *
32    * @param visibleFrom class loader to look from
33    * @param qName
34    * @return array of qName and aspect class name (dot formatted as in the aspect definition)
35    */

36   private static String JavaDoc[] getAspectQNameAndAspectClassName(final ClassLoader JavaDoc visibleFrom, final String JavaDoc qName) {
37     AspectDefinition aspectDefinition = lookupAspectDefinition(visibleFrom, qName);
38     return new String JavaDoc[]{aspectDefinition.getQualifiedName(), aspectDefinition.getClassName()};
39   }
40
41   /**
42    * Returns the singleton aspect instance for the aspect with the given qualified name.
43    * The aspect is looked up from the thread context classloader.
44    *
45    * @param qName the qualified name of the aspect
46    * @return the singleton aspect instance
47    */

48   public static Object JavaDoc aspectOf(final String JavaDoc qName) {
49     return aspectOf(Thread.currentThread().getContextClassLoader(), qName);
50   }
51
52   /**
53    * Returns the singleton aspect instance for the given aspect class.
54    * Consider using aspectOf(visibleFrom, qName) if the aspect is used more than once
55    * or if it is used in a class loader which is child of its own classloader.
56    *
57    * @param aspectClass the class of the aspect
58    * @return the singleton aspect instance
59    */

60   public static Object JavaDoc aspectOf(final Class JavaDoc aspectClass) {
61     String JavaDoc aspectClassName = aspectClass.getName().replace('/', '.');
62     return aspectOf(aspectClass.getClassLoader(), aspectClassName);
63   }
64
65   /**
66    * Returns the singleton aspect instance for given aspect qName, with visibility from the given class loader
67    *
68    * @param visibleFrom the class loader from where aspect is visible, likely to be the class loader of the
69    * advised classes, or the one where the system hosting the aspect is deployed.
70    * @return the singleton aspect instance
71    */

72   public static Object JavaDoc aspectOf(final ClassLoader JavaDoc visibleFrom, final String JavaDoc qName) {
73     String JavaDoc[] qNameAndAspectClassName = getAspectQNameAndAspectClassName(visibleFrom, qName);
74     return aspect$Of(qNameAndAspectClassName[0], qNameAndAspectClassName[1], visibleFrom);
75   }
76
77   /**
78    * Returns the per class aspect attached to targetClass
79    * Consider using aspectOf(qName, targetClass) if the aspect is used more than once
80    *
81    * @param aspectClass the name of the aspect
82    * @param targetClass the target class
83    * @return the per class aspect instance
84    */

85   public static Object JavaDoc aspectOf(final Class JavaDoc aspectClass, final Class JavaDoc targetClass) {
86     String JavaDoc aspectClassName = aspectClass.getName().replace('/', '.');
87     return aspectOf(aspectClassName, targetClass);
88   }
89
90   /**
91    * Returns the per class aspect instance for the aspect with the given qualified name for targetClass
92    *
93    * @param qName the qualified name of the aspect
94    * @param targetClass the target class
95    * @return the per class aspect instance
96    */

97   public static Object JavaDoc aspectOf(final String JavaDoc qName, final Class JavaDoc targetClass) {
98     // look up from the targetClass loader is enough in that case
99
String JavaDoc[] qNameAndAspectClassName = getAspectQNameAndAspectClassName(targetClass.getClassLoader(), qName);
100     return aspect$Of(qNameAndAspectClassName[0], qNameAndAspectClassName[1], targetClass);
101   }
102
103   /**
104    * Returns the per instance aspect attached to targetInstance
105    * Consider using aspectOf(qName, targetInstance) if the aspect is used more than once
106    *
107    * @param aspectClass the name of the aspect
108    * @param targetInstance the target instance
109    * @return the per class aspect instance
110    */

111   public static Object JavaDoc aspectOf(final Class JavaDoc aspectClass, final Object JavaDoc targetInstance) {
112     String JavaDoc aspectClassName = aspectClass.getName().replace('/', '.');
113     return aspectOf(aspectClassName, targetInstance);
114   }
115
116   /**
117    * Returns the per instance aspect attached to targetInstance
118    *
119    * @param qName the qualified name of the aspect
120    * @param targetInstance the target instance
121    * @return the per class aspect instance
122    */

123   public static Object JavaDoc aspectOf(final String JavaDoc qName, final Object JavaDoc targetInstance) {
124     // look up from the targetInstance loader is enough in that case
125
AspectDefinition aspectDef = lookupAspectDefinition(targetInstance.getClass().getClassLoader(), qName);
126     DeploymentModel deployModel = aspectDef.getDeploymentModel();
127     String JavaDoc[] qNameAndAspectClassName = getAspectQNameAndAspectClassName(
128             targetInstance.getClass().getClassLoader(), qName);
129
130     if (DeploymentModel.PER_INSTANCE.equals(deployModel)
131             || DeploymentModel.PER_THIS.equals(deployModel)
132             || DeploymentModel.PER_TARGET.equals(deployModel)) {
133       return aspect$Of(qNameAndAspectClassName[0], qNameAndAspectClassName[1], targetInstance);
134     } else {
135       throw new NoAspectBoundException("Cannot retrieve instance level aspect with "
136               + "deployment-scope "
137               + deployModel.toString()
138               + " named ",
139               qName);
140     }
141   }
142
143   /**
144    * Test if there is a per instance aspect (per instance, perthis/target) attached to targetInstance
145    *
146    * @param qName
147    * @param targetInstance
148    * @return
149    */

150   public static boolean hasAspect(final String JavaDoc qName, final Object JavaDoc targetInstance) {
151     String JavaDoc[] qNameAndAspectClassName = getAspectQNameAndAspectClassName(targetInstance.getClass().getClassLoader(), qName);
152     try {
153       Class JavaDoc factory = ContextClassLoader.forName(
154               targetInstance.getClass().getClassLoader(),
155               AspectFactoryManager.getAspectFactoryClassName(qNameAndAspectClassName[1], qName).replace('/', '.')
156       );
157       Method JavaDoc m = factory.getMethod("hasAspect", new Class JavaDoc[]{Object JavaDoc.class});
158       Boolean JavaDoc b = (Boolean JavaDoc) m.invoke(null, new Object JavaDoc[]{targetInstance});
159       return b.booleanValue();
160     } catch (Throwable JavaDoc t) {
161       return false;
162     }
163   }
164
165   //---------- weaver exposed
166
// TODO can we cache all those ? what would be the key ?
167

168   public static Object JavaDoc aspect$Of(String JavaDoc qName, String JavaDoc aspectClassName, ClassLoader JavaDoc loader) {
169     try {
170       Class JavaDoc factory = ContextClassLoader.forName(
171               loader,
172               AspectFactoryManager.getAspectFactoryClassName(aspectClassName, qName).replace('/', '.')
173       );
174       Method JavaDoc m = factory.getMethod("aspectOf", new Class JavaDoc[0]);
175       return m.invoke(null, new Object JavaDoc[0]);
176     } catch (NoAspectBoundException nabe) {
177       throw nabe;
178     } catch (Throwable JavaDoc t) {
179       throw new NoAspectBoundException(t, qName);
180     }
181   }
182
183   public static Object JavaDoc aspect$Of(String JavaDoc qName, String JavaDoc aspectClassName, final Class JavaDoc perClass) {
184     try {
185       Class JavaDoc factory = ContextClassLoader.forName(
186               perClass.getClassLoader(),
187               AspectFactoryManager.getAspectFactoryClassName(aspectClassName, qName).replace('/', '.')
188       );
189       Method JavaDoc m = factory.getMethod("aspectOf", new Class JavaDoc[]{Class JavaDoc.class});
190       return m.invoke(null, new Object JavaDoc[]{perClass});
191     } catch (NoAspectBoundException nabe) {
192       throw nabe;
193     } catch (Throwable JavaDoc t) {
194       throw new NoAspectBoundException(t, qName);
195     }
196   }
197
198   public static Object JavaDoc aspect$Of(String JavaDoc qName, String JavaDoc aspectClassName, final Object JavaDoc perInstance) {
199     try {
200       ClassLoader JavaDoc loader = perInstance.getClass().getClassLoader();
201       Class JavaDoc containerClass = ContextClassLoader.forName(
202               loader,
203               AspectFactoryManager.getAspectFactoryClassName(aspectClassName, qName).replace('/', '.')
204       );
205       Method JavaDoc m = containerClass.getMethod("aspectOf", new Class JavaDoc[]{Object JavaDoc.class});
206       return m.invoke(null, new Object JavaDoc[]{perInstance});
207     } catch (NoAspectBoundException nabe) {
208       throw nabe;
209     } catch (Throwable JavaDoc t) {
210       throw new NoAspectBoundException(t, qName);
211     }
212   }
213
214   //---------- helpers
215

216   /**
217    * Lookup the aspect definition with the given qName, visible from the given loader.
218    * If qName is a class name only, the fallback will ensure only one aspect use is found.
219    *
220    * @param visibleFrom
221    * @param qName
222    * @return
223    */

224   private static AspectDefinition lookupAspectDefinition(final ClassLoader JavaDoc visibleFrom, final String JavaDoc qName) {
225     AspectDefinition aspectDefinition = null;
226
227     Set definitions = SystemDefinitionContainer.getDefinitionsFor(visibleFrom);
228     if (qName.indexOf('/') > 0) {
229       // has system uuid ie real qName
230
for (Iterator iterator = definitions.iterator(); iterator.hasNext();) {
231         SystemDefinition systemDefinition = (SystemDefinition) iterator.next();
232         if (!qName.startsWith(systemDefinition.getUuid())) {
233           continue;
234         }
235         for (Iterator iterator1 = systemDefinition.getAspectDefinitions().iterator(); iterator1.hasNext();) {
236           AspectDefinition aspectDef = (AspectDefinition) iterator1.next();
237           if (qName.equals(aspectDef.getQualifiedName())) {
238             aspectDefinition = aspectDef;
239             break;
240           }
241         }
242       }
243     } else {
244       // fallback on class name lookup
245
// must find at most one
246
int found = 0;
247       for (Iterator iterator = definitions.iterator(); iterator.hasNext();) {
248         SystemDefinition systemDefinition = (SystemDefinition) iterator.next();
249         for (Iterator iterator1 = systemDefinition.getAspectDefinitions().iterator(); iterator1.hasNext();) {
250           AspectDefinition aspectDef = (AspectDefinition) iterator1.next();
251           if (qName.equals(aspectDef.getClassName())) {
252             aspectDefinition = aspectDef;
253             found++;
254           }
255         }
256       }
257       if (found > 1) {
258         throw new NoAspectBoundException("More than one AspectDefinition found, consider using other API methods", qName);
259       }
260
261     }
262
263     if (aspectDefinition == null) {
264       throw new NoAspectBoundException("Could not find AspectDefinition", qName);
265     }
266
267     return aspectDefinition;
268   }
269
270   /**
271    * Class is non-instantiable.
272    */

273   private Aspects() {
274   }
275
276 }
277
Popular Tags