Updates for 0.9.5

This commit is contained in:
Sampo Niskanen 2009-11-28 14:28:39 +00:00
parent 71a94858c4
commit 72f84c56e0
65 changed files with 531 additions and 160 deletions

View File

@ -1,3 +1,15 @@
2009-11-28 Sampo Niskanen
* Released version 0.9.5
* [BUG] NPE when clearing combo box selections
* Minor fixes to update checking
* Added a few guidance texts
2009-11-27 Sampo Niskanen
* [BUG] Fixed computing inner radius of centering ring
* Removed RuntimeException instantiation from all classes
2009-11-24 Sampo Niskanen
* Released version 0.9.4

View File

@ -1,4 +1,11 @@
OpenRocket 0.9.5 (2009-11-28):
-------------------------------
Fixed a serious defect which prevented adding a tube coupler and
centering ring on the same body tube. Other minor improvements.
OpenRocket 0.9.4 (2009-11-24):
-------------------------------

53
TODO
View File

@ -1,15 +1,12 @@
Feature roadmap for OpenRocket 1.0
----------------------------------
Must-have:
- Go through thrust curves and correct errors
or
- Hide duplicate motors
Bugs:
- Go through thrust curves and select best ones
- Updated splash screen
@ -20,28 +17,53 @@ Maybe:
- Add slight randomness to yaw moment
Postponed:
----------
Motor support:
- Integration with thrustcurve.org (syncing?)
- Reading thrust curves from external directory
- Plot motor thrust curve
- Water rocket modelling
- Screw weights for nose cones / transitions
Running:
- Windows executable wrapper (launch4j)
- Allow only one instance of OpenRocket running (RMI communication)
- Running from command line
UI issues:
- Only schedule rocket figure update instead of each time updating it
- Reading (writing) .RKT format
- Importing flight data (file/altimeter)
- Water rocket modelling
- Landing scatter plots
- Simulate other branches
- Saving as SVG
- Implement setDefaults() method for RocketComponent
- BUG: Inner tube cluster rotation, edit with spinner arrows, slider wrong
- NAR/CNES/etc competition validity checking
- Running from command line
- Print support
- Saving as SVG
Simulation:
- Landing scatter plots
- Simulate other branches
Component support:
- Screw weights for nose cones / transitions
- Support for external pods
- Support for tube fins
Other:
- Reading (writing) .RKT format
Refactoring tasks:
@ -57,7 +79,7 @@ Refactoring tasks:
Done:
-----
- Search field in motor selection dialog
- Motor selection/editing from Edit configurations dialog
- Change FreeformFinSet to throw checked exceptions
@ -88,4 +110,5 @@ In 0.9.4:
- Simulation plot dialog forces dialog one button row too high (All/None)
- Add styrofoam and depron materials
- Inform user about software updates
In 0.9.5:
- Add label to motor panel to tell current number of stages

View File

@ -1,7 +1,7 @@
# The OpenRocket build version
build.version=0.9.5pre
build.version=0.9.5
# The source of the package. When building a package for a specific

Binary file not shown.

BIN
dists/OpenRocket-0.9.5.jar Normal file

Binary file not shown.

View File

@ -39,8 +39,11 @@ foreach (getallheaders() as $header => $value) {
}
// Log the request
if (strlen($orversion) > 0 || strlen($orid) > 0 || strlen($oros) > 0
|| strlen($orjava) > 0 || strlen($orcountry) > 0) {
if ((strlen($orversion) > 0 || strlen($orid) > 0 || strlen($oros) > 0
|| strlen($orjava) > 0 || strlen($orcountry) > 0) &&
(strlen($orversion) < 20 && strlen($orid) < 50 && strlen($oros) < 50
&& strlen($orjava) < 50 && strlen($orcountry) < 50)) {
$file = $logfiles . gmdate("Y-m");
$line = gmdate("Y-m-d H:i:s") . ";" . $orid . ";" . $orversion .
@ -55,11 +58,33 @@ if (strlen($orversion) > 0 || strlen($orid) > 0 || strlen($oros) > 0
// Set HTTP content-type header
header("Content-type: text/plain; charset=utf-8");
// No charset allowed for 0.9.4
//header("Content-type: text/plain; charset=utf-8");
header("Content-type: text/plain");
/*
* Currently all old versions are handled manually.
* Update checking was introduced in OpenRocket 0.9.4
*/
$version = $_GET["version"];
$updates = "";
// No updates available
header("HTTP/1.0 204 No Content");
if (preg_match("/^0\.9\.(4|5pre)/",$version)) {
$updates = "Version: 0.9.5\n" .
"5: Important bug fixes";
}
if (strlen($updates) == 0) {
// No updates available
header("HTTP/1.0 204 No Content");
} else {
header("HTTP/1.0 200 OK");
echo $updates;
}
?>

View File

@ -1,26 +1,31 @@
Steps for making a release:
1. Update build.properties for the new version.
2. Update ReleaseNotes
3. Update ChangeLog
4. ant dist
5. Test new features (not in project directory)
6. Copy distribution files into dists/
7. Update Eclipse project and commit files to SVN
8. Tag the version in SVN, URL:
https://openrocket.svn.sourceforge.net/svnroot/openrocket/tags/Release_0.9.x
9. Upload JAR and source distribution and ReleaseNotes to Sourceforge
- Project Admin -> File Manager
- create new version directory under /openrocket
- upload JAR, ZIP and ReleaseNotes
- select ReleaseNotes properties, set as release notes
- select JAR properties, set release note file and default downloads
- select ZIP properties, set release note file
10. Update HTML: index.html (release notes) download.html (version number)
11. Update HTML to web server:
1. Update build.properties for the new version.
2. Update ReleaseNotes
3. Update ChangeLog
4. ant dist
5. Test new features (not in project directory)
6. Copy distribution files into dists/
7. Update Eclipse project and commit files to SVN
8. Tag the version in SVN, URL:
https://openrocket.svn.sourceforge.net/svnroot/openrocket/tags/Release_0.9.x
9. Update updates.php and test various versions using a different name:
scp updates.php plaa,openrocket@web.sourceforge.net:htdocs/actions/testupdates.php
java -Dopenrocket.debug.updateurl=http://openrocket.sourceforge.net/actions/testupdates.php -jar OpenRocket-0.9.4.jar
10. Upload JAR and source distribution and ReleaseNotes to Sourceforge
- Project Admin -> File Manager
- create new version directory under /openrocket
- upload JAR, ZIP and ReleaseNotes
- select ReleaseNotes properties, set as release notes
- select JAR properties, set release note file and default downloads
- select ZIP properties, set release note file
11. Update HTML: index.html (release notes) download.html (version number)
12. Update HTML to web server:
scp * plaa,openrocket@web.sourceforge.net:htdocs/
12. Test downloading from Sourceforge and web site
13. Update build.properties to "pre" version + commit
14. Send email about new release to openrocket-announce@lists.sourceforge.net
13. Test downloading from Sourceforge and web site
14. Update update.php to web server:
scp updates.php plaa,openrocket@web.sourceforge.net:htdocs/actions/
15. Update build.properties to "pre" version + commit
16. Send email about new release to openrocket-announce@lists.sourceforge.net

View File

@ -1,6 +1,7 @@
package net.sf.openrocket.aerodynamics;
import net.sf.openrocket.rocketcomponent.RocketComponent;
import net.sf.openrocket.util.BugException;
import net.sf.openrocket.util.Coordinate;
public class AerodynamicForces implements Cloneable {
@ -132,7 +133,7 @@ public class AerodynamicForces implements Cloneable {
try {
return (AerodynamicForces)super.clone();
} catch (CloneNotSupportedException e) {
throw new RuntimeException("CloneNotSupportedException?!?");
throw new BugException("CloneNotSupportedException?!?");
}
}

View File

@ -1,5 +1,7 @@
package net.sf.openrocket.aerodynamics;
import net.sf.openrocket.util.BugException;
public class AtmosphericConditions implements Cloneable {
/** Specific gas constant of dry air. */
@ -92,7 +94,7 @@ public class AtmosphericConditions implements Cloneable {
try {
return (AtmosphericConditions) super.clone();
} catch (CloneNotSupportedException e) {
throw new RuntimeException("BUG: CloneNotSupportedException encountered!");
throw new BugException("BUG: CloneNotSupportedException encountered!");
}
}

View File

@ -7,6 +7,7 @@ import javax.swing.event.ChangeEvent;
import javax.swing.event.ChangeListener;
import net.sf.openrocket.rocketcomponent.Configuration;
import net.sf.openrocket.util.BugException;
import net.sf.openrocket.util.ChangeSource;
import net.sf.openrocket.util.MathUtil;
@ -369,7 +370,7 @@ public class FlightConditions implements Cloneable, ChangeSource {
cond.atmosphericConditions = atmosphericConditions.clone();
return cond;
} catch (CloneNotSupportedException e) {
throw new RuntimeException("BUG: clone not supported!",e);
throw new BugException("BUG: clone not supported!",e);
}
}

View File

@ -4,6 +4,8 @@ import java.util.AbstractSet;
import java.util.ArrayList;
import java.util.Iterator;
import net.sf.openrocket.util.BugException;
/**
* A set that contains multiple <code>Warning</code>s. When adding a
* {@link Warning} to this set, the contents is checked for a warning of the
@ -72,7 +74,7 @@ public class WarningSet extends AbstractSet<Warning> implements Cloneable {
return newSet;
} catch (CloneNotSupportedException e) {
throw new RuntimeException("CloneNotSupportedException occurred, report bug!",e);
throw new BugException("CloneNotSupportedException occurred, report bug!",e);
}
}

View File

@ -10,6 +10,7 @@ import net.sf.openrocket.rocketcomponent.BodyTube;
import net.sf.openrocket.rocketcomponent.RocketComponent;
import net.sf.openrocket.rocketcomponent.SymmetricComponent;
import net.sf.openrocket.rocketcomponent.Transition;
import net.sf.openrocket.util.BugException;
import net.sf.openrocket.util.Coordinate;
import net.sf.openrocket.util.LinearInterpolator;
import net.sf.openrocket.util.MathUtil;
@ -172,7 +173,7 @@ public class SymmetricComponentCalc extends RocketComponentCalc {
return 0;
if (!(component instanceof Transition)) {
throw new RuntimeException("Pressure calculation of unknown type: "+
throw new BugException("Pressure calculation of unknown type: "+
component.getComponentName());
}

View File

@ -4,6 +4,8 @@ import java.io.UnsupportedEncodingException;
import java.net.HttpURLConnection;
import java.net.URLEncoder;
import net.sf.openrocket.util.BugException;
public abstract class Communicator {
protected static final String BUG_REPORT_URL;
@ -65,7 +67,7 @@ public abstract class Communicator {
try {
return URLEncoder.encode(str, "UTF-8");
} catch (UnsupportedEncodingException e) {
throw new RuntimeException("Unsupported encoding UTF-8", e);
throw new BugException("Unsupported encoding UTF-8", e);
}
}

View File

@ -47,4 +47,9 @@ public class UpdateInfo {
return (List<ComparablePair<Integer, String>>) updates.clone();
}
@Override
public String toString() {
return "UpdateInfo[version=" + latestVersion + "; updates=" + updates.toString() + "]";
}
}

View File

@ -153,7 +153,7 @@ public class UpdateInfoRetriever {
System.getProperty("java.version")));
connection.setRequestProperty("X-OpenRocket-Country",
Communicator.encode(System.getProperty("user.country") + " " +
Communicator.encode(System.getProperty("user.timezone"))));
System.getProperty("user.timezone")));
InputStream is = null;
try {
@ -169,15 +169,19 @@ public class UpdateInfoRetriever {
if (connection.getResponseCode() != Communicator.UPDATE_INFO_UPDATE_AVAILABLE) {
// Error communicating with server
System.out.println("Unknown response code: " + connection.getResponseCode());
return;
}
if (!Communicator.UPDATE_INFO_CONTENT_TYPE.equalsIgnoreCase(
connection.getContentType())) {
String contentType = connection.getContentType();
if (contentType == null ||
contentType.toLowerCase().indexOf(Communicator.UPDATE_INFO_CONTENT_TYPE) < 0) {
// Unknown response type
System.out.println("Unknown Content-type received:"+contentType);
return;
}
System.out.println("Update is available");
// Update is available, parse input
is = connection.getInputStream();
@ -209,12 +213,13 @@ public class UpdateInfoRetriever {
if (version == null || version.length() == 0 ||
version.equalsIgnoreCase(Prefs.getVersion())) {
// Invalid response
System.out.println("Invalid version received, ignoring.");
return;
}
info = new UpdateInfo(version, updates);
System.out.println("Found update: " + info);
} finally {
try {
if (is != null)

View File

@ -9,6 +9,7 @@ import net.sf.openrocket.file.GeneralMotorLoader;
import net.sf.openrocket.material.Material;
import net.sf.openrocket.material.MaterialStorage;
import net.sf.openrocket.motor.Motor;
import net.sf.openrocket.util.ConfigurationException;
import net.sf.openrocket.util.JarUtil;
import net.sf.openrocket.util.MathUtil;
import net.sf.openrocket.util.Prefs;
@ -65,7 +66,8 @@ public class Databases {
MOTOR.loadDirectory(dir, ".*\\.[eE][nN][gG]$");
} catch (IOException e1) {
System.out.println("Could not read thrust curves from directory either.");
throw new RuntimeException(e1);
throw new ConfigurationException("Couldn't read thrust curves from either " +
"JAR file or system resource directory", e1);
}
}
}

View File

@ -17,6 +17,7 @@ import net.sf.openrocket.rocketcomponent.ComponentChangeEvent;
import net.sf.openrocket.rocketcomponent.ComponentChangeListener;
import net.sf.openrocket.rocketcomponent.Configuration;
import net.sf.openrocket.rocketcomponent.Rocket;
import net.sf.openrocket.util.BugException;
import net.sf.openrocket.util.Icons;
@ -449,7 +450,7 @@ public class OpenRocketDocument implements ComponentChangeListener {
break;
default:
throw new RuntimeException("EEEK!");
throw new BugException("illegal type="+type);
}
if (desc != null)

View File

@ -18,6 +18,7 @@ import net.sf.openrocket.simulation.SimulationConditions;
import net.sf.openrocket.simulation.SimulationListener;
import net.sf.openrocket.simulation.exception.SimulationException;
import net.sf.openrocket.simulation.exception.SimulationListenerException;
import net.sf.openrocket.util.BugException;
import net.sf.openrocket.util.ChangeSource;
@ -250,7 +251,7 @@ public class Simulation implements ChangeSource, Cloneable {
l = (SimulationListener)c.newInstance();
} catch (Exception e) {
throw new SimulationListenerException("Could not instantiate listener of " +
"class: " + className);
"class: " + className, e);
}
simulator.addSimulationListener(l);
}
@ -347,7 +348,7 @@ public class Simulation implements ChangeSource, Cloneable {
} catch (CloneNotSupportedException e) {
throw new RuntimeException("Clone not supported, BUG", e);
throw new BugException("Clone not supported, BUG", e);
}
}

View File

@ -1,5 +1,7 @@
package net.sf.openrocket.document;
import net.sf.openrocket.util.BugException;
public class StorageOptions implements Cloneable {
public static final double SIMULATION_DATA_NONE = Double.POSITIVE_INFINITY;
@ -45,7 +47,7 @@ public class StorageOptions implements Cloneable {
try {
return (StorageOptions)super.clone();
} catch (CloneNotSupportedException e) {
throw new RuntimeException("CloneNotSupportedException?!?", e);
throw new BugException("CloneNotSupportedException?!?", e);
}
}
}

View File

@ -52,11 +52,6 @@ public abstract class RocketLoader {
throw e;
} catch (IOException e) {
throw new RocketLoadException("I/O error: " + e.getMessage());
} catch (Exception e) {
throw new RocketLoadException("An unknown error occurred. Please report a bug.", e);
} catch (Throwable e) {
throw new RocketLoadException("A serious error occurred and the software may be "
+ "unstable. Save your designs and restart OpenRocket.", e);
}
}

View File

@ -67,6 +67,7 @@ import net.sf.openrocket.simulation.FlightEvent;
import net.sf.openrocket.simulation.SimulationConditions;
import net.sf.openrocket.simulation.FlightEvent.Type;
import net.sf.openrocket.unit.UnitGroup;
import net.sf.openrocket.util.BugException;
import net.sf.openrocket.util.Coordinate;
import net.sf.openrocket.util.LineStyle;
import net.sf.openrocket.util.Reflection;
@ -179,7 +180,7 @@ class DocumentConfig {
constructors.put("stage", Stage.class.getConstructor(new Class<?>[0]));
} catch (NoSuchMethodException e) {
throw new RuntimeException(
throw new BugException(
"Error in constructing the 'constructors' HashMap.");
}
}
@ -665,11 +666,11 @@ class ComponentHandler extends ElementHandler {
try {
c = constructor.newInstance();
} catch (InstantiationException e) {
throw new RuntimeException("Error constructing component.", e);
throw new BugException("Error constructing component.", e);
} catch (IllegalAccessException e) {
throw new RuntimeException("Error constructing component.", e);
throw new BugException("Error constructing component.", e);
} catch (InvocationTargetException e) {
throw new RuntimeException("Error constructing component.", e);
throw Reflection.handleInvocationTargetException(e);
}
parent.addChild(c);

View File

@ -23,6 +23,7 @@ import net.sf.openrocket.simulation.FlightData;
import net.sf.openrocket.simulation.FlightDataBranch;
import net.sf.openrocket.simulation.FlightEvent;
import net.sf.openrocket.simulation.SimulationConditions;
import net.sf.openrocket.util.BugException;
import net.sf.openrocket.util.MathUtil;
import net.sf.openrocket.util.Pair;
import net.sf.openrocket.util.Prefs;
@ -213,7 +214,7 @@ public class OpenRocketSaver extends RocketSaver {
Reflection.Method m = Reflection.findMethod(METHOD_PACKAGE, component, METHOD_SUFFIX,
"getElements", RocketComponent.class);
if (m==null) {
throw new RuntimeException("Unable to find saving class for component "+
throw new BugException("Unable to find saving class for component "+
component.getComponentName());
}

View File

@ -12,6 +12,7 @@ import net.sf.openrocket.rocketcomponent.ComponentAssembly;
import net.sf.openrocket.rocketcomponent.MotorMount;
import net.sf.openrocket.rocketcomponent.Rocket;
import net.sf.openrocket.rocketcomponent.RocketComponent;
import net.sf.openrocket.util.BugException;
import net.sf.openrocket.util.LineStyle;
@ -94,7 +95,7 @@ public class RocketComponentSaver {
str += " type=\"bulk\"";
break;
default:
throw new RuntimeException("Unknown material type: " + mat.getType());
throw new BugException("Unknown material type: " + mat.getType());
}
return str + " density=\"" + mat.getDensity() + "\">" + RocketSaver.escapeXML(mat.getName()) + "</"+tag+">";

View File

@ -11,7 +11,9 @@ import javax.swing.AbstractAction;
import javax.swing.event.ChangeEvent;
import javax.swing.event.ChangeListener;
import net.sf.openrocket.util.BugException;
import net.sf.openrocket.util.ChangeSource;
import net.sf.openrocket.util.Reflection;
/**
@ -94,9 +96,9 @@ public class BooleanModel extends AbstractAction implements ChangeListener {
try {
return (Boolean)getMethod.invoke(source);
} catch (IllegalAccessException e) {
throw new RuntimeException("getMethod execution error for source "+source,e);
throw new BugException("getMethod execution error for source "+source,e);
} catch (InvocationTargetException e) {
throw new RuntimeException("getMethod execution error for source "+source,e);
throw Reflection.handleInvocationTargetException(e);
}
}
@ -104,9 +106,9 @@ public class BooleanModel extends AbstractAction implements ChangeListener {
try {
setMethod.invoke(source, new Object[] { (Boolean)b });
} catch (IllegalAccessException e) {
throw new RuntimeException("setMethod execution error for source "+source,e);
throw new BugException("setMethod execution error for source "+source,e);
} catch (InvocationTargetException e) {
throw new RuntimeException("setMethod execution error for source "+source,e);
throw Reflection.handleInvocationTargetException(e);
}
}
@ -167,9 +169,9 @@ public class BooleanModel extends AbstractAction implements ChangeListener {
try {
return (Boolean)getEnabled.invoke(source);
} catch (IllegalAccessException e) {
throw new RuntimeException("getEnabled execution error for source "+source,e);
throw new BugException("getEnabled execution error for source "+source,e);
} catch (InvocationTargetException e) {
throw new RuntimeException("getEnabled execution error for source "+source,e);
throw Reflection.handleInvocationTargetException(e);
}
}

View File

@ -17,8 +17,10 @@ import javax.swing.event.ChangeListener;
import net.sf.openrocket.unit.Unit;
import net.sf.openrocket.unit.UnitGroup;
import net.sf.openrocket.util.BugException;
import net.sf.openrocket.util.ChangeSource;
import net.sf.openrocket.util.MathUtil;
import net.sf.openrocket.util.Reflection;
/**
@ -589,11 +591,11 @@ public class DoubleModel implements ChangeListener, ChangeSource {
try {
return (Double)getMethod.invoke(source)*multiplier;
} catch (IllegalArgumentException e) {
throw new RuntimeException("BUG: Unable to invoke getMethod of "+this, e);
throw new BugException("BUG: Unable to invoke getMethod of "+this, e);
} catch (IllegalAccessException e) {
throw new RuntimeException("BUG: Unable to invoke getMethod of "+this, e);
throw new BugException("BUG: Unable to invoke getMethod of "+this, e);
} catch (InvocationTargetException e) {
throw new RuntimeException("BUG: Unable to invoke getMethod of "+this, e);
throw Reflection.handleInvocationTargetException(e);
}
}
@ -614,13 +616,12 @@ public class DoubleModel implements ChangeListener, ChangeSource {
try {
setMethod.invoke(source, v/multiplier);
return;
} catch (IllegalArgumentException e) {
throw new RuntimeException("BUG: Unable to invoke setMethod of "+this, e);
throw new BugException("BUG: Unable to invoke setMethod of "+this, e);
} catch (IllegalAccessException e) {
throw new RuntimeException("BUG: Unable to invoke setMethod of "+this, e);
throw new BugException("BUG: Unable to invoke setMethod of "+this, e);
} catch (InvocationTargetException e) {
throw new RuntimeException("Setter method of "+this+" threw exception", e);
throw Reflection.handleInvocationTargetException(e);
}
}
@ -643,13 +644,12 @@ public class DoubleModel implements ChangeListener, ChangeSource {
try {
return (Boolean)getAutoMethod.invoke(source);
} catch (IllegalArgumentException e) {
e.printStackTrace();
throw new BugException("Method call failed", e);
} catch (IllegalAccessException e) {
e.printStackTrace();
throw new BugException("Method call failed", e);
} catch (InvocationTargetException e) {
e.printStackTrace();
throw Reflection.handleInvocationTargetException(e);
}
return false; // Should not occur
}
/**
@ -662,18 +662,16 @@ public class DoubleModel implements ChangeListener, ChangeSource {
return;
}
lastAutomatic = auto;
try {
lastAutomatic = auto;
setAutoMethod.invoke(source, auto);
return;
} catch (IllegalArgumentException e) {
e.printStackTrace();
throw new BugException(e);
} catch (IllegalAccessException e) {
e.printStackTrace();
throw new BugException(e);
} catch (InvocationTargetException e) {
e.printStackTrace();
throw Reflection.handleInvocationTargetException(e);
}
fireStateChanged(); // Should not occur
}

View File

@ -76,6 +76,10 @@ public class EnumModel<T extends Enum<T>> extends AbstractListModel
@Override
public void setSelectedItem(Object item) {
if (item == null) {
// Clear selection - huh?
return;
}
if (item instanceof String) {
if (currentValue != null)
setMethod.invoke(source, (Object)null);

View File

@ -9,7 +9,9 @@ import javax.swing.SpinnerNumberModel;
import javax.swing.event.ChangeEvent;
import javax.swing.event.ChangeListener;
import net.sf.openrocket.util.BugException;
import net.sf.openrocket.util.ChangeSource;
import net.sf.openrocket.util.Reflection;
public class IntegerModel implements ChangeListener {
@ -149,13 +151,12 @@ public class IntegerModel implements ChangeListener {
try {
return (Integer)getMethod.invoke(source);
} catch (IllegalArgumentException e) {
e.printStackTrace();
throw new BugException(e);
} catch (IllegalAccessException e) {
e.printStackTrace();
throw new BugException(e);
} catch (InvocationTargetException e) {
e.printStackTrace();
throw Reflection.handleInvocationTargetException(e);
}
return lastValue; // Should not occur
}
/**
@ -164,15 +165,13 @@ public class IntegerModel implements ChangeListener {
public void setValue(int v) {
try {
setMethod.invoke(source, v);
return;
} catch (IllegalArgumentException e) {
e.printStackTrace();
throw new BugException(e);
} catch (IllegalAccessException e) {
e.printStackTrace();
throw new BugException(e);
} catch (InvocationTargetException e) {
e.printStackTrace();
throw Reflection.handleInvocationTargetException(e);
}
fireStateChanged(); // Should not occur
}

View File

@ -80,6 +80,11 @@ public class MaterialModel extends AbstractListModel implements
@Override
public void setSelectedItem(Object item) {
if (item == null) {
// Clear selection - huh?
return;
}
if (item == CUSTOM) {
// Open custom material dialog in the future, after combo box has closed

View File

@ -63,6 +63,10 @@ public class MotorConfigurationModel implements ComboBoxModel, ChangeListener {
@Override
public void setSelectedItem(Object item) {
if (item == null) {
// Clear selection - huh?
return;
}
if (item == EDIT) {
// Open edit dialog in the future, after combo box has closed
@ -76,8 +80,9 @@ public class MotorConfigurationModel implements ComboBoxModel, ChangeListener {
return;
}
if (!(item instanceof ID))
return;
if (!(item instanceof ID)) {
throw new IllegalArgumentException("MotorConfigurationModel item="+item);
}
ID idObject = (ID) item;
config.setMotorConfigurationID(idObject.getID());

View File

@ -12,6 +12,8 @@ import java.net.URISyntaxException;
import java.util.HashMap;
import java.util.Map;
import net.sf.openrocket.util.BugException;
/**
* A label of a URL that is clickable. Clicking the URL will launch the URL in
* the default browser if the Desktop class is supported.
@ -58,7 +60,7 @@ public class URLLabel extends SelectableLabel {
try {
d.browse(new URI(url));
} catch (URISyntaxException e1) {
throw new RuntimeException("BUG: Illegal URL: " + url, e1);
throw new BugException("BUG: Illegal URL: " + url, e1);
} catch (IOException e1) {
System.err.println("Unable to launch browser:");
e1.printStackTrace();

View File

@ -14,8 +14,10 @@ import net.sf.openrocket.document.OpenRocketDocument;
import net.sf.openrocket.rocketcomponent.ComponentChangeEvent;
import net.sf.openrocket.rocketcomponent.ComponentChangeListener;
import net.sf.openrocket.rocketcomponent.RocketComponent;
import net.sf.openrocket.util.BugException;
import net.sf.openrocket.util.GUIUtil;
import net.sf.openrocket.util.Prefs;
import net.sf.openrocket.util.Reflection;
/**
* A dialog that contains the configuration elements of one component.
@ -108,17 +110,17 @@ public class ComponentConfigDialog extends JDialog implements ComponentChangeLis
try {
return (RocketComponentConfig) c.newInstance(component);
} catch (InstantiationException e) {
throw new RuntimeException("BUG in constructor reflection",e);
throw new BugException("BUG in constructor reflection",e);
} catch (IllegalAccessException e) {
throw new RuntimeException("BUG in constructor reflection",e);
throw new BugException("BUG in constructor reflection",e);
} catch (InvocationTargetException e) {
throw new RuntimeException("BUG in constructor reflection",e);
throw Reflection.handleInvocationTargetException(e);
}
}
// Should never be reached, since RocketComponentConfig should catch all
// components without their own configurator.
throw new RuntimeException("Unable to find any configurator for "+component);
throw new BugException("Unable to find any configurator for "+component);
}
/**

View File

@ -23,6 +23,7 @@ import net.sf.openrocket.gui.adaptors.DoubleModel;
import net.sf.openrocket.gui.adaptors.EnumModel;
import net.sf.openrocket.gui.adaptors.MotorConfigurationModel;
import net.sf.openrocket.gui.components.BasicSlider;
import net.sf.openrocket.gui.components.StyledLabel;
import net.sf.openrocket.gui.components.UnitSelector;
import net.sf.openrocket.gui.dialogs.MotorChooserDialog;
import net.sf.openrocket.motor.Motor;
@ -123,10 +124,24 @@ public class MotorConfig extends JPanel {
spin.setEditor(new SpinnerEditor(spin));
panel.add(spin,"gap rel rel");
panel.add(new JLabel("seconds"),"wrap paragraph");
panel.add(new JLabel("seconds"),"wrap unrel");
// Check stage count
RocketComponent c = (RocketComponent)mount;
c = c.getRocket();
int stages = c.getChildCount();
if (stages == 1) {
panel.add(new StyledLabel("The current design has only one stage. " +
"Stages can be added by clicking \"New stage\".", -1),
"spanx, right, wrap para");
} else {
panel.add(new StyledLabel("The current design has " + stages + " stages.", -1),
"skip 1, spanx, wrap para");
}
// Select etc. buttons
button = new JButton("Select motor");

View File

@ -210,7 +210,13 @@ public class RingComponentConfig extends RocketComponentConfig {
((RingComponent) component).setRadialPosition(0.0);
}
});
panel.add(button,"spanx, right");
panel.add(button,"spanx, right, wrap para");
DescriptionArea note = new DescriptionArea(2);
note.setText("Note: An inner tube will not affect the aerodynamics" +
" of the rocket even if it is located outside of the body tube.");
panel.add(note, "spanx, growx");
return panel;

View File

@ -28,6 +28,7 @@ import net.miginfocom.swing.MigLayout;
import net.sf.openrocket.communication.BugReporter;
import net.sf.openrocket.gui.components.SelectableLabel;
import net.sf.openrocket.gui.components.StyledLabel;
import net.sf.openrocket.util.BugException;
import net.sf.openrocket.util.GUIUtil;
import net.sf.openrocket.util.JarUtil;
import net.sf.openrocket.util.Prefs;
@ -288,7 +289,7 @@ public class BugReportDialog extends JDialog {
text = URLEncoder.encode(text, "UTF-8");
version = URLEncoder.encode(Prefs.getVersion(), "UTF-8");
} catch (UnsupportedEncodingException e) {
throw new RuntimeException(e);
throw new BugException(e);
}

View File

@ -27,6 +27,7 @@ import javax.swing.JScrollPane;
import javax.swing.ListSelectionModel;
import net.miginfocom.swing.MigLayout;
import net.sf.openrocket.util.BugException;
import net.sf.openrocket.util.GUIUtil;
import net.sf.openrocket.util.JarUtil;
@ -160,7 +161,7 @@ public class ExampleDesignDialog extends JDialog {
designs[i] = new ExampleDesign(files[i].toURI().toURL(),
name.substring(0, name.length()-4));
} catch (MalformedURLException e) {
throw new RuntimeException(e);
throw new BugException(e);
}
}
return designs;
@ -185,7 +186,7 @@ public class ExampleDesignDialog extends JDialog {
fileUrl = file.toURI().toURL();
} catch (MalformedURLException e1) {
e1.printStackTrace();
throw new RuntimeException(e1);
throw new BugException(e1);
}
// Iterate over JAR entries searching for designs

View File

@ -4,6 +4,7 @@ import java.awt.Font;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStreamReader;
import javax.swing.JButton;
@ -46,7 +47,7 @@ public class LicenseDialog extends JDialog {
}
licenseText = sb.toString();
} catch (Exception e) {
} catch (IOException e) {
licenseText = DEFAULT_LICENSE_TEXT;

View File

@ -7,6 +7,7 @@ import java.util.Collections;
import java.util.List;
import javax.swing.JButton;
import javax.swing.JCheckBox;
import javax.swing.JDialog;
import javax.swing.JLabel;
import javax.swing.JPanel;
@ -20,6 +21,8 @@ import net.sf.openrocket.util.GUIUtil;
import net.sf.openrocket.util.Icons;
public class UpdateInfoDialog extends JDialog {
private final JCheckBox remind;
public UpdateInfoDialog(UpdateInfo info) {
super((Window)null, "OpenRocket update available", ModalityType.APPLICATION_MODAL);
@ -56,6 +59,11 @@ public class UpdateInfoDialog extends JDialog {
"gaptop para, alignx 50%, wrap unrel");
panel.add(new URLLabel(AboutDialog.OPENROCKET_URL), "alignx 50%, wrap para");
remind = new JCheckBox("Remind me later");
remind.setToolTipText("Show this update also the next time you start OpenRocket");
remind.setSelected(true);
panel.add(remind);
JButton button = new JButton("Close");
button.addActionListener(new ActionListener() {
@Override
@ -63,7 +71,7 @@ public class UpdateInfoDialog extends JDialog {
UpdateInfoDialog.this.dispose();
}
});
panel.add(button, "right");
panel.add(button, "right, gapright para");
this.add(panel);
@ -72,4 +80,9 @@ public class UpdateInfoDialog extends JDialog {
GUIUtil.setDisposableDialogOptions(this, button);
}
public boolean isReminderSelected() {
return remind.isSelected();
}
}

View File

@ -259,6 +259,10 @@ public class PreferencesDialog extends JDialog {
}
@Override
public void setSelectedItem(Object item) {
if (item == null) {
// Clear selection - huh?
return;
}
if (!(item instanceof Unit)) {
throw new IllegalArgumentException("Illegal argument "+item);
}
@ -297,6 +301,10 @@ public class PreferencesDialog extends JDialog {
@Override
public void setSelectedItem(Object item) {
if (item == null) {
// Clear selection - huh?
return;
}
if (!(item instanceof String)) {
throw new IllegalArgumentException("Illegal argument "+item);
}
@ -347,6 +355,10 @@ public class PreferencesDialog extends JDialog {
@Override
public void setSelectedItem(Object item) {
if (item == null) {
// Clear selection - huh?
return;
}
if (!(item instanceof String)) {
throw new IllegalArgumentException("Illegal argument "+item);
}
@ -442,7 +454,13 @@ public class PreferencesDialog extends JDialog {
"You are running the latest version of OpenRocket.",
"No updates available", JOptionPane.INFORMATION_MESSAGE, null);
} else {
new UpdateInfoDialog(info).setVisible(true);
UpdateInfoDialog infoDialog = new UpdateInfoDialog(info);
infoDialog.setVisible(true);
if (infoDialog.isReminderSelected()) {
Prefs.putString(Prefs.LAST_UPDATE, "");
} else {
Prefs.putString(Prefs.LAST_UPDATE, info.getLatestVersion());
}
}
}

View File

@ -87,6 +87,7 @@ import net.sf.openrocket.rocketcomponent.ComponentChangeListener;
import net.sf.openrocket.rocketcomponent.Rocket;
import net.sf.openrocket.rocketcomponent.RocketComponent;
import net.sf.openrocket.rocketcomponent.Stage;
import net.sf.openrocket.util.BugException;
import net.sf.openrocket.util.GUIUtil;
import net.sf.openrocket.util.Icons;
import net.sf.openrocket.util.OpenFileWorker;
@ -874,16 +875,16 @@ public class BasicFrame extends JFrame {
} else {
throw new RuntimeException("Unknown error when opening file", e);
throw new BugException("Unknown error when opening file", e);
}
} catch (InterruptedException e) {
throw new RuntimeException("EDT was interrupted", e);
throw new BugException("EDT was interrupted", e);
}
if (doc == null) {
throw new RuntimeException("BUG: Document loader returned null");
throw new BugException("BUG: Document loader returned null");
}
@ -1004,11 +1005,11 @@ public class BasicFrame extends JFrame {
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 saved;
@ -1262,8 +1263,14 @@ public class BasicFrame extends JFrame {
if (info != null && info.getLatestVersion() != null &&
!current.equals(info.getLatestVersion()) &&
!last.equals(info.getLatestVersion())) {
Prefs.putString(Prefs.LAST_UPDATE, info.getLatestVersion());
new UpdateInfoDialog(info).setVisible(true);
UpdateInfoDialog infoDialog = new UpdateInfoDialog(info);
infoDialog.setVisible(true);
if (infoDialog.isReminderSelected()) {
Prefs.putString(Prefs.LAST_UPDATE, "");
} else {
Prefs.putString(Prefs.LAST_UPDATE, info.getLatestVersion());
}
}
}
count--;

View File

@ -6,6 +6,7 @@ import java.awt.Dimension;
import java.awt.Rectangle;
import java.awt.event.ActionEvent;
import java.lang.reflect.Constructor;
import java.lang.reflect.InvocationTargetException;
import javax.swing.Icon;
import javax.swing.JButton;
@ -47,8 +48,10 @@ import net.sf.openrocket.rocketcomponent.Streamer;
import net.sf.openrocket.rocketcomponent.Transition;
import net.sf.openrocket.rocketcomponent.TrapezoidFinSet;
import net.sf.openrocket.rocketcomponent.TubeCoupler;
import net.sf.openrocket.util.BugException;
import net.sf.openrocket.util.Pair;
import net.sf.openrocket.util.Prefs;
import net.sf.openrocket.util.Reflection;
/**
* A component that contains addition buttons to add different types of rocket components
@ -393,9 +396,14 @@ public class ComponentAddButtons extends JPanel implements Scrollable {
RocketComponent component;
try {
component = (RocketComponent)constructor.newInstance();
} catch (Exception e) {
throw new RuntimeException("Could not construct new instance of class "+
} catch (InstantiationException e) {
throw new BugException("Could not construct new instance of class "+
constructor,e);
} catch (IllegalAccessException e) {
throw new BugException("Could not construct new instance of class "+
constructor,e);
} catch (InvocationTargetException e) {
throw Reflection.handleInvocationTargetException(e);
}
// Next undo position is set by opening the configuration dialog

View File

@ -389,6 +389,8 @@ public class SimulationRunDialog extends JDialog {
} else if (t instanceof Exception) {
// TODO: MEDIUM: Check the exception handling here...
DetailDialog.showDetailedMessageDialog(SimulationRunDialog.this,
new Object[] {
"An exception occurred during the simulation:",

View File

@ -1,5 +1,7 @@
package net.sf.openrocket.gui.plot;
import net.sf.openrocket.util.BugException;
public class Axis implements Cloneable {
private double minValue = Double.NaN;
@ -45,7 +47,7 @@ public class Axis implements Cloneable {
return (Axis) super.clone();
} catch (CloneNotSupportedException e) {
throw new RuntimeException("BUG! Could not clone().");
throw new BugException("BUG! Could not clone().");
}
}

View File

@ -9,6 +9,7 @@ import net.sf.openrocket.simulation.FlightDataBranch;
import net.sf.openrocket.simulation.FlightEvent;
import net.sf.openrocket.simulation.FlightDataBranch.Type;
import net.sf.openrocket.unit.Unit;
import net.sf.openrocket.util.BugException;
import net.sf.openrocket.util.MathUtil;
import net.sf.openrocket.util.Pair;
@ -733,7 +734,7 @@ public class PlotConfiguration implements Cloneable {
} catch (CloneNotSupportedException e) {
throw new RuntimeException("BUG! Could not clone().");
throw new BugException("BUG! Could not clone().");
}
}

View File

@ -34,6 +34,7 @@ import net.sf.openrocket.simulation.FlightDataBranch;
import net.sf.openrocket.simulation.FlightEvent;
import net.sf.openrocket.unit.Unit;
import net.sf.openrocket.unit.UnitGroup;
import net.sf.openrocket.util.BugException;
import net.sf.openrocket.util.GUIUtil;
import net.sf.openrocket.util.MathUtil;
import net.sf.openrocket.util.Pair;
@ -341,7 +342,7 @@ public class PlotDialog extends JDialog {
double t2 = time.get(tindex+1);
if ((t1 > t) || (t2 < t)) {
throw new RuntimeException("BUG: t1="+t1+" t2="+t2+" t="+t);
throw new BugException("BUG: t1="+t1+" t2="+t2+" t="+t);
}
if (MathUtil.equals(t1, t2)) {

View File

@ -25,6 +25,7 @@ import net.sf.openrocket.motor.Motor;
import net.sf.openrocket.rocketcomponent.Configuration;
import net.sf.openrocket.rocketcomponent.MotorMount;
import net.sf.openrocket.rocketcomponent.RocketComponent;
import net.sf.openrocket.util.BugException;
import net.sf.openrocket.util.Coordinate;
import net.sf.openrocket.util.LineStyle;
import net.sf.openrocket.util.MathUtil;
@ -438,7 +439,7 @@ public class RocketFigure extends AbstractScaleFigure {
break;
default:
throw new RuntimeException("Unknown figure type = "+type);
throw new BugException("Unknown figure type = "+type);
}
if (m == null) {
@ -537,7 +538,7 @@ public class RocketFigure extends AbstractScaleFigure {
return new Rectangle2D.Double(-maxR,-maxR,2*maxR,2*maxR);
default:
throw new RuntimeException("Illegal figure type = "+type);
throw new BugException("Illegal figure type = "+type);
}
}

View File

@ -28,6 +28,7 @@ import net.sf.openrocket.gui.components.UnitSelector;
import net.sf.openrocket.unit.Tick;
import net.sf.openrocket.unit.Unit;
import net.sf.openrocket.unit.UnitGroup;
import net.sf.openrocket.util.BugException;
@ -144,7 +145,7 @@ public class ScaleScrollPane extends JScrollPane
public void setFitting(boolean fit) {
if (fit && !allowFit) {
throw new RuntimeException("Attempting to fit figure not allowing fit.");
throw new BugException("Attempting to fit figure not allowing fit.");
}
this.fit = fit;
if (fit) {

View File

@ -6,6 +6,7 @@ import java.util.Locale;
import java.util.regex.Matcher;
import java.util.regex.Pattern;
import net.sf.openrocket.util.BugException;
import net.sf.openrocket.util.Coordinate;
import net.sf.openrocket.util.MathUtil;
@ -282,7 +283,7 @@ public abstract class Motor implements Comparable<Motor> {
avgTime *= time/(DIVISIONS+1);
if (Double.isNaN(avgTime))
throw new RuntimeException("Calculated avg. time is NaN for motor "+this);
throw new BugException("Calculated avg. time is NaN for motor "+this);
}
return avgTime;
@ -315,7 +316,7 @@ public abstract class Motor implements Comparable<Motor> {
avgThrust /= points;
if (Double.isNaN(avgThrust))
throw new RuntimeException("Calculated average thrust is NaN for motor "+this);
throw new BugException("Calculated average thrust is NaN for motor "+this);
}
return avgThrust;
}
@ -346,7 +347,7 @@ public abstract class Motor implements Comparable<Motor> {
}
if (Double.isNaN(totalImpulse))
throw new RuntimeException("Calculated total impulse is NaN for motor "+this);
throw new BugException("Calculated total impulse is NaN for motor "+this);
}
return totalImpulse;
}

View File

@ -20,7 +20,11 @@ public class CenteringRing extends RadiusRingComponent {
// Component can be parentless if disattached from rocket
if (this.getParent() != null) {
for (RocketComponent sibling: this.getParent().getChildren()) {
if (!(sibling instanceof RadialParent)) // Excludes itself
/*
* Only InnerTubes are considered when determining the automatic
* inner radius (for now).
*/
if (!(sibling instanceof InnerTube)) // Excludes itself
continue;
double pos1 = this.toRelative(Coordinate.NUL, sibling)[0].x;
@ -28,7 +32,6 @@ public class CenteringRing extends RadiusRingComponent {
if (pos2 < 0 || pos1 > sibling.getLength())
continue;
// TODO: CRITICAL: ClassCastException below:
innerRadius = Math.max(innerRadius, ((InnerTube)sibling).getOuterRadius());
}
innerRadius = Math.min(innerRadius, getOuterRadius());

View File

@ -13,6 +13,7 @@ import javax.swing.event.ChangeEvent;
import javax.swing.event.ChangeListener;
import javax.swing.event.EventListenerList;
import net.sf.openrocket.util.BugException;
import net.sf.openrocket.util.ChangeSource;
import net.sf.openrocket.util.Coordinate;
import net.sf.openrocket.util.MathUtil;
@ -393,7 +394,7 @@ public class Configuration implements Cloneable, ChangeSource, ComponentChangeLi
rocket.addComponentChangeListener(config);
return config;
} catch (CloneNotSupportedException e) {
throw new RuntimeException("BUG: clone not supported!",e);
throw new BugException("BUG: clone not supported!",e);
}
}

View File

@ -13,6 +13,7 @@ import java.util.UUID;
import javax.swing.event.ChangeListener;
import net.sf.openrocket.util.BugException;
import net.sf.openrocket.util.ChangeSource;
import net.sf.openrocket.util.Coordinate;
import net.sf.openrocket.util.LineStyle;
@ -307,7 +308,7 @@ public abstract class RocketComponent implements ChangeSource, Cloneable,
try {
clone = (RocketComponent)this.clone();
} catch (CloneNotSupportedException e) {
throw new RuntimeException("CloneNotSupportedException encountered, " +
throw new BugException("CloneNotSupportedException encountered, " +
"report a bug!",e);
}
@ -778,7 +779,7 @@ public abstract class RocketComponent implements ChangeSource, Cloneable,
break;
default:
throw new RuntimeException("Unknown relative positioning type of component"+
throw new BugException("Unknown relative positioning type of component"+
component+": "+component.relativePosition);
}
@ -1113,9 +1114,17 @@ public abstract class RocketComponent implements ChangeSource, Cloneable,
return null;
int pos = parent.getChildPosition(this);
if (pos < 0) {
throw new IllegalStateException("Inconsistent internal state: " +
"this="+this+" parent="+parent+" parent.children="+
parent.children.toString());
StringBuffer sb = new StringBuffer();
sb.append("Inconsistent internal state: ");
sb.append("this=").append(this).append('[').append(System.identityHashCode(this)).append(']');
sb.append(" parent.children=[");
for (int i=0; i < parent.children.size(); i++) {
RocketComponent c = parent.children.get(i);
sb.append(c).append('[').append(System.identityHashCode(c)).append(']');
if (i < parent.children.size()-1)
sb.append(", ");
}
throw new IllegalStateException(sb.toString());
}
assert(pos >= 0);
if (pos == 0)

View File

@ -1,6 +1,7 @@
package net.sf.openrocket.rocketcomponent;
import net.sf.openrocket.material.Material;
import net.sf.openrocket.util.BugException;
import net.sf.openrocket.util.MathUtil;
import net.sf.openrocket.util.Prefs;
@ -22,7 +23,7 @@ public class ShockCord extends MassObject {
public void setMaterial(Material m) {
if (m.getType() != Material.Type.LINE)
throw new RuntimeException("Attempting to set non-linear material.");
throw new BugException("Attempting to set non-linear material.");
if (material.equals(m))
return;
this.material = m;

View File

@ -9,6 +9,7 @@ import javax.swing.event.ChangeListener;
import net.sf.openrocket.aerodynamics.AtmosphericModel;
import net.sf.openrocket.aerodynamics.ExtendedISAModel;
import net.sf.openrocket.rocketcomponent.Rocket;
import net.sf.openrocket.util.BugException;
import net.sf.openrocket.util.ChangeSource;
import net.sf.openrocket.util.MathUtil;
@ -321,7 +322,7 @@ public class SimulationConditions implements ChangeSource, Cloneable {
copy.listeners = new ArrayList<ChangeListener>();
return copy;
} catch (CloneNotSupportedException e) {
throw new RuntimeException(e);
throw new BugException(e);
}
}

View File

@ -8,6 +8,7 @@ import net.sf.openrocket.aerodynamics.WarningSet;
import net.sf.openrocket.aerodynamics.WindSimulator;
import net.sf.openrocket.rocketcomponent.Configuration;
import net.sf.openrocket.rocketcomponent.RecoveryDevice;
import net.sf.openrocket.util.BugException;
import net.sf.openrocket.util.Coordinate;
@ -66,7 +67,7 @@ public class SimulationStatus implements Cloneable {
try {
return (SimulationStatus) super.clone();
} catch (CloneNotSupportedException e) {
throw new RuntimeException("BUG: CloneNotSupportedException?!?",e);
throw new BugException("BUG: CloneNotSupportedException?!?",e);
}
}
}

View File

@ -0,0 +1,25 @@
package net.sf.openrocket.util;
/**
* Thrown when a bug is noticed.
*
* @author Sampo Niskanen <sampo.niskanen@iki.fi>
*/
public class BugException extends FatalException {
public BugException() {
}
public BugException(String message) {
super(message);
}
public BugException(Throwable cause) {
super(cause);
}
public BugException(String message, Throwable cause) {
super(message, cause);
}
}

View File

@ -0,0 +1,26 @@
package net.sf.openrocket.util;
/**
* An exception to be thrown when a fatal problem with the environment
* is encountered (for example some file cannot be found).
*
* @author Sampo Niskanen <sampo.niskanen@iki.fi>
*/
public class ConfigurationException extends FatalException {
public ConfigurationException() {
}
public ConfigurationException(String message) {
super(message);
}
public ConfigurationException(Throwable cause) {
super(cause);
}
public ConfigurationException(String message, Throwable cause) {
super(message, cause);
}
}

View File

@ -0,0 +1,28 @@
package net.sf.openrocket.util;
/**
* A superclass for all types of fatal error conditions. This class is
* abstract so only subclasses can be used.
*
* @author Sampo Niskanen <sampo.niskanen@iki.fi>
* @see BugException
* @see ConfigurationException
*/
public abstract class FatalException extends RuntimeException {
public FatalException() {
}
public FatalException(String message) {
super(message);
}
public FatalException(Throwable cause) {
super(cause);
}
public FatalException(String message, Throwable cause) {
super(message, cause);
}
}

View File

@ -109,7 +109,7 @@ public class LinearInterpolator implements Cloneable {
other.sortMap = (TreeMap<Double,Double>)this.sortMap.clone();
return other;
} catch (CloneNotSupportedException e) {
throw new RuntimeException("CloneNotSupportedException?!",e);
throw new BugException("CloneNotSupportedException?!",e);
}
}

View File

@ -62,4 +62,10 @@ public class Pair<U,V> {
return ((u != null) ? u.hashCode() : 0) + ((v != null) ? v.hashCode() : 0);
}
@Override
public String toString() {
return "[" + u + ";" + v + "]";
}
}

View File

@ -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);

View File

@ -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");
}
}

View File

@ -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.
* <p>
* This method has a return type of Error in order to allow writing code like:
* <pre>throw Reflection.handleInvocationTargetException(e)</pre>
* 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");
}
}

View File

@ -118,11 +118,11 @@ public class SaveCSVWorker extends SwingWorker<Void, Void> {
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;

View File

@ -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);
}
}

View File

@ -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());
}
}
}