@@ -84,7 +84,14 @@ public class DefaultExtensionController extends ExtensionController {
8484
8585 // these are plugins for specific extension points, keyed by plugin name
8686 // (not path)
87- private List <ServerPlugin > serverPlugins = new ArrayList <ServerPlugin >();
87+ /*
88+ * A plugin class may implement several of the plugin type interfaces, in which case it is
89+ * registered once for each interface it implements. A Set holds a single entry per plugin,
90+ * so start() and stop() are invoked once per plugin rather than once per interface.
91+ * LinkedHashSet because initPlugins loads plugins in a deliberate order (by plugin weight)
92+ * and that order is preserved when they are started and stopped.
93+ */
94+ private Set <ServerPlugin > serverPlugins = new LinkedHashSet <ServerPlugin >();
8895 private Map <String , ServicePlugin > servicePlugins = new LinkedHashMap <String , ServicePlugin >();
8996 private Map <String , ChannelPlugin > channelPlugins = new LinkedHashMap <String , ChannelPlugin >();
9097 private Map <String , CodeTemplateServerPlugin > codeTemplateServerPlugins = new LinkedHashMap <String , CodeTemplateServerPlugin >();
@@ -240,42 +247,42 @@ public void initPlugins() {
240247 */
241248 servicePlugin .init (currentProperties );
242249 servicePlugins .put (servicePlugin .getPluginPointName (), servicePlugin );
243- addServerPlugin (servicePlugin );
250+ serverPlugins . add (servicePlugin );
244251 logger .debug ("sucessfully loaded server plugin: " + serverPlugin .getPluginPointName ());
245252 }
246253
247254 if (serverPlugin instanceof ChannelPlugin ) {
248255 ChannelPlugin channelPlugin = (ChannelPlugin ) serverPlugin ;
249256 channelPlugins .put (channelPlugin .getPluginPointName (), channelPlugin );
250- addServerPlugin (channelPlugin );
257+ serverPlugins . add (channelPlugin );
251258 logger .debug ("sucessfully loaded server channel plugin: " + serverPlugin .getPluginPointName ());
252259 }
253260
254261 if (serverPlugin instanceof CodeTemplateServerPlugin ) {
255262 CodeTemplateServerPlugin codeTemplateServerPlugin = (CodeTemplateServerPlugin ) serverPlugin ;
256263 codeTemplateServerPlugins .put (codeTemplateServerPlugin .getPluginPointName (), codeTemplateServerPlugin );
257- addServerPlugin (codeTemplateServerPlugin );
264+ serverPlugins . add (codeTemplateServerPlugin );
258265 logger .debug ("sucessfully loaded server code template plugin: " + serverPlugin .getPluginPointName ());
259266 }
260267
261268 if (serverPlugin instanceof DataTypeServerPlugin ) {
262269 DataTypeServerPlugin dataTypePlugin = (DataTypeServerPlugin ) serverPlugin ;
263270 dataTypePlugins .put (dataTypePlugin .getPluginPointName (), dataTypePlugin );
264- addServerPlugin (dataTypePlugin );
271+ serverPlugins . add (dataTypePlugin );
265272 logger .debug ("sucessfully loaded server data type plugin: " + serverPlugin .getPluginPointName ());
266273 }
267274
268275 if (serverPlugin instanceof ResourcePlugin ) {
269276 ResourcePlugin resourcePlugin = (ResourcePlugin ) serverPlugin ;
270277 resourcePlugins .put (resourcePlugin .getPluginPointName (), resourcePlugin );
271- addServerPlugin (resourcePlugin );
278+ serverPlugins . add (resourcePlugin );
272279 logger .debug ("Successfully loaded resource plugin: " + resourcePlugin .getPluginPointName ());
273280 }
274281
275282 if (serverPlugin instanceof TransmissionModeProvider ) {
276283 TransmissionModeProvider transmissionModeProvider = (TransmissionModeProvider ) serverPlugin ;
277284 transmissionModeProviders .put (transmissionModeProvider .getPluginPointName (), transmissionModeProvider );
278- addServerPlugin (transmissionModeProvider );
285+ serverPlugins . add (transmissionModeProvider );
279286 logger .debug ("Successfully loaded transmission mode provider plugin: " + transmissionModeProvider .getPluginPointName ());
280287 }
281288
@@ -287,7 +294,7 @@ public void initPlugins() {
287294 }
288295
289296 this .authorizationPlugin = authorizationPlugin ;
290- addServerPlugin (authorizationPlugin );
297+ serverPlugins . add (authorizationPlugin );
291298 logger .debug ("sucessfully loaded server authorization plugin: " + serverPlugin .getPluginPointName ());
292299 }
293300
@@ -299,7 +306,7 @@ public void initPlugins() {
299306 }
300307
301308 this .multiFactorAuthenticationPlugin = multiFactorAuthenticationPlugin ;
302- addServerPlugin (multiFactorAuthenticationPlugin );
309+ serverPlugins . add (multiFactorAuthenticationPlugin );
303310 logger .debug ("sucessfully loaded server multi-factor authentication plugin: " + serverPlugin .getPluginPointName ());
304311 }
305312 } catch (Exception e ) {
@@ -309,32 +316,6 @@ public void initPlugins() {
309316 }
310317 }
311318
312- /**
313- * Registers a plugin in the list used to start and stop all server plugins.
314- * <p>
315- * A single plugin class may implement more than one of the plugin type interfaces (for example
316- * both {@link ServicePlugin} and {@link ChannelPlugin}). Such a plugin is registered against
317- * each type it implements, so this method guards against adding the same instance more than
318- * once. Without the guard, {@link #startPlugins()} and {@link #stopPlugins()} would invoke
319- * {@link ServerPlugin#start()} and {@link ServerPlugin#stop()} once per implemented interface
320- * rather than once per plugin.
321- * <p>
322- * Instances are compared by identity on purpose. Two distinct plugin instances must both be
323- * registered even if the plugin class considers them equal.
324- * <p>
325- * Package private so it can be exercised directly by unit tests without going through the full
326- * extension loading process.
327- */
328- void addServerPlugin (ServerPlugin serverPlugin ) {
329- for (ServerPlugin registeredPlugin : serverPlugins ) {
330- if (registeredPlugin == serverPlugin ) {
331- return ;
332- }
333- }
334-
335- serverPlugins .add (serverPlugin );
336- }
337-
338319 /* These are the maps for the different types of plugins */
339320 /* ********************************************************************** */
340321
@@ -742,7 +723,8 @@ public List<String> getClientLibraries() {
742723 }
743724
744725 public List <ServerPlugin > getServerPlugins () {
745- return serverPlugins ;
726+ // Copied into a List so the ExtensionController signature stays unchanged for extensions.
727+ return new ArrayList <ServerPlugin >(serverPlugins );
746728 }
747729
748730 void extractZipEntry (ZipEntry entry , File installTempDir , ZipFile zipFile ) throws IOException {
0 commit comments