Class PluginExtensionRegistryImpl

java.lang.Object
com.xebialabs.xlrelease.osgi.spring.PluginExtensionRegistryImpl
All Implemented Interfaces:
PluginExtensionRegistry

@Component public class PluginExtensionRegistryImpl extends Object implements PluginExtensionRegistry
A single instance is shared between the root host ApplicationContext (as this @Component) and every plugin's curated parent context (PluginApiParentContext registers the exact same object as a singleton there) - not two copies, one shared reference, so a plugin-side registration is immediately visible to host-side queries.

Keyed internally by Bundle-SymbolicName, never the optional URL prefix, so one plugin's entries can be removed atomically on teardown regardless of whether it ever declared a prefix.

Mutations (register/unregister) are infrequent (plugin install/uninstall); a single monitor guarding both mutation and read is simple and sufficiently cheap, and it also sidesteps the ordering pitfall a ConcurrentHashMap-based structure would have (no insertion-order guarantee), which registration-order correctness depends on.

Feeds two consumption styles: host code that pulls a snapshot on demand (extensions(Class), e.g. PluginTaskExtensionResolver) and host code that wants to be pushed add/remove events as they happen (addListener(java.lang.Class<? extends com.xebialabs.xlrelease.osgi.api.spring.HostExtensionPoint>, com.xebialabs.xlrelease.osgi.spring.PluginExtensionRegistryImpl.ExtensionRegistryListener), e.g. an OSGi-service-backed extension kind that maintains external derived state). Both styles are fed by every feeder that calls register(java.lang.String, com.xebialabs.xlrelease.osgi.api.spring.HostExtensionPoint)/unregister(java.lang.String) - a Spring plugin-context bean and an OSGi-service extension arrive through the same two methods, so this class does not need to know which kind of bundle contributed a given extension.

  • Constructor Details

    • PluginExtensionRegistryImpl

      public PluginExtensionRegistryImpl()
  • Method Details

    • register

      public void register(String bundleSymbolicName, com.xebialabs.xlrelease.osgi.api.spring.HostExtensionPoint bean)
      Fans bean out to every HostExtensionPoint subtype it actually implements - a bean may implement more than one extension-point interface. Called by PluginContextFactory right after a successful ctx.refresh() for a Spring-plugin-context feeder, or by an OSGi-service feeder when a matching service appears.
    • unregister

      public void unregister(String bundleSymbolicName)
      Removes every entry registered under bundleSymbolicName, atomically. Called by PluginTeardown's ordered teardown, which decides where in that sequence it runs.
    • unregister

      public void unregister(String bundleSymbolicName, com.xebialabs.xlrelease.osgi.api.spring.HostExtensionPoint bean)
      Removes just bean from bundleSymbolicName's entries, pruning now-empty type/bundle map entries. Unlike unregister(String), does not affect any other bean the same bundle may have registered. Used by feeders that observe removal of a single contribution (e.g. one OSGi service going away) rather than a whole bundle's teardown.
    • addListener

      public void addListener(Class<? extends com.xebialabs.xlrelease.osgi.api.spring.HostExtensionPoint> type, PluginExtensionRegistryImpl.ExtensionRegistryListener listener)
      Subscribes listener to add/remove events for type, and immediately replays every currently-registered extension of type as a synthetic extensionAdded call (outside the lock, like every other notification) - so a listener never has to race "subscribe" against "read the current snapshot" to build a consistent picture, regardless of the order addListener(java.lang.Class<? extends com.xebialabs.xlrelease.osgi.api.spring.HostExtensionPoint>, com.xebialabs.xlrelease.osgi.spring.PluginExtensionRegistryImpl.ExtensionRegistryListener) and bundle installation happen to run in.
    • extensions

      public <T extends com.xebialabs.xlrelease.osgi.api.spring.HostExtensionPoint> List<T> extensions(Class<T> type)
      Specified by:
      extensions in interface PluginExtensionRegistry
      Returns:
      a freshly-built, independent list - never a live view - of every registered implementation of type, in registration order. No ordering/priority beyond registration order is supported in v1; this is a documented limitation, not an accidental behavior to discover later.