Binder.withSource() added. I'd still like to start using it within the exceptions, and then cleanup their static configuration of SourceProviders.
git-svn-id: https://google-guice.googlecode.com/svn/trunk@524 d779f126-a31b-0410-b53b-1d3aecad763e
diff --git a/src/com/google/inject/Binder.java b/src/com/google/inject/Binder.java
index 9382b75..579e12a 100644
--- a/src/com/google/inject/Binder.java
+++ b/src/com/google/inject/Binder.java
@@ -289,4 +289,16 @@
*/
void convertToTypes(Matcher<? super TypeLiteral<?>> typeMatcher,
TypeConverter converter);
+
+ /**
+ * Returns a binder that uses {@code source} as the reference location for
+ * errors in its configuration. This is typically a {@link StackTraceElement}
+ * for {@code .java} source but it could any binding source, such as the
+ * path to a {@code .properties} file.
+ *
+ * @param source any object representing the source location and has a
+ * concise {@link Object#toString() toString()} value
+ * @return a binder that shares its configuration with this binder
+ */
+ Binder withSource(Object source);
}
diff --git a/src/com/google/inject/InjectorBuilder.java b/src/com/google/inject/InjectorBuilder.java
index 841c2be..d08e66c 100644
--- a/src/com/google/inject/InjectorBuilder.java
+++ b/src/com/google/inject/InjectorBuilder.java
@@ -215,7 +215,7 @@
}
}
- private static class BuiltInModule extends AbstractModule {
+ private static class BuiltInModule implements Module {
final Injector injector;
final Stage stage;
@@ -224,18 +224,15 @@
this.stage = checkNotNull(stage, "stage");
}
- protected void configure() {
- SourceProviders.withDefault(SourceProviders.UNKNOWN_SOURCE, new Runnable() {
- public void run() {
- bind(Stage.class).toInstance(stage);
- bindScope(Singleton.class, SINGLETON);
- // Create default bindings.
- // We use toProvider() instead of toInstance() to avoid infinite recursion
- // in toString().
- bind(Injector.class).toProvider(new InjectorProvider(injector));
+ public void configure(Binder binder) {
+ binder = binder.withSource(SourceProviders.UNKNOWN_SOURCE);
- }
- });
+ binder.bind(Stage.class).toInstance(stage);
+ binder.bindScope(Singleton.class, SINGLETON);
+ // Create default bindings.
+ // We use toProvider() instead of toInstance() to avoid infinite recursion
+ // in toString().
+ binder.bind(Injector.class).toProvider(new InjectorProvider(injector));
}
class InjectorProvider implements Provider<Injector> {
diff --git a/src/com/google/inject/commands/CommandRecorder.java b/src/com/google/inject/commands/CommandRecorder.java
index c9c17f0..312428e 100644
--- a/src/com/google/inject/commands/CommandRecorder.java
+++ b/src/com/google/inject/commands/CommandRecorder.java
@@ -16,6 +16,7 @@
package com.google.inject.commands;
+import static com.google.common.base.Preconditions.checkNotNull;
import com.google.common.collect.Lists;
import com.google.common.collect.Sets;
import com.google.inject.Binder;
@@ -30,7 +31,6 @@
import com.google.inject.matcher.Matcher;
import com.google.inject.spi.Message;
import com.google.inject.spi.SourceProviders;
-import static com.google.inject.spi.SourceProviders.defaultSource;
import com.google.inject.spi.TypeConverter;
import java.lang.annotation.Annotation;
import java.lang.reflect.Method;
@@ -89,23 +89,36 @@
}
private class RecordingBinder implements Binder {
- private final Set<Module> modules = Sets.newHashSet();
- private final List<Command> commands = Lists.newArrayList();
+ private final Set<Module> modules;
+ private final List<Command> commands;
+
+ private RecordingBinder() {
+ modules = Sets.newHashSet();
+ commands = Lists.newArrayList();
+ }
+
+ /**
+ * Creates a recording binder that's backed by the same configuration as
+ * {@code backingBinder}.
+ */
+ private RecordingBinder(RecordingBinder backingBinder) {
+ modules = backingBinder.modules;
+ commands = backingBinder.commands;
+ }
public void bindInterceptor(
Matcher<? super Class<?>> classMatcher,
Matcher<? super Method> methodMatcher,
MethodInterceptor... interceptors) {
- commands.add(new BindInterceptorCommand(
- defaultSource(), classMatcher, methodMatcher, interceptors));
+ commands.add(new BindInterceptorCommand(getSource(), classMatcher, methodMatcher, interceptors));
}
public void bindScope(Class<? extends Annotation> annotationType, Scope scope) {
- commands.add(new BindScopeCommand(defaultSource(), annotationType, scope));
+ commands.add(new BindScopeCommand(getSource(), annotationType, scope));
}
public void requestStaticInjection(Class<?>... types) {
- commands.add(new RequestStaticInjectionCommand(defaultSource(), types));
+ commands.add(new RequestStaticInjectionCommand(getSource(), types));
}
public void install(Module module) {
@@ -119,11 +132,11 @@
}
public void addError(String message, Object... arguments) {
- commands.add(new AddMessageErrorCommand(defaultSource(), message, arguments));
+ commands.add(new AddMessageErrorCommand(getSource(), message, arguments));
}
public void addError(Throwable t) {
- commands.add(new AddThrowableErrorCommand(defaultSource(), t));
+ commands.add(new AddThrowableErrorCommand(getSource(), t));
}
public void addError(Message message) {
@@ -131,7 +144,7 @@
}
public <T> BindCommand<T>.BindingBuilder bind(Key<T> key) {
- BindCommand<T> bindCommand = new BindCommand<T>(defaultSource(), key);
+ BindCommand<T> bindCommand = new BindCommand<T>(getSource(), key);
commands.add(bindCommand);
return bindCommand.bindingBuilder(RecordingBinder.this);
}
@@ -145,13 +158,13 @@
}
public AnnotatedConstantBindingBuilder bindConstant() {
- BindConstantCommand bindConstantCommand = new BindConstantCommand(defaultSource());
+ BindConstantCommand bindConstantCommand = new BindConstantCommand(getSource());
commands.add(bindConstantCommand);
return bindConstantCommand.bindingBuilder(RecordingBinder.this);
}
public <T> Provider<T> getProvider(final Key<T> key) {
- commands.add(new GetProviderCommand<T>(defaultSource(), key, earlyRequestsProvider));
+ commands.add(new GetProviderCommand<T>(getSource(), key, earlyRequestsProvider));
return new Provider<T>() {
public T get() {
return earlyRequestsProvider.get(key);
@@ -169,7 +182,21 @@
public void convertToTypes(Matcher<? super TypeLiteral<?>> typeMatcher,
TypeConverter converter) {
- commands.add(new ConvertToTypesCommand(defaultSource(), typeMatcher, converter));
+ commands.add(new ConvertToTypesCommand(getSource(), typeMatcher, converter));
+ }
+
+ public Binder withSource(final Object source) {
+ checkNotNull(source, "source");
+
+ return new RecordingBinder(this) {
+ @Override protected Object getSource() {
+ return source;
+ }
+ };
+ }
+
+ protected Object getSource() {
+ return SourceProviders.defaultSource();
}
@Override public String toString() {
diff --git a/src/com/google/inject/commands/CommandReplayer.java b/src/com/google/inject/commands/CommandReplayer.java
index 96f3f7a..b40f793 100644
--- a/src/com/google/inject/commands/CommandReplayer.java
+++ b/src/com/google/inject/commands/CommandReplayer.java
@@ -16,6 +16,7 @@
package com.google.inject.commands;
+import static com.google.common.base.Preconditions.checkNotNull;
import com.google.inject.Binder;
import com.google.inject.Key;
import com.google.inject.Module;
@@ -23,11 +24,8 @@
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 org.aopalliance.intercept.MethodInterceptor;
-
import java.util.List;
+import org.aopalliance.intercept.MethodInterceptor;
/**
* Executes commands against a binder.
@@ -108,95 +106,65 @@
}
public void replayAddMessageError(final Binder binder, final AddMessageErrorCommand command) {
- SourceProviders.withDefault(command.getSource(), new Runnable() {
- public void run() {
- binder.addError(command.getMessage(), command.getArguments().toArray());
- }
- });
+ binder.withSource(command.getSource())
+ .addError(command.getMessage(), command.getArguments().toArray());
}
public void replayAddError(final Binder binder, final AddThrowableErrorCommand command) {
- SourceProviders.withDefault(command.getSource(), new Runnable() {
- public void run() {
- binder.addError(command.getThrowable());
- }
- });
+ binder.withSource(command.getSource()).addError(command.getThrowable());
}
public void replayBindInterceptor(final Binder binder, final BindInterceptorCommand command) {
- SourceProviders.withDefault(command.getSource(), new Runnable() {
- public void run() {
- List<MethodInterceptor> interceptors = command.getInterceptors();
- binder.bindInterceptor(command.getClassMatcher(), command.getMethodMatcher(),
- interceptors.toArray(new MethodInterceptor[interceptors.size()]));
- }
- });
+ List<MethodInterceptor> interceptors = command.getInterceptors();
+ binder.withSource(command.getSource()).bindInterceptor(
+ command.getClassMatcher(), command.getMethodMatcher(),
+ interceptors.toArray(new MethodInterceptor[interceptors.size()]));
}
public void replayBindScope(final Binder binder, final BindScopeCommand command) {
- SourceProviders.withDefault(command.getSource(), new Runnable() {
- public void run() {
- binder.bindScope(command.getAnnotationType(), command.getScope());
- }
- });
+ binder.withSource(command.getSource()).bindScope(
+ command.getAnnotationType(), command.getScope());
}
public void replayRequestStaticInjection(final Binder binder,
final RequestStaticInjectionCommand command) {
- SourceProviders.withDefault(command.getSource(), new Runnable() {
- public void run() {
- List<Class> types = command.getTypes();
- binder.requestStaticInjection(types.toArray(new Class[types.size()]));
- }
- });
+ List<Class> types = command.getTypes();
+ binder.withSource(command.getSource())
+ .requestStaticInjection(types.toArray(new Class[types.size()]));
}
public void replayBindConstant(final Binder binder, final BindConstantCommand command) {
- SourceProviders.withDefault(command.getSource(), new Runnable() {
- public void run() {
- AnnotatedConstantBindingBuilder constantBindingBuilder = binder.bindConstant();
+ AnnotatedConstantBindingBuilder constantBindingBuilder
+ = binder.withSource(command.getSource()).bindConstant();
- Key<Object> key = command.getKey();
- ConstantBindingBuilder builder = key.getAnnotation() != null
- ? constantBindingBuilder.annotatedWith(key.getAnnotation())
- : constantBindingBuilder.annotatedWith(key.getAnnotationType());
+ Key<Object> key = command.getKey();
+ ConstantBindingBuilder builder = key.getAnnotation() != null
+ ? constantBindingBuilder.annotatedWith(key.getAnnotation())
+ : constantBindingBuilder.annotatedWith(key.getAnnotationType());
- command.getTarget().execute(builder);
- }
- });
+ command.getTarget().execute(builder);
}
public void replayConvertToTypes(final Binder binder, final ConvertToTypesCommand command) {
- SourceProviders.withDefault(command.getSource(), new Runnable() {
- public void run() {
- binder.convertToTypes(command.getTypeMatcher(), command.getTypeConverter());
- }
- });
+ binder.withSource(command.getSource())
+ .convertToTypes(command.getTypeMatcher(), command.getTypeConverter());
}
public <T> void replayBind(final Binder binder, final BindCommand<T> command) {
- SourceProviders.withDefault(command.getSource(), new Runnable() {
- public void run() {
- LinkedBindingBuilder<T> lbb = binder.bind(command.getKey());
+ LinkedBindingBuilder<T> lbb = binder.withSource(command.getSource()).bind(command.getKey());
- BindTarget<T> bindTarget = command.getTarget();
- ScopedBindingBuilder sbb = bindTarget != null
- ? bindTarget.execute(lbb)
- : lbb;
+ BindTarget<T> bindTarget = command.getTarget();
+ ScopedBindingBuilder sbb = bindTarget != null
+ ? bindTarget.execute(lbb)
+ : lbb;
- BindScoping scoping = command.getScoping();
- if (scoping != null) {
- scoping.execute(sbb);
- }
- }
- });
+ BindScoping scoping = command.getScoping();
+ if (scoping != null) {
+ scoping.execute(sbb);
+ }
}
public <T> void replayGetProvider(final Binder binder, final GetProviderCommand<T> command) {
- SourceProviders.withDefault(command.getSource(), new Runnable() {
- public void run() {
- binder.getProvider(command.getKey());
- }
- });
+ binder.withSource(command.getSource()).getProvider(command.getKey());
}
}
diff --git a/src/com/google/inject/name/Names.java b/src/com/google/inject/name/Names.java
index f68117e..c3c1a1a 100644
--- a/src/com/google/inject/name/Names.java
+++ b/src/com/google/inject/name/Names.java
@@ -47,19 +47,13 @@
* Creates a constant binding to {@code @Named(key)} for each entry in
* {@code properties}.
*/
- public static void bindProperties(final Binder binder,
- final Map<String, String> properties) {
- SourceProviders.withDefault(
- SourceProviders.defaultSource(),
- new Runnable() {
- public void run() {
- for (Map.Entry<String, String> entry : properties.entrySet()) {
- String key = entry.getKey();
- String value = entry.getValue();
- binder.bind(Key.get(String.class, new NamedImpl(key))).toInstance(value);
- }
- }
- });
+ public static void bindProperties(Binder binder, Map<String, String> properties) {
+ binder = binder.withSource(getSource());
+ for (Map.Entry<String, String> entry : properties.entrySet()) {
+ String key = entry.getKey();
+ String value = entry.getValue();
+ binder.bind(Key.get(String.class, new NamedImpl(key))).toInstance(value);
+ }
}
/**
@@ -67,19 +61,18 @@
* method binds all properties including those inherited from
* {@link Properties#defaults defaults}.
*/
- public static void bindProperties(final Binder binder,
- final Properties properties) {
- SourceProviders.withDefault(
- SourceProviders.defaultSource(),
- new Runnable() {
- public void run() {
- // use enumeration to include the default properties
- for (Enumeration<?> e = properties.propertyNames(); e.hasMoreElements(); ) {
- String propertyName = (String) e.nextElement();
- String value = properties.getProperty(propertyName);
- binder.bind(Key.get(String.class, new NamedImpl(propertyName))).toInstance(value);
- }
- }
- });
+ public static void bindProperties(Binder binder, Properties properties) {
+ binder = binder.withSource(getSource());
+
+ // use enumeration to include the default properties
+ for (Enumeration<?> e = properties.propertyNames(); e.hasMoreElements(); ) {
+ String propertyName = (String) e.nextElement();
+ String value = properties.getProperty(propertyName);
+ 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/SourceProviders.java b/src/com/google/inject/spi/SourceProviders.java
index 1f566c4..e57c8bf 100644
--- a/src/com/google/inject/spi/SourceProviders.java
+++ b/src/com/google/inject/spi/SourceProviders.java
@@ -82,38 +82,6 @@
return localSourceProvider.get()[0].source();
}
- /**
- * Sets the default source provider, runs the given command, and then
- * restores the previous default source provider.
- */
- private static void withDefault(SourceProvider sourceProvider, Runnable r) {
- // We use a holder so we perform only 1 thread local access instead of 3.
- SourceProvider[] holder = localSourceProvider.get();
- SourceProvider previous = holder[0];
- try {
- holder[0] = sourceProvider;
- r.run();
- } finally {
- holder[0] = previous;
- }
- }
-
- /**
- * Sets the default source, runs the given command, and then
- * restores the previous default source provider.
- */
- public static void withDefault(final Object source, Runnable r) {
- withDefault(sourceProviderFor(source), r);
- }
-
- private static SourceProvider sourceProviderFor(final Object source) {
- return new SourceProvider() {
- public Object source() {
- return source;
- }
- };
- }
-
static class StacktraceSourceProvider implements SourceProvider {
public Object source() {
// Search up the stack until we find a class outside of this one.