KickJava   Java API By Example, From Geeks To Geeks.

Java > Open Source Codes > org > logicalcobwebs > cglib > core > ReflectUtils


1 /*
2  * The Apache Software License, Version 1.1
3  *
4  * Copyright (c) 2002 The Apache Software Foundation. All rights
5  * reserved.
6  *
7  * Redistribution and use in source and binary forms, with or without
8  * modification, are permitted provided that the following conditions
9  * are met:
10  *
11  * 1. Redistributions of source code must retain the above copyright
12  * notice, this list of conditions and the following disclaimer.
13  *
14  * 2. Redistributions in binary form must reproduce the above copyright
15  * notice, this list of conditions and the following disclaimer in
16  * the documentation and/or other materials provided with the
17  * distribution.
18  *
19  * 3. The end-user documentation included with the redistribution,
20  * if any, must include the following acknowledgment:
21  * "This product includes software developed by the
22  * Apache Software Foundation (http://www.apache.org/)."
23  * Alternately, this acknowledgment may appear in the software itself,
24  * if and wherever such third-party acknowledgments normally appear.
25  *
26  * 4. The names "Apache" and "Apache Software Foundation" must
27  * not be used to endorse or promote products derived from this
28  * software without prior written permission. For written
29  * permission, please contact apache@apache.org.
30  *
31  * 5. Products derived from this software may not be called "Apache",
32  * nor may "Apache" appear in their name, without prior written
33  * permission of the Apache Software Foundation.
34  *
35  * THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESSED OR IMPLIED
36  * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
37  * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
38  * DISCLAIMED. IN NO EVENT SHALL THE APACHE SOFTWARE FOUNDATION OR
39  * ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
40  * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
41  * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF
42  * USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
43  * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
44  * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT
45  * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
46  * SUCH DAMAGE.
47  * ====================================================================
48  *
49  * This software consists of voluntary contributions made by many
50  * individuals on behalf of the Apache Software Foundation. For more
51  * information on the Apache Software Foundation, please see
52  * <http://www.apache.org/>.
53  */

54 package org.logicalcobwebs.cglib.core;
55
56 import java.beans.*;
57 import java.lang.reflect.*;
58 import java.util.*;
59 import org.logicalcobwebs.asm.Type;
60
61 /**
62  * @version $Id: ReflectUtils.java,v 1.1 2003/12/12 19:28:11 billhorsman Exp $
63  */

64 public class ReflectUtils {
65     private ReflectUtils() { }
66     
67     private static final Map primitives = new HashMap(8);
68     private static final Map transforms = new HashMap(8);
69     private static final ClassLoader JavaDoc defaultLoader = ReflectUtils.class.getClassLoader();
70     private static final RuntimePermission JavaDoc DEFINE_CGLIB_CLASS_IN_JAVA_PACKAGE_PERMISSION =
71       new RuntimePermission JavaDoc("defineCGLIBClassInJavaPackage");
72     private static final Method DEFINE_CLASS;
73
74     static {
75         try {
76             DEFINE_CLASS = ClassLoader JavaDoc.class.getDeclaredMethod("defineClass", new Class JavaDoc[]{ byte[].class, int.class, int.class });
77         } catch (NoSuchMethodException JavaDoc e) {
78             throw new CodeGenerationException(e);
79         }
80     }
81
82     private static final String JavaDoc[] CGLIB_PACKAGES = {
83         "java.lang",
84     };
85
86     static {
87         primitives.put("byte", Byte.TYPE);
88         primitives.put("char", Character.TYPE);
89         primitives.put("double", Double.TYPE);
90         primitives.put("float", Float.TYPE);
91         primitives.put("int", Integer.TYPE);
92         primitives.put("long", Long.TYPE);
93         primitives.put("short", Short.TYPE);
94         primitives.put("boolean", Boolean.TYPE);
95
96         transforms.put("byte", "B");
97         transforms.put("char", "C");
98         transforms.put("double", "D");
99         transforms.put("float", "F");
100         transforms.put("int", "I");
101         transforms.put("long", "J");
102         transforms.put("short", "S");
103         transforms.put("boolean", "Z");
104     }
105
106     public static Type[] getExceptionTypes(Member member) {
107         if (member instanceof Method) {
108             return TypeUtils.getTypes(((Method)member).getExceptionTypes());
109         } else if (member instanceof Constructor) {
110             return TypeUtils.getTypes(((Constructor)member).getExceptionTypes());
111         } else {
112             throw new IllegalArgumentException JavaDoc("Cannot get exception types of a field");
113         }
114     }
115
116     public static Signature getSignature(Member member) {
117         if (member instanceof Method) {
118             return new Signature(member.getName(), Type.getMethodDescriptor((Method)member));
119         } else if (member instanceof Constructor) {
120             Type[] types = TypeUtils.getTypes(((Constructor)member).getParameterTypes());
121             return new Signature(Constants.CONSTRUCTOR_NAME,
122                                  Type.getMethodDescriptor(Type.VOID_TYPE, types));
123                                                           
124         } else {
125             throw new IllegalArgumentException JavaDoc("Cannot get signature of a field");
126         }
127     }
128
129     public static Constructor findConstructor(String JavaDoc desc) {
130          return findConstructor(desc, defaultLoader);
131     }
132
133     public static Constructor findConstructor(String JavaDoc desc, ClassLoader JavaDoc loader) {
134         try {
135             int lparen = desc.indexOf('(');
136             String JavaDoc className = desc.substring(0, lparen).trim();
137             return getClass(className, loader).getConstructor(parseTypes(desc, loader));
138         } catch (ClassNotFoundException JavaDoc e) {
139             throw new CodeGenerationException(e);
140         } catch (NoSuchMethodException JavaDoc e) {
141             throw new CodeGenerationException(e);
142         }
143     }
144
145     public static Method findMethod(String JavaDoc desc) {
146         return findMethod(desc, defaultLoader);
147     }
148
149     public static Method findMethod(String JavaDoc desc, ClassLoader JavaDoc loader) {
150         try {
151             int lparen = desc.indexOf('(');
152             int dot = desc.lastIndexOf('.', lparen);
153             String JavaDoc className = desc.substring(0, dot).trim();
154             String JavaDoc methodName = desc.substring(dot + 1, lparen).trim();
155             return getClass(className, loader).getDeclaredMethod(methodName, parseTypes(desc, loader));
156         } catch (ClassNotFoundException JavaDoc e) {
157             throw new CodeGenerationException(e);
158         } catch (NoSuchMethodException JavaDoc e) {
159             throw new CodeGenerationException(e);
160         }
161     }
162
163     private static Class JavaDoc[] parseTypes(String JavaDoc desc, ClassLoader JavaDoc loader) throws ClassNotFoundException JavaDoc {
164         int lparen = desc.indexOf('(');
165         int rparen = desc.indexOf(')', lparen);
166         List params = new ArrayList();
167         int start = lparen + 1;
168         for (;;) {
169             int comma = desc.indexOf(',', start);
170             if (comma < 0) {
171                 break;
172             }
173             params.add(desc.substring(start, comma).trim());
174             start = comma + 1;
175         }
176         if (start < rparen) {
177             params.add(desc.substring(start, rparen).trim());
178         }
179         Class JavaDoc[] types = new Class JavaDoc[params.size()];
180         for (int i = 0; i < types.length; i++) {
181             types[i] = getClass((String JavaDoc)params.get(i), loader);
182         }
183         return types;
184     }
185
186     private static Class JavaDoc getClass(String JavaDoc className, ClassLoader JavaDoc loader) throws ClassNotFoundException JavaDoc {
187         return getClass(className, loader, CGLIB_PACKAGES);
188     }
189     
190     private static Class JavaDoc getClass(String JavaDoc className, ClassLoader JavaDoc loader, String JavaDoc[] packages) throws ClassNotFoundException JavaDoc {
191         String JavaDoc save = className;
192         int dimensions = 0;
193         int index = 0;
194         while ((index = className.indexOf("[]", index) + 1) > 0) {
195             dimensions++;
196         }
197         StringBuffer JavaDoc brackets = new StringBuffer JavaDoc(className.length() - dimensions);
198         for (int i = 0; i < dimensions; i++) {
199             brackets.append('[');
200         }
201         className = className.substring(0, className.length() - 2 * dimensions);
202
203         String JavaDoc prefix = (dimensions > 0) ? brackets + "L" : "";
204         String JavaDoc suffix = (dimensions > 0) ? ";" : "";
205         try {
206             return Class.forName(prefix + className + suffix, false, loader);
207         } catch (ClassNotFoundException JavaDoc ignore) { }
208         for (int i = 0; i < packages.length; i++) {
209             try {
210                 return Class.forName(prefix + packages[i] + '.' + className + suffix, false, loader);
211             } catch (ClassNotFoundException JavaDoc ignore) { }
212         }
213         if (dimensions == 0) {
214             Class JavaDoc c = (Class JavaDoc)primitives.get(className);
215             if (c != null) {
216                 return c;
217             }
218         } else {
219             String JavaDoc transform = (String JavaDoc)transforms.get(className);
220             if (transform != null) {
221                 try {
222                     return Class.forName(brackets + transform, false, loader);
223                 } catch (ClassNotFoundException JavaDoc ignore) { }
224             }
225         }
226         throw new ClassNotFoundException JavaDoc(save);
227     }
228
229
230     public static Object JavaDoc newInstance(Class JavaDoc type) {
231         return newInstance(type, Constants.EMPTY_CLASS_ARRAY, null);
232     }
233
234     public static Object JavaDoc newInstance(Class JavaDoc type, Class JavaDoc[] parameterTypes, Object JavaDoc[] args) {
235         return newInstance(getConstructor(type, parameterTypes), args);
236     }
237
238     public static Object JavaDoc newInstance(Constructor cstruct, Object JavaDoc[] args) {
239         boolean flag = cstruct.isAccessible();
240         try {
241             cstruct.setAccessible(true);
242             Object JavaDoc result = cstruct.newInstance(args);
243             return result;
244         } catch (InstantiationException JavaDoc e) {
245             throw new CodeGenerationException(e);
246         } catch (IllegalAccessException JavaDoc e) {
247             throw new CodeGenerationException(e);
248         } catch (InvocationTargetException e) {
249             throw new CodeGenerationException(e.getTargetException());
250         } finally {
251             cstruct.setAccessible(flag);
252         }
253     }
254
255     public static Constructor getConstructor(Class JavaDoc type, Class JavaDoc[] parameterTypes) {
256         try {
257             return type.getConstructor(parameterTypes);
258         } catch (NoSuchMethodException JavaDoc e) {
259             throw new CodeGenerationException(e);
260         }
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     public static Method findDeclaredMethod(Class JavaDoc type, String JavaDoc methodName, Class JavaDoc[] parameterTypes)
328     throws NoSuchMethodException JavaDoc {
329         Class JavaDoc cl = type;
330         while (cl != null) {
331             try {
332                 return cl.getDeclaredMethod(methodName, parameterTypes);
333             } catch (NoSuchMethodException JavaDoc e) {
334                 cl = cl.getSuperclass();
335             }
336         }
337         throw new NoSuchMethodException JavaDoc(methodName);
338     }
339
340     public static List addAllMethods(Class JavaDoc type, List list) {
341         list.addAll(java.util.Arrays.asList(type.getDeclaredMethods()));
342         Class JavaDoc superclass = type.getSuperclass();
343         if (superclass != null) {
344             addAllMethods(superclass, list);
345         }
346         Class JavaDoc[] interfaces = type.getInterfaces();
347         for (int i = 0; i < interfaces.length; i++) {
348             addAllMethods(interfaces[i], list);
349         }
350         return list;
351     }
352
353     public static Method findInterfaceMethod(Class JavaDoc iface) {
354         if (!iface.isInterface()) {
355             throw new IllegalArgumentException JavaDoc(iface + " is not an interface");
356         }
357         Method[] methods = iface.getDeclaredMethods();
358         if (methods.length != 1) {
359             throw new IllegalArgumentException JavaDoc("expecting exactly 1 method in " + iface);
360         }
361         return methods[0];
362     }
363
364     public static Class JavaDoc defineClass(String JavaDoc className, byte[] b, ClassLoader JavaDoc loader) throws Exception JavaDoc {
365         SecurityManager JavaDoc sm = System.getSecurityManager();
366         if (className != null && className.startsWith("java.") && sm != null) {
367             sm.checkPermission(DEFINE_CGLIB_CLASS_IN_JAVA_PACKAGE_PERMISSION);
368         }
369         // deprecated method in jdk to define classes, used because it
370
// does not throw SecurityException if class name starts with "java."
371
Object JavaDoc[] args = new Object JavaDoc[]{ b, new Integer JavaDoc(0), new Integer JavaDoc(b.length) };
372         DEFINE_CLASS.setAccessible(true);
373         return (Class JavaDoc)DEFINE_CLASS.invoke(loader, args);
374     }
375
376     public static int findPackageProtected(Class JavaDoc[] classes) {
377         for (int i = 0; i < classes.length; i++) {
378             if (!Modifier.isPublic(classes[i].getModifiers())) {
379                 return i;
380             }
381         }
382         return 0;
383     }
384 }
385
Popular Tags