Add a better infrastructure for legacy hooks

We will add extension points in the next few commits that make sure that
the current legacy hooks (installed into ij.IJ._hooks) are called at the
appropriate time.

To avoid having to check ij.IJ._hooks for null all the time, the
EssentialLegacyHooks class is a fall-back, to be installed whenever
there are no other legacy hooks available.

This starts the process of disentangling the LegacyService from the
extension points inserted into ImageJ 1.x.

Signed-off-by: Johannes Schindelin <johannes.schindelin@gmx.de>
Implement legacy hooks for ImageJ2

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

Signed-off-by: Johannes Schindelin <johannes.schindelin@gmx.de>
LegacyInjector: add constructor with explicit headless mode

Rather than relying on the GraphicsEnvironment to know whether we want to
have a headless environment or not, let's have an explicit way to specify
that.

Signed-off-by: Johannes Schindelin <johannes.schindelin@gmx.de>
Do not require a CodeHacker for injectHooks()

Let's try to avoid using the CodeHacker directly...

Signed-off-by: Johannes Schindelin <johannes.schindelin@gmx.de>
Make LegacyJavaAgentIT less implementation-dependent

We are about to switch around a few things, in particular the assumption
that there is always a LegacyService available.

Signed-off-by: Johannes Schindelin <johannes.schindelin@gmx.de>
Remove obsolete patches for ij.macro.Functions

Signed-off-by: Johannes Schindelin <johannes.schindelin@gmx.de>
Move IJFunctions into the LegacyInjector/LegacyHooks

Signed-off-by: Johannes Schindelin <johannes.schindelin@gmx.de>
Move ImageJFunctions into LegacyInjector/LegacyHooks

Signed-off-by: Johannes Schindelin <johannes.schindelin@gmx.de>
Move ImagePlusFunctions into LegacyInjector/LegacyHooks

Signed-off-by: Johannes Schindelin <johannes.schindelin@gmx.de>
Move ImageWindowFunctions into LegacyInjector/LegacyHooks

Signed-off-by: Johannes Schindelin <johannes.schindelin@gmx.de>
Move PluginClassLoaderFunctions into LegacyInjector/LegacyHooks

Signed-off-by: Johannes Schindelin <johannes.schindelin@gmx.de>
Switch to Modern Mode: get the LegacyService through the Context

ImageJ 1.x should not know about any ImageJ2 classes explicitly...

Signed-off-by: Johannes Schindelin <johannes.schindelin@gmx.de>
Add an extension point for ij.IJ#runPlugIn()

Earlier, we overrode runPlugIn() to return the context and the legacy
service if the user asked for that class name.

However, since we want to keep the class loader in which ImageJ 1.x lives
free of ImageJ2 classes, we cannot do it that way any longer.

Instead, we add an extension point in the legacy hooks; that way, the
hooks can decide what they want to offer and what not.

Signed-off-by: Johannes Schindelin <johannes.schindelin@gmx.de>
Do not use $isLegacyMode() any longer

It is a method in the legacy hooks now. This will allow us to remove
the explicit LegacyService reference in ij.IJ.

Signed-off-by: Johannes Schindelin <johannes.schindelin@gmx.de>
No longer inject the Context & LegacyService in ij.IJ

We cannot: the class loader in which ImageJ 1.x lives should not need
to know any ImageJ2 class explicitly.

Instead, calling

	ij.IJ.runPlugIn("org.scijava.Context", null);

will be intercepted by the legacy hooks and ask the LegacyService itself
for the context.

Hence we no longer need to inject the Context nor the LegacyService into
the ij.IJ class as static fields.

Signed-off-by: Johannes Schindelin <johannes.schindelin@gmx.de>
Get rid of the DummyLegacyService

It was only needed because we conflated the concept of LegacyService and
LegacyHooks to begin with (i.e. the DummyLegacyService played the role
of the EssentialLegacyHooks, in other words a set of essential legacy
hooks in the absence of an active LegacyService)...

Signed-off-by: Johannes Schindelin <johannes.schindelin@gmx.de>
CodeHacker: copy a method from LegacyExtensions that is about to vanish

Signed-off-by: Johannes Schindelin <johannes.schindelin@gmx.de>
Move LegacyExtensions' hooks into LegacyHooks

This is only the first step; after the move, we will separate the patches
even further into ImageJ2 extension points and standard patches (i.e.
patches that are active even without the presence of ImageJ2 on the class
path).

Signed-off-by: Johannes Schindelin <johannes.schindelin@gmx.de>
Move some of the former LegacyExtensions into the ImageJ2-specific hooks

Our ultimate goal is to separate concerns; that means that patches for
ImageJ 1.x that are independent of ImageJ2 should go to the essential
legacy hooks while extensions that actually require ImageJ2 go to the
DefaultLegacyHooks class (so that we can factor out the patcher itself
into a separate project).

In this vein, let's move certain extension points we just moved out of
LegacyExtensions further into DefaultLegacyHooks, e.g. the editor hooks.

Basically everything we will want to implement via the SciJava-common
plugin framework needs to be handled by DefaultLegacyHooks.

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