diff --git a/core/.classpath b/core/.classpath index 48d0ca6fc..983289231 100644 --- a/core/.classpath +++ b/core/.classpath @@ -33,5 +33,7 @@ + + diff --git a/core/build.xml b/core/build.xml index 464ce484b..d4dee9e3d 100644 --- a/core/build.xml +++ b/core/build.xml @@ -101,6 +101,7 @@ + diff --git a/core/lib-test/test-plugin.jar b/core/lib-test/test-plugin.jar new file mode 100644 index 000000000..1a6f40aaf Binary files /dev/null and b/core/lib-test/test-plugin.jar differ diff --git a/core/lib/annotation-detector-3.0.2-SNAPSHOT.jar b/core/lib/annotation-detector-3.0.2-SNAPSHOT.jar new file mode 100644 index 000000000..bab8dc3e1 Binary files /dev/null and b/core/lib/annotation-detector-3.0.2-SNAPSHOT.jar differ diff --git a/core/resources/datafiles/presets/system.ser b/core/resources/datafiles/presets/system.ser index 113a824fb..0a867f52c 100644 Binary files a/core/resources/datafiles/presets/system.ser and b/core/resources/datafiles/presets/system.ser differ diff --git a/core/resources/datafiles/thrustcurves/thrustcurves.ser b/core/resources/datafiles/thrustcurves/thrustcurves.ser index 39fe9755d..231f2ca22 100644 Binary files a/core/resources/datafiles/thrustcurves/thrustcurves.ser and b/core/resources/datafiles/thrustcurves/thrustcurves.ser differ diff --git a/core/src/net/sf/openrocket/plugin/AnnotationFinder.java b/core/src/net/sf/openrocket/plugin/AnnotationFinder.java new file mode 100644 index 000000000..6e689e321 --- /dev/null +++ b/core/src/net/sf/openrocket/plugin/AnnotationFinder.java @@ -0,0 +1,16 @@ +package net.sf.openrocket.plugin; + +import java.util.List; + +/** + * Interface for finding annotated classes from the class path. + */ +public interface AnnotationFinder { + + /** + * Return a list of all types (classes and interfaces) that are annotated + * with the provided annotation. + */ + public List> findAnnotatedTypes(Class annotation); + +} diff --git a/core/src/net/sf/openrocket/plugin/AnnotationFinderImpl.java b/core/src/net/sf/openrocket/plugin/AnnotationFinderImpl.java new file mode 100644 index 000000000..3f4d4e9ba --- /dev/null +++ b/core/src/net/sf/openrocket/plugin/AnnotationFinderImpl.java @@ -0,0 +1,92 @@ +package net.sf.openrocket.plugin; + +import java.io.File; +import java.io.IOException; +import java.lang.annotation.Annotation; +import java.net.URL; +import java.net.URLClassLoader; +import java.util.ArrayList; +import java.util.HashSet; +import java.util.List; +import java.util.Set; + +import net.sf.openrocket.util.BugException; +import net.sf.openrocket.util.JarUtil; +import eu.infomas.annotation.AnnotationDetector; +import eu.infomas.annotation.AnnotationDetector.TypeReporter; + +/** + * An AnnotationFinder that uses annotation-detector library to scan + * the class path. Compatible with the JIJ loader. + */ +public class AnnotationFinderImpl implements AnnotationFinder { + + @SuppressWarnings("resource") + @Override + public List> findAnnotatedTypes(Class annotation) { + final List> classes = new ArrayList>(); + + TypeReporter reporter = new ListReporter(classes); + final AnnotationDetector cf = new AnnotationDetector(reporter); + try { + ClassLoader loader = this.getClass().getClassLoader(); + if (loader instanceof URLClassLoader) { + + /* + * In case of URLClassLoader (which may be our own instantiation) + * use the URLs from there, as java.class.path may not be up-to-date. + */ + + URLClassLoader urlClassLoader = (URLClassLoader) loader; + URL[] urls = urlClassLoader.getURLs(); + + List files = new ArrayList(); + for (URL url : urls) { + if (url.getProtocol() == "file") { + files.add(JarUtil.urlToFile(url)); + } + } + + cf.detect(files.toArray(new File[0])); + } else { + + /* + * If not using a URLClassLoader, just do the default. + */ + cf.detect(); + } + + } catch (IOException e) { + throw new BugException("Unable to search class path", e); + } + + return classes; + } + + + private static class ListReporter implements TypeReporter { + private final List> classes; + private final Set names = new HashSet(); + + public ListReporter(List> classes) { + this.classes = classes; + } + + @SuppressWarnings("unchecked") + @Override + public Class[] annotations() { + return new Class[] { Plugin.class }; + } + + @Override + public void reportTypeAnnotation(Class annotation, String className) { + if (names.add(className)) { + try { + classes.add(this.getClass().getClassLoader().loadClass(className)); + } catch (ClassNotFoundException e) { + // Ignore + } + } + } + } +} diff --git a/core/src/net/sf/openrocket/plugin/JIJ.java b/core/src/net/sf/openrocket/plugin/JIJ.java deleted file mode 100644 index 6d9fec052..000000000 --- a/core/src/net/sf/openrocket/plugin/JIJ.java +++ /dev/null @@ -1,29 +0,0 @@ -package net.sf.openrocket.plugin; - -import java.io.File; -import java.lang.reflect.Method; -import java.net.URL; -import java.net.URLClassLoader; -import java.util.Arrays; - -public class JIJ { - - public static void main(String[] args) throws Exception { - String cp = System.getProperty("java.class.path"); - String[] cps = cp.split(File.pathSeparator); - - URL[] urls = new URL[cps.length + 1]; - for (int i = 0; i < cps.length; i++) { - urls[i] = new File(cps[i]).toURI().toURL(); - } - urls[cps.length] = new File("/home/sampo/Projects/OpenRocket/core/example.jar").toURI().toURL(); - - System.out.println("Classpath: " + Arrays.toString(urls)); - - URLClassLoader loader = new URLClassLoader(urls, null); - Class c = loader.loadClass("net.sf.openrocket.plugin.Test"); - Method m = c.getMethod("main", args.getClass()); - m.invoke(null, (Object) args); - } - -} diff --git a/core/src/net/sf/openrocket/plugin/Plugin.java b/core/src/net/sf/openrocket/plugin/Plugin.java index de8eb4cdd..2dc2aee27 100644 --- a/core/src/net/sf/openrocket/plugin/Plugin.java +++ b/core/src/net/sf/openrocket/plugin/Plugin.java @@ -6,8 +6,10 @@ import java.lang.annotation.RetentionPolicy; import java.lang.annotation.Target; /** - * Annotation that defines an interface to be a plugin interface. - * Plugin interfaces are automatically discovered from plugin JARs and + * Annotation that defines an interface to be a plugin interface and + * classes as plugin implementations. + *

+ * Plugin interfaces are automatically discovered from the classpath and * registered as plugins in Guice. * * @author Sampo Niskanen diff --git a/core/src/net/sf/openrocket/plugin/PluginModule.java b/core/src/net/sf/openrocket/plugin/PluginModule.java index 5aaa24404..c16289b18 100644 --- a/core/src/net/sf/openrocket/plugin/PluginModule.java +++ b/core/src/net/sf/openrocket/plugin/PluginModule.java @@ -1,14 +1,9 @@ package net.sf.openrocket.plugin; -import java.io.File; -import java.io.IOException; import java.util.ArrayList; -import java.util.Enumeration; import java.util.HashMap; import java.util.List; import java.util.Map; -import java.util.jar.JarEntry; -import java.util.jar.JarFile; import com.google.inject.AbstractModule; import com.google.inject.multibindings.Multibinder; @@ -21,63 +16,46 @@ import com.google.inject.multibindings.Multibinder; */ public class PluginModule extends AbstractModule { - private final List jars; - private final ClassLoader classLoader; private Map, Multibinder> binders = new HashMap, Multibinder>(); - - - /** - * Sole constructor. - * - * @param jars the JAR files to search for plugins - * @param classLoader the class loader used to load classes from the JAR files - */ - public PluginModule(List jars, ClassLoader classLoader) { - this.jars = jars; - this.classLoader = classLoader; - } - - - @Override - protected void configure() { - for (File jar : jars) { - List classNames = readClassNames(jar); - for (String className : classNames) { - checkForPlugin(className); - } - } - } - + private AnnotationFinder finder = new AnnotationFinderImpl(); @SuppressWarnings("unchecked") - private void checkForPlugin(String className) { - try { + @Override + protected void configure() { + + List> classes = finder.findAnnotatedTypes(Plugin.class); + List> interfaces = new ArrayList>(); + List> unusedInterfaces; + + + // Find plugin interfaces + for (Class c : classes) { + if (c.isInterface()) { + interfaces.add(c); + } + } + unusedInterfaces = new ArrayList>(interfaces); + + // Find plugin implementations + for (Class c : classes) { + if (c.isInterface()) + continue; - Class c = classLoader.loadClass(className); for (Class intf : c.getInterfaces()) { - System.out.println("Testing class " + c + " interface " + intf); - - if (isPluginInterface(intf)) { - System.out.println("BINDING"); + if (interfaces.contains(intf)) { // Ugly hack to enable dynamic binding... Can this be done type-safely? Multibinder binder = (Multibinder) findBinder(intf); binder.addBinding().to(c); + unusedInterfaces.remove(intf); } } - - } catch (ClassNotFoundException e) { - System.err.println("Could not load class " + className + ": " + e); } + + // TODO: Unused plugin interfaces should be bound to an empty set - how? } - - private boolean isPluginInterface(Class intf) { - return intf.isAnnotationPresent(Plugin.class); - } - - private Multibinder findBinder(Class intf) { Multibinder binder = binders.get(intf); if (binder == null) { @@ -87,36 +65,4 @@ public class PluginModule extends AbstractModule { return binder; } - - private List readClassNames(File jar) { - List classNames = new ArrayList(); - - JarFile file = null; - try { - file = new JarFile(jar); - Enumeration entries = file.entries(); - while (entries.hasMoreElements()) { - JarEntry entry = entries.nextElement(); - String name = entry.getName(); - if (name.toLowerCase().endsWith(".class") && !name.contains("$")) { - name = name.substring(0, name.length() - 6); - name = name.replace('/', '.'); - classNames.add(name); - } - } - } catch (IOException e) { - System.err.println("Error reading JAR file " + jar); - } finally { - if (file != null) { - try { - file.close(); - } catch (IOException e) { - // Curse all checked exceptions... - } - } - } - - return classNames; - } - } diff --git a/core/src/net/sf/openrocket/plugin/Test.java b/core/src/net/sf/openrocket/plugin/Test.java deleted file mode 100644 index da2c0386c..000000000 --- a/core/src/net/sf/openrocket/plugin/Test.java +++ /dev/null @@ -1,47 +0,0 @@ -package net.sf.openrocket.plugin; - -import java.io.File; -import java.net.MalformedURLException; -import java.net.URL; -import java.net.URLClassLoader; -import java.util.Arrays; -import java.util.List; -import java.util.Set; - -import com.google.inject.Guice; -import com.google.inject.Inject; -import com.google.inject.Injector; - -public class Test { - - @Inject - private Set impls; - - - public void run() { - System.out.println("Plugin count: " + impls.size()); - for (ExamplePlugin i : impls) { - i.doit(); - } - } - - - public static void main(String[] args) throws MalformedURLException { - // Properties p = System.getProperties(); - // Enumeration e = p.keys(); - // while (e.hasMoreElements()) { - // Object key = e.nextElement(); - // Object value = p.get(key); - // System.out.println(key + " = " + value); - // } - - List jars = Arrays.asList(new File("/home/sampo/Projects/OpenRocket/core/example.jar")); - URL[] urls = { new File("/home/sampo/Projects/OpenRocket/core/example.jar").toURI().toURL() }; - ClassLoader classLoader = new URLClassLoader(urls); - - classLoader = Test.class.getClassLoader(); - - Injector injector = Guice.createInjector(new PluginModule(jars, classLoader)); - injector.getInstance(Test.class).run(); - } -} diff --git a/core/src/net/sf/openrocket/startup/GuiceStartup.java b/core/src/net/sf/openrocket/startup/GuiceStartup.java index 5ba0c5c34..865955b4c 100644 --- a/core/src/net/sf/openrocket/startup/GuiceStartup.java +++ b/core/src/net/sf/openrocket/startup/GuiceStartup.java @@ -16,7 +16,6 @@ import net.sf.openrocket.logging.LogHelper; import net.sf.openrocket.logging.LogLevel; import net.sf.openrocket.logging.LogLevelBufferLogger; import net.sf.openrocket.logging.PrintStreamLogger; -import net.sf.openrocket.plugin.PluginHelper; import net.sf.openrocket.plugin.PluginModule; import com.google.inject.Guice; @@ -135,26 +134,27 @@ public class GuiceStartup { " " + LOG_STDERR_PROPERTY + "=" + System.getProperty(LOG_STDERR_PROPERTY) + ")"; log.info(str); - + //Replace System.err with a PrintStream that logs lines to DEBUG, or VBOSE if they are indented. //If debug info is not being output to the console then the data is both logged and written to //stderr. - final boolean writeToStderr = !( printer.getOutput(LogLevel.DEBUG) == System.out || printer.getOutput(LogLevel.DEBUG) == System.err); - final PrintStream stdErr = System.err; + final boolean writeToStderr = !(printer.getOutput(LogLevel.DEBUG) == System.out || printer.getOutput(LogLevel.DEBUG) == System.err); + final PrintStream stdErr = System.err; System.setErr(new PrintStream(new OutputStream() { StringBuilder currentLine = new StringBuilder(); + @Override public synchronized void write(int b) throws IOException { - if ( writeToStderr ){ + if (writeToStderr) { //Write to real stderr stdErr.write(b); } if (b == '\r' || b == '\n') { //Line is complete, log it - if (currentLine.toString().trim().length() > 0){ + if (currentLine.toString().trim().length() > 0) { String s = currentLine.toString(); - if ( Character.isWhitespace(s.charAt(0))){ + if (Character.isWhitespace(s.charAt(0))) { log.verbose(currentLine.toString()); } else { log.debug(currentLine.toString()); @@ -247,7 +247,7 @@ public class GuiceStartup { private static Injector initializeGuice() { Module applicationModule = new ApplicationModule(); - Module pluginModule = new PluginModule(PluginHelper.getPluginJars(), GuiceStartup.class.getClassLoader()); + Module pluginModule = new PluginModule(); return Guice.createInjector(applicationModule, pluginModule); } diff --git a/core/src/net/sf/openrocket/unit/UnitGroup.java b/core/src/net/sf/openrocket/unit/UnitGroup.java index 432398dfb..8c140ae98 100644 --- a/core/src/net/sf/openrocket/unit/UnitGroup.java +++ b/core/src/net/sf/openrocket/unit/UnitGroup.java @@ -1,6 +1,12 @@ package net.sf.openrocket.unit; -import static net.sf.openrocket.util.Chars.*; +import static net.sf.openrocket.util.Chars.CUBED; +import static net.sf.openrocket.util.Chars.DEGREE; +import static net.sf.openrocket.util.Chars.DOT; +import static net.sf.openrocket.util.Chars.MICRO; +import static net.sf.openrocket.util.Chars.PERMILLE; +import static net.sf.openrocket.util.Chars.SQUARED; +import static net.sf.openrocket.util.Chars.ZWSP; import static net.sf.openrocket.util.MathUtil.pow2; import java.util.ArrayList; @@ -86,6 +92,7 @@ public class UnitGroup { static { UNITS_NONE = new UnitGroup(); UNITS_NONE.addUnit(Unit.NOUNIT); + UNITS_NONE.setDefaultUnit(0); UNITS_ENERGY = new UnitGroup(); UNITS_ENERGY.addUnit(new GeneralUnit(1, "J")); @@ -127,9 +134,9 @@ public class UnitGroup { UNITS_LENGTH.setDefaultUnit(1); UNITS_MOTOR_DIMENSIONS = new UnitGroup(); - UNITS_MOTOR_DIMENSIONS.addUnit(new GeneralUnit(1, "m")); // just added UNITS_MOTOR_DIMENSIONS.addUnit(new GeneralUnit(0.001, "mm")); UNITS_MOTOR_DIMENSIONS.addUnit(new GeneralUnit(0.01, "cm")); + UNITS_MOTOR_DIMENSIONS.addUnit(new GeneralUnit(1, "m")); UNITS_MOTOR_DIMENSIONS.addUnit(new GeneralUnit(0.0254, "in")); UNITS_MOTOR_DIMENSIONS.setDefaultUnit(0); @@ -140,6 +147,7 @@ public class UnitGroup { UNITS_DISTANCE.addUnit(new GeneralUnit(0.9144, "yd")); UNITS_DISTANCE.addUnit(new GeneralUnit(1609.344, "mi")); UNITS_DISTANCE.addUnit(new GeneralUnit(1852, "nmi")); + UNITS_DISTANCE.setDefaultUnit(0); UNITS_ALL_LENGTHS = new UnitGroup(); UNITS_ALL_LENGTHS.addUnit(new GeneralUnit(0.001, "mm")); @@ -164,15 +172,16 @@ public class UnitGroup { UNITS_STABILITY = new UnitGroup(); - UNITS_STABILITY.addUnit(new GeneralUnit(1, "m")); UNITS_STABILITY.addUnit(new GeneralUnit(0.001, "mm")); UNITS_STABILITY.addUnit(new GeneralUnit(0.01, "cm")); + UNITS_STABILITY.addUnit(new GeneralUnit(1, "m")); UNITS_STABILITY.addUnit(new GeneralUnit(0.0254, "in")); UNITS_STABILITY.addUnit(new CaliberUnit((Rocket) null)); - UNITS_STABILITY.setDefaultUnit(3); + UNITS_STABILITY.setDefaultUnit(4); UNITS_STABILITY_CALIBERS = new UnitGroup(); UNITS_STABILITY_CALIBERS.addUnit(new GeneralUnit(1, "cal")); + UNITS_STABILITY_CALIBERS.setDefaultUnit(0); UNITS_VELOCITY = new UnitGroup(); @@ -180,23 +189,27 @@ public class UnitGroup { UNITS_VELOCITY.addUnit(new GeneralUnit(1 / 3.6, "km/h")); UNITS_VELOCITY.addUnit(new GeneralUnit(0.3048, "ft/s")); UNITS_VELOCITY.addUnit(new GeneralUnit(0.44704, "mph")); + UNITS_VELOCITY.setDefaultUnit(0); UNITS_WINDSPEED = new UnitGroup(); UNITS_WINDSPEED.addUnit(new GeneralUnit(1, "m/s")); UNITS_WINDSPEED.addUnit(new GeneralUnit(1 / 3.6, "km/h")); UNITS_WINDSPEED.addUnit(new GeneralUnit(0.3048, "ft/s")); UNITS_WINDSPEED.addUnit(new GeneralUnit(0.44704, "mph")); + UNITS_WINDSPEED.setDefaultUnit(0); UNITS_ACCELERATION = new UnitGroup(); UNITS_ACCELERATION.addUnit(new GeneralUnit(1, "m/s" + SQUARED)); UNITS_ACCELERATION.addUnit(new GeneralUnit(0.3048, "ft/s" + SQUARED)); UNITS_ACCELERATION.addUnit(new GeneralUnit(9.80665, "G")); + UNITS_ACCELERATION.setDefaultUnit(0); UNITS_MASS = new UnitGroup(); UNITS_MASS.addUnit(new GeneralUnit(0.001, "g")); UNITS_MASS.addUnit(new GeneralUnit(1, "kg")); UNITS_MASS.addUnit(new GeneralUnit(0.0283495231, "oz")); UNITS_MASS.addUnit(new GeneralUnit(0.45359237, "lb")); + UNITS_MASS.setDefaultUnit(0); UNITS_INERTIA = new UnitGroup(); UNITS_INERTIA.addUnit(new GeneralUnit(0.0001, "kg" + DOT + "cm" + SQUARED)); @@ -211,6 +224,7 @@ public class UnitGroup { UNITS_ANGLE.addUnit(new DegreeUnit()); UNITS_ANGLE.addUnit(new FixedPrecisionUnit("rad", 0.01)); UNITS_ANGLE.addUnit(new GeneralUnit(1.0 / 3437.74677078, "arcmin")); + UNITS_ANGLE.setDefaultUnit(0); UNITS_DENSITY_BULK = new UnitGroup(); UNITS_DENSITY_BULK.addUnit(new GeneralUnit(1000, "g/cm" + CUBED)); @@ -218,6 +232,7 @@ public class UnitGroup { UNITS_DENSITY_BULK.addUnit(new GeneralUnit(1, "kg/m" + CUBED)); UNITS_DENSITY_BULK.addUnit(new GeneralUnit(1729.99404, "oz/in" + CUBED)); UNITS_DENSITY_BULK.addUnit(new GeneralUnit(16.0184634, "lb/ft" + CUBED)); + UNITS_DENSITY_BULK.setDefaultUnit(0); UNITS_DENSITY_SURFACE = new UnitGroup(); UNITS_DENSITY_SURFACE.addUnit(new GeneralUnit(10, "g/cm" + SQUARED)); @@ -232,15 +247,18 @@ public class UnitGroup { UNITS_DENSITY_LINE.addUnit(new GeneralUnit(0.001, "g/m")); UNITS_DENSITY_LINE.addUnit(new GeneralUnit(1, "kg/m")); UNITS_DENSITY_LINE.addUnit(new GeneralUnit(0.0930102465, "oz/ft")); + UNITS_DENSITY_LINE.setDefaultUnit(0); UNITS_FORCE = new UnitGroup(); UNITS_FORCE.addUnit(new GeneralUnit(1, "N")); UNITS_FORCE.addUnit(new GeneralUnit(4.44822162, "lbf")); UNITS_FORCE.addUnit(new GeneralUnit(9.80665, "kgf")); + UNITS_FORCE.setDefaultUnit(0); UNITS_IMPULSE = new UnitGroup(); UNITS_IMPULSE.addUnit(new GeneralUnit(1, "Ns")); UNITS_IMPULSE.addUnit(new GeneralUnit(4.44822162, "lbf" + DOT + "s")); + UNITS_IMPULSE.setDefaultUnit(0); UNITS_TIME_STEP = new UnitGroup(); UNITS_TIME_STEP.addUnit(new FixedPrecisionUnit("ms", 1, 0.001)); @@ -249,10 +267,12 @@ public class UnitGroup { UNITS_SHORT_TIME = new UnitGroup(); UNITS_SHORT_TIME.addUnit(new GeneralUnit(1, "s")); + UNITS_SHORT_TIME.setDefaultUnit(0); UNITS_FLIGHT_TIME = new UnitGroup(); UNITS_FLIGHT_TIME.addUnit(new GeneralUnit(1, "s")); UNITS_FLIGHT_TIME.addUnit(new GeneralUnit(60, "min")); + UNITS_FLIGHT_TIME.setDefaultUnit(0); UNITS_ROLL = new UnitGroup(); UNITS_ROLL.addUnit(new GeneralUnit(1, "rad/s")); @@ -274,32 +294,29 @@ public class UnitGroup { UNITS_PRESSURE.addUnit(new GeneralUnit(3386.389, "inHg")); UNITS_PRESSURE.addUnit(new GeneralUnit(6894.75729, "psi")); UNITS_PRESSURE.addUnit(new GeneralUnit(1, "Pa")); + UNITS_PRESSURE.setDefaultUnit(0); UNITS_RELATIVE = new UnitGroup(); UNITS_RELATIVE.addUnit(new FixedPrecisionUnit("" + ZWSP, 0.01, 1.0)); UNITS_RELATIVE.addUnit(new GeneralUnit(0.01, "%")); UNITS_RELATIVE.addUnit(new FixedPrecisionUnit("" + PERMILLE, 1, 0.001)); - // UNITS_RELATIVE.addUnit(new FixedPrecisionUnit("" + ZWSP, 0.01, 1.0)); - // UNITS_RELATIVE.addUnit(new FixedPrecisionUnit("%", 1, 0.01)); - // UNITS_RELATIVE.addUnit(new FixedPrecisionUnit("" + PERMILLE, 1, 0.001)); UNITS_RELATIVE.setDefaultUnit(1); UNITS_ROUGHNESS = new UnitGroup(); - UNITS_ROUGHNESS.addUnit(new GeneralUnit(1, "m")); // just added UNITS_ROUGHNESS.addUnit(new GeneralUnit(0.000001, MICRO + "m")); UNITS_ROUGHNESS.addUnit(new GeneralUnit(0.0000254, "mil")); + UNITS_ROUGHNESS.addUnit(new GeneralUnit(1, "m")); + UNITS_ROUGHNESS.setDefaultUnit(0); UNITS_COEFFICIENT = new UnitGroup(); UNITS_COEFFICIENT.addUnit(new FixedPrecisionUnit("" + ZWSP, 0.01)); // zero-width space + UNITS_COEFFICIENT.setDefaultUnit(0); // This is not used by OpenRocket, and not extensively tested: UNITS_FREQUENCY = new UnitGroup(); - // UNITS_FREQUENCY.addUnit(new GeneralUnit(1, "s")); - // UNITS_FREQUENCY.addUnit(new GeneralUnit(0.001, "ms")); - // UNITS_FREQUENCY.addUnit(new GeneralUnit(0.000001, MICRO + "s")); UNITS_FREQUENCY.addUnit(new FrequencyUnit(.001, "mHz")); UNITS_FREQUENCY.addUnit(new FrequencyUnit(1, "Hz")); UNITS_FREQUENCY.addUnit(new FrequencyUnit(1000, "kHz")); diff --git a/core/test/net/sf/openrocket/database/ThrustCurveMotorSetTest.java b/core/test/net/sf/openrocket/database/ThrustCurveMotorSetTest.java index 40bf5e942..a544e44b2 100644 --- a/core/test/net/sf/openrocket/database/ThrustCurveMotorSetTest.java +++ b/core/test/net/sf/openrocket/database/ThrustCurveMotorSetTest.java @@ -1,6 +1,10 @@ package net.sf.openrocket.database; -import static org.junit.Assert.*; +import static org.junit.Assert.assertEquals; +import static org.junit.Assert.assertFalse; +import static org.junit.Assert.assertNull; +import static org.junit.Assert.assertTrue; +import static org.junit.Assert.fail; import java.util.Arrays; import java.util.Collections; @@ -14,31 +18,31 @@ import net.sf.openrocket.util.Coordinate; import org.junit.Test; public class ThrustCurveMotorSetTest { - - + + private static final ThrustCurveMotor motor1 = new ThrustCurveMotor( Manufacturer.getManufacturer("A"), - "F12X", "Desc", Motor.Type.UNKNOWN, new double[] { }, - 0.024, 0.07, new double[] { 0, 1, 2 }, new double[] {0, 1, 0}, - new Coordinate[] {Coordinate.NUL, Coordinate.NUL, Coordinate.NUL}, "digestA"); + "F12X", "Desc", Motor.Type.UNKNOWN, new double[] {}, + 0.024, 0.07, new double[] { 0, 1, 2 }, new double[] { 0, 1, 0 }, + new Coordinate[] { Coordinate.NUL, Coordinate.NUL, Coordinate.NUL }, "digestA"); private static final ThrustCurveMotor motor2 = new ThrustCurveMotor( Manufacturer.getManufacturer("A"), "F12H", "Desc", Motor.Type.SINGLE, new double[] { 5 }, - 0.024, 0.07, new double[] { 0, 1, 2 }, new double[] {0, 1, 0}, - new Coordinate[] {Coordinate.NUL, Coordinate.NUL, Coordinate.NUL}, "digestB"); + 0.024, 0.07, new double[] { 0, 1, 2 }, new double[] { 0, 1, 0 }, + new Coordinate[] { Coordinate.NUL, Coordinate.NUL, Coordinate.NUL }, "digestB"); private static final ThrustCurveMotor motor3 = new ThrustCurveMotor( Manufacturer.getManufacturer("A"), "F12", "Desc", Motor.Type.UNKNOWN, new double[] { 0, Motor.PLUGGED }, - 0.024, 0.07, new double[] { 0, 1, 2 }, new double[] {0, 2, 0}, - new Coordinate[] {Coordinate.NUL, Coordinate.NUL, Coordinate.NUL}, "digestC"); - + 0.024, 0.07, new double[] { 0, 1, 2 }, new double[] { 0, 2, 0 }, + new Coordinate[] { Coordinate.NUL, Coordinate.NUL, Coordinate.NUL }, "digestC"); + private static final ThrustCurveMotor motor4 = new ThrustCurveMotor( Manufacturer.getManufacturer("A"), "F12", "Desc", Motor.Type.HYBRID, new double[] { 0 }, - 0.024, 0.07, new double[] { 0, 1, 2 }, new double[] {0, 2, 0}, - new Coordinate[] {Coordinate.NUL, Coordinate.NUL, Coordinate.NUL}, "digestD"); + 0.024, 0.07, new double[] { 0, 1, 2 }, new double[] { 0, 2, 0 }, + new Coordinate[] { Coordinate.NUL, Coordinate.NUL, Coordinate.NUL }, "digestD"); @Test @@ -50,7 +54,7 @@ public class ThrustCurveMotorSetTest { assertEquals("J115", ThrustCurveMotorSet.simplifyDesignation("384-J115")); assertEquals("A2", ThrustCurveMotorSet.simplifyDesignation("A2T")); assertEquals("1/2A2T", ThrustCurveMotorSet.simplifyDesignation("1/2A2T")); - assertEquals("Micro Maxx II", ThrustCurveMotorSet.simplifyDesignation("Micro Maxx II")); + assertEquals("MicroMaxxII", ThrustCurveMotorSet.simplifyDesignation("Micro Maxx II")); } @Test diff --git a/core/test/net/sf/openrocket/plugin/Example2Plugin.java b/core/test/net/sf/openrocket/plugin/Example2Plugin.java new file mode 100644 index 000000000..a705139bd --- /dev/null +++ b/core/test/net/sf/openrocket/plugin/Example2Plugin.java @@ -0,0 +1,9 @@ +package net.sf.openrocket.plugin; + +/** + * Example plugin interface for testing purposes. + */ +@Plugin +public interface Example2Plugin { + +} diff --git a/core/src/net/sf/openrocket/plugin/ExamplePlugin.java b/core/test/net/sf/openrocket/plugin/ExamplePlugin.java similarity index 62% rename from core/src/net/sf/openrocket/plugin/ExamplePlugin.java rename to core/test/net/sf/openrocket/plugin/ExamplePlugin.java index b69950e80..a3e78481c 100644 --- a/core/src/net/sf/openrocket/plugin/ExamplePlugin.java +++ b/core/test/net/sf/openrocket/plugin/ExamplePlugin.java @@ -1,8 +1,9 @@ package net.sf.openrocket.plugin; +/** + * Example plugin for testing purposes. + */ @Plugin public interface ExamplePlugin { - public void doit(); - } diff --git a/core/src/net/sf/openrocket/plugin/ExamplePluginImpl.java b/core/test/net/sf/openrocket/plugin/ExamplePluginImpl.java similarity index 50% rename from core/src/net/sf/openrocket/plugin/ExamplePluginImpl.java rename to core/test/net/sf/openrocket/plugin/ExamplePluginImpl.java index 05a0aeb5b..b63d4df3f 100644 --- a/core/src/net/sf/openrocket/plugin/ExamplePluginImpl.java +++ b/core/test/net/sf/openrocket/plugin/ExamplePluginImpl.java @@ -1,10 +1,9 @@ package net.sf.openrocket.plugin; +/** + * ExamplePlugin implementation for testing purposes. + */ +@Plugin public class ExamplePluginImpl implements ExamplePlugin { - @Override - public void doit() { - System.out.println("ExamplePluginImpl.doit() called"); - } - } diff --git a/core/test/net/sf/openrocket/plugin/MultiPluginImpl.java b/core/test/net/sf/openrocket/plugin/MultiPluginImpl.java new file mode 100644 index 000000000..a48398536 --- /dev/null +++ b/core/test/net/sf/openrocket/plugin/MultiPluginImpl.java @@ -0,0 +1,10 @@ +package net.sf.openrocket.plugin; + +/** + * Plugin that implements both ExamplePlugin and Example2Plugin + * for testing purposes. + */ +@Plugin +public class MultiPluginImpl implements ExamplePlugin, Example2Plugin { + +} diff --git a/core/test/net/sf/openrocket/plugin/NotAnExamplePluginImpl.java b/core/test/net/sf/openrocket/plugin/NotAnExamplePluginImpl.java new file mode 100644 index 000000000..3f717389b --- /dev/null +++ b/core/test/net/sf/openrocket/plugin/NotAnExamplePluginImpl.java @@ -0,0 +1,9 @@ +package net.sf.openrocket.plugin; + +/** + * An implementation of ExamplePlugin that is not annotated with @Plugin + * for testing purposes. This should not be injected into the test class. + */ +public class NotAnExamplePluginImpl implements ExamplePlugin { + +} diff --git a/core/test/net/sf/openrocket/plugin/PluginTest.java b/core/test/net/sf/openrocket/plugin/PluginTest.java new file mode 100644 index 000000000..8e425b622 --- /dev/null +++ b/core/test/net/sf/openrocket/plugin/PluginTest.java @@ -0,0 +1,26 @@ +package net.sf.openrocket.plugin; + +import org.junit.Test; + +import com.google.inject.Guice; +import com.google.inject.Injector; + +/** + * Test the plugin loading system using Guice. + * + * This is more of an integration than a unit test. It uses the + * PluginModule to load a Guice injector, and then verifies that it + * has found the appropriate plugins. + */ +public class PluginTest { + + @Test + public void testPluginModule() { + + Injector injector = Guice.createInjector(new PluginModule()); + PluginTester tester = injector.getInstance(PluginTester.class); + tester.testPlugins(); + + } + +} diff --git a/core/test/net/sf/openrocket/plugin/PluginTester.java b/core/test/net/sf/openrocket/plugin/PluginTester.java new file mode 100644 index 000000000..87ee2f202 --- /dev/null +++ b/core/test/net/sf/openrocket/plugin/PluginTester.java @@ -0,0 +1,38 @@ +package net.sf.openrocket.plugin; + +import static org.junit.Assert.assertEquals; +import static org.junit.Assert.assertTrue; + +import java.util.Arrays; +import java.util.List; +import java.util.Set; + +import net.sf.openrocket.util.ArrayList; + +import com.google.inject.Inject; + +public class PluginTester { + + @Inject + private Set examplePlugins; + @Inject + private Set example2Plugins; + + + public void testPlugins() { + assertContains(examplePlugins, ExamplePluginImpl.class, MultiPluginImpl.class, JarPluginImpl.class); + assertContains(example2Plugins, MultiPluginImpl.class); + } + + + private void assertContains(Set set, Class... classes) { + assertEquals(classes.length, set.size()); + + List> list = new ArrayList>(Arrays.asList(classes)); + for (Object o : set) { + Class c = o.getClass(); + assertTrue(list.contains(c)); + list.remove(c); + } + } +} diff --git a/core/test/net/sf/openrocket/util/TestMutex.java b/core/test/net/sf/openrocket/util/TestMutex.java index 94d5a9f58..aa220a510 100644 --- a/core/test/net/sf/openrocket/util/TestMutex.java +++ b/core/test/net/sf/openrocket/util/TestMutex.java @@ -1,6 +1,10 @@ package net.sf.openrocket.util; -import static org.junit.Assert.*; +import static org.junit.Assert.assertFalse; +import static org.junit.Assert.assertNotNull; +import static org.junit.Assert.assertNull; +import static org.junit.Assert.assertTrue; +import static org.junit.Assert.fail; import org.junit.Before; import org.junit.Test; @@ -53,7 +57,7 @@ public class TestMutex { } - + private volatile int testState = 0; private volatile String failure = null; @@ -106,6 +110,7 @@ public class TestMutex { testState = 6; } catch (Exception e) { + e.printStackTrace(); failure = "Exception occurred in thread: " + e; return; }