Initial commit
[debian/openrocket] / src / net / sf / openrocket / util / Reflection.java
1 package net.sf.openrocket.util;
2
3 import java.lang.reflect.Constructor;
4 import java.lang.reflect.InvocationTargetException;
5
6 import net.sf.openrocket.rocketcomponent.RocketComponent;
7
8
9 public class Reflection {
10         
11         private static final String ROCKETCOMPONENT_PACKAGE = "net.sf.openrocket.rocketcomponent";
12         
13         /**
14          * Simple wrapper class that converts the Method.invoke() exceptions into suitable
15          * RuntimeExceptions.
16          * 
17          * @author Sampo Niskanen <sampo.niskanen@iki.fi>
18          */
19         public static class Method {
20                 private final java.lang.reflect.Method method;
21                 public Method(java.lang.reflect.Method m) {
22                         method = m;
23                 }
24                 /**
25                  * Same as Method.invoke(), but the possible exceptions are wrapped into 
26                  * RuntimeExceptions.
27                  */
28                 public Object invoke(Object obj, Object... args) {
29                         try {
30                                 return method.invoke(obj, args);
31                         } catch (IllegalArgumentException e) {
32                                 throw new RuntimeException("Error while invoking method '"+method+"'. "+
33                                                 "Please report this as a bug.",e);
34                         } catch (IllegalAccessException e) {
35                                 throw new RuntimeException("Error while invoking method '"+method+"'. "+
36                                                 "Please report this as a bug.",e);
37                         } catch (InvocationTargetException e) {
38                                 throw new RuntimeException("Error while invoking method '"+method+"'. "+
39                                                 "Please report this as a bug.",e);
40                         }
41                 }
42                 /**
43                  * Invoke static method.  Equivalent to invoke(null, args...).
44                  */
45                 public Object invokeStatic(Object... args) {
46                         return invoke(null,args);
47                 }
48                 /**
49                  * Same as Method.toString().
50                  */
51                 @Override
52                 public String toString() {
53                         return method.toString();
54                 }
55         }
56         
57         
58         /**
59          * Throws an exception if method not found.
60          */
61         public static Reflection.Method findMethodStatic(
62                         Class<? extends RocketComponent> componentClass,
63                         String method, Class<?>... params) {
64                 Reflection.Method m = findMethod(ROCKETCOMPONENT_PACKAGE, componentClass, 
65                                 "", method, params);
66                 if (m == null) {
67                         throw new RuntimeException("Could not find method for componentClass="
68                                         +componentClass+" method="+method);
69                 }
70                 return m;
71         }
72         
73         
74         
75         public static Reflection.Method findMethod(String pack, RocketComponent component, 
76                         String method, Class<?>...params) {
77                 return findMethod(pack,component.getClass(),"",method,params);
78         }
79         
80         
81         public static Reflection.Method findMethod(String pack, RocketComponent component, 
82                         String suffix, String method, Class<?>... params) {
83                 return findMethod(pack, component.getClass(), suffix, method, params);
84         }
85
86         
87         public static Reflection.Method findMethod(String pack, 
88                         Class<? extends RocketComponent> componentClass, 
89                         String suffix, String method, Class<?>... params) {
90                 Class<?> currentclass;
91                 String name;
92                 
93                 currentclass = componentClass;
94                 while ((currentclass != null) && (currentclass != Object.class)) {
95                         name = currentclass.getCanonicalName();
96                         if (name.lastIndexOf('.')>=0)
97                                 name = name.substring(name.lastIndexOf(".")+1);
98                         name = pack + "." + name + suffix;
99                         
100                         try {
101                                 Class<?> c = Class.forName(name);
102                                 java.lang.reflect.Method m = c.getMethod(method,params);
103                                 return new Reflection.Method(m);
104                         } catch (ClassNotFoundException ignore) {
105                         } catch (NoSuchMethodException ignore) {
106                         }
107
108                         currentclass = currentclass.getSuperclass();
109                 }
110                 return null;
111         }
112         
113         
114         public static Object construct(String pack, RocketComponent component, String suffix,
115                         Object... params) {
116                 
117                 Class<?> currentclass;
118                 String name;
119                 
120                 currentclass = component.getClass();
121                 while ((currentclass != null) && (currentclass != Object.class)) {
122                         name = currentclass.getCanonicalName();
123                         if (name.lastIndexOf('.')>=0)
124                                 name = name.substring(name.lastIndexOf(".")+1);
125                         name = pack + "." + name + suffix;
126                         
127                         try {
128                                 Class<?> c = Class.forName(name);
129                                 Class<?>[] paramClasses = new Class<?>[params.length];
130                                 for (int i=0; i < params.length; i++) {
131                                         paramClasses[i] = params[i].getClass();
132                                 }
133                                 
134                                 // Constructors must be searched manually.  Why?!
135                                 main: for (Constructor<?> constructor: c.getConstructors()) {
136                                         Class<?>[] parameterTypes = constructor.getParameterTypes();
137                                         if (params.length != parameterTypes.length)
138                                                 continue;
139                                         for (int i=0; i < params.length; i++) {
140                                                 if (!parameterTypes[i].isInstance(params[i])) 
141                                                         continue main;
142                                         }
143                                         // Matching constructor found
144                                         return constructor.newInstance(params);
145                                 }
146                         } catch (ClassNotFoundException ignore) {
147                         } catch (IllegalArgumentException e) {
148                                 throw new RuntimeException("Construction of "+name+" failed",e);
149                         } catch (InstantiationException e) {
150                                 throw new RuntimeException("Construction of "+name+" failed",e);
151                         } catch (IllegalAccessException e) {
152                                 throw new RuntimeException("Construction of "+name+" failed",e);
153                         } catch (InvocationTargetException e) {
154                                 throw new RuntimeException("Construction of "+name+" failed",e);
155                         }
156
157                         currentclass = currentclass.getSuperclass();
158                 }
159                 throw new RuntimeException("Suitable constructor for component "+component+ 
160                                 " not found");
161         }
162 }