提交 00150769 编写于 作者: K Kohsuke Kawaguchi

experimenting

上级 39d90576
......@@ -364,6 +364,17 @@ THE SOFTWARE.
</exclusions>
</dependency>
<dependency>
<groupId>com.google.inject</groupId>
<artifactId>guice</artifactId>
<version>2.0</version>
</dependency>
<dependency>
<groupId>com.google.inject.extensions</groupId>
<artifactId>guice-multibindings</artifactId>
<version>2.0</version>
</dependency>
<dependency>
<groupId>org.jruby.ext.posix</groupId>
<artifactId>jna-posix</artifactId>
......
......@@ -23,6 +23,13 @@
*/
package hudson;
import com.google.inject.AbstractModule;
import com.google.inject.Guice;
import com.google.inject.Injector;
import com.google.inject.Module;
import com.google.inject.Provider;
import com.google.inject.Singleton;
import com.google.inject.name.Names;
import net.java.sezpoz.Index;
import net.java.sezpoz.IndexItem;
import hudson.model.Hudson;
......@@ -202,6 +209,126 @@ 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<Extension,Object> 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<T>(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 <T> Collection<ExtensionComponent<T>> find(Class<T> type, Hudson hudson) {
List<ExtensionComponent<T>> result = new ArrayList<ExtensionComponent<T>>();
ClassLoader cl = hudson.getPluginManager().uberClassLoader;
for (IndexItem<Extension,Object> 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<T>(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<Extension,Object> 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());
}
......@@ -27,6 +27,7 @@ import static hudson.init.InitMilestone.PLUGINS_PREPARED;
import static hudson.init.InitMilestone.PLUGINS_STARTED;
import static hudson.init.InitMilestone.PLUGINS_LISTED;
import com.google.inject.Guice;
import hudson.PluginWrapper.Dependency;
import hudson.init.InitStrategy;
import hudson.init.InitializerFinder;
......@@ -266,6 +267,8 @@ public abstract class PluginManager extends AbstractModelObject {
Hudson.getInstance().lookup.set(PluginInstanceStore.class,new PluginInstanceStore());
TaskGraphBuilder g = new TaskGraphBuilder();
Hudson.getInstance().container = Guice.createInjector();
// schedule execution of loading plugins
for (final PluginWrapper p : activePlugins.toArray(new PluginWrapper[activePlugins.size()])) {
g.followedBy().notFatal().attains(PLUGINS_PREPARED).add("Loading plugin " + p.getShortName(), new Executable() {
......
......@@ -26,6 +26,8 @@
package hudson.model;
import antlr.ANTLRException;
import com.google.inject.Guice;
import com.google.inject.Injector;
import com.thoughtworks.xstream.XStream;
import hudson.BulkChange;
import hudson.DNSMultiCast;
......@@ -243,6 +245,9 @@ public final class Hudson extends Node implements ItemGroup<TopLevelItem>, Stapl
*/
public transient final Lookup lookup = new Lookup();
// TODO: fix scope
public transient Injector container;
/**
* {@link Computer}s in this Hudson system. Read-only.
*/
......
package foo;
/**
* @author Kohsuke Kawaguchi
*/
public interface Animal {
}
package foo;
/**
* @author Kohsuke Kawaguchi
*/
public class Banana implements Cute {
}
package foo;
import com.google.inject.Singleton;
/**
* @author Kohsuke Kawaguchi
*/
public class Cat implements Animal, Cute {
}
package foo;
/**
* @author Kohsuke Kawaguchi
*/
public interface Cute {
}
package foo;
/**
* @author Kohsuke Kawaguchi
*/
public class Dog implements Animal {
}
package foo;
import com.google.inject.AbstractModule;
import com.google.inject.Guice;
import com.google.inject.Inject;
import com.google.inject.Injector;
import com.google.inject.Key;
import com.google.inject.Scope;
import com.google.inject.Singleton;
import com.google.inject.TypeLiteral;
import com.google.inject.multibindings.Multibinder;
import java.util.Set;
/**
* @author Kohsuke Kawaguchi
*/
public class Driver {
@Inject
public Set<Animal> animals;
@Inject
public Set<Cute> cute;
/*
If Cat has @Singleton, multiple bindings result in the same instance.
How can I achieve that without changing annotation?
*/
public static void main(String[] args) {
Injector i = Guice.createInjector(new AbstractModule() {
@Override
protected void configure() {
bind(Cat.class).in(Singleton.class);
Multibinder<Animal> ab = Multibinder.newSetBinder(binder(), Animal.class);
ab.addBinding().to(Dog.class);
ab.addBinding().to(Cat.class);
Multibinder<Cute> cb = Multibinder.newSetBinder(binder(), Cute.class);
cb.addBinding().to(Cat.class);
cb.addBinding().to(Banana.class);
}
});
i.getInstance(Driver.class).run();
// Dog isn't singleton scoped, so you get a different instance, but Cat is singleton,
// so you get the same value
System.out.println(i.getInstance(Key.get(new TypeLiteral<Set<Animal>>(){})));
}
public void run() {
System.out.println(animals);
System.out.println(cute);
}
}
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册