Make it possible to initialize extensions even when running headless

Feature request

Is your feature request related to a problem? Please describe.

QuPathExtension.installExtension(QuPathGUI qupath) is called whenever an extension is loaded through the user interface. This makes it possible to run some initialization code there.

However there isn't a similar method to call when an extension is 'loaded' headlessly. Rather, the only thing that happens is that the extension jar is added to the classpath.

This is a problem if the extension needs to register any custom JSON deserializers that are also required to load the project... because there isn't a way to call the necessary code early enough.

See https://forum.image.sc/t/qupath-headless-script-fails-on-warpy-overlaid-images/116770

Describe the solution you'd like

Proposed solution is to add a method to QuPathExtension with a default (do-nothing) implementation, e.g. installHeadless().

Describe alternatives you've considered

We could instantiate QuPathExtension instances in headless mode, then either

  • call installExtension(null) (but this is likely to break many extensions)
  • don't call installExtension (which could still help by at least running any static initialization code for the class)

Additional context

Leaving this in case more ideas come...