Injector.getAllBindings(), feature for issue 389.
git-svn-id: https://google-guice.googlecode.com/svn/trunk@1040 d779f126-a31b-0410-b53b-1d3aecad763e
diff --git a/src/com/google/inject/Injector.java b/src/com/google/inject/Injector.java
index e49540c..6ff563c 100644
--- a/src/com/google/inject/Injector.java
+++ b/src/com/google/inject/Injector.java
@@ -90,18 +90,31 @@
<T> MembersInjector<T> getMembersInjector(Class<T> type);
/**
- * Returns all explicit bindings.
+ * Returns this injector's <strong>explicit</strong> bindings.
*
* <p>The returned map does not include bindings inherited from a {@link #getParent() parent
* injector}, should one exist. The returned map is guaranteed to iterate (for example, with
- * its {@link java.util.Map#entrySet()} iterator) in the order of insertion. In other words,
- * the order in which bindings appear in user Modules.
+ * its {@link Map#entrySet()} iterator) in the order of insertion. In other words, the order in
+ * which bindings appear in user Modules.
*
* <p>This method is part of the Guice SPI and is intended for use by tools and extensions.
*/
Map<Key<?>, Binding<?>> getBindings();
/**
+ * Returns a snapshot of this injector's bindings, <strong>both explicit and
+ * just-in-time</strong>. The returned map is immutable; it contains only the bindings that were
+ * present when {@code getAllBindings()} was invoked. Subsequent calls may return a map with
+ * additional just-in-time bindings.
+ *
+ * <p>The returned map does not include bindings inherited from a {@link #getParent() parent
+ * injector}, should one exist.
+ *
+ * <p>This method is part of the Guice SPI and is intended for use by tools and extensions.
+ */
+ Map<Key<?>, Binding<?>> getAllBindings();
+
+ /**
* Returns the binding for the given injection key. This will be an explicit bindings if the key
* was bound explicitly by a module, or an implicit binding otherwise. The implicit binding will
* be created if necessary.
diff --git a/src/com/google/inject/internal/InjectorBuilder.java b/src/com/google/inject/internal/InjectorBuilder.java
index 0f80f41..67d0450 100644
--- a/src/com/google/inject/internal/InjectorBuilder.java
+++ b/src/com/google/inject/internal/InjectorBuilder.java
@@ -245,6 +245,9 @@
public Map<Key<?>, Binding<?>> getBindings() {
return this.delegateInjector.getBindings();
}
+ public Map<Key<?>, Binding<?>> getAllBindings() {
+ return this.delegateInjector.getAllBindings();
+ }
public <T> Binding<T> getBinding(Key<T> key) {
return this.delegateInjector.getBinding(key);
}
diff --git a/src/com/google/inject/internal/InjectorImpl.java b/src/com/google/inject/internal/InjectorImpl.java
index b55014e..9419935 100644
--- a/src/com/google/inject/internal/InjectorImpl.java
+++ b/src/com/google/inject/internal/InjectorImpl.java
@@ -625,11 +625,19 @@
return getBindingOrThrow(key, errors).getInternalFactory();
}
- // not test-covered
public Map<Key<?>, Binding<?>> getBindings() {
return state.getExplicitBindingsThisLevel();
}
+ public Map<Key<?>, Binding<?>> getAllBindings() {
+ synchronized (state.lock()) {
+ return new ImmutableMap.Builder<Key<?>, Binding<?>>()
+ .putAll(state.getExplicitBindingsThisLevel())
+ .putAll(jitBindings)
+ .build();
+ }
+ }
+
private static class BindingsMultimap {
final Map<TypeLiteral<?>, List<Binding<?>>> multimap = Maps.newHashMap();
diff --git a/test/com/google/inject/BindingTest.java b/test/com/google/inject/BindingTest.java
index fe5a40a..725a35a 100644
--- a/test/com/google/inject/BindingTest.java
+++ b/test/com/google/inject/BindingTest.java
@@ -26,8 +26,10 @@
import java.lang.reflect.Constructor;
import java.util.Collection;
import java.util.List;
+import java.util.Map;
import java.util.Set;
import java.util.concurrent.atomic.AtomicInteger;
+import java.util.logging.Logger;
import junit.framework.TestCase;
import org.aopalliance.intercept.MethodInterceptor;
import org.aopalliance.intercept.MethodInvocation;
@@ -363,6 +365,37 @@
heardTypes);
}
+ public void testGetAllBindings() {
+ Injector injector = Guice.createInjector(new AbstractModule() {
+ protected void configure() {
+ bind(D.class).toInstance(new D(Stage.PRODUCTION));
+ bind(Object.class).to(D.class);
+ getProvider(new Key<C<Stage>>() {});
+ }
+ });
+
+ Map<Key<?>,Binding<?>> bindings = injector.getAllBindings();
+ assertEquals(ImmutableSet.of(Key.get(Injector.class), Key.get(Stage.class), Key.get(D.class),
+ Key.get(Logger.class), Key.get(Object.class), new Key<C<Stage>>() {}),
+ bindings.keySet());
+
+ // add a JIT binding
+ injector.getInstance(F.class);
+
+ Map<Key<?>,Binding<?>> bindings2 = injector.getAllBindings();
+ assertEquals(ImmutableSet.of(Key.get(Injector.class), Key.get(Stage.class), Key.get(D.class),
+ Key.get(Logger.class), Key.get(Object.class), new Key<C<Stage>>() {}, Key.get(F.class)),
+ bindings2.keySet());
+
+ // the original map shouldn't have changed
+ assertEquals(ImmutableSet.of(Key.get(Injector.class), Key.get(Stage.class), Key.get(D.class),
+ Key.get(Logger.class), Key.get(Object.class), new Key<C<Stage>>() {}),
+ bindings.keySet());
+
+ // check the bindings' values
+ assertEquals(injector, bindings.get(Key.get(Injector.class)).getProvider().get());
+ }
+
public static class C<T> {
private Stage stage;
private T t;