diff --git a/core/src/main/java/hudson/PluginManager.java b/core/src/main/java/hudson/PluginManager.java index c742d5808e..3784009fca 100644 --- a/core/src/main/java/hudson/PluginManager.java +++ b/core/src/main/java/hudson/PluginManager.java @@ -29,6 +29,7 @@ import static hudson.init.InitMilestone.PLUGINS_LISTED; import hudson.PluginWrapper.Dependency; import hudson.init.InitStrategy; +import hudson.init.InitializerFinder; import hudson.model.AbstractModelObject; import hudson.model.Failure; import hudson.model.Hudson; @@ -249,8 +250,11 @@ public abstract class PluginManager extends AbstractModelObject { builder = TaskBuilder.EMPTY_BUILDER; } + final InitializerFinder initializerFinder = new InitializerFinder(uberClassLoader); // misc. stuff + // lists up initialization tasks about loading plugins. - return TaskBuilder.union(builder,new TaskGraphBuilder() {{ + return TaskBuilder.union(initializerFinder, // this scans @Initializer in the core once + builder,new TaskGraphBuilder() {{ requires(PLUGINS_LISTED).attains(PLUGINS_PREPARED).add("Loading plugins",new Executable() { /** * Once the plugins are listed, schedule their initialization. @@ -292,6 +296,13 @@ public abstract class PluginManager extends AbstractModelObject { }); } + g.followedBy().attains(PLUGINS_STARTED).add("Discovering plugin initialization tasks", new Executable() { + public void run(Reactor reactor) throws Exception { + // rescan to find plugin-contributed @Initializer + reactor.addAll(initializerFinder.discoverTasks(reactor)); + } + }); + // register them all session.addAll(g.discoverTasks(session)); } diff --git a/core/src/main/java/hudson/init/InitializerFinder.java b/core/src/main/java/hudson/init/InitializerFinder.java index 7efdfe8b6d..3203e77eac 100644 --- a/core/src/main/java/hudson/init/InitializerFinder.java +++ b/core/src/main/java/hudson/init/InitializerFinder.java @@ -37,7 +37,9 @@ import java.lang.reflect.Method; import java.lang.reflect.Modifier; import java.util.ArrayList; import java.util.Collection; +import java.util.HashSet; import java.util.List; +import java.util.Set; import java.util.logging.Logger; import hudson.model.Hudson; @@ -52,6 +54,8 @@ import static java.util.logging.Level.WARNING; public class InitializerFinder extends TaskBuilder { private final ClassLoader cl; + private final Set discovered = new HashSet(); + public InitializerFinder(ClassLoader cl) { this.cl = cl; } @@ -63,6 +67,9 @@ public class InitializerFinder extends TaskBuilder { public Collection discoverTasks(Reactor session) throws IOException { List result = new ArrayList(); for (Method e : Index.list(Initializer.class,cl,Method.class)) { + if (!discovered.add(e)) + continue; // already reported once + if (!Modifier.isStatic(e.getModifiers())) throw new IOException(e+" is not a static method"); diff --git a/core/src/main/java/hudson/model/Hudson.java b/core/src/main/java/hudson/model/Hudson.java index d7198d2144..bc837d62c0 100644 --- a/core/src/main/java/hudson/model/Hudson.java +++ b/core/src/main/java/hudson/model/Hudson.java @@ -626,7 +626,6 @@ public final class Hudson extends Node implements ItemGroup, Stapl // initialization consists of ... executeReactor( is, - new InitializerFinder(), // misc. stuff pluginManager.initTasks(is), // loading and preparing plugins loadTasks(), // load jobs InitMilestone.ordering() // forced ordering among key milestones