diff --git a/core/src/main/java/hudson/ExtensionFinder.java b/core/src/main/java/hudson/ExtensionFinder.java
index 516a4d5bd5..106d70dd77 100644
--- a/core/src/main/java/hudson/ExtensionFinder.java
+++ b/core/src/main/java/hudson/ExtensionFinder.java
@@ -133,12 +133,11 @@ public abstract class ExtensionFinder implements ExtensionPoint {
}
/**
- * The default implementation that looks for the {@link Extension} marker.
+ * The bootstrap implementation that looks for the {@link Extension} marker.
*
*
* Uses Sezpoz as the underlying mechanism.
*/
- @Extension
public static final class Sezpoz extends ExtensionFinder {
public Collection> find(Class type, Hudson hudson) {
List> result = new ArrayList>();
@@ -210,125 +209,5 @@ public abstract class ExtensionFinder implements ExtensionPoint {
}
}
- @Extension
- public static final class GuiceFinder extends ExtensionFinder {
- private Injector container;
-
- public GuiceFinder() {
- Module m = new AbstractModule() {
- @Override
- protected void configure() {
- ClassLoader cl = Hudson.getInstance().getPluginManager().uberClassLoader;
- int id=0;
- for (final IndexItem item : Index.load(Extension.class, Object.class, cl)) {
- id++;
- try {
- AnnotatedElement e = item.element();
- Class extType;
- if (e instanceof Class) {
- extType = (Class) e;
- bind((Class>)e);
- continue;
- } else
- if (e instanceof Field) {
- extType = ((Field)e).getType();
- bind(extType).annotatedWith(Names.named(String.valueOf(id)))
- .toInstance(item.instance());
- } else
- if (e instanceof Method) {
- extType = ((Method)e).getReturnType();
- } else
- throw new AssertionError();
-
- if(type.isAssignableFrom(extType)) {
- Object instance = item.instance();
- if(instance!=null)
- result.add(new ExtensionComponent(type.cast(instance),item.annotation()));
- }
- } catch (LinkageError e) {
- // sometimes the instantiation fails in an indirect classloading failure,
- // which results in a LinkageError
- LOGGER.log(item.annotation().optional() ? Level.FINE : Level.WARNING,
- "Failed to load "+item.className(), e);
- } catch (InstantiationException e) {
- LOGGER.log(item.annotation().optional() ? Level.FINE : Level.WARNING,
- "Failed to load "+item.className(), e);
- }
- }
- }
- };
- container = Guice.createInjector(m);
- }
-
- public Collection> find(Class type, Hudson hudson) {
- List> result = new ArrayList>();
-
- ClassLoader cl = hudson.getPluginManager().uberClassLoader;
- for (IndexItem item : Index.load(Extension.class, Object.class, cl)) {
- try {
- AnnotatedElement e = item.element();
- Class> extType;
- if (e instanceof Class) {
- extType = (Class) e;
- } else
- if (e instanceof Field) {
- extType = ((Field)e).getType();
- } else
- if (e instanceof Method) {
- extType = ((Method)e).getReturnType();
- } else
- throw new AssertionError();
-
- if(type.isAssignableFrom(extType)) {
- Object instance = item.instance();
- if(instance!=null)
- result.add(new ExtensionComponent(type.cast(instance),item.annotation()));
- }
- } catch (LinkageError e) {
- // sometimes the instantiation fails in an indirect classloading failure,
- // which results in a LinkageError
- LOGGER.log(item.annotation().optional() ? Level.FINE : Level.WARNING,
- "Failed to load "+item.className(), e);
- } catch (InstantiationException e) {
- LOGGER.log(item.annotation().optional() ? Level.FINE : Level.WARNING,
- "Failed to load "+item.className(), e);
- }
- }
-
- return result;
- }
-
- @Override
- public void scout(Class extensionType, Hudson hudson) {
- ClassLoader cl = hudson.getPluginManager().uberClassLoader;
- for (IndexItem item : Index.load(Extension.class, Object.class, cl)) {
- try {
- AnnotatedElement e = item.element();
- Class> extType;
- if (e instanceof Class) {
- extType = (Class) e;
- } else
- if (e instanceof Field) {
- extType = ((Field)e).getType();
- } else
- if (e instanceof Method) {
- extType = ((Method)e).getReturnType();
- } else
- throw new AssertionError();
- // accroding to http://bugs.sun.com/bugdatabase/view_bug.do?bug_id=6459208
- // this appears to be the only way to force a class initialization
- Class.forName(extType.getName(),true,extType.getClassLoader());
- } catch (InstantiationException e) {
- LOGGER.log(item.annotation().optional() ? Level.FINE : Level.WARNING,
- "Failed to scout "+item.className(), e);
- } catch (ClassNotFoundException e) {
- LOGGER.log(Level.WARNING,"Failed to scout "+item.className(), e);
- } catch (LinkageError e) {
- LOGGER.log(Level.WARNING,"Failed to scout "+item.className(), e);
- }
- }
- }
- }
-
private static final Logger LOGGER = Logger.getLogger(ExtensionFinder.class.getName());
}
diff --git a/core/src/main/java/hudson/guice/FaultTorelantScope.java b/core/src/main/java/hudson/guice/FaultTorelantScope.java
new file mode 100644
index 0000000000..0ad3a53183
--- /dev/null
+++ b/core/src/main/java/hudson/guice/FaultTorelantScope.java
@@ -0,0 +1,38 @@
+package hudson.guice;
+
+import com.google.inject.Key;
+import com.google.inject.Provider;
+import com.google.inject.Scope;
+import com.google.inject.Scopes;
+
+import java.util.logging.Level;
+import java.util.logging.Logger;
+
+/**
+ * Decorating {@link Scope} that tolerates a failure to instantiate an object.
+ *
+ *
+ * This is necessary as a failure to load one plugin shouldn't fail the startup of the entire Hudson.
+ * Instead, we should just drop the failing plugins.
+ *
+ * @author Kohsuke Kawaguchi
+ */
+public class FaultTorelantScope implements Scope {
+ public static final Scope INSTANCE = new FaultTorelantScope();
+
+ public Provider scope(Key key, Provider unscoped) {
+ final Provider base = Scopes.SINGLETON.scope(key,unscoped);
+ return new Provider() {
+ public T get() {
+ try {
+ return base.get();
+ } catch (Exception e) {
+ LOGGER.log(Level.WARNING,"Failed to instantiate",e);
+ return null;
+ }
+ }
+ };
+ }
+
+ private static final Logger LOGGER = Logger.getLogger(FaultTorelantScope.class.getName());
+}
diff --git a/core/src/main/java/hudson/guice/GuiceFinder.java b/core/src/main/java/hudson/guice/GuiceFinder.java
new file mode 100644
index 0000000000..314dcfde7d
--- /dev/null
+++ b/core/src/main/java/hudson/guice/GuiceFinder.java
@@ -0,0 +1,124 @@
+package hudson.guice;
+
+import com.google.inject.AbstractModule;
+import com.google.inject.Binding;
+import com.google.inject.Guice;
+import com.google.inject.Injector;
+import com.google.inject.Key;
+import com.google.inject.Module;
+import com.google.inject.Provider;
+import com.google.inject.Scopes;
+import com.google.inject.name.Names;
+import hudson.Extension;
+import hudson.ExtensionComponent;
+import hudson.ExtensionFinder;
+import hudson.model.Hudson;
+import net.java.sezpoz.Index;
+import net.java.sezpoz.IndexItem;
+
+import java.lang.reflect.AnnotatedElement;
+import java.lang.reflect.Field;
+import java.lang.reflect.Method;
+import java.util.ArrayList;
+import java.util.Collection;
+import java.util.List;
+import java.util.Map.Entry;
+import java.util.logging.Level;
+import java.util.logging.Logger;
+
+/**
+* @author Kohsuke Kawaguchi
+*/
+@Extension
+public final class GuiceFinder extends ExtensionFinder {
+ private Injector container;
+
+ public GuiceFinder() {
+ List modules = new ArrayList();
+ modules.add(new AbstractModule() {
+ @SuppressWarnings({"unchecked", "ChainOfInstanceofChecks"})
+ @Override
+ protected void configure() {
+ ClassLoader cl = Hudson.getInstance().getPluginManager().uberClassLoader;
+ int id=0;
+
+ for (final IndexItem item : Index.load(Extension.class, Object.class, cl)) {
+ id++;
+ try {
+ AnnotatedElement e = item.element();
+ Class extType;
+ if (e instanceof Class) {
+ bind((Class>)e).in(FaultTorelantScope.INSTANCE);
+ } else {
+ if (e instanceof Field) {
+ extType = ((Field)e).getType();
+ } else
+ if (e instanceof Method) {
+ extType = ((Method)e).getReturnType();
+ } else
+ throw new AssertionError();
+
+ // use arbitrary
+ bind(extType).annotatedWith(Names.named(String.valueOf(id)))
+ .toProvider(new Provider() {
+ public Object get() {
+ return instantiate(item);
+ }
+ }).in(FaultTorelantScope.INSTANCE);
+ }
+ } catch (LinkageError e) {
+ // sometimes the instantiation fails in an indirect classloading failure,
+ // which results in a LinkageError
+ LOGGER.log(item.annotation().optional() ? Level.FINE : Level.WARNING,
+ "Failed to load "+item.className(), e);
+ } catch (InstantiationException e) {
+ LOGGER.log(item.annotation().optional() ? Level.FINE : Level.WARNING,
+ "Failed to load "+item.className(), e);
+ }
+ }
+ }
+ });
+
+ for (ExtensionComponent ec : new Sezpoz().find(Module.class, Hudson.getInstance())) {
+ modules.add(ec.getInstance());
+ }
+
+ container = Guice.createInjector(modules);
+ }
+
+ private Object instantiate(IndexItem item) {
+ try {
+ return item.instance();
+ } catch (LinkageError e) {
+ // sometimes the instantiation fails in an indirect classloading failure,
+ // which results in a LinkageError
+ LOGGER.log(item.annotation().optional() ? Level.FINE : Level.WARNING,
+ "Failed to load "+item.className(), e);
+ } catch (InstantiationException e) {
+ LOGGER.log(item.annotation().optional() ? Level.FINE : Level.WARNING,
+ "Failed to load "+item.className(), e);
+ }
+ return null;
+ }
+
+ public Collection> find(Class type, Hudson hudson) {
+ List> result = new ArrayList>();
+
+ for (Entry, Binding>> e : container.getBindings().entrySet()) {
+ if (type.isAssignableFrom(e.getKey().getTypeLiteral().getRawType())) {
+ // TODO: how do we get ordinal?
+ Object o = e.getValue().getProvider().get();
+ if (o!=null)
+ result.add(new ExtensionComponent(type.cast(o)));
+ }
+ }
+
+ return result;
+ }
+
+ @Override
+ public void scout(Class extensionType, Hudson hudson) {
+ }
+
+ private static final Logger LOGGER = Logger.getLogger(GuiceFinder.class.getName());
+}