KickJava   Java API By Example, From Geeks To Geeks.

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


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.DefaultMixinFactory;
9 import com.tc.aspectwerkz.aspect.MixinFactory;
10 import com.tc.aspectwerkz.definition.MixinDefinition;
11 import com.tc.aspectwerkz.definition.SystemDefinition;
12 import com.tc.aspectwerkz.definition.SystemDefinitionContainer;
13 import com.tc.aspectwerkz.exception.DefinitionException;
14 import com.tc.aspectwerkz.util.ContextClassLoader;
15
16 import java.util.*;
17 import java.lang.reflect.Constructor JavaDoc;
18 import java.lang.reflect.InvocationTargetException JavaDoc;
19
20 /**
21  * Manages the mixins, registry for the mixin factories (one factory per mixin type).
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 Mixins {
27
28   /**
29    * The default mixin factory class.
30    */

31   public static final String JavaDoc DEFAULT_MIXIN_FACTORY = DefaultMixinFactory.class.getName();
32
33   /**
34    * Map with all the mixin factories mapped to the mixin class
35    */

36   private static final Map MIXIN_FACTORIES = new WeakHashMap();
37
38   /**
39    * Returns the mixin factory for the mixin with the given name.
40    *
41    * @param mixinClass the class of the mixin
42    * @param mixinCalledFromLoader
43    * @return the factory, put in cache based on mixin class as a key
44    */

45   public static MixinFactory getFactory(final Class JavaDoc mixinClass, final ClassLoader JavaDoc mixinCalledFromLoader) {
46     synchronized (MIXIN_FACTORIES) {
47       MixinFactory factory = (MixinFactory) MIXIN_FACTORIES.get(mixinClass);
48       if (factory == null) {
49         factory = createMixinFactory(mixinClass, mixinCalledFromLoader);
50         //FIXME by using a lookup by uuid/aspectNickName
51
// right now broken since we have 1 container per mixin CLASS while the definition
52
// does allow for some mix (several mixin, several container, same mixin class)
53
MIXIN_FACTORIES.put(mixinClass, factory);
54       }
55       return factory;
56     }
57   }
58
59   /**
60    * Returns the per JVM mixin instance for the mixin with the given name
61    *
62    * @param name the name of the mixin
63    * @param loader target class classloader
64    * @return the per jvm mixin instance
65    */

66   public static Object JavaDoc mixinOf(final String JavaDoc name, ClassLoader JavaDoc loader) {
67     try {
68       Class JavaDoc mixinClass = Class.forName(name, false, loader);
69       return mixinOf(mixinClass);
70     } catch (ClassNotFoundException JavaDoc e) {
71       throw new RuntimeException JavaDoc("could not load mixin " + name + " from " + loader);
72     }
73   }
74
75   /**
76    * Returns the per jvm mixin instance for the mixin with the given implementation class
77    * deployed using the perJVM model.
78    *
79    * @param mixinClass the name of the mixin
80    * @return the per jvm mixin instance
81    */

82   public static Object JavaDoc mixinOf(final Class JavaDoc mixinClass) {
83     return getFactory(mixinClass, mixinClass.getClassLoader()).mixinOf();
84   }
85
86   /**
87    * Returns the per class mixin instance for the mixin with the given name for the perClass model
88    *
89    * @param name the name of the mixin
90    * @param targetClass the targetClass class
91    * @return the per class mixin instance
92    */

93   public static Object JavaDoc mixinOf(final String JavaDoc name, final Class JavaDoc targetClass) {
94     try {
95       Class JavaDoc mixinClass = Class.forName(name, false, targetClass.getClassLoader());
96       return mixinOf(mixinClass, targetClass);
97     } catch (ClassNotFoundException JavaDoc e) {
98       throw new RuntimeException JavaDoc("could not load mixin " + name + " from " + targetClass.getClassLoader());
99     }
100   }
101
102   /**
103    * Returns the per class mixin instance for the mixin with the given implemnentation class
104    * deployed using the perClass model.
105    *
106    * @param mixinClass the name of the mixin
107    * @param targetClass the targetClass class
108    * @return the per class mixin instance
109    */

110   public static Object JavaDoc mixinOf(final Class JavaDoc mixinClass, final Class JavaDoc targetClass) {
111     return getFactory(mixinClass, targetClass.getClassLoader()).mixinOf(targetClass);
112   }
113
114   /**
115    * Returns the per targetClass instance mixin instance for the mixin with the given name for the perInstance model.
116    *
117    * @param name the name of the mixin
118    * @param targetInstance the targetClass instance, can be null (static method, ctor call)
119    * @return the per instance mixin instance, fallback on perClass if targetInstance is null
120    */

121   public static Object JavaDoc mixinOf(final String JavaDoc name, final Object JavaDoc targetInstance) {
122     try {
123       Class JavaDoc mixinClass = Class.forName(name, false, targetInstance.getClass().getClassLoader());
124       return mixinOf(mixinClass, targetInstance);
125     } catch (ClassNotFoundException JavaDoc e) {
126       throw new RuntimeException JavaDoc(
127               "could not load mixin " + name + " from " + targetInstance.getClass().getClassLoader()
128       );
129     }
130   }
131
132   /**
133    * Returns the per class mixin instance for the mixin with the given implemnentation class
134    * deployed using the perClass model.
135    *
136    * @param mixinClass the name of the mixin
137    * @param targetInstance the targetClass instance, can be null
138    * @return the per targetClass instance mixin instance, fallback to perClass if targetInstance is null
139    */

140   public static Object JavaDoc mixinOf(final Class JavaDoc mixinClass, final Object JavaDoc targetInstance) {
141     //TODO WHAT IF targetInstance is null ? f.e. ITD static methods
142
return getFactory(mixinClass, targetInstance.getClass().getClassLoader()).mixinOf(targetInstance);
143   }
144
145   /**
146    * Creates a new mixin factory.
147    *
148    * @param mixinClass the mixin class
149    * @param mixinCalledFromLoader classloader of the target class advised by the mixin (app server packaging)
150    */

151   private static MixinFactory createMixinFactory(final Class JavaDoc mixinClass, final ClassLoader JavaDoc mixinCalledFromLoader) {
152     final MixinDefinition mixinDefinition = getMixinDefinition(mixinClass, mixinCalledFromLoader);
153
154     String JavaDoc factoryClassName = mixinDefinition.getFactoryClassName();
155     try {
156       Class JavaDoc containerClass;
157       if (factoryClassName == null) {
158         containerClass = ContextClassLoader.forName(mixinClass.getClassLoader(), DEFAULT_MIXIN_FACTORY);
159       } else {
160         containerClass = ContextClassLoader.forName(mixinClass.getClassLoader(), factoryClassName);
161       }
162       Constructor JavaDoc constructor = containerClass.getConstructor(new Class JavaDoc[]{Class JavaDoc.class, DeploymentModel.class});
163       final MixinFactory factory = (MixinFactory) constructor.newInstance(
164               new Object JavaDoc[]{mixinClass, mixinDefinition.getDeploymentModel()}
165       );
166       return factory;
167     } catch (InvocationTargetException JavaDoc e) {
168       throw new DefinitionException(e.getTargetException().toString());
169     } catch (NoSuchMethodException JavaDoc e) {
170       throw new DefinitionException(
171               "mixin factory does not have a valid constructor ["
172                       + factoryClassName
173                       + "] need to have a signature like this [MyMixinFactory(Class mixin, DeploymentModel scope)]: "
174                       + e.toString()
175       );
176     } catch (Throwable JavaDoc e) {
177       StringBuffer JavaDoc cause = new StringBuffer JavaDoc();
178       cause.append("could not create mixin container using the implementation specified [");
179       cause.append(factoryClassName);
180       cause.append("] due to: ");
181       cause.append(e.toString());
182       throw new DefinitionException(cause.toString());
183     }
184   }
185
186   /**
187    * Returns the parameter for a mixin based on the mixin implementation class and a classloader from
188    * where the mixin is visible (the classloader that owns the aop.xml with the "mixin" element, or a child of it).
189    * <p/>
190    * Note: the mixinClass classloader can be different, if you place the mixin in the system classpath, and reference
191    * it only from a deployed application.
192    * <p/>
193    * Note: you should not use a mixin more than once. Consider subclassing the mixin in this case. The returned parameters
194    * are the one from the first mixin found.
195    *
196    * @param mixinClass
197    * @return
198    */

199   public static Map getParameters(Class JavaDoc mixinClass, ClassLoader JavaDoc loader) {
200     MixinDefinition mixinDefinition = getMixinDefinition(mixinClass, loader);
201     return mixinDefinition.getParameters();
202   }
203
204   /**
205    * Lookups a mixin definition based on the mixin impl class and a classloader from where the mixin is
206    * visible. The given classloader can be different from the mixin class classloader.
207    *
208    * @param mixinClass
209    * @param visibleFrom
210    * @return
211    */

212   public static MixinDefinition getMixinDefinition(Class JavaDoc mixinClass, ClassLoader JavaDoc visibleFrom) {
213     MixinDefinition mixinDefinition = null;
214
215     Set definitions = SystemDefinitionContainer.getDefinitionsFor(visibleFrom);
216     for (Iterator iterator = definitions.iterator(); iterator.hasNext() && mixinDefinition == null;) {
217       SystemDefinition systemDefinition = (SystemDefinition) iterator.next();
218       for (Iterator iterator1 = systemDefinition.getMixinDefinitions().iterator(); iterator1.hasNext();) {
219         MixinDefinition mixinDef = (MixinDefinition) iterator1.next();
220         if (mixinClass.getName().replace('/', '.').equals(mixinDef.getMixinImpl().getName())) {
221           mixinDefinition = mixinDef;
222           break;
223         }
224       }
225     }
226     if (mixinDefinition == null) {
227       throw new DefinitionException("could not find definition for mixin: " + mixinClass.getName()
228               + " (loader " + mixinClass.getClassLoader() + ")"
229               + " from loader " + visibleFrom);
230     }
231     return mixinDefinition;
232   }
233
234   /**
235    * Class is non-instantiable.
236    */

237   private Mixins() {
238   }
239 }
240
Popular Tags