Revision: d51292d5a4a7
Author:   Sam Berlin <[email protected]>
Date:     Sun Feb 26 18:23:19 2012
Log: Change ProvisionListener to expose Binding instead of Key, and change bindListener to use a Matcher for Binding instead of Key. This is a backwards incompatible change, but we haven't released yet, so it's worth doing.

Revision created by MOE tool push_codebase.
MOE_MIGRATION=4269

http://code.google.com/p/google-guice/source/detail?r=d51292d5a4a7

Modified:
 /core/src/com/google/inject/AbstractModule.java
 /core/src/com/google/inject/Binder.java
 /core/src/com/google/inject/internal/BindingProcessor.java
 /core/src/com/google/inject/internal/BoundProviderFactory.java
 /core/src/com/google/inject/internal/ConstructorBindingImpl.java
 /core/src/com/google/inject/internal/ConstructorInjector.java
 /core/src/com/google/inject/internal/InjectorImpl.java
/core/src/com/google/inject/internal/InternalFactoryToInitializableAdapter.java
 /core/src/com/google/inject/internal/ProvidedByInternalFactory.java
 /core/src/com/google/inject/internal/ProviderInternalFactory.java
 /core/src/com/google/inject/internal/ProvisionListenerCallbackStore.java
 /core/src/com/google/inject/internal/ProvisionListenerStackCallback.java
 /core/src/com/google/inject/spi/DependencyAndSource.java
 /core/src/com/google/inject/spi/Elements.java
 /core/src/com/google/inject/spi/ProvisionListener.java
 /core/src/com/google/inject/spi/ProvisionListenerBinding.java
 /core/test/com/google/inject/ProvisionListenerTest.java

=======================================
--- /core/src/com/google/inject/AbstractModule.java     Tue Oct 18 13:43:18 2011
+++ /core/src/com/google/inject/AbstractModule.java     Sun Feb 26 18:23:19 2012
@@ -256,11 +256,11 @@
   }

   /**
-   * @see Binder#bindListener(Matcher, ProvisionListener)
+   * @see Binder#bindListener(Matcher, ProvisionListener...)
    * @since 4.0
    */
-  protected void bindListener(Matcher<? super Key<?>> keyMatcher,
+  protected void bindListener(Matcher<? super Binding<?>> bindingMatcher,
       ProvisionListener... listener) {
-    binder().bindListener(keyMatcher, listener);
+    binder().bindListener(bindingMatcher, listener);
   }
 }
=======================================
--- /core/src/com/google/inject/Binder.java     Thu Jul  7 17:34:16 2011
+++ /core/src/com/google/inject/Binder.java     Sun Feb 26 18:23:19 2012
@@ -383,12 +383,12 @@
* through Providers) can also be notified through TypeListeners registered in
    * {@link #bindListener}.
    *
- * @param keyMatcher that matches keys of provisioned objects the listener + * @param bindingMatcher that matches bindings of provisioned objects the listener
    *          should be notified of
-   * @param listeners for provisioned objects matched by keyMatcher   *
+   * @param listeners for provisioned objects matched by bindingMatcher
    * @since 4.0
    */
- void bindListener(Matcher<? super Key<?>> keyMatcher, ProvisionListener... listeners); + void bindListener(Matcher<? super Binding<?>> bindingMatcher, ProvisionListener... listeners);

   /**
* Returns a binder that uses {@code source} as the reference location for
=======================================
--- /core/src/com/google/inject/internal/BindingProcessor.java Thu Jul 7 17:34:16 2011 +++ /core/src/com/google/inject/internal/BindingProcessor.java Sun Feb 26 18:23:19 2012
@@ -67,6 +67,7 @@
     }

return command.acceptTargetVisitor(new Processor<T, Boolean>((BindingImpl<T>)command) {
+      @Override
       public Boolean visit(ConstructorBinding<? extends T> binding) {
         prepareBinding();
         try {
@@ -81,6 +82,7 @@
         return true;
       }

+      @Override
       public Boolean visit(InstanceBinding<? extends T> binding) {
         prepareBinding();
         Set<InjectionPoint> injectionPoints = binding.getInjectionPoints();
@@ -95,15 +97,18 @@
         return true;
       }

+      @Override
       public Boolean visit(ProviderInstanceBinding<? extends T> binding) {
         prepareBinding();
         Provider<? extends T> provider = binding.getProviderInstance();
         Set<InjectionPoint> injectionPoints = binding.getInjectionPoints();
         Initializable<Provider<? extends T>> initializable = initializer
.<Provider<? extends T>>requestInjection(injector, provider, null, source, injectionPoints);
+        // always visited with Binding<T>
+        @SuppressWarnings("unchecked")
InternalFactory<T> factory = new InternalFactoryToInitializableAdapter<T>( initializable, source, !injector.options.disableCircularProxies,
-            injector.provisionListenerStore.get(key));
+ injector.provisionListenerStore.get((ProviderInstanceBinding<T>)binding));
         InternalFactory<? extends T> scopedFactory
             = Scoping.scope(key, injector, factory, source, scoping);
putBinding(new ProviderInstanceBindingImpl<T>(injector, key, source, scopedFactory, scoping,
@@ -111,12 +116,15 @@
         return true;
       }

+      @Override
       public Boolean visit(ProviderKeyBinding<? extends T> binding) {
         prepareBinding();
Key<? extends javax.inject.Provider<? extends T>> providerKey = binding.getProviderKey();
+        // always visited with Binding<T>
+        @SuppressWarnings("unchecked")
BoundProviderFactory<T> boundProviderFactory = new BoundProviderFactory<T>( injector, providerKey, source, !injector.options.disableCircularProxies,
-            injector.provisionListenerStore.get(key));
+ injector.provisionListenerStore.get((ProviderKeyBinding<T>)binding));
         bindingData.addCreationListener(boundProviderFactory);
         InternalFactory<? extends T> scopedFactory = Scoping.scope(
key, injector, (InternalFactory<? extends T>) boundProviderFactory, source, scoping);
@@ -125,6 +133,7 @@
         return true;
       }

+      @Override
       public Boolean visit(LinkedKeyBinding<? extends T> binding) {
         prepareBinding();
         Key<? extends T> linkedKey = binding.getLinkedKey();
@@ -141,18 +150,22 @@
         return true;
       }

+      @Override
       public Boolean visit(UntargettedBinding<? extends T> untargetted) {
         return false;
       }

+      @Override
       public Boolean visit(ExposedBinding<? extends T> binding) {
throw new IllegalArgumentException("Cannot apply a non-module element");
       }
-
+
+      @Override
       public Boolean visit(ConvertedConstantBinding<? extends T> binding) {
throw new IllegalArgumentException("Cannot apply a non-module element");
       }
-
+
+      @Override
       public Boolean visit(ProviderBinding<? extends T> binding) {
throw new IllegalArgumentException("Cannot apply a non-module element");
       }
=======================================
--- /core/src/com/google/inject/internal/BoundProviderFactory.java Thu Jul 7 17:34:16 2011 +++ /core/src/com/google/inject/internal/BoundProviderFactory.java Sun Feb 26 18:23:19 2012
@@ -16,6 +16,8 @@

 package com.google.inject.internal;

+import static com.google.common.base.Preconditions.checkNotNull;
+
 import com.google.inject.Key;
 import com.google.inject.internal.InjectorImpl.JitLimitation;
 import com.google.inject.spi.Dependency;
@@ -27,6 +29,7 @@
  */
final class BoundProviderFactory<T> extends ProviderInternalFactory<T> implements CreationListener {

+  private final ProvisionListenerStackCallback<T> provisionCallback;
   private final InjectorImpl injector;
   final Key<? extends javax.inject.Provider<? extends T>> providerKey;
private InternalFactory<? extends javax.inject.Provider<? extends T>> providerFactory;
@@ -37,7 +40,8 @@
       Object source,
       boolean allowProxy,
       ProvisionListenerStackCallback<T> provisionCallback) {
-    super(source, allowProxy, provisionCallback);
+    super(source, allowProxy);
+ this.provisionCallback = checkNotNull(provisionCallback, "provisionCallback");
     this.injector = injector;
     this.providerKey = providerKey;
   }
@@ -56,7 +60,7 @@
     try {
       errors = errors.withSource(providerKey);
javax.inject.Provider<? extends T> provider = providerFactory.get(errors, context, dependency, true);
-      return circularGet(provider, errors, context, dependency, linked);
+ return circularGet(provider, errors, context, dependency, linked, provisionCallback);
     } finally {
       context.popState();
     }
=======================================
--- /core/src/com/google/inject/internal/ConstructorBindingImpl.java Thu Jul 7 17:34:16 2011 +++ /core/src/com/google/inject/internal/ConstructorBindingImpl.java Sun Feb 26 18:23:19 2012
@@ -127,7 +127,7 @@
     factory.constructorInjector =
(ConstructorInjector<T>) injector.constructors.get(constructorInjectionPoint, errors);
     factory.provisionCallback =
-      injector.provisionListenerStore.get(getKey());
+      injector.provisionListenerStore.get(this);
   }

   /** True if this binding has been initialized and is ready for use. */
=======================================
--- /core/src/com/google/inject/internal/ConstructorInjector.java Thu Jul 7 17:34:16 2011 +++ /core/src/com/google/inject/internal/ConstructorInjector.java Sun Feb 26 18:23:19 2012
@@ -81,6 +81,7 @@
       return t;
     }

+    constructionContext.startConstruction();
     try {
// Optimization: Don't go through the callback stack if we have no listeners.
       if (!provisionCallback.hasListeners()) {
@@ -94,6 +95,7 @@
       }
     } finally {
       constructionContext.removeCurrentReference();
+      constructionContext.finishConstruction();
     }
   }

@@ -101,7 +103,6 @@
   private T provision(Errors errors, InternalContext context,
       ConstructionContext<T> constructionContext) throws ErrorsException {
     try {
-      constructionContext.startConstruction();
       T t;
       try {
Object[] parameters = SingleParameterInjector.getAll(errors, context, parameterInjectors);
=======================================
--- /core/src/com/google/inject/internal/InjectorImpl.java Tue Sep 13 10:41:32 2011 +++ /core/src/com/google/inject/internal/InjectorImpl.java Sun Feb 26 18:23:19 2012
@@ -548,7 +548,7 @@
// We do not pass cb.getInternalConstructor as the second parameter
           // so that cached exceptions while constructing it get stored.
           // See TypeListenerTest#testTypeListenerThrows
-          removeFailedJitBinding(key, null);
+          removeFailedJitBinding(binding, null);
           cleanup(binding, new HashSet<Key>());
         }
       }
@@ -579,7 +579,7 @@
             }
           }
           if(failed) {
-            removeFailedJitBinding(depKey, ip);
+            removeFailedJitBinding(depBinding, ip);
             bindingFailed = true;
           }
         } else if(state.getExplicitBinding(depKey) == null) {
@@ -593,11 +593,11 @@
   }

/** Cleans up any state that may have been cached when constructing the JIT binding. */
-  private void removeFailedJitBinding(Key<?> key, InjectionPoint ip) {
-    failedJitBindings.add(key);
-    jitBindings.remove(key);
-    membersInjectorStore.remove(key.getTypeLiteral());
-    provisionListenerStore.remove(key);
+ private void removeFailedJitBinding(Binding<?> binding, InjectionPoint ip) {
+    failedJitBindings.add(binding.getKey());
+    jitBindings.remove(binding.getKey());
+    membersInjectorStore.remove(binding.getKey().getTypeLiteral());
+    provisionListenerStore.remove(binding);
     if(ip != null) {
       constructors.remove(ip);
     }
@@ -700,10 +700,9 @@
Key<? extends Provider<T>> providerKey = (Key<? extends Provider<T>>) Key.get(providerType);
     ProvidedByInternalFactory<T> internalFactory =
         new ProvidedByInternalFactory<T>(rawType, providerType,
-            providerKey, !options.disableCircularProxies,
-            provisionListenerStore.get(key));
+            providerKey, !options.disableCircularProxies);
     Object source = rawType;
-    return LinkedProviderBindingImpl.createWithInitializer(
+ BindingImpl<T> binding = LinkedProviderBindingImpl.createWithInitializer(
         this,
         key,
         source,
@@ -711,6 +710,8 @@
         scoping,
         providerKey,
         internalFactory);
+ internalFactory.setProvisionListenerCallback(provisionListenerStore.get(binding));
+    return binding;
   }

   /** Creates a binding for a type annotated with @ImplementedBy. */
=======================================
--- /core/src/com/google/inject/internal/InternalFactoryToInitializableAdapter.java Thu Jul 7 17:34:16 2011 +++ /core/src/com/google/inject/internal/InternalFactoryToInitializableAdapter.java Sun Feb 26 18:23:19 2012
@@ -30,19 +30,22 @@
 */
final class InternalFactoryToInitializableAdapter<T> extends ProviderInternalFactory<T> {

+  private final ProvisionListenerStackCallback<T> provisionCallback;
   private final Initializable<Provider<? extends T>> initializable;

   public InternalFactoryToInitializableAdapter(
       Initializable<Provider<? extends T>> initializable,
       Object source, boolean allowProxy,
       ProvisionListenerStackCallback<T> provisionCallback) {
-    super(source, allowProxy, provisionCallback);
+    super(source, allowProxy);
+ this.provisionCallback = checkNotNull(provisionCallback, "provisionCallback");
     this.initializable = checkNotNull(initializable, "provider");
   }

public T get(Errors errors, InternalContext context, Dependency<?> dependency, boolean linked)
       throws ErrorsException {
- return circularGet(initializable.get(errors), errors, context, dependency, linked); + return circularGet(initializable.get(errors), errors, context, dependency, linked,
+        provisionCallback);
   }

   @Override
=======================================
--- /core/src/com/google/inject/internal/ProvidedByInternalFactory.java Sun Jun 26 14:02:54 2011 +++ /core/src/com/google/inject/internal/ProvidedByInternalFactory.java Sun Feb 26 18:23:19 2012
@@ -37,22 +37,26 @@
   private final Class<? extends Provider<?>> providerType;
   private final Key<? extends Provider<T>> providerKey;
   private BindingImpl<? extends Provider<T>> providerBinding;
+  private ProvisionListenerStackCallback<T> provisionCallback;

   ProvidedByInternalFactory(
       Class<?> rawType,
       Class<? extends Provider<?>> providerType,
       Key<? extends Provider<T>> providerKey,
-      boolean allowProxy,
-      ProvisionListenerStackCallback<T> provisionCallback) {
-    super(providerKey, allowProxy, provisionCallback);
+      boolean allowProxy) {
+    super(providerKey, allowProxy);
     this.rawType = rawType;
     this.providerType = providerType;
     this.providerKey = providerKey;
   }
+
+ void setProvisionListenerCallback(ProvisionListenerStackCallback<T> listener) {
+    provisionCallback = listener;
+  }

public void initialize(InjectorImpl injector, Errors errors) throws ErrorsException {
     providerBinding =
- injector.getBindingOrThrow(providerKey, errors, JitLimitation.NEW_OR_EXISTING_JIT); + injector.getBindingOrThrow(providerKey, errors, JitLimitation.NEW_OR_EXISTING_JIT);
   }

   @SuppressWarnings("unchecked")//
@@ -65,12 +69,13 @@
       errors = errors.withSource(providerKey);
       Provider provider = providerBinding.getInternalFactory().get(
           errors, context, dependency, true);
-      return circularGet(provider, errors, context, dependency, linked);
+ return circularGet(provider, errors, context, dependency, linked, provisionCallback);
     } finally {
       context.popState();
     }
   }

+  @Override
protected T provision(javax.inject.Provider<? extends T> provider, Errors errors,
       Dependency<?> dependency, ConstructionContext<T> constructionContext)
       throws ErrorsException {
=======================================
--- /core/src/com/google/inject/internal/ProviderInternalFactory.java Thu Jul 7 17:34:16 2011 +++ /core/src/com/google/inject/internal/ProviderInternalFactory.java Sun Feb 26 18:23:19 2012
@@ -32,19 +32,17 @@
  */
 abstract class ProviderInternalFactory<T> implements InternalFactory<T> {

-  private final ProvisionListenerStackCallback<T> provisionCallback;
   private final boolean allowProxy;
   protected final Object source;

-  ProviderInternalFactory(Object source, boolean allowProxy,
-      ProvisionListenerStackCallback<T> provisionCallback) {
- this.provisionCallback = checkNotNull(provisionCallback, "provisionCallback");
+  ProviderInternalFactory(Object source, boolean allowProxy) {
     this.source = checkNotNull(source, "source");
     this.allowProxy = allowProxy;
   }

protected T circularGet(final Provider<? extends T> provider, final Errors errors, - InternalContext context, final Dependency<?> dependency, boolean linked) + InternalContext context, final Dependency<?> dependency, boolean linked,
+      ProvisionListenerStackCallback<T> provisionCallback)
       throws ErrorsException {
Class<?> expectedType = dependency.getKey().getTypeLiteral().getRawType(); final ConstructionContext<T> constructionContext = context.getConstructionContext(this);
@@ -62,14 +60,20 @@
     }

// Optimization: Don't go through the callback stack if no one's listening.
-    if (!provisionCallback.hasListeners()) {
-      return provision(provider, errors, dependency, constructionContext);
-    } else {
- return provisionCallback.provision(errors, context, new ProvisionCallback<T>() {
-        public T call() throws ErrorsException {
- return provision(provider, errors, dependency, constructionContext);
-        }
-      });
+    constructionContext.startConstruction();
+    try {
+      if (!provisionCallback.hasListeners()) {
+ return provision(provider, errors, dependency, constructionContext);
+      } else {
+ return provisionCallback.provision(errors, context, new ProvisionCallback<T>() {
+          public T call() throws ErrorsException {
+ return provision(provider, errors, dependency, constructionContext);
+          }
+        });
+      }
+    } finally {
+      constructionContext.removeCurrentReference();
+      constructionContext.finishConstruction();
     }
   }

@@ -79,13 +83,8 @@
    */
protected T provision(Provider<? extends T> provider, Errors errors, Dependency<?> dependency,
       ConstructionContext<T> constructionContext) throws ErrorsException {
-    constructionContext.startConstruction();
-    try {
-      T t = errors.checkForNull(provider.get(), source, dependency);
-      constructionContext.setProxyDelegates(t);
-      return t;
-    } finally {
-      constructionContext.finishConstruction();
-    }
+    T t = errors.checkForNull(provider.get(), source, dependency);
+    constructionContext.setProxyDelegates(t);
+    return t;
   }
 }
=======================================
--- /core/src/com/google/inject/internal/ProvisionListenerCallbackStore.java Thu Jul 7 17:34:16 2011 +++ /core/src/com/google/inject/internal/ProvisionListenerCallbackStore.java Sun Feb 26 18:23:19 2012
@@ -20,6 +20,7 @@
 import com.google.common.collect.ImmutableList;
 import com.google.common.collect.Lists;
 import com.google.common.collect.MapMaker;
+import com.google.inject.Binding;
 import com.google.inject.Key;
 import com.google.inject.spi.ProvisionListener;
 import com.google.inject.spi.ProvisionListenerBinding;
@@ -35,11 +36,11 @@
 final class ProvisionListenerCallbackStore {
   private final ImmutableList<ProvisionListenerBinding> listenerBindings;

-  private final Map<Key<?>, ProvisionListenerStackCallback<?>> cache
+  private final Map<KeyBinding, ProvisionListenerStackCallback<?>> cache
       = new MapMaker().makeComputingMap(
-          new Function<Key<?>, ProvisionListenerStackCallback<?>>() {
-            public ProvisionListenerStackCallback<?> apply(Key<?> key) {
-              return create(key);
+          new Function<KeyBinding, ProvisionListenerStackCallback<?>>() {
+ public ProvisionListenerStackCallback<?> apply(KeyBinding key) {
+              return create(key.binding);
             }
           });

@@ -50,8 +51,8 @@
   /** Returns a new {@link ProvisionListenerStackCallback} for the key.
    */
@SuppressWarnings("unchecked") // the ProvisionListenerStackCallback type always agrees with the passed type
-  public <T> ProvisionListenerStackCallback<T> get(Key<T> key) {
-    return (ProvisionListenerStackCallback<T>) cache.get(key);
+  public <T> ProvisionListenerStackCallback<T> get(Binding<T> binding) {
+ return (ProvisionListenerStackCallback<T>) cache.get(new KeyBinding(binding.getKey(), binding));
   }

   /**
@@ -63,7 +64,7 @@
    *
    * Returns true if the type was stored in the cache, false otherwise.
    */
-  boolean remove(Key<?> type) {
+  boolean remove(Binding<?> type) {
     return cache.remove(type) != null;
   }

@@ -71,19 +72,39 @@
* Creates a new {@link ProvisionListenerStackCallback} with the correct listeners
    * for the key.
    */
-  private <T> ProvisionListenerStackCallback<T> create(Key<T> key) {
+ private <T> ProvisionListenerStackCallback<T> create(Binding<T> binding) {
     List<ProvisionListener> listeners = null;
-    for (ProvisionListenerBinding binding : listenerBindings) {
-      if (binding.getKeyMatcher().matches(key)) {
+    for (ProvisionListenerBinding provisionBinding : listenerBindings) {
+      if (provisionBinding.getBindingMatcher().matches(binding)) {
         if (listeners == null) {
           listeners = Lists.newArrayList();
         }
-        listeners.addAll(binding.getListeners());
+        listeners.addAll(provisionBinding.getListeners());
       }
     }
     if (listeners == null) {
       listeners = ImmutableList.of();
     }
-    return new ProvisionListenerStackCallback<T>(key, listeners);
+    return new ProvisionListenerStackCallback<T>(binding, listeners);
+  }
+
+ /** A struct that holds key & binding but uses just key for equality/hashcode. */
+  private static class KeyBinding {
+    final Key<?> key;
+    final Binding<?> binding;
+
+    KeyBinding(Key<?> key, Binding<?> binding) {
+      this.key = key;
+      this.binding = binding;
+    }
+
+    @Override
+    public boolean equals(Object obj) {
+ return obj instanceof KeyBinding && key.equals(((KeyBinding)obj).key);
+    }
+    @Override
+    public int hashCode() {
+      return key.hashCode();
+    }
   }
 }
=======================================
--- /core/src/com/google/inject/internal/ProvisionListenerStackCallback.java Thu Jul 7 17:34:16 2011 +++ /core/src/com/google/inject/internal/ProvisionListenerStackCallback.java Sun Feb 26 18:23:19 2012
@@ -16,7 +16,7 @@

 package com.google.inject.internal;

-import com.google.inject.Key;
+import com.google.inject.Binding;
 import com.google.inject.ProvisionException;
 import com.google.inject.spi.DependencyAndSource;
 import com.google.inject.spi.ProvisionListener;
@@ -32,10 +32,10 @@

private static final ProvisionListener EMPTY_LISTENER[] = new ProvisionListener[0];
   private final ProvisionListener[] listeners;
-  private final Key<T> key;
-
- public ProvisionListenerStackCallback(Key<T> key, List<ProvisionListener> listeners) {
-    this.key = key;
+  private final Binding<T> binding;
+
+ public ProvisionListenerStackCallback(Binding<T> binding, List<ProvisionListener> listeners) {
+    this.binding = binding;
     if (listeners.isEmpty()) {
       this.listeners = EMPTY_LISTENER;
     } else {
@@ -64,7 +64,7 @@
           provision.erredListener.getClass() : "(unknown)";
       throw errors
.errorInUserCode(caught, "Error notifying ProvisionListener %s of %s.%n"
-              + " Reason: %s", listener, key, caught)
+              + " Reason: %s", listener, binding.getKey(), caught)
           .toException();
     } else {
       return provision.result;
@@ -105,6 +105,7 @@
       } else if (index < listeners.length) {
         int currentIdx = index;
         try {
+
           listeners[index].onProvision(this);
         } catch(RuntimeException re) {
           erredListener = listeners[currentIdx];
@@ -121,8 +122,11 @@
     }

     @Override
-    public Key<T> getKey() {
-      return key;
+    public Binding<T> getBinding() {
+ // TODO(sameb): Because so many places cast directly to BindingImpl & subclasses, + // we can't decorate this to prevent calling getProvider().get(), which means
+      // if someone calls that they'll get strange errors.
+      return binding;
     }

     @Override
=======================================
--- /core/src/com/google/inject/spi/DependencyAndSource.java Thu Jul 7 17:34:16 2011 +++ /core/src/com/google/inject/spi/DependencyAndSource.java Sun Feb 26 18:23:19 2012
@@ -16,7 +16,9 @@

 package com.google.inject.spi;

+import com.google.inject.Binder;
 import com.google.inject.Binding;
+import com.google.inject.Injector;
 import com.google.inject.internal.util.StackTraceElements;

 import java.lang.reflect.Member;
@@ -40,7 +42,7 @@
* Returns the Dependency, if one exists. For anything that can be referenced * by {@link Injector#getBinding}, a dependency exists. A dependency will not
    * exist (and this will return null) for types initialized with
- * {@link Binder#requestInjection} or {@link Injector#injectMembers(Object), + * {@link Binder#requestInjection} or {@link Injector#injectMembers(Object)},
    * nor will it exist for objects injected into Providers bound with
    * LinkedBindingBuilder#toProvider(Provider).
    */
=======================================
--- /core/src/com/google/inject/spi/Elements.java       Thu Jul  7 17:34:16 2011
+++ /core/src/com/google/inject/spi/Elements.java       Sun Feb 26 18:23:19 2012
@@ -208,8 +208,9 @@
elements.add(new TypeListenerBinding(getSource(), listener, typeMatcher));
     }

- public void bindListener(Matcher<? super Key<?>> keyMatcher, ProvisionListener... listeners) { - elements.add(new ProvisionListenerBinding(getSource(), keyMatcher, listeners));
+    public void bindListener(Matcher<? super Binding<?>> bindingMatcher,
+        ProvisionListener... listeners) {
+ elements.add(new ProvisionListenerBinding(getSource(), bindingMatcher, listeners));
     }

     public void requestStaticInjection(Class<?>... types) {
=======================================
--- /core/src/com/google/inject/spi/ProvisionListener.java Thu Jul 7 17:34:16 2011 +++ /core/src/com/google/inject/spi/ProvisionListener.java Sun Feb 26 18:23:19 2012
@@ -16,7 +16,7 @@

 package com.google.inject.spi;

-import com.google.inject.Key;
+import com.google.inject.Binding;
 import com.google.inject.Provider;
 import com.google.inject.Scope;

@@ -50,13 +50,19 @@
   /** Encapsulates a single act of provisioning.*/
   public abstract static class ProvisionInvocation<T> {

-    /** Returns the Key which will be provisioned. */
-    public abstract Key<T> getKey();
+    /**
+     * Returns the Binding this is provisioning.
+     * <p>
+     * You must not call {@link Provider#get()} on the provider returned by
+ * {@link Binding#getProvider}, otherwise you will get confusing error messages.
+     */
+    public abstract Binding<T> getBinding();

     /** Performs the provision, returning the object provisioned. */
     public abstract T provision();

/** Returns the dependency chain that led to this object being provisioned. */
     public abstract List<DependencyAndSource> getDependencyChain();
+
   }
 }
=======================================
--- /core/src/com/google/inject/spi/ProvisionListenerBinding.java Fri Jul 22 14:13:53 2011 +++ /core/src/com/google/inject/spi/ProvisionListenerBinding.java Sun Feb 26 18:23:19 2012
@@ -18,14 +18,14 @@

 import com.google.common.collect.ImmutableList;
 import com.google.inject.Binder;
-import com.google.inject.Key;
+import com.google.inject.Binding;
 import com.google.inject.matcher.Matcher;

 import java.util.List;

 /**
* Binds keys (picked using a Matcher) to a provision listener. Listeners are created explicitly in - * a module using {@link Binder#bindListener(Matcher, ProvisionListener)} statements: + * a module using {@link Binder#bindListener(Matcher, ProvisionListener...)} statements:
  *
  * @author [email protected] (Sam Berlin)
  * @since 4.0
@@ -33,14 +33,14 @@
 public final class ProvisionListenerBinding implements Element {

   private final Object source;
-  private final Matcher<? super Key<?>> keyMatcher;
+  private final Matcher<? super Binding<?>> bindingMatcher;
   private final List<ProvisionListener> listeners;

   ProvisionListenerBinding(Object source,
-      Matcher<? super Key<?>> typeMatcher,
+      Matcher<? super Binding<?>> bindingMatcher,
       ProvisionListener[] listeners) {
     this.source = source;
-    this.keyMatcher = typeMatcher;
+    this.bindingMatcher = bindingMatcher;
     this.listeners = ImmutableList.copyOf(listeners);
   }

@@ -49,9 +49,11 @@
     return listeners;
   }

- /** Returns the key matcher which chooses which keys the listener should be notified of. */
-  public Matcher<? super Key<?>> getKeyMatcher() {
-    return keyMatcher;
+  /**
+ * Returns the binding matcher which chooses which bindings the listener should be notified of.
+   */
+  public Matcher<? super Binding<?>> getBindingMatcher() {
+    return bindingMatcher;
   }

   public Object getSource() {
@@ -63,7 +65,7 @@
   }

   public void applyTo(Binder binder) {
-    binder.withSource(getSource()).bindListener(keyMatcher,
+    binder.withSource(getSource()).bindListener(bindingMatcher,
         listeners.toArray(new ProvisionListener[listeners.size()]));
   }
 }
=======================================
--- /core/test/com/google/inject/ProvisionListenerTest.java Thu Jul 7 17:34:16 2011 +++ /core/test/com/google/inject/ProvisionListenerTest.java Sun Feb 26 18:23:19 2012
@@ -22,6 +22,7 @@

 import com.google.common.collect.ImmutableList;
 import com.google.common.collect.Lists;
+import com.google.inject.matcher.AbstractMatcher;
 import com.google.inject.matcher.Matcher;
 import com.google.inject.matcher.Matchers;
 import com.google.inject.name.Named;
@@ -282,6 +283,59 @@
     assertNotNull(injector.getInstance(JitFoo.class));
     assertEquals(of(Key.get(Foo.class)), capturer.getAndClear());
   }
+
+  public void testSingletonMatcher() {
+    final Counter counter = new Counter();
+    Injector injector = Guice.createInjector(new AbstractModule() {
+      @Override
+      protected void configure() {
+        bindListener(new AbstractMatcher<Binding<?>>() {
+          @Override
+          public boolean matches(Binding<?> t) {
+            return Scopes.isSingleton(t);
+          }
+        }, counter);
+      }
+    });
+    assertEquals(0, counter.count);
+    // no increment for getting Many.
+    injector.getInstance(Many.class);
+    assertEquals(0, counter.count);
+    // but an increment for getting Sole, since it's a singleton.
+    injector.getInstance(Sole.class);
+    assertEquals(1, counter.count);
+  }
+
+  public void testCallingBindingDotGetProviderDotGet() {
+    Injector injector = Guice.createInjector(new AbstractModule() {
+      @Override
+      protected void configure() {
+        bindListener(Matchers.any(), new ProvisionListener() {
+          @Override
+          public <T> void onProvision(ProvisionInvocation<T> provision) {
+            provision.getBinding().getProvider().get(); // AGH!
+          }
+        });
+      }
+    });
+
+    try {
+      injector.getInstance(Sole.class);
+      fail();
+    } catch(ProvisionException expected) {
+ // We don't really care what kind of error you get, we only care you get an error.
+    }
+
+    try {
+      injector.getInstance(Many.class);
+      fail();
+    } catch(ProvisionException expected) {
+ // We don't really care what kind of error you get, we only care you get an error.
+    }
+  }
+
+  @Singleton static class Sole {}
+  static class Many {}

   @ImplementedBy(Foo.class) static interface JitFoo {}
   @ProvidedBy(JitFoo2P.class) static class JitFoo2 {}
@@ -314,9 +368,9 @@
   private static class Capturer implements ProvisionListener {
     List<Key> keys = Lists.newArrayList();
     public <T> void onProvision(ProvisionInvocation<T> provision) {
-      keys.add(provision.getKey());
+      keys.add(provision.getBinding().getKey());
       T provisioned = provision.provision();
- assertEquals(provision.getKey().getRawType(), provisioned.getClass()); + assertEquals(provision.getBinding().getKey().getRawType(), provisioned.getClass());
     }

     List<Key> getAndClear() {
@@ -368,12 +422,17 @@
         actual.add(dep.getDependency().getKey().getRawType());
       }
       assertEquals(expected, actual);
-      provisionList.add(provision.getKey().getRawType());
+      provisionList.add(provision.getBinding().getKey().getRawType());
     }
   }

-  private static Matcher<Object> keyMatcher(Class<?> clazz) {
-    return Matchers.only(Key.get(clazz));
+  private static Matcher<Binding<?>> keyMatcher(final Class<?> clazz) {
+    return new AbstractMatcher<Binding<?>>() {
+      @Override
+      public boolean matches(Binding<?> t) {
+        return t.getKey().equals(Key.get(clazz));
+      }
+    };
   }

   @SuppressWarnings("unchecked")
@@ -389,7 +448,7 @@

         bindListener(Matchers.any(), new ProvisionListener() {
           public <T> void onProvision(ProvisionInvocation<T> provision) {
-            totalList.add(provision.getKey().getRawType());
+            totalList.add(provision.getBinding().getKey().getRawType());
           }
         });

@@ -490,7 +549,7 @@

     public <T> void onProvision(ProvisionInvocation<T> provision) {
       notified.set(true);
-      assertEquals(notifyType, provision.getKey().getRawType());
+ assertEquals(notifyType, provision.getBinding().getKey().getRawType());
       assertEquals(2, provision.getDependencyChain().size());

assertEquals(null, provision.getDependencyChain().get(0).getDependency());

--
You received this message because you are subscribed to the Google Groups 
"google-guice-dev" group.
To post to this group, send email to [email protected].
To unsubscribe from this group, send email to 
[email protected].
For more options, visit this group at 
http://groups.google.com/group/google-guice-dev?hl=en.

Reply via email to