1 package net.sf.openrocket.util;
3 import java.lang.reflect.Constructor;
4 import java.lang.reflect.InvocationTargetException;
6 import net.sf.openrocket.rocketcomponent.RocketComponent;
9 public class Reflection {
11 private static final String ROCKETCOMPONENT_PACKAGE = "net.sf.openrocket.rocketcomponent";
14 * Simple wrapper class that converts the Method.invoke() exceptions into suitable
17 * @author Sampo Niskanen <sampo.niskanen@iki.fi>
19 public static class Method {
20 private final java.lang.reflect.Method method;
21 public Method(java.lang.reflect.Method m) {
25 * Same as Method.invoke(), but the possible exceptions are wrapped into
28 public Object invoke(Object obj, Object... args) {
30 return method.invoke(obj, args);
31 } catch (IllegalArgumentException e) {
32 throw new BugException("Error while invoking method '"+method+"'. "+
33 "Please report this as a bug.",e);
34 } catch (IllegalAccessException e) {
35 throw new BugException("Error while invoking method '"+method+"'. "+
36 "Please report this as a bug.",e);
37 } catch (InvocationTargetException e) {
38 throw Reflection.handleWrappedException(e);
42 * Invoke static method. Equivalent to invoke(null, args...).
44 public Object invokeStatic(Object... args) {
45 return invoke(null,args);
48 * Same as Method.toString().
51 public String toString() {
52 return method.toString();
58 * Handles an InvocationTargetException gracefully. If the cause is an unchecked
59 * exception it is thrown, otherwise it is encapsulated in a BugException.
61 * This method has a return type of Error in order to allow writing code like:
62 * <pre>throw Reflection.handleInvocationTargetException(e)</pre>
63 * This allows the compiler verifying that the call will never succeed correctly
64 * and ending that branch of execution.
66 * @param e the InvocationTargetException that occurred (not null).
67 * @return never returns normally.
69 public static Error handleWrappedException(Exception e) {
70 Throwable cause = e.getCause();
72 throw new BugException("BUG: wrapped exception without cause", e);
74 if (cause instanceof RuntimeException) {
75 throw (RuntimeException)cause;
77 if (cause instanceof Error) {
80 throw new BugException("wrapped exception occurred", cause);
86 * Throws an exception if method not found.
88 public static Reflection.Method findMethodStatic(
89 Class<? extends RocketComponent> componentClass,
90 String method, Class<?>... params) {
91 Reflection.Method m = findMethod(ROCKETCOMPONENT_PACKAGE, componentClass,
94 throw new BugException("Could not find method for componentClass="
95 +componentClass+" method="+method);
102 public static Reflection.Method findMethod(String pack, RocketComponent component,
103 String method, Class<?>...params) {
104 return findMethod(pack,component.getClass(),"",method,params);
108 public static Reflection.Method findMethod(String pack, RocketComponent component,
109 String suffix, String method, Class<?>... params) {
110 return findMethod(pack, component.getClass(), suffix, method, params);
114 public static Reflection.Method findMethod(String pack,
115 Class<? extends RocketComponent> componentClass,
116 String suffix, String method, Class<?>... params) {
117 Class<?> currentclass;
120 currentclass = componentClass;
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;
128 Class<?> c = Class.forName(name);
129 java.lang.reflect.Method m = c.getMethod(method,params);
130 return new Reflection.Method(m);
131 } catch (ClassNotFoundException ignore) {
132 } catch (NoSuchMethodException ignore) {
135 currentclass = currentclass.getSuperclass();
141 public static Object construct(String pack, RocketComponent component, String suffix,
144 Class<?> currentclass;
147 currentclass = component.getClass();
148 while ((currentclass != null) && (currentclass != Object.class)) {
149 name = currentclass.getCanonicalName();
150 if (name.lastIndexOf('.')>=0)
151 name = name.substring(name.lastIndexOf(".")+1);
152 name = pack + "." + name + suffix;
155 Class<?> c = Class.forName(name);
156 Class<?>[] paramClasses = new Class<?>[params.length];
157 for (int i=0; i < params.length; i++) {
158 paramClasses[i] = params[i].getClass();
161 // Constructors must be searched manually. Why?!
162 main: for (Constructor<?> constructor: c.getConstructors()) {
163 Class<?>[] parameterTypes = constructor.getParameterTypes();
164 if (params.length != parameterTypes.length)
166 for (int i=0; i < params.length; i++) {
167 if (!parameterTypes[i].isInstance(params[i]))
170 // Matching constructor found
171 return constructor.newInstance(params);
173 } catch (ClassNotFoundException ignore) {
174 } catch (IllegalArgumentException e) {
175 throw new BugException("Construction of "+name+" failed",e);
176 } catch (InstantiationException e) {
177 throw new BugException("Construction of "+name+" failed",e);
178 } catch (IllegalAccessException e) {
179 throw new BugException("Construction of "+name+" failed",e);
180 } catch (InvocationTargetException e) {
181 throw Reflection.handleWrappedException(e);
184 currentclass = currentclass.getSuperclass();
186 throw new BugException("Suitable constructor for component "+component+