KickJava   Java API By Example, From Geeks To Geeks.

Java > Open Source Codes > org > codehaus > aspectwerkz > aspect > management > Mixins


1 /**************************************************************************************
2  * Copyright (c) Jonas Bonér, Alexandre Vasseur. All rights reserved. *
3  * http://aspectwerkz.codehaus.org *
4  * ---------------------------------------------------------------------------------- *
5  * The software in this package is published under the terms of the LGPL license *
6  * a copy of which has been included with this distribution in the license.txt file. *
7  **************************************************************************************/

8 package org.codehaus.aspectwerkz.aspect.management;
9
10 import org.codehaus.aspectwerkz.aspect.DefaultMixinFactory;
11 import org.codehaus.aspectwerkz.aspect.MixinFactory;
12 import org.codehaus.aspectwerkz.util.ContextClassLoader;
13 import org.codehaus.aspectwerkz.DeploymentModel;
14 import org.codehaus.aspectwerkz.util.ContextClassLoader;
15 import org.codehaus.aspectwerkz.definition.SystemDefinition;
16 import org.codehaus.aspectwerkz.definition.SystemDefinitionContainer;
17 import org.codehaus.aspectwerkz.definition.MixinDefinition;
18 import org.codehaus.aspectwerkz.exception.DefinitionException;
19 import org.codehaus.aspectwerkz.DeploymentModel;
20
21 import java.util.*;
22 import java.lang.reflect.Constructor JavaDoc;
23 import java.lang.reflect.InvocationTargetException JavaDoc;
24
25 /**
26  * Manages the mixins, registry for the mixin factories (one factory per mixin type).
27  *
28  * @author <a HREF="mailto:jboner@codehaus.org">Jonas Bonér </a>
29  * @author <a HREF="mailto:alex AT gnilux DOT com">Alexandre Vasseur</a>
30  */

31 public class Mixins {
32
33     /**
34      * The default mixin factory class.
35      */

36     public static final String JavaDoc DEFAULT_MIXIN_FACTORY = DefaultMixinFactory.class.getName();
37
38     /**
39      * Map with all the mixin factories mapped to the mixin class
40      */

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

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

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

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

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

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

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

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

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

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

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

242     private Mixins() {
243     }
244 }
245
Popular Tags