3232
3333package org .scijava .plugin ;
3434
35+ import java .util .ArrayList ;
3536import java .util .Collections ;
3637import java .util .HashMap ;
3738import java .util .List ;
3839import java .util .Map ;
3940
41+ import org .scijava .event .EventHandler ;
4042import org .scijava .log .LogService ;
4143import org .scijava .object .ObjectService ;
44+ import org .scijava .plugin .event .PluginsAddedEvent ;
45+ import org .scijava .plugin .event .PluginsRemovedEvent ;
4246
4347/**
4448 * Abstract base class for {@link SingletonService}s.
@@ -56,9 +60,6 @@ public abstract class AbstractSingletonService<PT extends SingletonPlugin>
5660 @ Parameter
5761 private ObjectService objectService ;
5862
59- // TODO: Listen for PluginsAddedEvent and PluginsRemovedEvent
60- // and update the list of singletons accordingly.
61-
6263 /** List of singleton plugin instances. */
6364 private List <PT > instances ;
6465
@@ -74,7 +75,7 @@ public ObjectService objectService() {
7475 @ Override
7576 public List <PT > getInstances () {
7677 if (instances == null ) initInstances ();
77- return instances ;
78+ return Collections . unmodifiableList ( instances ) ;
7879 }
7980
8081 @ SuppressWarnings ("unchecked" )
@@ -84,20 +85,63 @@ public <P extends PT> P getInstance(final Class<P> pluginClass) {
8485 return (P ) instanceMap .get (pluginClass );
8586 }
8687
88+ //-- Event handlers --
89+
90+ @ EventHandler
91+ protected void onEvent (final PluginsRemovedEvent event ) {
92+ if (instanceMap == null ) return ;
93+ for (final PluginInfo <?> info : event .getItems ()) {
94+ final PT obj = instanceMap .remove (info .getPluginClass ());
95+ if (obj != null ) { // we actually removed a plugin
96+ instances .remove (obj );
97+ objectService .removeObject (obj );
98+ }
99+ }
100+ }
101+
102+ @ EventHandler
103+ protected void onEvent (final PluginsAddedEvent event ) {
104+ if (instanceMap == null ) return ;
105+ // collect singleton plugins
106+ final List <PluginInfo <PT >> singletons = new ArrayList <>();
107+ for (final PluginInfo <?> pluginInfo : event .getItems ()) {
108+ if (getPluginType ().isAssignableFrom (pluginInfo .getPluginType ())) {
109+ @ SuppressWarnings ("unchecked" )
110+ final PT plugin = pluginService ().createInstance (
111+ (PluginInfo <PT >) pluginInfo );
112+ @ SuppressWarnings ("unchecked" )
113+ final Class <? extends PT > pluginClass = (Class <? extends PT >) plugin
114+ .getClass ();
115+ instanceMap .put (pluginClass , plugin );
116+ instances .add (plugin );
117+ }
118+ }
119+
120+ for (final PluginInfo <PT > pluginInfo : singletons ) {
121+ final PT plugin = pluginService ().createInstance (pluginInfo );
122+ @ SuppressWarnings ("unchecked" )
123+ final Class <? extends PT > pluginClass = (Class <? extends PT >) plugin
124+ .getClass ();
125+ instanceMap .put (pluginClass , plugin );
126+ instances .add (plugin );
127+ }
128+
129+ }
130+
87131 // -- Helper methods --
88132
89133 private synchronized void initInstances () {
90134 if (instances != null ) return ;
91135
92- final List <PT > list = Collections .unmodifiableList (filterInstances (
93- pluginService ().createInstancesOfType (getPluginType ())));
136+ @ SuppressWarnings ("unchecked" )
137+ final List <PT > list = (List <PT >) filterInstances (pluginService ()
138+ .createInstancesOfType (getPluginType ()));
94139
95- final HashMap <Class <? extends PT >, PT > map =
96- new HashMap <>();
140+ final Map <Class <? extends PT >, PT > map = new HashMap <>();
97141
98142 for (final PT plugin : list ) {
99143 @ SuppressWarnings ("unchecked" )
100- final Class <? extends PT > ptClass =
144+ final Class <? extends PT > ptClass = //
101145 (Class <? extends PT >) plugin .getClass ();
102146 map .put (ptClass , plugin );
103147 }
0 commit comments