KickJava   Java API By Example, From Geeks To Geeks.

Java > Open Source Codes > net > sf > cglib > core > ReflectUtils


1 /*
2  * Copyright 2003,2004 The Apache Software Foundation
3  *
4  * Licensed under the Apache License, Version 2.0 (the "License");
5  * you may not use this file except in compliance with the License.
6  * You may obtain a copy of the License at
7  *
8  * http://www.apache.org/licenses/LICENSE-2.0
9  *
10  * Unless required by applicable law or agreed to in writing, software
11  * distributed under the License is distributed on an "AS IS" BASIS,
12  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13  * See the License for the specific language governing permissions and
14  * limitations under the License.
15  */

16 package net.sf.cglib.core;
17
18 import java.beans.*;
19 import java.lang.reflect.*;
20 import java.security.AccessController JavaDoc;
21 import java.security.PrivilegedAction JavaDoc;
22 import java.security.ProtectionDomain JavaDoc;
23 import java.util.*;
24 import org.objectweb.asm.Attribute;
25 import org.objectweb.asm.Type;
26
27 /**
28  * @version $Id: ReflectUtils.java,v 1.29 2006/02/28 00:30:51 herbyderby Exp $
29  */

30 public class ReflectUtils {
31     private ReflectUtils() { }
32     
33     private static final Map primitives = new HashMap(8);
34     private static final Map transforms = new HashMap(8);
35     private static final ClassLoader JavaDoc defaultLoader = ReflectUtils.class.getClassLoader();
36     private static Method DEFINE_CLASS;
37     private static final ProtectionDomain JavaDoc PROTECTION_DOMAIN;
38     
39     static {
40         PROTECTION_DOMAIN = (ProtectionDomain JavaDoc)AccessController.doPrivileged(new PrivilegedAction JavaDoc() {
41             public Object JavaDoc run() {
42                 return ReflectUtils.class.getProtectionDomain();
43             }
44         });
45         
46         AccessController.doPrivileged(new PrivilegedAction JavaDoc() {
47             public Object JavaDoc run() {
48                 try {
49                     Class JavaDoc loader = Class.forName("java.lang.ClassLoader"); // JVM crash w/o this
50
DEFINE_CLASS = loader.getDeclaredMethod("defineClass",
51                                                             new Class JavaDoc[]{ String JavaDoc.class,
52                                                                          byte[].class,
53                                                                          Integer.TYPE,
54                                                                          Integer.TYPE,
55                                                                          ProtectionDomain JavaDoc.class });
56                     DEFINE_CLASS.setAccessible(true);
57                 } catch (ClassNotFoundException JavaDoc e) {
58                     throw new CodeGenerationException(e);
59                 } catch (NoSuchMethodException JavaDoc e) {
60                     throw new CodeGenerationException(e);
61                 }
62                 return null;
63             }
64         });
65     }
66         
67     private static final String JavaDoc[] CGLIB_PACKAGES = {
68         "java.lang",
69     };
70         
71     static {
72         primitives.put("byte", Byte.TYPE);
73         primitives.put("char", Character.TYPE);
74         primitives.put("double", Double.TYPE);
75         primitives.put("float", Float.TYPE);
76         primitives.put("int", Integer.TYPE);
77         primitives.put("long", Long.TYPE);
78         primitives.put("short", Short.TYPE);
79         primitives.put("boolean", Boolean.TYPE);
80             
81         transforms.put("byte", "B");
82         transforms.put("char", "C");
83         transforms.put("double", "D");
84         transforms.put("float", "F");
85         transforms.put("int", "I");
86         transforms.put("long", "J");
87         transforms.put("short", "S");
88         transforms.put("boolean", "Z");
89     }
90         
91     public static Type[] getExceptionTypes(Member member) {
92         if (member instanceof Method) {
93             return TypeUtils.getTypes(((Method)member).getExceptionTypes());
94         } else if (member instanceof Constructor) {
95             return TypeUtils.getTypes(((Constructor)member).getExceptionTypes());
96         } else {
97             throw new IllegalArgumentException JavaDoc("Cannot get exception types of a field");
98         }
99     }
100         
101     public static Signature getSignature(Member member) {
102         if (member instanceof Method) {
103             return new Signature(member.getName(), Type.getMethodDescriptor((Method)member));
104         } else if (member instanceof Constructor) {
105             Type[] types = TypeUtils.getTypes(((Constructor)member).getParameterTypes());
106             return new Signature(Constants.CONSTRUCTOR_NAME,
107                                  Type.getMethodDescriptor(Type.VOID_TYPE, types));
108                 
109         } else {
110             throw new IllegalArgumentException JavaDoc("Cannot get signature of a field");
111         }
112     }
113         
114     public static Constructor findConstructor(String JavaDoc desc) {
115         return findConstructor(desc, defaultLoader);
116     }
117         
118     public static Constructor findConstructor(String JavaDoc desc, ClassLoader JavaDoc loader) {
119         try {
120             int lparen = desc.indexOf('(');
121             String JavaDoc className = desc.substring(0, lparen).trim();
122             return getClass(className, loader).getConstructor(parseTypes(desc, loader));
123         } catch (ClassNotFoundException JavaDoc e) {
124             throw new CodeGenerationException(e);
125         } catch (NoSuchMethodException JavaDoc e) {
126             throw new CodeGenerationException(e);
127         }
128     }
129         
130     public static Method findMethod(String JavaDoc desc) {
131         return findMethod(desc, defaultLoader);
132     }
133         
134     public static Method findMethod(String JavaDoc desc, ClassLoader JavaDoc loader) {
135         try {
136             int lparen = desc.indexOf('(');
137             int dot = desc.lastIndexOf('.', lparen);
138             String JavaDoc className = desc.substring(0, dot).trim();
139             String JavaDoc methodName = desc.substring(dot + 1, lparen).trim();
140             return getClass(className, loader).getDeclaredMethod(methodName, parseTypes(desc, loader));
141         } catch (ClassNotFoundException JavaDoc e) {
142             throw new CodeGenerationException(e);
143         } catch (NoSuchMethodException JavaDoc e) {
144             throw new CodeGenerationException(e);
145         }
146     }
147         
148     private static Class JavaDoc[] parseTypes(String JavaDoc desc, ClassLoader JavaDoc loader) throws ClassNotFoundException JavaDoc {
149         int lparen = desc.indexOf('(');
150         int rparen = desc.indexOf(')', lparen);
151         List params = new ArrayList();
152         int start = lparen + 1;
153         for (;;) {
154             int comma = desc.indexOf(',', start);
155             if (comma < 0) {
156                 break;
157             }
158             params.add(desc.substring(start, comma).trim());
159             start = comma + 1;
160         }
161         if (start < rparen) {
162             params.add(desc.substring(start, rparen).trim());
163         }
164         Class JavaDoc[] types = new Class JavaDoc[params.size()];
165         for (int i = 0; i < types.length; i++) {
166             types[i] = getClass((String JavaDoc)params.get(i), loader);
167         }
168         return types;
169     }
170         
171     private static Class JavaDoc getClass(String JavaDoc className, ClassLoader JavaDoc loader) throws ClassNotFoundException JavaDoc {
172         return getClass(className, loader, CGLIB_PACKAGES);
173     }
174         
175     private static Class JavaDoc getClass(String JavaDoc className, ClassLoader JavaDoc loader, String JavaDoc[] packages) throws ClassNotFoundException JavaDoc {
176         String JavaDoc save = className;
177         int dimensions = 0;
178         int index = 0;
179         while ((index = className.indexOf("[]", index) + 1) > 0) {
180             dimensions++;
181         }
182         StringBuffer JavaDoc brackets = new StringBuffer JavaDoc(className.length() - dimensions);
183         for (int i = 0; i < dimensions; i++) {
184             brackets.append('[');
185         }
186         className = className.substring(0, className.length() - 2 * dimensions);
187             
188         String JavaDoc prefix = (dimensions > 0) ? brackets + "L" : "";
189         String JavaDoc suffix = (dimensions > 0) ? ";" : "";
190         try {
191             return Class.forName(prefix + className + suffix, false, loader);
192         } catch (ClassNotFoundException JavaDoc ignore) { }
193         for (int i = 0; i < packages.length; i++) {
194             try {
195                 return Class.forName(prefix + packages[i] + '.' + className + suffix, false, loader);
196             } catch (ClassNotFoundException JavaDoc ignore) { }
197         }
198         if (dimensions == 0) {
199             Class JavaDoc c = (Class JavaDoc)primitives.get(className);
200             if (c != null) {
201                 return c;
202             }
203         } else {
204             String JavaDoc transform = (String JavaDoc)transforms.get(className);
205             if (transform != null) {
206                 try {
207                     return Class.forName(brackets + transform, false, loader);
208                 } catch (ClassNotFoundException JavaDoc ignore) { }
209             }
210         }
211         throw new ClassNotFoundException JavaDoc(save);
212     }
213         
214         
215     public static Object JavaDoc newInstance(Class JavaDoc type) {
216         return newInstance(type, Constants.EMPTY_CLASS_ARRAY, null);
217     }
218         
219     public static Object JavaDoc newInstance(Class JavaDoc type, Class JavaDoc[] parameterTypes, Object JavaDoc[] args) {
220         return newInstance(getConstructor(type, parameterTypes), args);
221     }
222         
223     public static Object JavaDoc newInstance(final Constructor cstruct, final Object JavaDoc[] args) {
224             
225         boolean flag = cstruct.isAccessible();
226         try {
227             cstruct.setAccessible(true);
228             Object JavaDoc result = cstruct.newInstance(args);
229             return result;
230         } catch (InstantiationException JavaDoc e) {
231             throw new CodeGenerationException(e);
232         } catch (IllegalAccessException JavaDoc e) {
233             throw new CodeGenerationException(e);
234         } catch (InvocationTargetException e) {
235             throw new CodeGenerationException(e.getTargetException());
236         } finally {
237             cstruct.setAccessible(flag);
238         }
239                 
240     }
241         
242     public static Constructor getConstructor(Class JavaDoc type, Class JavaDoc[] parameterTypes) {
243         try {
244             Constructor constructor = type.getDeclaredConstructor(parameterTypes);
245             constructor.setAccessible(true);
246             return constructor;
247         } catch (NoSuchMethodException JavaDoc e) {
248             throw new CodeGenerationException(e);
249         }
250     }
251
252     public static String JavaDoc[] getNames(Class JavaDoc[] classes)
253     {
254         if (classes == null)
255             return null;
256         String JavaDoc[] names = new String JavaDoc[classes.length];
257         for (int i = 0; i < names.length; i++) {
258             names[i] = classes[i].getName();
259         }
260         return names;
261     }
262         
263     public static Class JavaDoc[] getClasses(Object JavaDoc[] objects) {
264         Class JavaDoc[] classes = new Class JavaDoc[objects.length];
265         for (int i = 0; i < objects.length; i++) {
266             classes[i] = objects[i].getClass();
267         }
268         return classes;
269     }
270         
271     public static Method findNewInstance(Class JavaDoc iface) {
272         Method m = findInterfaceMethod(iface);
273         if (!m.getName().equals("newInstance")) {
274             throw new IllegalArgumentException JavaDoc(iface + " missing newInstance method");
275         }
276         return m;
277     }
278
279     public static Method[] getPropertyMethods(PropertyDescriptor[] properties, boolean read, boolean write) {
280         Set methods = new HashSet();
281         for (int i = 0; i < properties.length; i++) {
282             PropertyDescriptor pd = properties[i];
283             if (read) {
284                 methods.add(pd.getReadMethod());
285             }
286             if (write) {
287                 methods.add(pd.getWriteMethod());
288             }
289         }
290         methods.remove(null);
291         return (Method[])methods.toArray(new Method[methods.size()]);
292     }
293         
294     public static PropertyDescriptor[] getBeanProperties(Class JavaDoc type) {
295         return getPropertiesHelper(type, true, true);
296     }
297         
298     public static PropertyDescriptor[] getBeanGetters(Class JavaDoc type) {
299         return getPropertiesHelper(type, true, false);
300     }
301         
302     public static PropertyDescriptor[] getBeanSetters(Class JavaDoc type) {
303         return getPropertiesHelper(type, false, true);
304     }
305         
306     private static PropertyDescriptor[] getPropertiesHelper(Class JavaDoc type, boolean read, boolean write) {
307         try {
308             BeanInfo info = Introspector.getBeanInfo(type, Object JavaDoc.class);
309             PropertyDescriptor[] all = info.getPropertyDescriptors();
310             if (read && write) {
311                 return all;
312             }
313             List properties = new ArrayList(all.length);
314             for (int i = 0; i < all.length; i++) {
315                 PropertyDescriptor pd = all[i];
316                 if ((read && pd.getReadMethod() != null) ||
317                     (write && pd.getWriteMethod() != null)) {
318                     properties.add(pd);
319                 }
320             }
321             return (PropertyDescriptor[])properties.toArray(new PropertyDescriptor[properties.size()]);
322         } catch (IntrospectionException e) {
323             throw new CodeGenerationException(e);
324         }
325     }
326         
327         
328         
329     public static Method findDeclaredMethod(final Class JavaDoc type,
330                                             final String JavaDoc methodName, final Class JavaDoc[] parameterTypes)
331     throws NoSuchMethodException JavaDoc {
332                         
333         Class JavaDoc cl = type;
334         while (cl != null) {
335             try {
336                 return cl.getDeclaredMethod(methodName, parameterTypes);
337             } catch (NoSuchMethodException JavaDoc e) {
338                 cl = cl.getSuperclass();
339             }
340         }
341         throw new NoSuchMethodException JavaDoc(methodName);
342             
343     }
344         
345     public static List addAllMethods(final Class JavaDoc type, final List list) {
346             
347             
348         list.addAll(java.util.Arrays.asList(type.getDeclaredMethods()));
349         Class JavaDoc superclass = type.getSuperclass();
350         if (superclass != null) {
351             addAllMethods(superclass, list);
352         }
353         Class JavaDoc[] interfaces = type.getInterfaces();
354         for (int i = 0; i < interfaces.length; i++) {
355             addAllMethods(interfaces[i], list);
356         }
357             
358         return list;
359     }
360         
361     public static List addAllInterfaces(Class JavaDoc type, List list) {
362         Class JavaDoc superclass = type.getSuperclass();
363         if (superclass != null) {
364             list.addAll(Arrays.asList(type.getInterfaces()));
365             addAllInterfaces(superclass, list);
366         }
367         return list;
368     }
369         
370         
371     public static Method findInterfaceMethod(Class JavaDoc iface) {
372         if (!iface.isInterface()) {
373             throw new IllegalArgumentException JavaDoc(iface + " is not an interface");
374         }
375         Method[] methods = iface.getDeclaredMethods();
376         if (methods.length != 1) {
377             throw new IllegalArgumentException JavaDoc("expecting exactly 1 method in " + iface);
378         }
379         return methods[0];
380     }
381         
382     public static Class JavaDoc defineClass(String JavaDoc className, byte[] b, ClassLoader JavaDoc loader) throws Exception JavaDoc {
383         Object JavaDoc[] args = new Object JavaDoc[]{className, b, new Integer JavaDoc(0), new Integer JavaDoc(b.length), PROTECTION_DOMAIN };
384         return (Class JavaDoc)DEFINE_CLASS.invoke(loader, args);
385     }
386         
387     public static int findPackageProtected(Class JavaDoc[] classes) {
388         for (int i = 0; i < classes.length; i++) {
389             if (!Modifier.isPublic(classes[i].getModifiers())) {
390                 return i;
391             }
392         }
393         return 0;
394     }
395
396     public static MethodInfo getMethodInfo(final Member member, final int modifiers) {
397         final Signature sig = getSignature(member);
398         return new MethodInfo() {
399             private ClassInfo ci;
400             public ClassInfo getClassInfo() {
401                 if (ci == null)
402                     ci = ReflectUtils.getClassInfo(member.getDeclaringClass());
403                 return ci;
404             }
405             public int getModifiers() {
406                 return modifiers;
407             }
408             public Signature getSignature() {
409                 return sig;
410             }
411             public Type[] getExceptionTypes() {
412                 return ReflectUtils.getExceptionTypes(member);
413             }
414             public Attribute getAttribute() {
415                 return null;
416             }
417         };
418     }
419
420     public static MethodInfo getMethodInfo(Member member) {
421         return getMethodInfo(member, member.getModifiers());
422     }
423
424     public static ClassInfo getClassInfo(final Class JavaDoc clazz) {
425         final Type type = Type.getType(clazz);
426         final Type sc = (clazz.getSuperclass() == null) ? null : Type.getType(clazz.getSuperclass());
427         return new ClassInfo() {
428             public Type getType() {
429                 return type;
430             }
431             public Type getSuperType() {
432                 return sc;
433             }
434             public Type[] getInterfaces() {
435                 return TypeUtils.getTypes(clazz.getInterfaces());
436             }
437             public int getModifiers() {
438                 return clazz.getModifiers();
439             }
440         };
441     }
442
443     // used by MethodInterceptorGenerated generated code
444
public static Method[] findMethods(String JavaDoc[] namesAndDescriptors, Method[] methods)
445     {
446         Map map = new HashMap();
447         for (int i = 0; i < methods.length; i++) {
448             Method method = methods[i];
449             map.put(method.getName() + Type.getMethodDescriptor(method), method);
450         }
451         Method[] result = new Method[namesAndDescriptors.length / 2];
452         for (int i = 0; i < result.length; i++) {
453             result[i] = (Method)map.get(namesAndDescriptors[i * 2] + namesAndDescriptors[i * 2 + 1]);
454             if (result[i] == null) {
455                 // TODO: error?
456
}
457         }
458         return result;
459     }
460 }
461
Popular Tags