maven-helper: point out invalid subcommands

Signed-off-by: Johannes Schindelin <johannes.schindelin@gmx.de>
Add a helper for performance benchmarking

We often encounter the situation where a list of similar operations needs
to be sped up, and we need to find the most promising candidate quickly.
For example, when the startup of a context is slow, there are typically
only very few services dominating the time, and they are the best targets
for optimization.

The Timing helper makes it easy to find out those candidates by
accumulating a list of items with durations and reporting a sorted list
when the report() method is called.

The helper lives in src/test/java/ to avoid tainting the official
scijava-common API with it; that way, we can easily adapt it to new needs
or even break backwards-compatibility without having to worry about
bumping the version. In Eclipse, you can still use it because Eclipse is a
bit challenged with class path scopes: it simply mooshes all dependencies
together, including 'test' and 'compile' scoped ones, anyway.

Signed-off-by: Johannes Schindelin <johannes.schindelin@gmx.de>
Timing: fix getCaller()

Signed-off-by: Johannes Schindelin <johannes.schindelin@gmx.de>
Timing: add more convenience

Now it is sufficient to call the reset() method to reset the current
timing to 0, and you can call report(null) to make debugging easier
when the file name and line number are sufficient for the performance
benchmarking.

Signed-off-by: Johannes Schindelin <johannes.schindelin@gmx.de>
More convenience methods in Timing

Now you can perform performance benchmarks by adding

	final Timing timing = Timing.start(condition);
	...
	Timing.tick(timing);
	...
	Timing.tick(timing);
	...
	Timing.tick(timing);
	...
	Timing.stop(timing);

The stop() method will measure the last tick, order all the individual
steps (i.e. between ticks) by time and output a sorted list.

All of this only happens if the condition is true, which is really
convenient if you want to benchmark a method only for a given parameter.

Signed-off-by: Johannes Schindelin <johannes.schindelin@gmx.de>
Move Timing out of src/test/

Required for Maven...

Signed-off-by: Johannes Schindelin <johannes.schindelin@gmx.de>
Speed up ObjectIndex#add, part one

Instead of obtaining the complete class/interface hierarchy for ever
item we add, we can do that once per class; the next time we add an
item of the same class, we'll have the list already.

This shaves off around 10-15% of ImageJ's DefaultCommandService's
initialization.

Signed-off-by: Johannes Schindelin <johannes.schindelin@gmx.de>
Speed up ObjectIndex#add, part two

Instead of looking up the list for every interface implemented by the
current item to add, we cache pre-calculated lists for every class
we encountered.

This shaves off another 5-10% of ImageJ's DefaultCommandService's
initialization.

Signed-off-by: Johannes Schindelin <johannes.schindelin@gmx.de>
EventService: do not use AWT's event queue for publishLater()

EventQueue.invokeLater consumes a whopping 100ms here, while a simple
spawned thread only consumes 3ms. Quite a difference.

Signed-off-by: Johannes Schindelin <johannes.schindelin@gmx.de>
ObjectIndex: support PluginIndex better

We used to require overriding the add() method for only one reason:
the type by which the objects are indexed in PluginIndex are not
obtained by getClass(), but by getPluginType().

This suggests that the base class actually needs a more flexible way
to obtain the types by which to index, so let's do that instead.

This will help with the upcoming performance enhancements which will
bypass the add() method completely for SortedObjectIndex' addAll().

Signed-off-by: Johannes Schindelin <johannes.schindelin@gmx.de>
Try to speed up the SortedObjectIndex further

Rather than adding things blindly to several typed lists which are all
supported to be sorted already, only to sort them again in the end,
let's

- sort the elements to be added

- make sub-lists of the sorted list for the individual typed lists

- merge the sorted lists in O(n)

instead.

While at it, we should not iterate the elements of HashSets with
supposedly immutable contents over and over and over again. Let's make
performant arrays from them as soon as we generated the sets.

Signed-off-by: Johannes Schindelin <johannes.schindelin@gmx.de>
Speed up loading the services by publishing the ServicesLoadedEvent lazily

Signed-off-by: Johannes Schindelin <johannes.schindelin@gmx.de>
DefaultEventBus: avoid publishing events nobody is interested in

The AWT EventQueue is really slow: EventQueue.invokeAndWait() can take
up to 30x as long as creating a new thread and starting it on the
provided Runnable.

If there is not even a subscriber to the event we are about to send,
let's just not bother.

Signed-off-by: Johannes Schindelin <johannes.schindelin@gmx.de>
release-version: die when maven-helper could not be run

Signed-off-by: Johannes Schindelin <johannes.schindelin@gmx.de>
ClassUtils: add getLeafInterface methods

Added a getLeafInterfaces and getLeafInterfacesOfType method to
ClassUtils.

These methods scan an array of classes and build a list of all
interfaces implemented by those classes, that are not further
subclassed.

For example, if Foo.class on the class list implements IfaceA and
IfaceB, Bar.class on the class list implements IfaceC, and IfaceC
extends IfaceB, then these methods would return IfaceA and IfaceC,
because IfaceB was not a leaf interface.

The "..OfType" signature allows the specification of an upper bound on
the returned interface types. For example, type == Service.class, only
leaf interfaces that extend Service.class will be returned.
ServiceHelper: load all leaves when given an iface

The loadClasses method, when loading its list of service classes, will
now load interfaces and implementations differently.

Implementations can be loaded directly (unchanged behavior).

For a given interface, a list of all known leaf interfaces extending the
provided interface will be constructed, and each discovered leaf
interface will be loaded. This allows consuming software to define its
own marker interfaces for services, and contexts created with these
marker interfaces to load all extending types dynamically discovered at
runtime.
Added ScijavaService

Created a ScijavaService class and updated all scijava-common services
to extend it.

This allows for granular selection of all scijava-common services during
Context creation, without necessitating an explicit list.

Updated Context creation unit tests as appropriate.