public class LegacyEnvironment extends Object
This class is a partner to the LegacyClassLoader
, intended to make
sure that the ImageJ 1.x contained in a given class loader is patched and can
be accessed conveniently.
Constructor and Description |
---|
LegacyEnvironment(ClassLoader loader,
boolean headless)
Constructs a new legacy environment.
|
Modifier and Type | Method and Description |
---|---|
void |
addPluginClasspath(ClassLoader fromClassLoader)
Adds the class path of a given
ClassLoader to the plugin class
loader. |
void |
addPluginClasspath(File... classpathEntries)
Adds extra elements to the class path of ImageJ 1.x' plugin class loader.
|
void |
applyPatches()
Applies the configuration patches.
|
void |
disableIJ1PluginDirs()
Disallows the encapsulated ImageJ 1.x from parsing the directories listed
in
ij1.plugin.dirs . |
void |
disableInitializer()
Disables the execution of the
ij1.patcher.initializer . |
ClassLoader |
getClassLoader()
Gets the class loader containing the ImageJ 1.x classes used in this legacy
environment.
|
Map<String,String> |
getMenuStructure()
Gets the ImageJ 1.x menu structure as a map
|
static LegacyEnvironment |
getPatchedImageJ1()
Launches a fully-patched, self-contained ImageJ 1.x.
|
static boolean |
isImageJ1Initialized(ClassLoader loader)
Determines whether there is already an ImageJ 1.x instance.
|
void |
main(String... args)
Runs
ImageJ.main(args) in the legacy environment. |
Object |
newImageJ1(boolean hidden)
Initializes a new ImageJ 1.x instance.
|
void |
noPluginClassLoader()
Forces ImageJ 1.x to use the same
ClassLoader for plugins as for
ImageJ 1.x itself. |
void |
run(String command,
String options)
Runs
IJ.run(command, options) in the legacy environment. |
void |
runMacro(String macro,
String arg)
Runs
IJ.runMacro(macro, arg) in the legacy environment. |
Object |
runPlugIn(String className,
String arg)
Runs
IJ.runPlugIn(className, arg) in the legacy environment. |
void |
setMacroOptions(String options)
Sets the macro options.
|
void |
suppressIJ1ScriptDiscovery()
Disallows ImageJ 1.x from discovering macros and scripts to put into the
menu structure.
|
public LegacyEnvironment(ClassLoader loader, boolean headless) throws ClassNotFoundException
loader
- the ClassLoader
to use for loading the (patched)
ImageJ 1.x classes; if null
, a LegacyClassLoader
is constructed.headless
- whether to patch in support for headless operation
(compatible only with "well-behaved" plugins, i.e. plugins that do
not use graphical components directly)ClassNotFoundException
public void disableIJ1PluginDirs()
ij1.plugin.dirs
.
The patched ImageJ 1.x has a feature where it interprets the value of the
ij1.plugin.dirs
system property as a list of directories in which
to discover plugins in addition to <imagej.dir>/plugins
. In the
case that the ij1.plugin.dirs
property is not set, the directory
$HOME/.plugins/
-- if it exists -- is inspected instead.
This is a convenient behavior when the user starts up ImageJ 1.x as an application, but it is less than desirable when running in a cluster or from unit tests. For such use cases, this method needs to be called in order to disable additional plugin directories.
public void disableInitializer()
ij1.patcher.initializer
.
A fully patched ImageJ 1.x will allow an initializer class implementing the
Runnable
interface (and discovered via ImageJ 1.x' own
PluginClassLoader
) to run just after ImageJ 1.x was
initialized. If the system property ij1.patcher.initializer
is
unset, it defaults to ImageJ2's LegacyInitializer
class.
Users of the LegacyEnvironment class can call this method to disable that behavior.
public void noPluginClassLoader()
ClassLoader
for plugins as for
ImageJ 1.x itself.
ImageJ 1.x has a command Help>Refresh Menus that allows users to
ask ImageJ 1.x to parse the plugins/
directory for new, or
modified, plugins, and to remove menu labels corresponding to plugins whose
files were deleted while ImageJ 1.x is running. The intended use case is to
support developing ImageJ 1.x plugins without having to restart ImageJ 1.x
all the time, just to test new iterations of the same plugin.
To support this, a PluginClassLoader
that loads the plugin
classes is instantiated at initialization, and whenever the user calls
Refresh Menus, essentially releasing the old ClassLoader
.
This is a fragile solution, as no measures are taken to ensure that the
classes loaded by the previous PluginClassLoader
are no
longer used, but it works most of the time.
With ImageJ2 being developed in a modular manner, it is no longer easy to have one class loader containing only the ImageJ classes and another class loader containing all the plugins. Therefore, this method is required to be able to force ImageJ 1.x to reuse the same class loader for plugins as for ImageJ classes, implying that the Refresh Menus command needs to be disabled.
Since the advent of powerful Integrated Development Environments such as
Netbeans and Eclipse, it is preferable to develop even ImageJ 1.x plugins
in such environments instead of using a text editor to edit the
.java
source, then running javac
from the command-line,
calling Refresh Menus and finally repeating the manual test
procedure, anyway.
public void suppressIJ1ScriptDiscovery()
Some callers -- most notably ImageJ2 and Fiji -- want to improve on the scripting support, which unfortunately implies overriding the non-extensible script and macro handling of ImageJ 1.x.
public void addPluginClasspath(ClassLoader fromClassLoader)
ClassLoader
to the plugin class
loader.
This method is intended to be used in unit tests as well as interactive
debugging from inside an Integrated Development Environment where the
plugin's classes are not available inside a .jar
file.
At the moment, the only supported parameters are URLClassLoader
s.
fromClassLoader
- the class path donorpublic void addPluginClasspath(File... classpathEntries)
The typical use case for a LegacyEnvironment
is to run specific
plugins in an encapsulated environment. However, in the case of multiple
one wants to use multiple legacy environments with separate sets of plugins
enabled, it becomes impractical to pass the location of the plugins'
.jar
files via the plugins.dir
system property (because of
threading issues).
In other cases, the plugins' .jar
files are not located in a single
directory, or worse: they might be contained in a directory among
.jar
files one might not want to add to the plugin class
loader's class path.
This method addresses that need by allowing to add individual .jar
files to the class path of the plugin class loader and ensuring that their
plugins.config
files are parsed.
classpathEntries
- the class path entries containing ImageJ 1.x
pluginspublic void setMacroOptions(String options)
Both run(String, String)
and runMacro(String, String)
take an argument that is typically recorded by the macro recorder. For
runPlugIn(String, String)
, however, only the arg
parameter
that is to be passed to the plugins run()
or setup()
method
can be specified. For those use cases where one wants to call a plugin
class directly, but still provide macro options, this method is the
solution.
options
- the macro options to use for the next call to
runPlugIn(String, String)
public void run(String command, String options)
IJ.run(command, options)
in the legacy environment.command
- the command to runoptions
- the options to pass to the commandpublic void runMacro(String macro, String arg)
IJ.runMacro(macro, arg)
in the legacy environment.macro
- the macro code to runarg
- an optional argument (which can be retrieved in the macro code
via getArgument()
)public Object runPlugIn(String className, String arg)
IJ.runPlugIn(className, arg)
in the legacy environment.className
- the plugin class to runarg
- an optional argument (which get passed to the run()
or
setup()
method of the plugin)public void main(String... args)
ImageJ.main(args)
in the legacy environment.args
- the arguments to pass to the main() methodpublic Object newImageJ1(boolean hidden)
This method starts up a fully-patched ImageJ 1.x, optionally hidden (in
headless
mode, it must be hidden).
hidden
- whether to hide the ImageJ 1.x main window upon startupImageJ
class, or null
in
headless modepublic void applyPatches()
After calling methods to configure the current LegacyEnvironment
(e.g. disableIJ1PluginDirs()
), the final step before using the
encapsulated ImageJ 1.x is to apply the configuring patches to the
EssentialLegacyHooks
class. This method needs to be called if the
configuration has to be finalized, but ImageJ 1.x is not run right away,
e.g. to prepare for third-party libraries using ImageJ 1.x classes
directly.
public ClassLoader getClassLoader()
public Map<String,String> getMenuStructure()
public static LegacyEnvironment getPatchedImageJ1() throws ClassNotFoundException
ClassNotFoundException
public static boolean isImageJ1Initialized(ClassLoader loader)
In contrast to IJ.getInstance()
, this method avoids loading any
ImageJ 1.x class, and is therefore suitable for testing whether a
LegacyEnvironment
needs to be created when the caller wants the
classes to be patched in its own ClassLoader
.
loader
- the class loader in which to look for the ImageJ 1.x instanceCopyright © 2014–2022 ImageJ. All rights reserved.