)this.sortMap.clone();
return other;
} catch (CloneNotSupportedException e) {
- throw new RuntimeException("CloneNotSupportedException?!",e);
+ throw new BugException("CloneNotSupportedException?!",e);
}
}
diff --git a/src/net/sf/openrocket/util/Pair.java b/src/net/sf/openrocket/util/Pair.java
index e95587b5c..9a562cb85 100644
--- a/src/net/sf/openrocket/util/Pair.java
+++ b/src/net/sf/openrocket/util/Pair.java
@@ -62,4 +62,10 @@ public class Pair {
return ((u != null) ? u.hashCode() : 0) + ((v != null) ? v.hashCode() : 0);
}
+
+ @Override
+ public String toString() {
+ return "[" + u + ";" + v + "]";
+ }
+
}
diff --git a/src/net/sf/openrocket/util/Prefs.java b/src/net/sf/openrocket/util/Prefs.java
index 70a3e558e..eb2e3d473 100644
--- a/src/net/sf/openrocket/util/Prefs.java
+++ b/src/net/sf/openrocket/util/Prefs.java
@@ -142,7 +142,7 @@ public class Prefs {
root.node(NODENAME).removeNode();
}
} catch (BackingStoreException e) {
- throw new RuntimeException("Unable to clear preference node",e);
+ throw new BugException("Unable to clear preference node",e);
}
}
PREFNODE = root.node(NODENAME);
diff --git a/src/net/sf/openrocket/util/Quaternion.java b/src/net/sf/openrocket/util/Quaternion.java
index 3c457caba..ee2a2d25a 100644
--- a/src/net/sf/openrocket/util/Quaternion.java
+++ b/src/net/sf/openrocket/util/Quaternion.java
@@ -135,7 +135,7 @@ public class Quaternion implements Cloneable {
try {
return (Quaternion) super.clone();
} catch (CloneNotSupportedException e) {
- throw new RuntimeException("CloneNotSupportedException encountered");
+ throw new BugException("CloneNotSupportedException encountered");
}
}
diff --git a/src/net/sf/openrocket/util/Reflection.java b/src/net/sf/openrocket/util/Reflection.java
index 26c00beff..d837a4971 100644
--- a/src/net/sf/openrocket/util/Reflection.java
+++ b/src/net/sf/openrocket/util/Reflection.java
@@ -29,14 +29,13 @@ public class Reflection {
try {
return method.invoke(obj, args);
} catch (IllegalArgumentException e) {
- throw new RuntimeException("Error while invoking method '"+method+"'. "+
+ throw new BugException("Error while invoking method '"+method+"'. "+
"Please report this as a bug.",e);
} catch (IllegalAccessException e) {
- throw new RuntimeException("Error while invoking method '"+method+"'. "+
+ throw new BugException("Error while invoking method '"+method+"'. "+
"Please report this as a bug.",e);
} catch (InvocationTargetException e) {
- throw new RuntimeException("Error while invoking method '"+method+"'. "+
- "Please report this as a bug.",e);
+ throw Reflection.handleInvocationTargetException(e);
}
}
/**
@@ -55,6 +54,34 @@ public class Reflection {
}
+ /**
+ * Handles an InvocationTargetException gracefully. If the cause is an unchecked
+ * exception it is thrown, otherwise it is encapsulated in a BugException.
+ *
+ * This method has a return type of Error in order to allow writing code like:
+ *
throw Reflection.handleInvocationTargetException(e)
+ * This allows the compiler verifying that the call will never succeed correctly
+ * and ending that branch of execution.
+ *
+ * @param e the InvocationTargetException that occurred (not null).
+ * @return never returns normally.
+ */
+ public static Error handleInvocationTargetException(InvocationTargetException e) {
+ Throwable cause = e.getCause();
+ if (cause == null) {
+ throw new BugException("BUG: InvocationTargetException without cause", e);
+ }
+ if (cause instanceof RuntimeException) {
+ throw (RuntimeException)cause;
+ }
+ if (cause instanceof Error) {
+ throw (Error)cause;
+ }
+ throw new BugException("InvocationTargetException occurred", cause);
+ }
+
+
+
/**
* Throws an exception if method not found.
*/
@@ -64,7 +91,7 @@ public class Reflection {
Reflection.Method m = findMethod(ROCKETCOMPONENT_PACKAGE, componentClass,
"", method, params);
if (m == null) {
- throw new RuntimeException("Could not find method for componentClass="
+ throw new BugException("Could not find method for componentClass="
+componentClass+" method="+method);
}
return m;
@@ -145,18 +172,18 @@ public class Reflection {
}
} catch (ClassNotFoundException ignore) {
} catch (IllegalArgumentException e) {
- throw new RuntimeException("Construction of "+name+" failed",e);
+ throw new BugException("Construction of "+name+" failed",e);
} catch (InstantiationException e) {
- throw new RuntimeException("Construction of "+name+" failed",e);
+ throw new BugException("Construction of "+name+" failed",e);
} catch (IllegalAccessException e) {
- throw new RuntimeException("Construction of "+name+" failed",e);
+ throw new BugException("Construction of "+name+" failed",e);
} catch (InvocationTargetException e) {
- throw new RuntimeException("Construction of "+name+" failed",e);
+ throw Reflection.handleInvocationTargetException(e);
}
currentclass = currentclass.getSuperclass();
}
- throw new RuntimeException("Suitable constructor for component "+component+
+ throw new BugException("Suitable constructor for component "+component+
" not found");
}
}
diff --git a/src/net/sf/openrocket/util/SaveCSVWorker.java b/src/net/sf/openrocket/util/SaveCSVWorker.java
index a4a65c46c..aeb68ad49 100644
--- a/src/net/sf/openrocket/util/SaveCSVWorker.java
+++ b/src/net/sf/openrocket/util/SaveCSVWorker.java
@@ -118,11 +118,11 @@ public class SaveCSVWorker extends SwingWorker {
e.getMessage() }, "Saving failed", JOptionPane.ERROR_MESSAGE);
return false;
} else {
- throw new RuntimeException("Unknown error when saving file", e);
+ throw new BugException("Unknown error when saving file", e);
}
} catch (InterruptedException e) {
- throw new RuntimeException("EDT was interrupted", e);
+ throw new BugException("EDT was interrupted", e);
}
return true;
diff --git a/test/net/sf/openrocket/communication/HttpURLConnectionMock.java b/test/net/sf/openrocket/communication/HttpURLConnectionMock.java
index 0ae317b38..ab5c48ab7 100644
--- a/test/net/sf/openrocket/communication/HttpURLConnectionMock.java
+++ b/test/net/sf/openrocket/communication/HttpURLConnectionMock.java
@@ -16,6 +16,8 @@ import java.util.HashMap;
import java.util.List;
import java.util.Map;
+import net.sf.openrocket.util.BugException;
+
public class HttpURLConnectionMock extends HttpURLConnection {
private static final URL MOCK_URL;
@@ -23,7 +25,7 @@ public class HttpURLConnectionMock extends HttpURLConnection {
try {
MOCK_URL = new URL("http://localhost/");
} catch (MalformedURLException e) {
- throw new RuntimeException(e);
+ throw new BugException(e);
}
}
diff --git a/test/net/sf/openrocket/util/ReflectionTest.java b/test/net/sf/openrocket/util/ReflectionTest.java
new file mode 100644
index 000000000..217332bef
--- /dev/null
+++ b/test/net/sf/openrocket/util/ReflectionTest.java
@@ -0,0 +1,50 @@
+package net.sf.openrocket.util;
+
+import static org.junit.Assert.*;
+
+import java.io.IOException;
+import java.lang.reflect.InvocationTargetException;
+
+import org.junit.Test;
+
+public class ReflectionTest {
+
+ @Test
+ public void textHandleInvocationTargetException() {
+ Throwable cause = null;
+
+ try {
+ cause = new InvocationTargetException(null);
+ Reflection.handleInvocationTargetException((InvocationTargetException)cause);
+ fail();
+ } catch (BugException e) {
+ assertTrue(cause == e.getCause());
+ }
+
+ try {
+ cause = new IllegalStateException("Test");
+ Reflection.handleInvocationTargetException(new InvocationTargetException(cause));
+ fail();
+ } catch (IllegalStateException e) {
+ assertTrue(cause == e);
+ }
+
+ try {
+ cause = new AbstractMethodError();
+ Reflection.handleInvocationTargetException(new InvocationTargetException(cause));
+ fail();
+ } catch (AbstractMethodError e) {
+ assertTrue(cause == e);
+ }
+
+ try {
+ cause = new IOException();
+ Reflection.handleInvocationTargetException(new InvocationTargetException(cause));
+ fail();
+ } catch (BugException e) {
+ assertTrue(cause == e.getCause());
+ }
+
+ }
+
+}