Move NoSuchMethodError handling from fiji-compat into ij-legacy

Signed-off-by: Johannes Schindelin <johannes.schindelin@gmx.de>
ij-legacy: clarify the double-purpose of LegacyHacker

LegacyHacker serves two purposes:

- making it possible to synchronize legacy and modern ImageJ instances,

- give fiji-compat's backwards-compatibility patches a safe home (Fiji
  made ImageJ 1.x more backwards-compatible than it wanted to be).

The latter purpose also includes hooks introduced by Fiji e.g. for
setting the application name, the window icon, or patching in the Script
Editor in place of the bare-bones text editor of ImageJ 1.x.

Signed-off-by: Johannes Schindelin <johannes.schindelin@gmx.de>
Move Fiji's JavassistHelper#disassemble() into the CodeHacker

Signed-off-by: Johannes Schindelin <johannes.schindelin@gmx.de>
Move Fiji's JavassistHelper#writeJar() into the CodeHacker

Signed-off-by: Johannes Schindelin <johannes.schindelin@gmx.de>
Add documentation for CodeHacker#disassemble

Signed-off-by: Johannes Schindelin <johannes.schindelin@gmx.de>
Add documentation for CodeHacker#writeJar

Signed-off-by: Johannes Schindelin <johannes.schindelin@gmx.de>
CodeHackerTest: clarify an assertion

Signed-off-by: Johannes Schindelin <johannes.schindelin@gmx.de>
CodeHacker: organize imports

Signed-off-by: Johannes Schindelin <johannes.schindelin@gmx.de>
Hack bytecode verification into the CodeHacker

This is extremely hacky at the moment: it assumes that you have
a Fiji.app/ in your home directory and loads the ASM embedded in
Fiji's jruby.jar. This is extremely fragile and needs to be cleaned
up. However, in the interest of YAGNI, this commit does not do
that yet.

Signed-off-by: Johannes Schindelin <johannes.schindelin@gmx.de>
ij-legacy: add legacy plugins from $HOME/.plugins/

This is the first step to replace Fiji's FijiClassLoader: it looks
also in ~/.plugins/.

However, to test, and to be able to override, we also look at the
property 'ij1.plugin.dirs' which is interpreted as a PATH-style list
of directories. If this property is set, ~/.plugins/ is not looked
at automatically.

Signed-off-by: Johannes Schindelin <johannes.schindelin@gmx.de>
Test ij-legacy's ~/.plugins/ support

Signed-off-by: Johannes Schindelin <johannes.schindelin@gmx.de>
ij-legacy: stop the Java Agent whenever CodeHacker loads classes

Signed-off-by: Johannes Schindelin <johannes.schindelin@gmx.de>
ij-legacy tests: refactor getClassLoader()

This method serves only one purpose: to get a fresh class loader that
does not have any ImageJ 1.x classes loaded yet. That is too useful
for the legacy tests to be hidden in the headless unit test class.

While at it (because it is needed now), make the code more robust: do
not load the ImageJ class at all yet.

Signed-off-by: Johannes Schindelin <johannes.schindelin@gmx.de>
ij-legacy tests: further refactor getFreshClassLoader()

We might need to make sure that other classes are found than the
Headless Example Plugin...

Signed-off-by: Johannes Schindelin <johannes.schindelin@gmx.de>
Add javadocs for LegacyTestUtils#getFreshClassLoader

Signed-off-by: Johannes Schindelin <johannes.schindelin@gmx.de>
LegacyInjector: for testing, accept a fully-initialized CodeHacker

... instead of a ClassLoader.

But do not set the LegacyService in ij.IJ._service in that case because it
is most likely from another class loader.

Signed-off-by: Johannes Schindelin <johannes.schindelin@gmx.de>
LegacyTestUtils#getFreshIJClassLoader: offer legacy patching

For testing, we will want to run ImageJ 1.x stuff with and without
LegacyInjector().injectHooks() run first.

Signed-off-by: Johannes Schindelin <johannes.schindelin@gmx.de>
LegacyTestUtils: offer to write ImageJ 1.x-style plugin .jar files

Signed-off-by: Johannes Schindelin <johannes.schindelin@gmx.de>
Turn the ij-legacy class loader integration into a simple unit test

It is much easier to debug a simple unit test than integration tests.
In the case of the ij-legacy class loder tests, we made them integration
tests only so that we would have a fresh class loader, unencumbered from
any patched or unpatched ImageJ 1.x classes.

But we just needed to refactor the legacy headless tests which created
exactly such a class loader.

Signed-off-by: Johannes Schindelin <johannes.schindelin@gmx.de>
LegacyTestUtils: the LegacyInjector's and ij.IJ's class loader must match

Otherwise, LegacyInjector's setLegacyService() tries to assign a new
instance of DummyLegacyService to ij.IJ._service, but that fails because
the DummyLegacyService and the type of ij.IJ._service were loaded with
different class loaders and are therefore incompatible.

Signed-off-by: Johannes Schindelin <johannes.schindelin@gmx.de>