Eliminated static from SourceProviders. The new mechanism to specify the source of a binding is like this:
Binder myBinder = binder.withSource(source);
git-svn-id: https://google-guice.googlecode.com/svn/trunk@525 d779f126-a31b-0410-b53b-1d3aecad763e
diff --git a/extensions/assistedinject/test/com/google/inject/assistedinject/FactoryProviderTest.java b/extensions/assistedinject/test/com/google/inject/assistedinject/FactoryProviderTest.java
index 86a76f4..0ca95d9 100755
--- a/extensions/assistedinject/test/com/google/inject/assistedinject/FactoryProviderTest.java
+++ b/extensions/assistedinject/test/com/google/inject/assistedinject/FactoryProviderTest.java
@@ -16,16 +16,21 @@
package com.google.inject.assistedinject;
-import com.google.inject.*;
+import com.google.inject.AbstractModule;
import static com.google.inject.Asserts.assertContains;
+import com.google.inject.CreationException;
+import com.google.inject.Guice;
+import com.google.inject.Inject;
+import com.google.inject.Injector;
+import com.google.inject.Provider;
+import com.google.inject.TypeLiteral;
import com.google.inject.name.Named;
import com.google.inject.name.Names;
-import junit.framework.TestCase;
-
-import java.awt.*;
+import java.awt.Color;
import java.util.Collection;
import java.util.Collections;
import java.util.Set;
+import junit.framework.TestCase;
/**
* @author jmourits@google.com (Jerome Mourits)
@@ -508,8 +513,8 @@
}
});
fail();
- } catch (ProvisionException expected) {
- assertContains(expected.getCause().getMessage(),
+ } catch (CreationException expected) {
+ assertContains(expected.getMessage(),
"Parameter of type 'double' is not injectable or annotated with @Assisted");
}
}
diff --git a/extensions/multibindings/src/com/google/inject/multibindings/MapBinder.java b/extensions/multibindings/src/com/google/inject/multibindings/MapBinder.java
index 48f6e03..7be7f28 100644
--- a/extensions/multibindings/src/com/google/inject/multibindings/MapBinder.java
+++ b/extensions/multibindings/src/com/google/inject/multibindings/MapBinder.java
@@ -16,13 +16,18 @@
package com.google.inject.multibindings;
-import com.google.inject.*;
-import com.google.inject.util.Types;
+import static com.google.common.base.Preconditions.checkNotNull;
+import static com.google.common.base.Preconditions.checkState;
+import com.google.inject.Binder;
+import com.google.inject.Inject;
+import com.google.inject.Key;
+import com.google.inject.Module;
+import com.google.inject.Provider;
+import com.google.inject.TypeLiteral;
import com.google.inject.binder.LinkedBindingBuilder;
import com.google.inject.multibindings.Multibinder.RealMultibinder;
-import com.google.inject.spi.SourceProviders;
-import static com.google.common.base.Preconditions.checkNotNull;
-
+import com.google.inject.spi.SourceProvider;
+import com.google.inject.util.Types;
import java.lang.annotation.Annotation;
import java.lang.reflect.Type;
import java.util.Collections;
@@ -88,9 +93,9 @@
*/
public abstract class MapBinder<K, V> {
private MapBinder() {}
- static {
- SourceProviders.skip(RealMapBinder.class);
- }
+
+ private static final SourceProvider sourceProvider
+ = new SourceProvider(MapBinder.class, RealMapBinder.class);
/**
* Returns a new mapbinder that collects entries of {@code keyType}/{@code
@@ -153,7 +158,7 @@
Multibinder<Entry<K, Provider<V>>> entrySetBinder) {
RealMapBinder<K, V> mapBinder = new RealMapBinder<K, V>(binder,
valueType, mapKey, providerMapKey, entrySetBinder);
- binder.install(mapBinder);
+ binder.withSource(sourceProvider.get()).install(mapBinder);
return mapBinder;
}
@@ -199,7 +204,7 @@
private final Key<Map<K, V>> mapKey;
private final Key<Map<K, Provider<V>>> providerMapKey;
private final RealMultibinder<Map.Entry<K, Provider<V>>> entrySetBinder;
-
+
/* the target injector's binder. non-null until initialization, null afterwards */
private Binder binder;
@@ -219,59 +224,52 @@
*/
@Override public LinkedBindingBuilder<V> addBinding(K key) {
checkNotNull(key, "key");
- if (isInitialized()) {
- throw new IllegalStateException("MapBinder was already initialized");
- }
+ checkState(!isInitialized(), "MapBinder was already initialized");
+ Object source = sourceProvider.get();
@SuppressWarnings("unchecked")
Key<V> valueKey = (Key<V>) Key.get(valueType, new RealElement(entrySetBinder.getSetName()));
- entrySetBinder.addBinding()
- .toInstance(new MapEntry<K, Provider<V>>(key, binder.getProvider(valueKey)));
- return binder.bind(valueKey);
+ entrySetBinder.addBinding().toInstance(new MapEntry<K, Provider<V>>(key,
+ binder.withSource(source).getProvider(valueKey)));
+ return binder.withSource(source).bind(valueKey);
}
public void configure(Binder binder) {
- if (isInitialized()) {
- throw new IllegalStateException("MapBinder was already initialized");
- }
+ checkState(!isInitialized(), "MapBinder was already initialized");
// binds a Map<K, Provider<V>> from a collection of Map<Entry<K, Provider<V>>
- final Provider<Set<Entry<K,Provider<V>>>> entrySetProvider
- = binder.getProvider(entrySetBinder.getSetKey());
+ final Provider<Set<Entry<K, Provider<V>>>> entrySetProvider = binder
+ .getProvider(entrySetBinder.getSetKey());
binder.bind(providerMapKey).toProvider(new Provider<Map<K, Provider<V>>>() {
private Map<K, Provider<V>> providerMap;
-
+
@SuppressWarnings("unused")
@Inject void initialize() {
RealMapBinder.this.binder = null;
-
+
Map<K, Provider<V>> providerMapMutable = new LinkedHashMap<K, Provider<V>>();
- for (Map.Entry<K, Provider<V>> entry : entrySetProvider.get()) {
- if (providerMapMutable.put(entry.getKey(), entry.getValue()) != null) {
- throw new IllegalStateException("Map injection failed due to duplicated key \""
- + entry.getKey() + "\"");
- }
+ for (Entry<K, Provider<V>> entry : entrySetProvider.get()) {
+ checkState(providerMapMutable.put(entry.getKey(), entry.getValue()) == null,
+ "Map injection failed due to duplicated key \"%s\"", entry.getKey());
}
-
+
providerMap = Collections.unmodifiableMap(providerMapMutable);
}
-
+
public Map<K, Provider<V>> get() {
return providerMap;
}
- });
+ });
final Provider<Map<K, Provider<V>>> mapProvider = binder.getProvider(providerMapKey);
binder.bind(mapKey).toProvider(new Provider<Map<K, V>>() {
public Map<K, V> get() {
Map<K, V> map = new LinkedHashMap<K, V>();
- for (Map.Entry<K, Provider<V>> entry : mapProvider.get().entrySet()) {
+ for (Entry<K, Provider<V>> entry : mapProvider.get().entrySet()) {
V value = entry.getValue().get();
K key = entry.getKey();
- if (value == null) {
- throw new IllegalStateException("Map injection failed due to null value for key \""
- + key + "\"");
- }
+ checkState(value != null,
+ "Map injection failed due to null value for key \"%s\"", key);
map.put(key, value);
}
return Collections.unmodifiableMap(map);
diff --git a/extensions/multibindings/src/com/google/inject/multibindings/Multibinder.java b/extensions/multibindings/src/com/google/inject/multibindings/Multibinder.java
index d85d178..9068246 100644
--- a/extensions/multibindings/src/com/google/inject/multibindings/Multibinder.java
+++ b/extensions/multibindings/src/com/google/inject/multibindings/Multibinder.java
@@ -16,15 +16,27 @@
package com.google.inject.multibindings;
-import com.google.inject.*;
-import com.google.inject.util.Types;
-import com.google.inject.binder.LinkedBindingBuilder;
-import com.google.inject.spi.SourceProviders;
import static com.google.common.base.Preconditions.checkNotNull;
-
+import static com.google.common.base.Preconditions.checkState;
+import com.google.inject.Binder;
+import com.google.inject.Binding;
+import com.google.inject.Inject;
+import com.google.inject.Injector;
+import com.google.inject.Key;
+import com.google.inject.Module;
+import com.google.inject.Provider;
+import com.google.inject.TypeLiteral;
+import com.google.inject.binder.LinkedBindingBuilder;
+import com.google.inject.spi.SourceProvider;
+import com.google.inject.util.Types;
import java.lang.annotation.Annotation;
import java.lang.reflect.Type;
-import java.util.*;
+import java.util.ArrayList;
+import java.util.Collections;
+import java.util.LinkedHashSet;
+import java.util.List;
+import java.util.Map;
+import java.util.Set;
/**
* An API to bind multiple values separately, only to later inject them as a
@@ -72,9 +84,9 @@
*/
public abstract class Multibinder<T> {
private Multibinder() {}
- static {
- SourceProviders.skip(RealMultibinder.class);
- }
+
+ private static final SourceProvider sourceProvider
+ = new SourceProvider(RealMultibinder.class, Multibinder.class);
/**
* Returns a new multibinder that collects instances of {@code type} in a
@@ -83,7 +95,7 @@
public static <T> Multibinder<T> newSetBinder(Binder binder, Type type) {
RealMultibinder<T> result = new RealMultibinder<T>(binder, type, "",
Key.get(Multibinder.<T>setOf(type)));
- binder.install(result);
+ binder.withSource(sourceProvider.get()).install(result);
return result;
}
@@ -94,7 +106,7 @@
public static <T> Multibinder<T> newSetBinder(Binder binder, Type type, Annotation annotation) {
RealMultibinder<T> result = new RealMultibinder<T>(binder, type, annotation.toString(),
Key.get(Multibinder.<T>setOf(type), annotation));
- binder.install(result);
+ binder.withSource(sourceProvider.get()).install(result);
return result;
}
@@ -106,7 +118,7 @@
Class<? extends Annotation> annotationType) {
RealMultibinder<T> result = new RealMultibinder<T>(binder, type, "@" + annotationType.getName(),
Key.get(Multibinder.<T>setOf(type), annotationType));
- binder.install(result);
+ binder.withSource(sourceProvider.get()).install(result);
return result;
}
@@ -172,20 +184,17 @@
@SuppressWarnings("unchecked")
public void configure(Binder binder) {
- if (isInitialized()) {
- throw new IllegalStateException("Multibinder was already initialized");
- }
+ checkState(!isInitialized(), "Multibinder was already initialized");
binder.bind(setKey).toProvider(this);
}
@SuppressWarnings("unchecked")
@Override public LinkedBindingBuilder<T> addBinding() {
- if (isInitialized()) {
- throw new IllegalStateException("Multibinder was already initialized");
- }
+ checkState(!isInitialized(), "Multibinder was already initialized");
- return binder.bind((Key<T>) Key.get(elementType, new RealElement(setName)));
+ return binder.withSource(sourceProvider.get())
+ .bind((Key<T>) Key.get(elementType, new RealElement(setName)));
}
/**
@@ -217,20 +226,14 @@
}
public Set<T> get() {
- if (!isInitialized()) {
- throw new IllegalStateException("Multibinder is not initialized");
- }
+ checkState(isInitialized(), "Multibinder is not initialized");
Set<T> result = new LinkedHashSet<T>();
for (Provider<T> provider : providers) {
final T newValue = provider.get();
- if (newValue == null) {
- throw new IllegalStateException("Set injection failed due to null element");
- }
- if (!result.add(newValue)) {
- throw new IllegalStateException("Set injection failed due to duplicated element \""
- + newValue + "\"");
- }
+ checkState(newValue != null, "Set injection failed due to null element");
+ checkState(result.add(newValue),
+ "Set injection failed due to duplicated element \"%s\"", newValue);
}
return Collections.unmodifiableSet(result);
}
diff --git a/extensions/multibindings/test/com/google/inject/multibindings/MapBinderTest.java b/extensions/multibindings/test/com/google/inject/multibindings/MapBinderTest.java
index 6f4ae79..f9a818b 100644
--- a/extensions/multibindings/test/com/google/inject/multibindings/MapBinderTest.java
+++ b/extensions/multibindings/test/com/google/inject/multibindings/MapBinderTest.java
@@ -16,18 +16,26 @@
package com.google.inject.multibindings;
-import com.google.inject.*;
+import com.google.inject.AbstractModule;
import static com.google.inject.Asserts.assertContains;
+import com.google.inject.BindingAnnotation;
+import com.google.inject.CreationException;
+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.ProvisionException;
+import com.google.inject.TypeLiteral;
import com.google.inject.name.Names;
import static com.google.inject.name.Names.named;
import com.google.inject.util.Providers;
-import junit.framework.TestCase;
-
import java.lang.annotation.Retention;
import static java.lang.annotation.RetentionPolicy.RUNTIME;
import java.util.Collections;
import java.util.HashMap;
import java.util.Map;
+import junit.framework.TestCase;
/**
* @author dpb@google.com (David P. Baker)
@@ -212,9 +220,9 @@
}
});
fail();
- } catch(ProvisionException expected) {
- assertEquals("Map injection failed due to duplicated key \"a\"",
- expected.getCause().getMessage());
+ } catch(CreationException expected) {
+ assertContains(expected.getMessage(),
+ "Map injection failed due to duplicated key \"a\"");
}
}
@@ -276,8 +284,8 @@
});
fail();
} catch (CreationException expected) {
- assertContains(expected.getMessage(), "Error at " + getClass().getName());
- assertContains(expected.getMessage(), "No implementation was specified.");
+ assertContains(expected.getMessage(), "Error at " + getClass().getName(),
+ "No implementation for java.lang.Integer");
}
}
diff --git a/extensions/multibindings/test/com/google/inject/multibindings/MultibinderTest.java b/extensions/multibindings/test/com/google/inject/multibindings/MultibinderTest.java
index 2ff4400..f80333e 100644
--- a/extensions/multibindings/test/com/google/inject/multibindings/MultibinderTest.java
+++ b/extensions/multibindings/test/com/google/inject/multibindings/MultibinderTest.java
@@ -16,19 +16,27 @@
package com.google.inject.multibindings;
-import com.google.inject.*;
+import com.google.common.collect.Sets;
+import com.google.inject.AbstractModule;
import static com.google.inject.Asserts.assertContains;
+import com.google.inject.BindingAnnotation;
+import com.google.inject.CreationException;
+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.ProvisionException;
+import com.google.inject.TypeLiteral;
import com.google.inject.name.Names;
import static com.google.inject.name.Names.named;
import com.google.inject.util.Providers;
-import junit.framework.TestCase;
-
import java.lang.annotation.Retention;
import static java.lang.annotation.RetentionPolicy.RUNTIME;
import java.util.Arrays;
import java.util.Collections;
-import java.util.HashSet;
import java.util.Set;
+import junit.framework.TestCase;
/**
* @author jessewilson@google.com (Jesse Wilson)
@@ -243,7 +251,7 @@
fail();
} catch (CreationException expected) {
assertContains(expected.getMessage(), "Error at " + getClass().getName());
- assertContains(expected.getMessage(), "No implementation was specified.");
+ assertContains(expected.getMessage(), "No implementation for java.lang.Integer");
}
}
@@ -254,7 +262,7 @@
@interface De {}
private <T> Set<T> setOf(T... elements) {
- Set<T> result = new HashSet<T>();
+ Set<T> result = Sets.newHashSet();
result.addAll(Arrays.asList(elements));
return result;
}
diff --git a/spring/src/com/google/inject/spring/SpringIntegration.java b/spring/src/com/google/inject/spring/SpringIntegration.java
index a74ccee..2151c60 100644
--- a/spring/src/com/google/inject/spring/SpringIntegration.java
+++ b/spring/src/com/google/inject/spring/SpringIntegration.java
@@ -16,12 +16,12 @@
package com.google.inject.spring;
+import static com.google.common.base.Preconditions.checkNotNull;
import com.google.inject.Binder;
import com.google.inject.Inject;
import com.google.inject.Provider;
import com.google.inject.name.Names;
-import com.google.inject.spi.SourceProviders;
-import static com.google.common.base.Preconditions.checkNotNull;
+import com.google.inject.spi.SourceProvider;
import org.springframework.beans.factory.BeanFactory;
import org.springframework.beans.factory.ListableBeanFactory;
@@ -31,13 +31,12 @@
* @author crazybob@google.com (Bob Lee)
*/
public class SpringIntegration {
-
- static {
- SourceProviders.skip(SpringIntegration.class);
- }
-
private SpringIntegration() {}
+
+ private static final SourceProvider sourceProvider
+ = new SourceProvider(SpringIntegration.class);
+
/**
* Creates a provider which looks up objects from Spring using the given name.
* Expects a binding to {@link
@@ -61,6 +60,8 @@
* @see com.google.inject.name.Names#named(String)
*/
public static void bindAll(Binder binder, ListableBeanFactory beanFactory) {
+ binder = binder.withSource(sourceProvider.get());
+
for (String name : beanFactory.getBeanDefinitionNames()) {
Class<?> type = beanFactory.getType(name);
bindBean(binder, beanFactory, name, type);
diff --git a/src/com/google/inject/AbstractModule.java b/src/com/google/inject/AbstractModule.java
index 87c6491..92cd0ba 100644
--- a/src/com/google/inject/AbstractModule.java
+++ b/src/com/google/inject/AbstractModule.java
@@ -23,7 +23,6 @@
import com.google.inject.binder.LinkedBindingBuilder;
import com.google.inject.matcher.Matcher;
import com.google.inject.spi.Message;
-import com.google.inject.spi.SourceProviders;
import com.google.inject.spi.TypeConverter;
import java.lang.annotation.Annotation;
import java.lang.reflect.Method;
@@ -52,10 +51,6 @@
*/
public abstract class AbstractModule implements Module {
- static {
- SourceProviders.skip(AbstractModule.class);
- }
-
Binder binder;
public final synchronized void configure(Binder builder) {
diff --git a/src/com/google/inject/ConvertToTypesCommandProcessor.java b/src/com/google/inject/ConvertToTypesCommandProcessor.java
index 45e26a8..d5f5172 100644
--- a/src/com/google/inject/ConvertToTypesCommandProcessor.java
+++ b/src/com/google/inject/ConvertToTypesCommandProcessor.java
@@ -24,7 +24,7 @@
import com.google.inject.matcher.AbstractMatcher;
import com.google.inject.matcher.Matcher;
import com.google.inject.matcher.Matchers;
-import com.google.inject.spi.SourceProviders;
+import com.google.inject.spi.SourceProvider;
import com.google.inject.spi.TypeConverter;
import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;
@@ -162,7 +162,7 @@
private void internalConvertToTypes(Matcher<? super TypeLiteral<?>> typeMatcher,
TypeConverter converter) {
- converters.add(new MatcherAndConverter(typeMatcher, converter, SourceProviders.UNKNOWN_SOURCE));
+ converters.add(new MatcherAndConverter(typeMatcher, converter, SourceProvider.UNKNOWN_SOURCE));
}
@Override public Boolean visitConvertToTypes(ConvertToTypesCommand command) {
diff --git a/src/com/google/inject/InjectorBuilder.java b/src/com/google/inject/InjectorBuilder.java
index d08e66c..74be70f 100644
--- a/src/com/google/inject/InjectorBuilder.java
+++ b/src/com/google/inject/InjectorBuilder.java
@@ -28,7 +28,7 @@
import com.google.inject.internal.ErrorsException;
import com.google.inject.internal.Stopwatch;
import com.google.inject.spi.InjectionPoint;
-import com.google.inject.spi.SourceProviders;
+import com.google.inject.spi.SourceProvider;
import java.lang.reflect.Member;
import java.util.List;
import java.util.logging.Logger;
@@ -171,17 +171,20 @@
errors.throwCreationExceptionIfErrorsExist();
}
- /** Inject everything that can be injected. This uses runtime error handling. */
+ /** Inject everything that can be injected. */
private void fulfillInjectionRequests() {
futureInjector.initialize(injector);
requestStaticInjectionCommandProcessor.injectMembers(injector);
stopwatch.resetAndLog("Static member injection");
+
injector.fulfillOutstandingInjections(errors);
stopwatch.resetAndLog("Instance injection");
+ errors.throwCreationExceptionIfErrorsExist();
loadEagerSingletons();
stopwatch.resetAndLog("Preloading");
+ errors.throwCreationExceptionIfErrorsExist();
}
public void loadEagerSingletons() {
@@ -225,7 +228,7 @@
}
public void configure(Binder binder) {
- binder = binder.withSource(SourceProviders.UNKNOWN_SOURCE);
+ binder = binder.withSource(SourceProvider.UNKNOWN_SOURCE);
binder.bind(Stage.class).toInstance(stage);
binder.bindScope(Singleton.class, SINGLETON);
@@ -261,7 +264,7 @@
LoggerFactory loggerFactory = new LoggerFactory();
injector.explicitBindings.put(key,
new ProviderInstanceBindingImpl<Logger>(injector, key,
- SourceProviders.UNKNOWN_SOURCE, loggerFactory, Scopes.NO_SCOPE,
+ SourceProvider.UNKNOWN_SOURCE, loggerFactory, Scopes.NO_SCOPE,
loggerFactory, LoadStrategy.LAZY));
}
diff --git a/src/com/google/inject/InjectorImpl.java b/src/com/google/inject/InjectorImpl.java
index d6966ba..6f6eb1e 100644
--- a/src/com/google/inject/InjectorImpl.java
+++ b/src/com/google/inject/InjectorImpl.java
@@ -37,7 +37,7 @@
import com.google.inject.spi.ConvertedConstantBinding;
import com.google.inject.spi.InjectionPoint;
import com.google.inject.spi.ProviderBinding;
-import com.google.inject.spi.SourceProviders;
+import com.google.inject.spi.SourceProvider;
import com.google.inject.util.Providers;
import java.lang.annotation.Annotation;
import java.lang.reflect.AnnotatedElement;
@@ -294,7 +294,7 @@
super(
injector,
key,
- SourceProviders.UNKNOWN_SOURCE,
+ SourceProvider.UNKNOWN_SOURCE,
createInternalFactory(providedBinding),
Scopes.NO_SCOPE,
loadStrategy);
@@ -389,7 +389,7 @@
ConvertedConstantBindingImpl(
InjectorImpl injector, Key<T> key, T value, Binding<String> originalBinding) {
- super(injector, key, SourceProviders.UNKNOWN_SOURCE, new ConstantFactory<T>(value),
+ super(injector, key, SourceProvider.UNKNOWN_SOURCE, new ConstantFactory<T>(value),
Scopes.NO_SCOPE, LoadStrategy.LAZY);
this.value = value;
provider = Providers.of(value);
@@ -424,7 +424,7 @@
<T> BindingImpl<T> createBindingFromType(
Class<T> type, LoadStrategy loadStrategy, Errors errors) throws ErrorsException {
BindingImpl<T> binding = createUnitializedBinding(
- type, null, SourceProviders.defaultSource(), loadStrategy, errors);
+ type, null, StackTraceElements.forType(type), loadStrategy, errors);
initializeBinding(binding, errors);
return binding;
}
diff --git a/src/com/google/inject/InternalFactoryToProviderAdapter.java b/src/com/google/inject/InternalFactoryToProviderAdapter.java
index c7cd465..b1424f8 100644
--- a/src/com/google/inject/InternalFactoryToProviderAdapter.java
+++ b/src/com/google/inject/InternalFactoryToProviderAdapter.java
@@ -20,7 +20,7 @@
import com.google.inject.internal.Errors;
import com.google.inject.internal.ErrorsException;
import com.google.inject.spi.InjectionPoint;
-import com.google.inject.spi.SourceProviders;
+import com.google.inject.spi.SourceProvider;
/**
* @author crazybob@google.com (Bob Lee)
@@ -31,7 +31,7 @@
private final Object source;
public InternalFactoryToProviderAdapter(Provider<? extends T> provider) {
- this(provider, SourceProviders.UNKNOWN_SOURCE);
+ this(provider, SourceProvider.UNKNOWN_SOURCE);
}
public InternalFactoryToProviderAdapter(
diff --git a/src/com/google/inject/commands/BindCommand.java b/src/com/google/inject/commands/BindCommand.java
index db6cd56..996841b 100644
--- a/src/com/google/inject/commands/BindCommand.java
+++ b/src/com/google/inject/commands/BindCommand.java
@@ -26,7 +26,7 @@
import com.google.inject.binder.ConstantBindingBuilder;
import com.google.inject.binder.LinkedBindingBuilder;
import com.google.inject.binder.ScopedBindingBuilder;
-import com.google.inject.spi.SourceProviders;
+import com.google.inject.spi.SourceProvider;
import java.lang.annotation.Annotation;
/**
@@ -36,9 +36,8 @@
*/
public final class BindCommand<T> implements Command {
- static {
- SourceProviders.skip(BindCommand.BindingBuilder.class);
- }
+ private static final SourceProvider sourceProvider = new SourceProvider(
+ BindCommand.BindingBuilder.class);
private static final BindTarget<Object> EMPTY_BIND_TARGET = new AbstractTarget<Object>() {
public ScopedBindingBuilder execute(LinkedBindingBuilder<Object> linkedBindingBuilder) {
@@ -317,25 +316,25 @@
private void checkNotTargetted() {
if (bindTarget != EMPTY_BIND_TARGET) {
- binder.addError(IMPLEMENTATION_ALREADY_SET);
+ binder.withSource(sourceProvider.get()).addError(IMPLEMENTATION_ALREADY_SET);
}
}
private void checkNotAnnotated() {
if (BindCommand.this.key.getAnnotationType() != null) {
- binder.addError(ANNOTATION_ALREADY_SPECIFIED);
+ binder.withSource(sourceProvider.get()).addError(ANNOTATION_ALREADY_SPECIFIED);
}
}
private void checkNotScoped() {
// Scoping isn't allowed when we have only one instance.
if (bindTarget.get() != null) {
- binder.addError(SINGLE_INSTANCE_AND_SCOPE);
+ binder.withSource(sourceProvider.get()).addError(SINGLE_INSTANCE_AND_SCOPE);
return;
}
if (bindScoping != EMPTY_SCOPING) {
- binder.addError(SCOPE_ALREADY_SET);
+ binder.withSource(sourceProvider.get()).addError(SCOPE_ALREADY_SET);
}
}
diff --git a/src/com/google/inject/commands/BindConstantCommand.java b/src/com/google/inject/commands/BindConstantCommand.java
index 7e28458..d51e349 100644
--- a/src/com/google/inject/commands/BindConstantCommand.java
+++ b/src/com/google/inject/commands/BindConstantCommand.java
@@ -16,6 +16,8 @@
package com.google.inject.commands;
+import static com.google.common.base.Preconditions.checkNotNull;
+import com.google.inject.AbstractModule;
import com.google.inject.Binder;
import com.google.inject.Key;
import com.google.inject.Provider;
@@ -23,9 +25,7 @@
import com.google.inject.binder.ConstantBindingBuilder;
import com.google.inject.binder.LinkedBindingBuilder;
import com.google.inject.binder.ScopedBindingBuilder;
-import com.google.inject.spi.SourceProviders;
-import static com.google.common.base.Preconditions.checkNotNull;
-
+import com.google.inject.spi.SourceProvider;
import java.lang.annotation.Annotation;
/**
@@ -34,9 +34,8 @@
* @author jessewilson@google.com (Jesse Wilson)
*/
public final class BindConstantCommand implements Command {
- static {
- SourceProviders.skip(BindingBuilder.class);
- }
+ private static final SourceProvider sourceProvider = new SourceProvider(
+ BindingBuilder.class, AbstractModule.class);
private final Object source;
private BindingAnnotation bindingAnnotation;
@@ -348,13 +347,13 @@
private void assertNoBindingAnnotation() {
if (bindingAnnotation != null) {
- binder.addError(ANNOTATION_ALREADY_SPECIFIED);
+ binder.withSource(sourceProvider.get()).addError(ANNOTATION_ALREADY_SPECIFIED);
}
}
private void assertNoTarget() {
if (target != null) {
- binder.addError(CONSTANT_VALUE_ALREADY_SET);
+ binder.withSource(sourceProvider.get()).addError(CONSTANT_VALUE_ALREADY_SET);
}
}
diff --git a/src/com/google/inject/commands/CommandRecorder.java b/src/com/google/inject/commands/CommandRecorder.java
index 312428e..d91b01a 100644
--- a/src/com/google/inject/commands/CommandRecorder.java
+++ b/src/com/google/inject/commands/CommandRecorder.java
@@ -19,6 +19,7 @@
import static com.google.common.base.Preconditions.checkNotNull;
import com.google.common.collect.Lists;
import com.google.common.collect.Sets;
+import com.google.inject.AbstractModule;
import com.google.inject.Binder;
import com.google.inject.Key;
import com.google.inject.Module;
@@ -30,7 +31,7 @@
import com.google.inject.binder.AnnotatedConstantBindingBuilder;
import com.google.inject.matcher.Matcher;
import com.google.inject.spi.Message;
-import com.google.inject.spi.SourceProviders;
+import com.google.inject.spi.SourceProvider;
import com.google.inject.spi.TypeConverter;
import java.lang.annotation.Annotation;
import java.lang.reflect.Method;
@@ -47,13 +48,12 @@
* @author jessewilson@google.com (Jesse Wilson)
*/
public final class CommandRecorder {
+ private static final SourceProvider sourceProvider = new SourceProvider(
+ RecordingBinder.class, AbstractModule.class);
+
private Stage currentStage = Stage.DEVELOPMENT;
private final EarlyRequestsProvider earlyRequestsProvider;
- static {
- SourceProviders.skip(RecordingBinder.class);
- }
-
/**
* @param earlyRequestsProvider satisfies requests to
* {@link Binder#getProvider} at module execution time. For modules that
@@ -196,7 +196,7 @@
}
protected Object getSource() {
- return SourceProviders.defaultSource();
+ return sourceProvider.get();
}
@Override public String toString() {
diff --git a/src/com/google/inject/commands/FutureInjector.java b/src/com/google/inject/commands/FutureInjector.java
index ce1b4fa..30f972c 100644
--- a/src/com/google/inject/commands/FutureInjector.java
+++ b/src/com/google/inject/commands/FutureInjector.java
@@ -16,10 +16,10 @@
package com.google.inject.commands;
+import static com.google.common.base.Preconditions.checkState;
import com.google.inject.Injector;
import com.google.inject.Key;
-
/**
* Satisfies binding requests using an eventually-created Injector. To use:
*
@@ -43,18 +43,14 @@
private Injector injector;
public void initialize(Injector injector) {
- if (this.injector != null) {
- throw new IllegalStateException("Already initialized");
- }
+ checkState(this.injector == null, "Already initialized");
this.injector = injector;
}
public <T> T get(Key<T> key) {
- if (injector == null) {
- throw new IllegalStateException("This provider cannot be used until the"
- + " Injector has been created.");
- }
+ checkState(injector != null,
+ "This provider cannot be used until the Injector has been created.");
return injector.getInstance(key);
}
diff --git a/src/com/google/inject/internal/Errors.java b/src/com/google/inject/internal/Errors.java
index 5e82f4a..0ee4702 100644
--- a/src/com/google/inject/internal/Errors.java
+++ b/src/com/google/inject/internal/Errors.java
@@ -28,7 +28,7 @@
import com.google.inject.TypeLiteral;
import com.google.inject.spi.InjectionPoint;
import com.google.inject.spi.Message;
-import com.google.inject.spi.SourceProviders;
+import com.google.inject.spi.SourceProvider;
import java.io.Serializable;
import java.lang.annotation.Annotation;
import java.lang.reflect.Constructor;
@@ -375,7 +375,7 @@
} else if (!sources.isEmpty()) {
source = sources.get(sources.size() - 1);
} else {
- source = SourceProviders.UNKNOWN_SOURCE;
+ source = SourceProvider.UNKNOWN_SOURCE;
}
errors.add(new Message(source, message, ImmutableList.copyOf(injectionPoints), cause));
diff --git a/src/com/google/inject/internal/StackTraceElements.java b/src/com/google/inject/internal/StackTraceElements.java
index 56c373e..fcabe40 100644
--- a/src/com/google/inject/internal/StackTraceElements.java
+++ b/src/com/google/inject/internal/StackTraceElements.java
@@ -18,7 +18,7 @@
import static com.google.inject.internal.ReferenceType.SOFT;
import static com.google.inject.internal.ReferenceType.WEAK;
-import com.google.inject.spi.SourceProviders;
+import com.google.inject.spi.SourceProvider;
import java.io.IOException;
import java.lang.reflect.Constructor;
import java.lang.reflect.Member;
@@ -45,7 +45,7 @@
public static Object forMember(Member member) {
if (member == null) {
- return SourceProviders.UNKNOWN_SOURCE;
+ return SourceProvider.UNKNOWN_SOURCE;
}
Class declaringClass = member.getDeclaringClass();
diff --git a/src/com/google/inject/name/Names.java b/src/com/google/inject/name/Names.java
index c3c1a1a..53bc7d5 100644
--- a/src/com/google/inject/name/Names.java
+++ b/src/com/google/inject/name/Names.java
@@ -16,9 +16,10 @@
package com.google.inject.name;
+import com.google.inject.AbstractModule;
import com.google.inject.Binder;
import com.google.inject.Key;
-import com.google.inject.spi.SourceProviders;
+import com.google.inject.spi.SourceProvider;
import java.util.Enumeration;
import java.util.Map;
import java.util.Properties;
@@ -30,11 +31,10 @@
*/
public class Names {
- private Names() {}
+ private static final SourceProvider sourceProvider = new SourceProvider(
+ Names.class, AbstractModule.class);
- static {
- SourceProviders.skip(Names.class);
- }
+ private Names() {}
/**
* Creates a {@link Named} annotation with {@code name} as the value.
@@ -48,7 +48,7 @@
* {@code properties}.
*/
public static void bindProperties(Binder binder, Map<String, String> properties) {
- binder = binder.withSource(getSource());
+ binder = binder.withSource(sourceProvider.get());
for (Map.Entry<String, String> entry : properties.entrySet()) {
String key = entry.getKey();
String value = entry.getValue();
@@ -62,7 +62,7 @@
* {@link Properties#defaults defaults}.
*/
public static void bindProperties(Binder binder, Properties properties) {
- binder = binder.withSource(getSource());
+ binder = binder.withSource(sourceProvider.get());
// use enumeration to include the default properties
for (Enumeration<?> e = properties.propertyNames(); e.hasMoreElements(); ) {
@@ -71,8 +71,4 @@
binder.bind(Key.get(String.class, new NamedImpl(propertyName))).toInstance(value);
}
}
-
- private static Object getSource() {
- return SourceProviders.defaultSource();
- }
}
diff --git a/src/com/google/inject/spi/Message.java b/src/com/google/inject/spi/Message.java
index 97e4222..5b5a53c 100644
--- a/src/com/google/inject/spi/Message.java
+++ b/src/com/google/inject/spi/Message.java
@@ -47,7 +47,7 @@
}
public Message(String message) {
- this(SourceProviders.UNKNOWN_SOURCE, message, ImmutableList.<InjectionPoint>of(), null);
+ this(SourceProvider.UNKNOWN_SOURCE, message, ImmutableList.<InjectionPoint>of(), null);
}
/**
diff --git a/src/com/google/inject/spi/SourceProvider.java b/src/com/google/inject/spi/SourceProvider.java
index 127f5ba..062a816 100644
--- a/src/com/google/inject/spi/SourceProvider.java
+++ b/src/com/google/inject/spi/SourceProvider.java
@@ -16,20 +16,37 @@
package com.google.inject.spi;
+import com.google.common.collect.ImmutableSet;
+import java.util.Set;
+
/**
- * Provides source objects to the {@link com.google.inject.Binder}.
- * A source object is any object which points back to the current location
- * within the configuration. Guice uses source objects in error messages
- * and associates them with bindings.
- *
+ * Provides access to the calling line of code.
+ *
* @author crazybob@google.com (Bob Lee)
*/
-public interface SourceProvider {
+public class SourceProvider {
- /**
- * Creates an object pointing to the current location within the
- * configuration. If we run into a problem later, we'll be able to trace it
- * back to the original source. Useful for debugging.
- */
- Object source();
+ /** Indicates that the source is unknown. */
+ public static final Object UNKNOWN_SOURCE = "[unknown source]";
+
+ private final Set<String> classNamesToSkip;
+
+ public SourceProvider(Class... classesToSkip) {
+ String[] classNamesToSkip = new String[classesToSkip.length + 1];
+ for (int i = 0; i < classesToSkip.length; i++) {
+ classNamesToSkip[i] = classesToSkip[i].getName();
+ }
+ classNamesToSkip[classesToSkip.length] = SourceProvider.class.getName();
+ this.classNamesToSkip = ImmutableSet.of(classNamesToSkip);
+ }
+
+ public Object get() {
+ for (final StackTraceElement element : new Throwable().getStackTrace()) {
+ String className = element.getClassName();
+ if (!classNamesToSkip.contains(className)) {
+ return element;
+ }
+ }
+ throw new AssertionError();
+ }
}
diff --git a/src/com/google/inject/spi/SourceProviders.java b/src/com/google/inject/spi/SourceProviders.java
deleted file mode 100644
index e57c8bf..0000000
--- a/src/com/google/inject/spi/SourceProviders.java
+++ /dev/null
@@ -1,98 +0,0 @@
-/**
- * Copyright (C) 2006 Google Inc.
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package com.google.inject.spi;
-
-import com.google.common.collect.Sets;
-import java.util.Collections;
-import java.util.Set;
-
-/**
- * Provides access to the default {@link SourceProvider} implementation and
- * common controls for certain implementations.
- *
- * @author crazybob@google.com (Bob Lee)
- */
-public class SourceProviders {
-
- private SourceProviders() {}
-
- /**
- * Indicates that the source is unknown.
- */
- public static final Object UNKNOWN_SOURCE = "[unknown source]";
-
- static final SourceProvider DEFAULT_INSTANCE = new StacktraceSourceProvider();
-
- static Set<String> skippedClassNames = Collections.emptySet();
-
- static {
- skip(SourceProviders.class);
- skip(StacktraceSourceProvider.class);
- }
-
- /**
- * Instructs stacktrace-based providers to skip the given class in the stack
- * trace when determining the source. Use this to keep the binder from
- * logging utility methods as the sources of bindings (i.e. it will skip to
- * the utility methods' callers instead).
- *
- * <p>Skipping only takes place after this method is called.
- */
- public synchronized static void skip(Class<?> clazz) {
- // Poor man's copy-on-write hash set.
- Set<String> copy = Sets.newHashSet();
- copy.addAll(skippedClassNames);
- copy.add(clazz.getName());
- skippedClassNames = Collections.unmodifiableSet(copy);
- }
-
- /**
- * Gets the set of class names which should be skipped by stacktrace-based
- * providers.
- */
- public synchronized static Set<String> getSkippedClassNames() {
- return skippedClassNames;
- }
-
- static ThreadLocal<SourceProvider[]> localSourceProvider =
- new ThreadLocal<SourceProvider[]>() {
- protected SourceProvider[] initialValue() {
- return new SourceProvider[] { DEFAULT_INSTANCE };
- }
- };
-
- /**
- * Returns the current source obtained from the default provider.
- */
- public static Object defaultSource() {
- return localSourceProvider.get()[0].source();
- }
-
- static class StacktraceSourceProvider implements SourceProvider {
- public Object source() {
- // Search up the stack until we find a class outside of this one.
- Set<String> skippedClassNames = getSkippedClassNames();
- for (final StackTraceElement element : new Throwable().getStackTrace()) {
- String className = element.getClassName();
- if (!skippedClassNames.contains(className)) {
- return element;
- }
- }
- throw new AssertionError();
- }
- }
-}