View Javadoc

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.annotation.instrumentation;
9   
10  import org.codehaus.aspectwerkz.annotation.instrumentation.javassist.JavassistAttributeExtractor;
11  import org.codehaus.aspectwerkz.exception.WrappedRuntimeException;
12  
13  import java.util.Map;
14  import java.util.WeakHashMap;
15  
16  import javassist.CtClass;
17  
18  /***
19   * Retrieves attributes from the class bytecode on class, method and field level.
20   *
21   * FIXME - remove in 2.0
22   * 
23   * @author <a href="mailto:jboner@codehaus.org">Jonas Bonér </a>
24   */
25  public class Attributes {
26  //    private static final Object[] EMPTY_OBJECT_ARRAY = new Object[0];
27  
28      /***
29       * Hold a cache of AttributeExtractors so we don't have to load the class loaded repeatedly when accessing custom
30       * attributes.
31       */
32      private static final Map s_extractorCache = new WeakHashMap();
33  
34  //    /***
35  //     * Return the list (possibly empty) of custom attributes associated with the class "klass".
36  //     *
37  //     * @param klass The java.lang.Class object to find the attributes on.
38  //     * @return The possibly 0-length array of attributes
39  //     */
40  //    public static Object[] getAttributes(final Class klass) {
41  //        AttributeExtractor extractor = getAttributeExtractor(klass);
42  //        if (extractor == null) {
43  //            return EMPTY_OBJECT_ARRAY;
44  //        } else {
45  //            return extractor.getClassAttributes();
46  //        }
47  //    }
48  //
49  //    /***
50  //     * Return all the attributes associated with the given method.
51  //     *
52  //     * @param method The java.lang.reflect.Method describing the method.
53  //     * @return Attribute[] all attributes associated with the method. Returns a 0 length array in case no attributes
54  //     *         were found.
55  //     */
56  //    public static Object[] getAttributes(final Method method) {
57  //        Class klass = method.getDeclaringClass();
58  //        ArrayList attribList = new ArrayList();
59  //
60  //        // search for superclass
61  //        while (true) {
62  //            Object[] returnAttribs = searchForMethodAttributes(klass, method);
63  //            if (returnAttribs.length > 0) {
64  //                // already in the list and the attribute is allowed to be specified mulitple times.
65  //                attribList.addAll(Arrays.asList(returnAttribs));
66  //            }
67  //            Class superClass = klass.getSuperclass();
68  //            if (superClass == null) {
69  //                break;
70  //            } else if (superClass.getName().startsWith("java.")) {
71  //                break;
72  //            } else {
73  //                klass = superClass;
74  //            }
75  //        }
76  //
77  //        // search for interfaces.
78  //        while (true) {
79  //            Class[] interfaceClasses = klass.getInterfaces();
80  //            for (int i = 0; i < interfaceClasses.length; i++) {
81  //                Object[] intAttribs = searchForMethodAttributes(interfaceClasses[i], method);
82  //                if (intAttribs.length > 0) {
83  //                    attribList.addAll(Arrays.asList(intAttribs));
84  //                }
85  //            }
86  //            Class superClass = klass.getSuperclass();
87  //            if (superClass == null) {
88  //                break;
89  //            } else if (superClass.getName().startsWith("java.")) {
90  //                break;
91  //            } else {
92  //                klass = superClass;
93  //            }
94  //        }
95  //        return attribList.toArray(new Object[attribList.size()]);
96  //    }
97  //
98  //    /***
99  //     * Return all the attributes associated with the given method.
100 //     *
101 //     * @param method The java.lang.reflect.Method describing the method.
102 //     * @return Attribute[] all attributes associated with the method. Returns a 0 length array in case no attributes
103 //     *         were found.
104 //     */
105 //    public static Object[] getAttributes(final Constructor constructor) {
106 //        Class klass = constructor.getDeclaringClass();
107 //        ArrayList attribList = new ArrayList();
108 //
109 //        // search for superclass
110 //        while (true) {
111 //            Object[] returnAttribs = searchForConstructorAttributes(klass, constructor);
112 //            if (returnAttribs.length > 0) {
113 //                // already in the list and the attribute is allowed to be specified mulitple times.
114 //                attribList.addAll(Arrays.asList(returnAttribs));
115 //            }
116 //            Class superClass = klass.getSuperclass();
117 //            if (superClass == null) {
118 //                break;
119 //            } else if (superClass.getName().startsWith("java.")) {
120 //                break;
121 //            } else {
122 //                klass = superClass;
123 //            }
124 //        }
125 //
126 //        // search for interfaces.
127 //        while (true) {
128 //            Class[] interfaceClasses = klass.getInterfaces();
129 //            for (int i = 0; i < interfaceClasses.length; i++) {
130 //                Object[] intAttribs = searchForConstructorAttributes(interfaceClasses[i], constructor);
131 //                if (intAttribs.length > 0) {
132 //                    attribList.addAll(Arrays.asList(intAttribs));
133 //                }
134 //            }
135 //            Class superClass = klass.getSuperclass();
136 //            if (superClass == null) {
137 //                break;
138 //            } else if (superClass.getName().startsWith("java.")) {
139 //                break;
140 //            } else {
141 //                klass = superClass;
142 //            }
143 //        }
144 //        return attribList.toArray(new Object[attribList.size()]);
145 //    }
146 //
147 //    /***
148 //     * Return the list (possibly empty) of custom attributes associated with the field.
149 //     *
150 //     * @param field The java.lang.reflect.Field object to find the attributes on.
151 //     * @return The possibly 0-length array of attributes
152 //     */
153 //    public static Object[] getAttributes(final Field field) {
154 //        AttributeExtractor extractor = getAttributeExtractor(field.getDeclaringClass());
155 //        if (extractor == null) {
156 //            return EMPTY_OBJECT_ARRAY;
157 //        } else {
158 //            return extractor.getFieldAttributes(field.getName());
159 //        }
160 //    }
161 //
162 //    /***
163 //     * Searches for method attributes
164 //     *
165 //     * @param klass
166 //     * @param method
167 //     * @return Attribute[]
168 //     */
169 //    private static Object[] searchForMethodAttributes(final Class klass, final Method method) {
170 //        AttributeExtractor extractor = getAttributeExtractor(klass);
171 //        if (extractor == null) {
172 //            return EMPTY_OBJECT_ARRAY;
173 //        } else {
174 //            String[] paramTypes = new String[method.getParameterTypes().length];
175 //            for (int i = 0; i < paramTypes.length; i++) {
176 //                String paramType = method.getParameterTypes()[i].getName();
177 //
178 //                // TODO: is this fix generic? are there other cases not handled?
179 //                // handle array types
180 //                if (paramType.startsWith("[L")) {
181 //                    paramType = paramType.substring(2, paramType.length() - 1) + "[]";
182 //                }
183 //                paramTypes[i] = paramType;
184 //            }
185 //            return extractor.getMethodAttributes(method.getName(), paramTypes);
186 //        }
187 //    }
188 //
189 //    /***
190 //     * Searches for constructor attributes
191 //     *
192 //     * @param klass
193 //     * @param constructor
194 //     * @return Attribute[]
195 //     */
196 //    private static Object[] searchForConstructorAttributes(final Class klass, final Constructor constructor) {
197 //        AttributeExtractor extractor = getAttributeExtractor(klass);
198 //        if (extractor != null) {
199 //            String[] paramTypes = new String[constructor.getParameterTypes().length];
200 //            for (int i = 0; i < paramTypes.length; i++) {
201 //                String paramType = constructor.getParameterTypes()[i].getName();
202 //
203 //                // TODO: is this fix generic? are there other cases not handled?
204 //                // handle array types
205 //                if (paramType.startsWith("[L")) {
206 //                    paramType = paramType.substring(2, paramType.length() - 1) + "[]";
207 //                }
208 //                paramTypes[i] = paramType;
209 //            }
210 //            return extractor.getConstructorAttributes(paramTypes);
211 //        } else {
212 //            return EMPTY_OBJECT_ARRAY;
213 //        }
214 //    }
215 
216 //    /***
217 //     * Return the attribute extractor associated with the class.
218 //     *
219 //     * @param klass the Class object to find the attributes on.
220 //     * @return the attribute extractor or null if the class bytecode could not be found
221 //     */
222 //    public static synchronized AttributeExtractor getAttributeExtractor(final Class klass) {
223 //        if (klass.isPrimitive() || klass.isArray() || klass.getName().startsWith("java.")) {
224 //            return null;
225 //        }
226 //        AsmAttributeExtractor extractor;
227 //        if ((extractor = (AsmAttributeExtractor) s_extractorCache.get(klass)) == null) {
228 //            String className = klass.getName();
229 //            try {
230 //                ClassLoader loader = klass.getClassLoader();
231 //                if (loader != null) {
232 //                    extractor = new AsmAttributeExtractor();
233 //                    if (extractor.initialize(className, klass.getClassLoader())) {
234 //                        s_extractorCache.put(klass, extractor);
235 //                    } else {
236 //                        return null;
237 //                    }
238 //                } else {
239 //                    // bootstrap classloader
240 //                    extractor = new AsmAttributeExtractor();
241 //                    if (extractor.initialize(className, ClassLoader.getSystemClassLoader())) {
242 //                        s_extractorCache.put(klass, extractor);
243 //                    } else {
244 //                        return null;
245 //                    }
246 //                }
247 //            } catch (Exception e) {
248 //                throw new WrappedRuntimeException(e);
249 //            }
250 //        }
251 //        return extractor;
252 //    }
253 
254     /***
255      * Return the list (possibly empty) of custom attributes associated with the class.
256      * 
257      * @param ctClass the class name
258      * @param loader the class loader
259      * @return the possibly 0-length array of attributes
260      */
261     public static synchronized AttributeExtractor getAttributeExtractor(final CtClass ctClass, final ClassLoader loader) {
262         if (ctClass.isPrimitive() || ctClass.isArray() || ctClass.getName().startsWith("java.")) {
263             return null;
264         }
265         JavassistAttributeExtractor extractor;
266         Integer hash = new Integer((29 * ctClass.hashCode()) + loader.hashCode());
267         if ((extractor = (JavassistAttributeExtractor) s_extractorCache.get(hash)) == null) {
268             try {
269                 extractor = new JavassistAttributeExtractor();
270                 extractor.initialize(ctClass);
271                 s_extractorCache.put(hash, extractor);
272             } catch (Exception e) {
273                 throw new WrappedRuntimeException(e);
274             }
275         }
276         return extractor;
277     }
278 }