1
2
3
4
5
6
7
8 package org.codehaus.metaclass;
9
10 import java.lang.reflect.Constructor;
11 import java.lang.reflect.Field;
12 import java.lang.reflect.Method;
13 import java.util.ArrayList;
14 import org.codehaus.metaclass.introspector.MetaClassException;
15 import org.codehaus.metaclass.introspector.MetaClassIntrospector;
16 import org.codehaus.metaclass.model.Attribute;
17 import org.codehaus.metaclass.model.ClassDescriptor;
18 import org.codehaus.metaclass.model.FieldDescriptor;
19 import org.codehaus.metaclass.model.MethodDescriptor;
20 import org.codehaus.metaclass.model.ParameterDescriptor;
21
22 /***
23 * Utility class to make it easy to access attributes for
24 * classes and methods. The utility class makes it possible
25 * to access attributes for methods and fields by using one
26 * method call such as;
27 * <pre>
28 * //Get all Class attributes for 'MyClass'
29 * Attribute[] attributes =
30 * Attributes.getAttributes( MyClass.class );
31 *
32 * //Get all Class attributes for 'MyClass'
33 * //that have name 'dna.service'
34 * Attribute[] attributes =
35 * Attributes.getAttributes( MyClass.class, "dna.service" );
36 *
37 * //Get attribute named 'dna.component' for 'MyClass'
38 * //Note: that this may return null
39 * Attribute attribute =
40 * Attributes.getAttribute( MyClass.class, "dna.component" );
41 * </pre>
42 *
43 * <p>Note that none of the methods in this class throw an
44 * exception. If an error occurs retrieving attributes for
45 * a particular artefact (such as being unable to load
46 * ClassDescriptor for class) then either an empty array
47 * or a null will be returned depending on the method.</p>
48 *
49 * @version $Revision: 1.11 $ $Date: 2003/10/14 01:24:23 $
50 */
51 public class Attributes
52 {
53 /***
54 * Return the Attributes with specified name
55 * from specified attributes.
56 *
57 * @param attributes the attributes
58 * @param name the name of attribute to collect
59 * @return the attribute from set with specified name
60 */
61 public static Attribute getAttributeByName( final Attribute[] attributes,
62 final String name )
63 {
64 for( int i = 0; i < attributes.length; i++ )
65 {
66 final Attribute attribute = attributes[ i ];
67 if( attribute.getName().equals( name ) )
68 {
69 return attribute;
70 }
71 }
72 return null;
73 }
74
75 /***
76 * Return the set of Attributes with specified name
77 * from specified attributes.
78 *
79 * @param attributes the attributes
80 * @param name the name of attributes to collect
81 * @return the attributes from set with specified name
82 */
83 public static Attribute[] getAttributesByName( final Attribute[] attributes,
84 final String name )
85 {
86 final ArrayList results = new ArrayList();
87 for( int i = 0; i < attributes.length; i++ )
88 {
89 final Attribute attribute = attributes[ i ];
90 final String attributeName = attribute.getName();
91 if( attributeName.equals( name ) )
92 {
93 results.add( attribute );
94 }
95 }
96 return (Attribute[])results.toArray( new Attribute[ results.size() ] );
97 }
98
99 /***
100 * Return the attributes for specified Class.
101 *
102 * @param clazz the class
103 * @return the 'Class' attributes
104 */
105 public static Attribute[] getAttributes( final Class clazz )
106 {
107 try
108 {
109 final ClassDescriptor descriptor = getClassInfo( clazz );
110 return descriptor.getAttributes();
111 }
112 catch( final Exception e )
113 {
114 return Attribute.EMPTY_SET;
115 }
116 }
117
118 /***
119 * Return the attributes for specified Class
120 * that have specified name.
121 *
122 * @param clazz the class
123 * @param name the attribute name
124 * @return the attributes
125 */
126 public static Attribute[] getAttributes( final Class clazz, final String name )
127 {
128 try
129 {
130 final ClassDescriptor descriptor = getClassInfo( clazz );
131 return getAttributesByName( descriptor.getAttributes(),
132 name );
133 }
134 catch( final Exception e )
135 {
136 return Attribute.EMPTY_SET;
137 }
138 }
139
140 /***
141 * Return the attribute for specified Class
142 * that has the specified name. If there are multiple
143 * attributes with the same name then the first
144 * attribute will be returned.
145
146 * @param clazz the class
147 * @param name the attribute name
148 * @return the attribute or null if no such attribute
149 */
150 public static Attribute getAttribute( final Class clazz,
151 final String name )
152 {
153 try
154 {
155 final ClassDescriptor descriptor = getClassInfo( clazz );
156 return getAttributeByName( descriptor.getAttributes(), name );
157 }
158 catch( final Exception e )
159 {
160 return null;
161 }
162 }
163
164 /***
165 * Return the attributes for specified Class.
166 *
167 * @param field the field
168 * @return the 'Field' attributes
169 */
170 public static Attribute[] getAttributes( final Field field )
171 {
172 try
173 {
174 return getField( field ).getAttributes();
175 }
176 catch( final Exception e )
177 {
178 return Attribute.EMPTY_SET;
179 }
180 }
181
182 /***
183 * Return the attributes for specified Field
184 * that have specified name.
185 *
186 * @param field the field
187 * @param name the attribute name
188 * @return the 'Field' attributes
189 */
190 public static Attribute[] getAttributes( final Field field,
191 final String name )
192 {
193 try
194 {
195 return getAttributesByName( getField( field ).getAttributes(), name );
196 }
197 catch( final Exception e )
198 {
199 return Attribute.EMPTY_SET;
200 }
201 }
202
203 /***
204 * Return the attribute for specified Field
205 * that has the specified name. If there are multiple
206 * attributes with the same name then the first
207 * attribute will be returned.
208
209 * @param field the field
210 * @param name the attribute name
211 * @return the attribute or null if no such attribute
212 */
213 public static Attribute getAttribute( final Field field,
214 final String name )
215 {
216 try
217 {
218 return getAttributeByName( getField( field ).getAttributes(), name );
219 }
220 catch( Exception e )
221 {
222 return null;
223 }
224 }
225
226 /***
227 * Return the attributes for specified Method.
228 *
229 * @param method the method
230 * @return the 'Method' attributes
231 */
232 public static Attribute[] getAttributes( final Method method )
233 {
234 try
235 {
236 final MethodDescriptor descriptor = getMethod( method );
237 return descriptor.getAttributes();
238 }
239 catch( final Exception e )
240 {
241 return Attribute.EMPTY_SET;
242 }
243 }
244
245 /***
246 * Return the attributes for specified Method
247 * that have specified name.
248 *
249 * @param method the Method
250 * @param name the attribute name
251 * @return the attributes
252 */
253 public static Attribute[] getAttributes( final Method method, final String name )
254 {
255 try
256 {
257 final MethodDescriptor descriptor = getMethod( method );
258 return getAttributesByName( descriptor.getAttributes(), name );
259 }
260 catch( Exception e )
261 {
262 return Attribute.EMPTY_SET;
263 }
264 }
265
266 /***
267 * Return the attribute for specified Method
268 * that has the specified name. If there are multiple
269 * attributes with the same name then the first
270 * attribute will be returned.
271
272 * @param method the method
273 * @param name the attribute name
274 * @return the attribute or null if no such attribute
275 */
276 public static Attribute getAttribute( final Method method, final String name )
277 {
278 try
279 {
280 final MethodDescriptor descriptor = getMethod( method );
281 return getAttributeByName( descriptor.getAttributes(), name );
282 }
283 catch( Exception e )
284 {
285 return null;
286 }
287 }
288
289 /***
290 * Return the attributes for specified Constructor.
291 *
292 * @param constructor the constructor
293 * @return the 'Constructor' attributes
294 */
295 public static Attribute[] getAttributes( final Constructor constructor )
296 {
297 try
298 {
299 return getConstructor( constructor ).getAttributes();
300 }
301 catch( Exception e )
302 {
303 return Attribute.EMPTY_SET;
304 }
305 }
306
307 /***
308 * Return the attributes for specified Constructor
309 * that have specified name.
310 *
311 * @param constructor the Constructor
312 * @param name the attribute name
313 * @return the attributes
314 */
315 public static Attribute[] getAttributes( final Constructor constructor,
316 final String name )
317 {
318 try
319 {
320 final Attribute[] attributes =
321 getConstructor( constructor ).getAttributes();
322 return getAttributesByName( attributes, name );
323 }
324 catch( Exception e )
325 {
326 return Attribute.EMPTY_SET;
327 }
328 }
329
330 /***
331 * Return the attribute for specified Constructor
332 * that has the specified name. If there are multiple
333 * attributes with the same name then the first
334 * attribute will be returned.
335
336 * @param constructor the constructor
337 * @param name the attribute name
338 * @return the attribute or null if no such attribute
339 */
340 public static Attribute getAttribute( final Constructor constructor, final String name )
341 {
342 try
343 {
344 final Attribute[] attributes =
345 getConstructor( constructor ).getAttributes();
346 return getAttributeByName( attributes, name );
347 }
348 catch( Exception e )
349 {
350 return null;
351 }
352 }
353
354 /***
355 * Get the FieldDescriptor with specified name
356 * for specified Class.
357 *
358 * @param field the field
359 * @return the FieldDescriptor
360 * @throws MetaClassException if unable to locate FieldDescriptor for Field
361 */
362 public static FieldDescriptor getField( final Field field )
363 throws MetaClassException
364 {
365 final FieldDescriptor[] fields =
366 getClassInfo( field.getDeclaringClass() ).getFields();
367 for( int i = 0; i < fields.length; i++ )
368 {
369 final FieldDescriptor candidate = fields[ i ];
370 if( candidate.getName().equals( field.getName() ) )
371 {
372 return candidate;
373 }
374 }
375 throw new MetaClassException( "No FieldDescriptor matching " + field );
376 }
377
378 /***
379 * Get the MethodDescriptor for specified method.
380 *
381 * @param method the method
382 * @return the MethodDescriptor
383 * @throws MetaClassException if unable to locate MethodDescriptor for Method
384 */
385 public static MethodDescriptor getMethod( final Method method )
386 throws MetaClassException
387 {
388 final Class[] parameterTypes = method.getParameterTypes();
389
390 final MethodDescriptor[] methods =
391 getClassInfo( method.getDeclaringClass() ).getMethods();
392 for( int i = 0; i < methods.length; i++ )
393 {
394 final MethodDescriptor candidate = methods[ i ];
395 final ParameterDescriptor[] parameters = candidate.getParameters();
396 if( candidate.getName().equals( method.getName() ) &&
397 parameters.length == parameterTypes.length )
398 {
399 boolean match = true;
400 for( int j = 0; j < parameters.length; j++ )
401 {
402 final ParameterDescriptor parameter = parameters[ j ];
403 final Class type = parameterTypes[ j ];
404 if( !type.getName().equals( parameter.getType() ) )
405 {
406 match = false;
407 break;
408 }
409 }
410 if( match )
411 {
412 return candidate;
413 }
414 }
415 }
416 throw new MetaClassException( "No MethodDescriptor matching " + method );
417 }
418
419 /***
420 * Get the MethodDescriptor for specified Constructor.
421 *
422 * @param constructor the Constructor
423 * @return the MethodDescriptor
424 * @throws MetaClassException if unable to locate MethodDescriptor for Constructor
425 */
426 public static MethodDescriptor getConstructor( final Constructor constructor )
427 throws MetaClassException
428 {
429 String name = constructor.getName();
430 final int index = name.lastIndexOf( "." );
431 if( -1 != index )
432 {
433 name = name.substring( index + 1 );
434 }
435 final Class[] parameterTypes = constructor.getParameterTypes();
436 final MethodDescriptor[] methods =
437 getClassInfo( constructor.getDeclaringClass() ).getMethods();
438 for( int i = 0; i < methods.length; i++ )
439 {
440 final MethodDescriptor candidate = methods[ i ];
441 final ParameterDescriptor[] parameters = candidate.getParameters();
442 if( candidate.getName().equals( name ) &&
443 parameters.length == parameterTypes.length )
444 {
445 boolean match = true;
446 for( int j = 0; j < parameters.length; j++ )
447 {
448 final String parameter = parameters[ j ].getType();
449 final String type = parameterTypes[ j ].getName();
450 if( !type.equals( parameter ) )
451 {
452 match = false;
453 break;
454 }
455 }
456 if( match )
457 {
458 return candidate;
459 }
460 }
461 }
462 throw new MetaClassException( "No MethodDescriptor matching " + constructor );
463 }
464
465 /***
466 * Utility method to get ClassDescriptor for specified class.
467 *
468 * @param clazz the class
469 * @return the ClassDescriptor
470 * @throws MetaClassException if unable to get ClassDescriptor
471 */
472 private static ClassDescriptor getClassInfo( final Class clazz )
473 throws MetaClassException
474 {
475 return MetaClassIntrospector.getClassDescriptor( clazz );
476 }
477 }