Big change - changing BinderImpl to use commands/
git-svn-id: https://google-guice.googlecode.com/svn/trunk@420 d779f126-a31b-0410-b53b-1d3aecad763e
diff --git a/extensions/commands/src/com/google/inject/commands/AddMessageErrorCommand.java b/extensions/commands/src/com/google/inject/commands/AddMessageErrorCommand.java
index d6f0077..2e336cd 100644
--- a/extensions/commands/src/com/google/inject/commands/AddMessageErrorCommand.java
+++ b/extensions/commands/src/com/google/inject/commands/AddMessageErrorCommand.java
@@ -16,6 +16,8 @@
package com.google.inject.commands;
+import static com.google.inject.internal.Objects.nonNull;
+
import java.util.Arrays;
import static java.util.Collections.unmodifiableList;
import java.util.List;
@@ -26,14 +28,20 @@
* @author jessewilson@google.com (Jesse Wilson)
*/
public final class AddMessageErrorCommand implements Command {
+ private final Object source;
private final String message;
private final List<Object> arguments;
- AddMessageErrorCommand(String message, Object[] arguments) {
- this.message = message;
+ AddMessageErrorCommand(Object source, String message, Object[] arguments) {
+ this.source = nonNull(source, "source");
+ this.message = nonNull(message, "message");
this.arguments = unmodifiableList(Arrays.asList(arguments.clone()));
}
+ public Object getSource() {
+ return source;
+ }
+
public <T> T acceptVisitor(Visitor<T> visitor) {
return visitor.visitAddMessageError(this);
}
diff --git a/extensions/commands/src/com/google/inject/commands/AddThrowableErrorCommand.java b/extensions/commands/src/com/google/inject/commands/AddThrowableErrorCommand.java
index 38be96e..fb28038 100644
--- a/extensions/commands/src/com/google/inject/commands/AddThrowableErrorCommand.java
+++ b/extensions/commands/src/com/google/inject/commands/AddThrowableErrorCommand.java
@@ -16,16 +16,24 @@
package com.google.inject.commands;
+import static com.google.inject.internal.Objects.nonNull;
+
/**
* Immutable snapshot of a request to add a throwable message.
*
* @author jessewilson@google.com (Jesse Wilson)
*/
public final class AddThrowableErrorCommand implements Command {
+ private final Object source;
private final Throwable throwable;
- AddThrowableErrorCommand(Throwable throwable) {
- this.throwable = throwable;
+ AddThrowableErrorCommand(Object source, Throwable throwable) {
+ this.source = nonNull(source, "source");
+ this.throwable = nonNull(throwable, "throwable");
+ }
+
+ public Object getSource() {
+ return source;
}
public <T> T acceptVisitor(Visitor<T> visitor) {
diff --git a/extensions/commands/src/com/google/inject/commands/BindCommand.java b/extensions/commands/src/com/google/inject/commands/BindCommand.java
index c8ef971..b666ed4 100644
--- a/extensions/commands/src/com/google/inject/commands/BindCommand.java
+++ b/extensions/commands/src/com/google/inject/commands/BindCommand.java
@@ -16,10 +16,8 @@
package com.google.inject.commands;
-import com.google.inject.Key;
-import com.google.inject.Provider;
-import com.google.inject.Scope;
-import com.google.inject.TypeLiteral;
+import com.google.inject.*;
+import com.google.inject.spi.SourceProviders;
import com.google.inject.binder.AnnotatedBindingBuilder;
import com.google.inject.binder.ConstantBindingBuilder;
import com.google.inject.binder.LinkedBindingBuilder;
@@ -34,14 +32,44 @@
* @author jessewilson@google.com (Jesse Wilson)
*/
public final class BindCommand<T> implements Command {
- private Key<T> key;
- private BindTarget<T> bindTarget;
- private BindScoping bindScoping;
- BindCommand(Key<T> key) {
+ static {
+ SourceProviders.skip(BindCommand.BindingBuilder.class);
+ }
+
+ private static final BindTarget<Object> EMPTY_BIND_TARGET = new AbstractTarget<Object>() {
+ public ScopedBindingBuilder execute(LinkedBindingBuilder<Object> linkedBindingBuilder) {
+ return linkedBindingBuilder;
+ }
+ public <V> V acceptVisitor(Visitor<Object, V> visitor) {
+ return visitor.visitUntargetted();
+ }
+ };
+
+ private static final BindScoping EMPTY_SCOPING = new AbstractScoping() {
+ public void execute(ScopedBindingBuilder scopedBindingBuilder) {
+ // do nothing
+ }
+ public <V> V acceptVisitor(Visitor<V> visitor) {
+ return visitor.visitNoScoping();
+ }
+ };
+
+ private final Object source;
+ private Key<T> key;
+ @SuppressWarnings({"unchecked"})
+ private BindTarget<T> bindTarget = (BindTarget<T>) EMPTY_BIND_TARGET;
+ private BindScoping bindScoping = EMPTY_SCOPING;
+
+ BindCommand(Object source, Key<T> key) {
+ this.source = nonNull(source, "source");
this.key = nonNull(key, "key");
}
+ public Object getSource() {
+ return source;
+ }
+
public <V> V acceptVisitor(Visitor<V> visitor) {
return visitor.visitBind(this);
}
@@ -60,26 +88,25 @@
@Override public String toString() {
return "bind " + key
- + (bindTarget == null ? "" : (" to " + bindTarget))
- + (bindScoping == null ? "" : (" in " + bindScoping));
+ + (bindTarget == EMPTY_BIND_TARGET ? "" : (" to " + bindTarget))
+ + (bindScoping == EMPTY_SCOPING ? "" : (" in " + bindScoping));
}
private static abstract class AbstractTarget<T> implements BindTarget<T> {
public void execute(ConstantBindingBuilder builder) {
throw new UnsupportedOperationException();
}
- public T get(T defaultValue) {
- return defaultValue;
+ public T get() {
+ return null;
}
- public Key<? extends Provider<? extends T>> getProviderKey(
- Key<Provider<? extends T>> defaultValue) {
- return defaultValue;
+ public Key<? extends Provider<? extends T>> getProviderKey() {
+ return null;
}
- public Provider<? extends T> getProvider(Provider<? extends T> defaultValue) {
- return defaultValue;
+ public Provider<? extends T> getProvider() {
+ return null;
}
- public Key<? extends T> getKey(Key<? extends T> defaultValue) {
- return defaultValue;
+ public Key<? extends T> getKey() {
+ return null;
}
}
@@ -87,25 +114,31 @@
public boolean isEagerSingleton() {
return false;
}
- public Scope getScope(Scope defaultValue) {
- return defaultValue;
+ public Scope getScope() {
+ return null;
}
- public Class<? extends Annotation> getScopeAnnotation(
- Class<? extends Annotation> defaultValue) {
- return defaultValue;
+ public Class<? extends Annotation> getScopeAnnotation() {
+ return null;
}
}
- BindingBuilder bindingBuilder() {
- return new BindingBuilder();
+ BindingBuilder bindingBuilder(Binder binder) {
+ return new BindingBuilder(binder);
}
/**
* Package-private write access to the internal state of this command.
*/
class BindingBuilder implements AnnotatedBindingBuilder<T> {
+ private final Binder binder;
+
+ BindingBuilder(Binder binder) {
+ this.binder = binder;
+ }
+
public LinkedBindingBuilder<T> annotatedWith(
Class<? extends Annotation> annotationType) {
+ nonNull(annotationType, "annotationType");
assertNotAnnotated();
key = Key.get(key.getTypeLiteral(), annotationType);
return this;
@@ -134,9 +167,12 @@
public ScopedBindingBuilder execute(LinkedBindingBuilder<T> linkedBindingBuilder) {
return linkedBindingBuilder.to(targetKey);
}
- @Override public Key<? extends T> getKey(Key<? extends T> defaultValue) {
+ @Override public Key<? extends T> getKey() {
return targetKey;
}
+ public <V> V acceptVisitor(Visitor<T, V> visitor) {
+ return visitor.visitToKey(targetKey);
+ }
@Override public String toString() {
return String.valueOf(targetKey);
}
@@ -145,16 +181,23 @@
}
public void toInstance(final T instance) {
- nonNull(instance, "instance"); // might someday want to tolerate null here
+ // might someday want to tolerate null here, probably by setting up a
+ // Provider<null> rather than trying to distinguish between null and
+ // not set
+ nonNull(instance, "instance");
+
assertNoTarget();
bindTarget = new AbstractTarget<T>() {
public ScopedBindingBuilder execute(LinkedBindingBuilder<T> linkedBindingBuilder) {
linkedBindingBuilder.toInstance(instance);
return null;
}
- @Override public T get(T defaultValue) {
+ @Override public T get() {
return instance;
}
+ public <V> V acceptVisitor(Visitor<T, V> visitor) {
+ return visitor.visitToInstance(instance);
+ }
@Override public String toString() {
return "instance " + instance;
}
@@ -168,9 +211,12 @@
public ScopedBindingBuilder execute(LinkedBindingBuilder<T> linkedBindingBuilder) {
return linkedBindingBuilder.toProvider(provider);
}
- @Override public Provider<? extends T> getProvider(Provider<? extends T> defaultValue) {
+ @Override public Provider<? extends T> getProvider() {
return provider;
}
+ public <V> V acceptVisitor(Visitor<T, V> visitor) {
+ return visitor.visitToProvider(provider);
+ }
@Override public String toString() {
return "provider " + provider;
}
@@ -191,10 +237,12 @@
public ScopedBindingBuilder execute(LinkedBindingBuilder<T> linkedBindingBuilder) {
return linkedBindingBuilder.toProvider(providerKey);
}
- @Override public Key<? extends Provider<? extends T>> getProviderKey(
- Key<Provider<? extends T>> defaultValue) {
+ @Override public Key<? extends Provider<? extends T>> getProviderKey() {
return providerKey;
}
+ public <V> V acceptVisitor(Visitor<T, V> visitor) {
+ return visitor.visitToProviderKey(providerKey);
+ }
@Override public String toString() {
return "provider " + providerKey;
}
@@ -210,10 +258,12 @@
public void execute(ScopedBindingBuilder scopedBindingBuilder) {
scopedBindingBuilder.in(scopeAnnotation);
}
- @Override public Class<? extends Annotation> getScopeAnnotation(
- Class<? extends Annotation> defaultValue) {
+ @Override public Class<? extends Annotation> getScopeAnnotation() {
return scopeAnnotation;
}
+ public <V> V acceptVisitor(Visitor<V> visitor) {
+ return visitor.visitScopeAnnotation(scopeAnnotation);
+ }
@Override public String toString() {
return scopeAnnotation.getName();
}
@@ -224,12 +274,16 @@
nonNull(scope, "scope");
assertNoScope();
bindScoping = new AbstractScoping() {
+
public void execute(ScopedBindingBuilder scopedBindingBuilder) {
scopedBindingBuilder.in(scope);
}
- @Override public Scope getScope(Scope defaultValue) {
+ @Override public Scope getScope() {
return scope;
}
+ public <V> V acceptVisitor(Visitor<V> visitor) {
+ return visitor.visitScope(scope);
+ }
@Override public String toString() {
return String.valueOf(scope);
}
@@ -245,27 +299,44 @@
@Override public boolean isEagerSingleton() {
return true;
}
+ public <V> V acceptVisitor(Visitor<V> visitor) {
+ return visitor.visitEagerSingleton();
+ }
@Override public String toString() {
return "eager singleton";
}
};
}
+ static final String IMPLEMENTATION_ALREADY_SET
+ = "Implementation is set more than once.";
+ static final String SINGLE_INSTANCE_AND_SCOPE = "Setting the scope is not"
+ + " permitted when binding to a single instance.";
+ static final String SCOPE_ALREADY_SET = "Scope is set more than once.";
+ static final String ANNOTATION_ALREADY_SPECIFIED = "More than one annotation"
+ + " is specified for this binding.";
+
private void assertNoTarget() {
- if (bindTarget != null) {
- throw new IllegalStateException("Already targetted to " + bindTarget);
+ if (bindTarget != EMPTY_BIND_TARGET) {
+ binder.addError(IMPLEMENTATION_ALREADY_SET);
}
}
private void assertNotAnnotated() {
if (BindCommand.this.key.getAnnotationType() != null) {
- throw new IllegalStateException("Already annotated with " + key.getAnnotationType());
+ binder.addError(ANNOTATION_ALREADY_SPECIFIED);
}
}
private void assertNoScope() {
- if (bindScoping != null) {
- throw new IllegalStateException("Already scoped by " + bindScoping);
+ // Scoping isn't allowed when we have only one instance.
+ if (bindTarget.get() != null) {
+ binder.addError(SINGLE_INSTANCE_AND_SCOPE);
+ return;
+ }
+
+ if (bindScoping != EMPTY_SCOPING) {
+ binder.addError(SCOPE_ALREADY_SET);
}
}
}
diff --git a/extensions/commands/src/com/google/inject/commands/BindConstantCommand.java b/extensions/commands/src/com/google/inject/commands/BindConstantCommand.java
index 142bb19..af131ec 100644
--- a/extensions/commands/src/com/google/inject/commands/BindConstantCommand.java
+++ b/extensions/commands/src/com/google/inject/commands/BindConstantCommand.java
@@ -18,11 +18,14 @@
import com.google.inject.Key;
import com.google.inject.Provider;
+import com.google.inject.Binder;
+import com.google.inject.spi.SourceProviders;
import com.google.inject.binder.AnnotatedConstantBindingBuilder;
import com.google.inject.binder.ConstantBindingBuilder;
import com.google.inject.binder.LinkedBindingBuilder;
import com.google.inject.binder.ScopedBindingBuilder;
import com.google.inject.internal.Objects;
+import static com.google.inject.internal.Objects.nonNull;
import java.lang.annotation.Annotation;
@@ -32,11 +35,20 @@
* @author jessewilson@google.com (Jesse Wilson)
*/
public final class BindConstantCommand implements Command {
+ static {
+ SourceProviders.skip(BindingBuilder.class);
+ }
+
+ private final Object source;
private BindingAnnotation bindingAnnotation;
private ConstantTarget<?> target;
- BindConstantCommand() {
- // hide public constructor
+ BindConstantCommand(Object source) {
+ this.source = nonNull(source, "source");
+ }
+
+ public Object getSource() {
+ return source;
}
public <T> T acceptVisitor(Visitor<T> visitor) {
@@ -68,15 +80,17 @@
public ScopedBindingBuilder execute(LinkedBindingBuilder linkedBindingBuilder) {
throw new UnsupportedOperationException();
}
- public Provider<? extends T> getProvider(Provider<? extends T> defaultValue) {
- return defaultValue;
+ public <V> V acceptVisitor(Visitor<T, V> visitor) {
+ return visitor.visitToInstance(get());
}
- public Key<? extends Provider<? extends T>> getProviderKey(
- Key<Provider<? extends T>> defaultValue) {
- return defaultValue;
+ public Provider<? extends T> getProvider() {
+ return null;
}
- public Key<? extends T> getKey(Key<? extends T> defaultValue) {
- return defaultValue;
+ public Key<? extends Provider<? extends T>> getProviderKey() {
+ return null;
+ }
+ public Key<? extends T> getKey() {
+ return null;
}
}
@@ -88,8 +102,8 @@
abstract <T> Key<T> getKey();
}
- BindingBuilder bindingBuilder() {
- return new BindingBuilder();
+ BindingBuilder bindingBuilder(Binder binder) {
+ return new BindingBuilder(binder);
}
/**
@@ -97,20 +111,14 @@
*/
class BindingBuilder
implements AnnotatedConstantBindingBuilder, ConstantBindingBuilder {
+ private final Binder binder;
- private void assertNoBindingAnnotation() {
- if (bindingAnnotation != null) {
- throw new IllegalStateException("Already annotated with " + bindingAnnotation);
- }
- }
-
- private void assertNoTarget() {
- if (target != null) {
- throw new IllegalStateException("Already targetted to " + target);
- }
+ BindingBuilder(Binder binder) {
+ this.binder = binder;
}
public ConstantBindingBuilder annotatedWith(final Class<? extends Annotation> annotationType) {
+ nonNull(annotationType, "annotationType");
assertNoBindingAnnotation();
bindingAnnotation = new BindingAnnotation() {
@@ -126,6 +134,7 @@
}
public ConstantBindingBuilder annotatedWith(final Annotation annotation) {
+ nonNull(annotation, "annotation");
assertNoBindingAnnotation();
bindingAnnotation = new BindingAnnotation() {
@@ -141,13 +150,14 @@
}
public void to(final String value) {
+ nonNull(value, "value");
assertNoTarget();
BindConstantCommand.this.target = new ConstantTarget() {
public void execute(ConstantBindingBuilder builder) {
builder.to(value);
}
- public Object get(Object defaultValue) {
+ public Object get() {
return value;
}
public Class getType() {
@@ -166,11 +176,11 @@
public void execute(ConstantBindingBuilder builder) {
builder.to(value);
}
- public Object get(Object defaultValue) {
+ public Object get() {
return value;
}
public Class getType() {
- return Integer.class;
+ return int.class;
}
@Override public String toString() {
return String.valueOf(value);
@@ -185,11 +195,11 @@
public void execute(ConstantBindingBuilder builder) {
builder.to(value);
}
- public Object get(Object defaultValue) {
+ public Object get() {
return value;
}
public Class getType() {
- return Long.class;
+ return long.class;
}
@Override public String toString() {
return String.valueOf(value);
@@ -204,11 +214,11 @@
public void execute(ConstantBindingBuilder builder) {
builder.to(value);
}
- public Object get(Object defaultValue) {
+ public Object get() {
return value;
}
public Class getType() {
- return Boolean.class;
+ return boolean.class;
}
@Override public String toString() {
return String.valueOf(value);
@@ -223,11 +233,11 @@
public void execute(ConstantBindingBuilder builder) {
builder.to(value);
}
- public Object get(Object defaultValue) {
+ public Object get() {
return value;
}
public Class getType() {
- return Double.class;
+ return double.class;
}
@Override public String toString() {
return String.valueOf(value);
@@ -242,11 +252,11 @@
public void execute(ConstantBindingBuilder builder) {
builder.to(value);
}
- public Object get(Object defaultValue) {
+ public Object get() {
return value;
}
public Class getType() {
- return Float.class;
+ return float.class;
}
@Override public String toString() {
return String.valueOf(value);
@@ -261,11 +271,11 @@
public void execute(ConstantBindingBuilder builder) {
builder.to(value);
}
- public Object get(Object defaultValue) {
+ public Object get() {
return value;
}
public Class getType() {
- return Short.class;
+ return short.class;
}
@Override public String toString() {
return String.valueOf(value);
@@ -280,11 +290,11 @@
public void execute(ConstantBindingBuilder builder) {
builder.to(value);
}
- public Object get(Object defaultValue) {
+ public Object get() {
return value;
}
public Class getType() {
- return Character.class;
+ return char.class;
}
@Override public String toString() {
return String.valueOf(value);
@@ -293,13 +303,14 @@
}
public void to(final Class<?> value) {
+ nonNull(value, "value");
assertNoTarget();
BindConstantCommand.this.target = new ConstantTarget() {
public void execute(ConstantBindingBuilder builder) {
builder.to(value);
}
- public Object get(Object defaultValue) {
+ public Object get() {
return value;
}
public Class getType() {
@@ -319,7 +330,7 @@
public void execute(ConstantBindingBuilder builder) {
builder.to(value);
}
- public Object get(Object defaultValue) {
+ public Object get() {
return value;
}
public Class getType() {
@@ -330,5 +341,22 @@
}
};
}
+
+ static final String CONSTANT_VALUE_ALREADY_SET = "Constant value is set more"
+ + " than once.";
+ static final String ANNOTATION_ALREADY_SPECIFIED = "More than one annotation"
+ + " is specified for this binding.";
+
+ private void assertNoBindingAnnotation() {
+ if (bindingAnnotation != null) {
+ binder.addError(ANNOTATION_ALREADY_SPECIFIED);
+ }
+ }
+
+ private void assertNoTarget() {
+ if (target != null) {
+ binder.addError(CONSTANT_VALUE_ALREADY_SET);
+ }
+ }
}
}
diff --git a/extensions/commands/src/com/google/inject/commands/BindInterceptorCommand.java b/extensions/commands/src/com/google/inject/commands/BindInterceptorCommand.java
index ad12345..7485346 100644
--- a/extensions/commands/src/com/google/inject/commands/BindInterceptorCommand.java
+++ b/extensions/commands/src/com/google/inject/commands/BindInterceptorCommand.java
@@ -17,6 +17,7 @@
package com.google.inject.commands;
import com.google.inject.matcher.Matcher;
+import static com.google.inject.internal.Objects.nonNull;
import org.aopalliance.intercept.MethodInterceptor;
import java.lang.reflect.Method;
@@ -30,19 +31,26 @@
* @author jessewilson@google.com (Jesse Wilson)
*/
public final class BindInterceptorCommand implements Command {
+ private final Object source;
private final Matcher<? super Class<?>> classMatcher;
private final Matcher<? super Method> methodMatcher;
private final List<MethodInterceptor> interceptors;
BindInterceptorCommand(
+ Object source,
Matcher<? super Class<?>> classMatcher,
Matcher<? super Method> methodMatcher,
MethodInterceptor[] interceptors) {
- this.classMatcher = classMatcher;
- this.methodMatcher = methodMatcher;
+ this.source = nonNull(source, "source");
+ this.classMatcher = nonNull(classMatcher, "classMatcher");
+ this.methodMatcher = nonNull(methodMatcher, "methodMatcher");
this.interceptors = unmodifiableList(Arrays.asList(interceptors.clone()));
}
+ public Object getSource() {
+ return source;
+ }
+
public Matcher<? super Class<?>> getClassMatcher() {
return classMatcher;
}
diff --git a/extensions/commands/src/com/google/inject/commands/BindScopeCommand.java b/extensions/commands/src/com/google/inject/commands/BindScopeCommand.java
index 639f2c5..1c0e9f8 100644
--- a/extensions/commands/src/com/google/inject/commands/BindScopeCommand.java
+++ b/extensions/commands/src/com/google/inject/commands/BindScopeCommand.java
@@ -17,6 +17,7 @@
package com.google.inject.commands;
import com.google.inject.Scope;
+import static com.google.inject.internal.Objects.nonNull;
import java.lang.annotation.Annotation;
@@ -26,13 +27,18 @@
* @author jessewilson@google.com (Jesse Wilson)
*/
public final class BindScopeCommand implements Command {
+ private final Object source;
private final Class<? extends Annotation> annotationType;
private final Scope scope;
- BindScopeCommand(
- Class<? extends Annotation> annotationType, Scope scope) {
- this.annotationType = annotationType;
- this.scope = scope;
+ BindScopeCommand(Object source, Class<? extends Annotation> annotationType, Scope scope) {
+ this.source = nonNull(source, "source");
+ this.annotationType = nonNull(annotationType, "annotationType");
+ this.scope = nonNull(scope, "scope");
+ }
+
+ public Object getSource() {
+ return source;
}
public Class<? extends Annotation> getAnnotationType() {
diff --git a/extensions/commands/src/com/google/inject/commands/BindScoping.java b/extensions/commands/src/com/google/inject/commands/BindScoping.java
index 52e162d..1eb2a83 100644
--- a/extensions/commands/src/com/google/inject/commands/BindScoping.java
+++ b/extensions/commands/src/com/google/inject/commands/BindScoping.java
@@ -30,6 +30,14 @@
public interface BindScoping {
void execute(ScopedBindingBuilder scopedBindingBuilder);
boolean isEagerSingleton();
- Scope getScope(Scope defaultValue);
- Class<? extends Annotation> getScopeAnnotation(Class<? extends Annotation> defaultValue);
+ Scope getScope();
+ Class<? extends Annotation> getScopeAnnotation();
+ <V> V acceptVisitor(Visitor<V> visitor);
+
+ interface Visitor<V> {
+ V visitEagerSingleton();
+ V visitScope(Scope scope);
+ V visitScopeAnnotation(Class<? extends Annotation> scopeAnnotation);
+ V visitNoScoping();
+ }
}
diff --git a/extensions/commands/src/com/google/inject/commands/BindTarget.java b/extensions/commands/src/com/google/inject/commands/BindTarget.java
index 99bf418..e76569d 100644
--- a/extensions/commands/src/com/google/inject/commands/BindTarget.java
+++ b/extensions/commands/src/com/google/inject/commands/BindTarget.java
@@ -41,14 +41,23 @@
void execute(ConstantBindingBuilder builder);
/**
- * Returns the bound instance, if it exists, or {@code defaultValue}
- * if no bound value exists.
+ * Returns the bound instance, if it exists, or {@code null} if no bound value exists.
*/
- T get(T defaultValue);
+ T get();
- Provider<? extends T> getProvider(Provider<? extends T> defaultValue);
+ Provider<? extends T> getProvider();
- Key<? extends Provider<? extends T>> getProviderKey(Key<Provider<? extends T>> defaultValue);
+ Key<? extends Provider<? extends T>> getProviderKey();
- Key<? extends T> getKey(Key<? extends T> defaultValue);
+ Key<? extends T> getKey();
+
+ <V> V acceptVisitor(Visitor<T, V> visitor);
+
+ interface Visitor<T, V> {
+ V visitToInstance(T instance);
+ V visitToProvider(Provider<? extends T> provider);
+ V visitToProviderKey(Key<? extends Provider<? extends T>> providerKey);
+ V visitToKey(Key<? extends T> key);
+ V visitUntargetted();
+ }
}
diff --git a/extensions/commands/src/com/google/inject/commands/Command.java b/extensions/commands/src/com/google/inject/commands/Command.java
index 15c1729..862a77f 100644
--- a/extensions/commands/src/com/google/inject/commands/Command.java
+++ b/extensions/commands/src/com/google/inject/commands/Command.java
@@ -22,6 +22,7 @@
* @author jessewilson@google.com (Jesse Wilson)
*/
public interface Command {
+ Object getSource();
<T> T acceptVisitor(Visitor<T> visitor);
/**
diff --git a/extensions/commands/src/com/google/inject/commands/CommandRecorder.java b/extensions/commands/src/com/google/inject/commands/CommandRecorder.java
index 9c3ed9b..e6ce8f2 100644
--- a/extensions/commands/src/com/google/inject/commands/CommandRecorder.java
+++ b/extensions/commands/src/com/google/inject/commands/CommandRecorder.java
@@ -20,15 +20,14 @@
import com.google.inject.binder.AnnotatedBindingBuilder;
import com.google.inject.binder.AnnotatedConstantBindingBuilder;
import com.google.inject.matcher.Matcher;
+import static com.google.inject.spi.SourceProviders.defaultSource;
import com.google.inject.spi.TypeConverter;
+import com.google.inject.spi.SourceProviders;
import org.aopalliance.intercept.MethodInterceptor;
import java.lang.annotation.Annotation;
import java.lang.reflect.Method;
-import java.util.ArrayList;
-import java.util.Arrays;
-import java.util.Collections;
-import java.util.List;
+import java.util.*;
/**
* Records commands executed by a module so they can be inspected or
@@ -37,9 +36,13 @@
* @author jessewilson@google.com (Jesse Wilson)
*/
public final class CommandRecorder {
- private final Stage stage = Stage.DEVELOPMENT;
+ 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
@@ -50,6 +53,13 @@
}
/**
+ * Sets the stage reported by the binder.
+ */
+ public void setCurrentStage(Stage currentStage) {
+ this.currentStage = currentStage;
+ }
+
+ /**
* Records the commands executed by {@code modules}.
*/
public List<Command> recordCommands(Module... modules) {
@@ -62,49 +72,53 @@
public List<Command> recordCommands(Iterable<Module> modules) {
RecordingBinder binder = new RecordingBinder();
for (Module module : modules) {
- module.configure(binder);
+ binder.install(module);
}
return Collections.unmodifiableList(binder.commands);
}
private class RecordingBinder implements Binder {
+ private final Set<Module> modules = new HashSet<Module>();
private final List<Command> commands = new ArrayList<Command>();
public void bindInterceptor(
Matcher<? super Class<?>> classMatcher,
Matcher<? super Method> methodMatcher,
MethodInterceptor... interceptors) {
- commands.add(new BindInterceptorCommand(classMatcher, methodMatcher, interceptors));
+ commands.add(new BindInterceptorCommand(
+ defaultSource(), classMatcher, methodMatcher, interceptors));
}
public void bindScope(Class<? extends Annotation> annotationType, Scope scope) {
- commands.add(new BindScopeCommand(annotationType, scope));
+ commands.add(new BindScopeCommand(defaultSource(), annotationType, scope));
}
public void requestStaticInjection(Class<?>... types) {
- commands.add(new RequestStaticInjectionCommand(types));
+ commands.add(new RequestStaticInjectionCommand(defaultSource(), types));
}
public void install(Module module) {
- module.configure(this);
+ if (modules.add(module)) {
+ module.configure(this);
+ }
}
public Stage currentStage() {
- return stage;
+ return currentStage;
}
public void addError(String message, Object... arguments) {
- commands.add(new AddMessageErrorCommand(message, arguments));
+ commands.add(new AddMessageErrorCommand(defaultSource(), message, arguments));
}
public void addError(Throwable t) {
- commands.add(new AddThrowableErrorCommand(t));
+ commands.add(new AddThrowableErrorCommand(defaultSource(), t));
}
public <T> BindCommand<T>.BindingBuilder bind(Key<T> key) {
- BindCommand<T> bindCommand = new BindCommand<T>(key);
+ BindCommand<T> bindCommand = new BindCommand<T>(defaultSource(), key);
commands.add(bindCommand);
- return bindCommand.bindingBuilder();
+ return bindCommand.bindingBuilder(RecordingBinder.this);
}
public <T> AnnotatedBindingBuilder<T> bind(TypeLiteral<T> typeLiteral) {
@@ -116,13 +130,13 @@
}
public AnnotatedConstantBindingBuilder bindConstant() {
- BindConstantCommand bindConstantCommand = new BindConstantCommand();
+ BindConstantCommand bindConstantCommand = new BindConstantCommand(defaultSource());
commands.add(bindConstantCommand);
- return bindConstantCommand.bindingBuilder();
+ return bindConstantCommand.bindingBuilder(RecordingBinder.this);
}
public <T> Provider<T> getProvider(final Key<T> key) {
- commands.add(new GetProviderCommand<T>(key, earlyRequestsProvider));
+ commands.add(new GetProviderCommand<T>(defaultSource(), key, earlyRequestsProvider));
return new Provider<T>() {
public T get() {
return earlyRequestsProvider.get(key);
@@ -135,8 +149,8 @@
}
public void convertToTypes(Matcher<? super TypeLiteral<?>> typeMatcher,
- TypeConverter converter) {
- commands.add(new ConvertToTypesCommand(typeMatcher, converter));
+ TypeConverter converter) {
+ commands.add(new ConvertToTypesCommand(defaultSource(), typeMatcher, converter));
}
}
}
diff --git a/extensions/commands/src/com/google/inject/commands/CommandReplayer.java b/extensions/commands/src/com/google/inject/commands/CommandReplayer.java
index 4b06890..d4326fb 100644
--- a/extensions/commands/src/com/google/inject/commands/CommandReplayer.java
+++ b/extensions/commands/src/com/google/inject/commands/CommandReplayer.java
@@ -19,6 +19,7 @@
import com.google.inject.Binder;
import com.google.inject.Key;
import com.google.inject.Module;
+import com.google.inject.spi.SourceProviders;
import com.google.inject.binder.AnnotatedConstantBindingBuilder;
import com.google.inject.binder.ConstantBindingBuilder;
import com.google.inject.binder.LinkedBindingBuilder;
@@ -106,59 +107,96 @@
}
}
- public void replayAddMessageError(Binder binder, AddMessageErrorCommand command) {
- binder.addError(command.getMessage(), command.getArguments().toArray());
+ 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());
+ }
+ });
}
- public void replayAddError(Binder binder, AddThrowableErrorCommand command) {
- binder.addError(command.getThrowable());
+ public void replayAddError(final Binder binder, final AddThrowableErrorCommand command) {
+ SourceProviders.withDefault(command.getSource(), new Runnable() {
+ public void run() {
+ binder.addError(command.getThrowable());
+ }
+ });
}
- public void replayBindInterceptor(Binder binder, BindInterceptorCommand command) {
- List<MethodInterceptor> interceptors = command.getInterceptors();
- binder.bindInterceptor(command.getClassMatcher(), command.getMethodMatcher(),
- interceptors.toArray(new MethodInterceptor[interceptors.size()]));
+ 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()]));
+ }
+ });
}
- public void replayBindScope(Binder binder, BindScopeCommand command) {
- binder.bindScope(command.getAnnotationType(), command.getScope());
+ public void replayBindScope(final Binder binder, final BindScopeCommand command) {
+ SourceProviders.withDefault(command.getSource(), new Runnable() {
+ public void run() {
+ binder.bindScope(command.getAnnotationType(), command.getScope());
+ }
+ });
}
- public void replayRequestStaticInjection(Binder binder, RequestStaticInjectionCommand command) {
- List<Class> types = command.getTypes();
- binder.requestStaticInjection(types.toArray(new Class[types.size()]));
+ 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()]));
+ }
+ });
}
- public void replayBindConstant(Binder binder, BindConstantCommand command) {
- AnnotatedConstantBindingBuilder constantBindingBuilder = binder.bindConstant();
+ public void replayBindConstant(final Binder binder, final BindConstantCommand command) {
+ SourceProviders.withDefault(command.getSource(), new Runnable() {
+ public void run() {
+ AnnotatedConstantBindingBuilder constantBindingBuilder = binder.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(Binder binder, ConvertToTypesCommand command) {
- binder.convertToTypes(command.getTypeMatcher(), command.getTypeConverter());
+ public void replayConvertToTypes(final Binder binder, final ConvertToTypesCommand command) {
+ SourceProviders.withDefault(command.getSource(), new Runnable() {
+ public void run() {
+ binder.convertToTypes(command.getTypeMatcher(), command.getTypeConverter());
+ }
+ });
}
- public <T> void replayBind(Binder binder, BindCommand<T> command) {
- LinkedBindingBuilder<T> lbb = binder.bind(command.getKey());
+ 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());
- 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(Binder binder, GetProviderCommand<T> command) {
- binder.getProvider(command.getKey());
+ public <T> void replayGetProvider(final Binder binder, final GetProviderCommand<T> command) {
+ SourceProviders.withDefault(command.getSource(), new Runnable() {
+ public void run() {
+ binder.getProvider(command.getKey());
+ }
+ });
}
}
diff --git a/extensions/commands/src/com/google/inject/commands/ConvertToTypesCommand.java b/extensions/commands/src/com/google/inject/commands/ConvertToTypesCommand.java
index a02536e..ba7a6e8 100644
--- a/extensions/commands/src/com/google/inject/commands/ConvertToTypesCommand.java
+++ b/extensions/commands/src/com/google/inject/commands/ConvertToTypesCommand.java
@@ -17,6 +17,7 @@
package com.google.inject.commands;
import com.google.inject.TypeLiteral;
+import static com.google.inject.internal.Objects.nonNull;
import com.google.inject.matcher.Matcher;
import com.google.inject.spi.TypeConverter;
@@ -27,13 +28,19 @@
* @author jessewilson@google.com (Jesse Wilson)
*/
public final class ConvertToTypesCommand implements Command {
+ private final Object source;
private final Matcher<? super TypeLiteral<?>> typeMatcher;
private final TypeConverter typeConverter;
- ConvertToTypesCommand(Matcher<? super TypeLiteral<?>> typeMatcher,
+ ConvertToTypesCommand(Object source, Matcher<? super TypeLiteral<?>> typeMatcher,
TypeConverter typeConverter) {
- this.typeMatcher = typeMatcher;
- this.typeConverter = typeConverter;
+ this.source = nonNull(source, "source");
+ this.typeMatcher = nonNull(typeMatcher, "typeMatcher");
+ this.typeConverter = nonNull(typeConverter, "typeConverter");
+ }
+
+ public Object getSource() {
+ return source;
}
public Matcher<? super TypeLiteral<?>> getTypeMatcher() {
diff --git a/extensions/commands/src/com/google/inject/commands/FutureInjector.java b/extensions/commands/src/com/google/inject/commands/FutureInjector.java
index e846ec1..ce1b4fa 100644
--- a/extensions/commands/src/com/google/inject/commands/FutureInjector.java
+++ b/extensions/commands/src/com/google/inject/commands/FutureInjector.java
@@ -52,7 +52,8 @@
public <T> T get(Key<T> key) {
if (injector == null) {
- throw new IllegalStateException("Not yet initialized");
+ throw new IllegalStateException("This provider cannot be used until the"
+ + " Injector has been created.");
}
return injector.getInstance(key);
diff --git a/extensions/commands/src/com/google/inject/commands/GetProviderCommand.java b/extensions/commands/src/com/google/inject/commands/GetProviderCommand.java
index e155cd7..0839f2c 100644
--- a/extensions/commands/src/com/google/inject/commands/GetProviderCommand.java
+++ b/extensions/commands/src/com/google/inject/commands/GetProviderCommand.java
@@ -17,6 +17,7 @@
package com.google.inject.commands;
import com.google.inject.Key;
+import static com.google.inject.internal.Objects.nonNull;
/**
* Immutable snapshot of a request for a provider.
@@ -24,14 +25,20 @@
* @author jessewilson@google.com (Jesse Wilson)
*/
public final class GetProviderCommand<T> implements Command {
+ private final Object source;
private final Key<T> key;
private final EarlyRequestsProvider earlyRequestsProvider;
- GetProviderCommand(Key<T> key, EarlyRequestsProvider earlyRequestsProvider) {
+ GetProviderCommand(Object source, Key<T> key, EarlyRequestsProvider earlyRequestsProvider) {
+ this.source = nonNull(source, "source");
this.key = key;
this.earlyRequestsProvider = earlyRequestsProvider;
}
+ public Object getSource() {
+ return source;
+ }
+
public Key<T> getKey() {
return key;
}
diff --git a/extensions/commands/src/com/google/inject/commands/RequestStaticInjectionCommand.java b/extensions/commands/src/com/google/inject/commands/RequestStaticInjectionCommand.java
index 677bd34..dbf3a1c 100644
--- a/extensions/commands/src/com/google/inject/commands/RequestStaticInjectionCommand.java
+++ b/extensions/commands/src/com/google/inject/commands/RequestStaticInjectionCommand.java
@@ -16,6 +16,8 @@
package com.google.inject.commands;
+import static com.google.inject.internal.Objects.nonNull;
+
import java.util.Arrays;
import static java.util.Collections.unmodifiableList;
import java.util.List;
@@ -26,12 +28,18 @@
* @author jessewilson@google.com (Jesse Wilson)
*/
public final class RequestStaticInjectionCommand implements Command {
+ private final Object source;
private final List<Class> types;
- RequestStaticInjectionCommand(Class[] types) {
+ RequestStaticInjectionCommand(Object source, Class[] types) {
+ this.source = nonNull(source, "source");
this.types = unmodifiableList(Arrays.asList(types.clone()));
}
+ public Object getSource() {
+ return source;
+ }
+
public List<Class> getTypes() {
return types;
}
diff --git a/extensions/commands/test/com/google/inject/commands/CommandRecorderTest.java b/extensions/commands/test/com/google/inject/commands/CommandRecorderTest.java
index a6a566d..0bbc848 100644
--- a/extensions/commands/test/com/google/inject/commands/CommandRecorderTest.java
+++ b/extensions/commands/test/com/google/inject/commands/CommandRecorderTest.java
@@ -35,6 +35,7 @@
import static java.lang.annotation.RetentionPolicy.RUNTIME;
import java.lang.annotation.Target;
import java.util.*;
+import java.util.concurrent.atomic.AtomicInteger;
/**
* @author jessewilson@google.com (Jesse Wilson)
@@ -49,6 +50,8 @@
private CommandRecorder commandRecorder = new CommandRecorder(earlyRequestProvider);
+ // Binder fidelity tests
+
public void testAddMessageErrorCommand() {
checkModule(
new AbstractModule() {
@@ -96,7 +99,7 @@
new FailingVisitor() {
@Override public Void visitBindConstant(BindConstantCommand command) {
assertEquals(Key.get(String.class, SampleAnnotation.class), command.getKey());
- assertEquals("A", command.getTarget().get(null));
+ assertEquals("A", command.getTarget().get());
return null;
}
},
@@ -104,7 +107,7 @@
new FailingVisitor() {
@Override public Void visitBindConstant(BindConstantCommand command) {
assertEquals(Key.get(String.class, Names.named("Bee")), command.getKey());
- assertEquals("B", command.getTarget().get(null));
+ assertEquals("B", command.getTarget().get());
return null;
}
}
@@ -131,7 +134,7 @@
new FailingVisitor() {
@Override public Void visitBindConstant(BindConstantCommand command) {
assertEquals(Key.get(String.class, Names.named("String")), command.getKey());
- assertEquals("A", command.getTarget().get(null));
+ assertEquals("A", command.getTarget().get());
return null;
}
},
@@ -139,7 +142,7 @@
new FailingVisitor() {
@Override public Void visitBindConstant(BindConstantCommand command) {
assertEquals(Key.get(Integer.class, Names.named("int")), command.getKey());
- assertEquals(2, command.getTarget().get(null));
+ assertEquals(2, command.getTarget().get());
return null;
}
},
@@ -147,7 +150,7 @@
new FailingVisitor() {
@Override public Void visitBindConstant(BindConstantCommand command) {
assertEquals(Key.get(Long.class, Names.named("long")), command.getKey());
- assertEquals(3L, command.getTarget().get(null));
+ assertEquals(3L, command.getTarget().get());
return null;
}
},
@@ -155,7 +158,7 @@
new FailingVisitor() {
@Override public Void visitBindConstant(BindConstantCommand command) {
assertEquals(Key.get(Boolean.class, Names.named("boolean")), command.getKey());
- assertEquals(false, command.getTarget().get(null));
+ assertEquals(false, command.getTarget().get());
return null;
}
},
@@ -163,7 +166,7 @@
new FailingVisitor() {
@Override public Void visitBindConstant(BindConstantCommand command) {
assertEquals(Key.get(Double.class, Names.named("double")), command.getKey());
- assertEquals(5.0d, command.getTarget().get(null));
+ assertEquals(5.0d, command.getTarget().get());
return null;
}
},
@@ -171,7 +174,7 @@
new FailingVisitor() {
@Override public Void visitBindConstant(BindConstantCommand command) {
assertEquals(Key.get(Float.class, Names.named("float")), command.getKey());
- assertEquals(6.0f, command.getTarget().get(null));
+ assertEquals(6.0f, command.getTarget().get());
return null;
}
},
@@ -179,7 +182,7 @@
new FailingVisitor() {
@Override public Void visitBindConstant(BindConstantCommand command) {
assertEquals(Key.get(Short.class, Names.named("short")), command.getKey());
- assertEquals((short) 7, command.getTarget().get(null));
+ assertEquals((short) 7, command.getTarget().get());
return null;
}
},
@@ -187,7 +190,7 @@
new FailingVisitor() {
@Override public Void visitBindConstant(BindConstantCommand command) {
assertEquals(Key.get(Character.class, Names.named("char")), command.getKey());
- assertEquals('h', command.getTarget().get(null));
+ assertEquals('h', command.getTarget().get());
return null;
}
},
@@ -195,7 +198,7 @@
new FailingVisitor() {
@Override public Void visitBindConstant(BindConstantCommand command) {
assertEquals(Key.get(Class.class, Names.named("Class")), command.getKey());
- assertEquals(Iterator.class, command.getTarget().get(null));
+ assertEquals(Iterator.class, command.getTarget().get());
return null;
}
},
@@ -203,7 +206,7 @@
new FailingVisitor() {
@Override public Void visitBindConstant(BindConstantCommand command) {
assertEquals(Key.get(CoinSide.class, Names.named("Enum")), command.getKey());
- assertEquals(CoinSide.TAILS, command.getTarget().get(null));
+ assertEquals(CoinSide.TAILS, command.getTarget().get());
return null;
}
}
@@ -293,7 +296,7 @@
new FailingVisitor() {
@Override public <T> Void visitBind(BindCommand<T> command) {
assertEquals(Key.get(String.class), command.getKey());
- assertEquals("A", command.getTarget().getProvider(null).get());
+ assertEquals("A", command.getTarget().getProvider().get());
return null;
}
},
@@ -301,8 +304,8 @@
new FailingVisitor() {
@Override public <T> Void visitBind(BindCommand<T> command) {
assertEquals(Key.get(List.class), command.getKey());
- assertNull(command.getTarget().get(null));
- assertEquals(Key.get(ListProvider.class), command.getTarget().getProviderKey(null));
+ assertNull(command.getTarget().get());
+ assertEquals(Key.get(ListProvider.class), command.getTarget().getProviderKey());
return null;
}
},
@@ -310,8 +313,8 @@
new FailingVisitor() {
@Override public <T> Void visitBind(BindCommand<T> command) {
assertEquals(Key.get(Collection.class), command.getKey());
- assertNull(command.getTarget().get(null));
- assertEquals(Key.get(ListProvider.class), command.getTarget().getProviderKey(null));
+ assertNull(command.getTarget().get());
+ assertEquals(Key.get(ListProvider.class), command.getTarget().getProviderKey());
return null;
}
}
@@ -331,7 +334,7 @@
new FailingVisitor() {
@Override public <T> Void visitBind(BindCommand<T> command) {
assertEquals(Key.get(List.class), command.getKey());
- assertEquals(Key.get(ArrayList.class), command.getTarget().getKey(null));
+ assertEquals(Key.get(ArrayList.class), command.getTarget().getKey());
return null;
}
},
@@ -339,7 +342,7 @@
new FailingVisitor() {
@Override public <T> Void visitBind(BindCommand<T> command) {
assertEquals(Key.get(Map.class), command.getKey());
- assertEquals(Key.get(new TypeLiteral<HashMap<Integer, String>>() {}), command.getTarget().getKey(null));
+ assertEquals(Key.get(new TypeLiteral<HashMap<Integer, String>>() {}), command.getTarget().getKey());
return null;
}
},
@@ -347,7 +350,7 @@
new FailingVisitor() {
@Override public <T> Void visitBind(BindCommand<T> command) {
assertEquals(Key.get(Set.class), command.getKey());
- assertEquals(Key.get(TreeSet.class, SampleAnnotation.class), command.getTarget().getKey(null));
+ assertEquals(Key.get(TreeSet.class, SampleAnnotation.class), command.getTarget().getKey());
return null;
}
}
@@ -365,7 +368,7 @@
new FailingVisitor() {
@Override public <T> Void visitBind(BindCommand<T> command) {
assertEquals(Key.get(String.class), command.getKey());
- assertEquals("A", command.getTarget().get(null));
+ assertEquals("A", command.getTarget().get());
return null;
}
}
@@ -385,8 +388,8 @@
new FailingVisitor() {
@Override public <T> Void visitBind(BindCommand<T> command) {
assertEquals(Key.get(List.class), command.getKey());
- assertEquals(Scopes.SINGLETON, command.getScoping().getScope(null));
- assertNull(command.getScoping().getScopeAnnotation(null));
+ assertEquals(Scopes.SINGLETON, command.getScoping().getScope());
+ assertNull(command.getScoping().getScopeAnnotation());
assertFalse(command.getScoping().isEagerSingleton());
return null;
}
@@ -395,8 +398,8 @@
new FailingVisitor() {
@Override public <T> Void visitBind(BindCommand<T> command) {
assertEquals(Key.get(Map.class), command.getKey());
- assertEquals(Singleton.class, command.getScoping().getScopeAnnotation(null));
- assertNull(command.getScoping().getScope(null));
+ assertEquals(Singleton.class, command.getScoping().getScopeAnnotation());
+ assertNull(command.getScoping().getScope());
assertFalse(command.getScoping().isEagerSingleton());
return null;
}
@@ -405,8 +408,8 @@
new FailingVisitor() {
@Override public <T> Void visitBind(BindCommand<T> command) {
assertEquals(Key.get(Set.class), command.getKey());
- assertNull(command.getScoping().getScopeAnnotation(null));
- assertNull(command.getScoping().getScope(null));
+ assertNull(command.getScoping().getScopeAnnotation());
+ assertNull(command.getScoping().getScope());
assertTrue(command.getScoping().isEagerSingleton());
return null;
}
@@ -613,6 +616,32 @@
});
}
+ // Business logic tests
+
+ public void testModulesAreInstalledAtMostOnce() {
+ final AtomicInteger aConfigureCount = new AtomicInteger(0);
+ final Module a = new AbstractModule() {
+ public void configure() {
+ aConfigureCount.incrementAndGet();
+ }
+ };
+
+ commandRecorder.recordCommands(a, a);
+ assertEquals(1, aConfigureCount.get());
+
+ aConfigureCount.set(0);
+ Module b = new AbstractModule() {
+ protected void configure() {
+ install(a);
+ install(a);
+ }
+ };
+
+ commandRecorder.recordCommands(b);
+ assertEquals(1, aConfigureCount.get());
+ }
+
+
/**
* Ensures the module performs the commands consistent with {@code visitors}.
*/
@@ -624,6 +653,7 @@
for (int i = 0; i < visitors.length; i++) {
Command.Visitor<?> visitor = visitors[i];
Command command = commands.get(i);
+ assertTrue(command.getSource().toString().contains("CommandRecorderTest"));
command.acceptVisitor(visitor);
}
}
diff --git a/extensions/commands/test/com/google/inject/commands/CommandRewriteTest.java b/extensions/commands/test/com/google/inject/commands/CommandRewriteTest.java
index 7515b4b..690c822 100644
--- a/extensions/commands/test/com/google/inject/commands/CommandRewriteTest.java
+++ b/extensions/commands/test/com/google/inject/commands/CommandRewriteTest.java
@@ -43,7 +43,7 @@
// create a rewriter that rewrites the binding to 'Wine' with a binding to 'Beer'
CommandReplayer rewriter = new CommandReplayer() {
@Override public <T> void replayBind(Binder binder, BindCommand<T> command) {
- if ("Wine".equals(command.getTarget().get(null))) {
+ if ("Wine".equals(command.getTarget().get())) {
binder.bind(CharSequence.class).toInstance("Beer");
} else {
super.replayBind(binder, command);
diff --git a/guice.iml b/guice.iml
index bdec154..a451284 100644
--- a/guice.iml
+++ b/guice.iml
@@ -111,6 +111,7 @@
<SOURCES />
</library>
</orderEntry>
+ <orderEntry type="module" module-name="commands" />
<orderEntryProperties />
</component>
</module>
diff --git a/guice.ipr b/guice.ipr
index 71829d4..18123fd 100644
--- a/guice.ipr
+++ b/guice.ipr
@@ -356,6 +356,26 @@
<option name="GENERATE_IIOP_STUBS" value="false" />
<option name="ADDITIONAL_OPTIONS_STRING" value="" />
</component>
+ <component name="SvnBranchConfigurationManager">
+ <option name="myConfigurationMap">
+ <map>
+ <entry key="$PROJECT_DIR$">
+ <value>
+ <SvnBranchConfiguration>
+ <option name="branchUrls">
+ <list>
+ <option value="https://google-guice.googlecode.com/svn/branches" />
+ <option value="https://google-guice.googlecode.com/svn/tags" />
+ <option value="https://google-guice.googlecode.com/svn/wiki" />
+ </list>
+ </option>
+ <option name="trunkUrl" value="https://google-guice.googlecode.com/svn/trunk" />
+ </SvnBranchConfiguration>
+ </value>
+ </entry>
+ </map>
+ </option>
+ </component>
<component name="VcsDirectoryMappings">
<mapping directory="" vcs="svn" />
</component>
diff --git a/src/com/google/inject/BindCommandProcessor.java b/src/com/google/inject/BindCommandProcessor.java
new file mode 100644
index 0000000..458e174
--- /dev/null
+++ b/src/com/google/inject/BindCommandProcessor.java
@@ -0,0 +1,356 @@
+/**
+ * Copyright (C) 2008 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;
+
+import com.google.inject.commands.BindCommand;
+import com.google.inject.commands.BindConstantCommand;
+import com.google.inject.commands.BindScoping;
+import com.google.inject.commands.BindTarget;
+import com.google.inject.internal.Annotations;
+import com.google.inject.internal.Objects;
+import com.google.inject.internal.StackTraceElements;
+
+import java.lang.annotation.Annotation;
+import java.lang.reflect.Type;
+import java.util.*;
+import java.util.logging.Logger;
+
+/**
+ * Handles {@link Binder#bind} and {@link Binder#bindConstant} commands.
+ *
+ * @author crazybob@google.com (Bob Lee)
+ * @author jessewilson@google.com (Jesse Wilson)
+ */
+class BindCommandProcessor extends CommandProcessor {
+
+ private final InjectorImpl injector;
+ private final Map<Class<? extends Annotation>, Scope> scopes;
+ private final List<CreationListener> creationListeners
+ = new ArrayList<CreationListener>();
+ private final List<ContextualCallable<Void>> preloaders
+ = new ArrayList<ContextualCallable<Void>>();
+ private final Stage stage;
+ private final Map<Key<?>, BindingImpl<?>> bindings;
+ private final List<MembersInjector> membersInjectors = new ArrayList<MembersInjector>();
+
+ BindCommandProcessor(InjectorImpl injector,
+ Map<Class<? extends Annotation>, Scope> scopes,
+ Stage stage,
+ Map<Key<?>, BindingImpl<?>> bindings) {
+ this.injector = injector;
+ this.scopes = scopes;
+ this.stage = stage;
+ this.bindings = bindings;
+ }
+
+ @Override public <T> Boolean visitBind(BindCommand<T> command) {
+ final Object source = command.getSource();
+
+ final Key<T> key = command.getKey();
+ Class<? super T> rawType = key.getTypeLiteral().getRawType();
+
+ if (rawType == Provider.class) {
+ addError(source, ErrorMessages.BINDING_TO_PROVIDER);
+ return true;
+ }
+
+ if (Logger.class == rawType) {
+ // TODO(jessewilson): assert this is coming from the internal module?
+ // addError(source, ErrorMessages.LOGGER_ALREADY_BOUND);
+ // return true;
+ }
+
+ validateKey(command.getSource(), command.getKey());
+
+ // TODO(jessewilson): Scope annotation on type, like @Singleton
+ final boolean shouldPreload = command.getScoping().isEagerSingleton();
+ final Scope scope = command.getScoping().acceptVisitor(new BindScoping.Visitor<Scope>() {
+ public Scope visitEagerSingleton() {
+ return Scopes.SINGLETON;
+ }
+
+ public Scope visitScope(Scope scope) {
+ return scope;
+ }
+
+ public Scope visitScopeAnnotation(Class<? extends Annotation> scopeAnnotation) {
+ Scope scope = scopes.get(scopeAnnotation);
+ if (scope != null) {
+ return scope;
+ } else {
+ addError(source, ErrorMessages.SCOPE_NOT_FOUND,
+ "@" + scopeAnnotation.getSimpleName());
+ return Scopes.NO_SCOPE;
+ }
+ }
+
+ public Scope visitNoScoping() {
+ return null;
+ }
+ });
+
+ command.getTarget().acceptVisitor(new BindTarget.Visitor<T, Void>() {
+ public Void visitToInstance(T instance) {
+ InternalFactory<? extends T> factory = new ConstantFactory<T>(instance);
+ registerInstanceForInjection(instance);
+ InternalFactory<? extends T> scopedFactory
+ = Scopes.scope(key, injector, factory, scope);
+ createBinding(source, shouldPreload, new InstanceBindingImpl<T>(
+ injector, key, source, scopedFactory, instance));
+ return null;
+ }
+
+ public Void visitToProvider(Provider<? extends T> provider) {
+ InternalFactory<? extends T> factory
+ = new InternalFactoryToProviderAdapter<T>(provider, source);
+ registerInstanceForInjection(provider);
+ InternalFactory<? extends T> scopedFactory
+ = Scopes.scope(key, injector, factory, scope);
+ createBinding(source, shouldPreload, new ProviderInstanceBindingImpl<T>(
+ injector, key, source, scopedFactory, scope, provider));
+ return null;
+ }
+
+ public Void visitToProviderKey(Key<? extends Provider<? extends T>> providerKey) {
+ final BoundProviderFactory<T> boundProviderFactory =
+ new BoundProviderFactory<T>(providerKey, source);
+ creationListeners.add(boundProviderFactory);
+ InternalFactory<? extends T> scopedFactory = Scopes.scope(
+ key, injector, (InternalFactory<? extends T>) boundProviderFactory, scope);
+ createBinding(source, shouldPreload, new LinkedProviderBindingImpl<T>(
+ injector, key, source, scopedFactory, scope, providerKey));
+ return null;
+ }
+
+ public Void visitToKey(Key<? extends T> targetKey) {
+ if (key.equals(targetKey)) {
+ addError(source, ErrorMessages.RECURSIVE_BINDING);
+ }
+
+ FactoryProxy<T> factory = new FactoryProxy<T>(key, targetKey, source);
+ creationListeners.add(factory);
+ InternalFactory<? extends T> scopedFactory
+ = Scopes.scope(key, injector, factory, scope);
+ createBinding(source, shouldPreload, new LinkedBindingImpl<T>(
+ injector, key, source, scopedFactory, scope, targetKey));
+ return null;
+ }
+
+ public Void visitUntargetted() {
+ Type type = key.getTypeLiteral().getType();
+
+ // Error: Missing implementation.
+ // Example: bind(Date.class).annotatedWith(Red.class);
+ // We can't assume abstract types aren't injectable. They may have an
+ // @ImplementedBy annotation or something.
+ if (key.hasAnnotationType() || !(type instanceof Class<?>)) {
+ addError(source, ErrorMessages.MISSING_IMPLEMENTATION);
+ createBinding(source, shouldPreload, invalidBinding(injector, key, source));
+ return null;
+ }
+
+ // This cast is safe after the preceeding check.
+ @SuppressWarnings("unchecked")
+ Class<T> clazz = (Class<T>) type;
+
+ BindingImpl<T> binding = injector.createBindingFromType(clazz, scope, source);
+ // TODO: Should we clean up the binding left behind in jitBindings?
+
+ if (binding == null) {
+ addError(source, ErrorMessages.CANNOT_INJECT_ABSTRACT_TYPE, clazz);
+ createBinding(source, shouldPreload, invalidBinding(injector, key, source));
+ return null;
+ }
+
+ createBinding(source, shouldPreload, binding);
+ return null;
+ }
+ });
+
+ return true;
+ }
+
+ private <T> void validateKey(Object source, Key<T> key) {
+ if (key.hasAnnotationType()) {
+ Class<? extends Annotation> annotationType = key.getAnnotationType();
+
+ if (!Annotations.isRetainedAtRuntime(annotationType)) {
+ addError(StackTraceElements.forType(annotationType),
+ ErrorMessages.MISSING_RUNTIME_RETENTION, source);
+ }
+
+ if (!Key.isBindingAnnotation(annotationType)) {
+ addError(StackTraceElements.forType(annotationType),
+ ErrorMessages.MISSING_BINDING_ANNOTATION, source);
+ }
+ }
+ }
+
+ <T> InvalidBindingImpl<T> invalidBinding(InjectorImpl injector, Key<T> key, Object source) {
+ return new InvalidBindingImpl<T>(injector, key, source);
+ }
+
+ void registerInstanceForInjection(final Object o) {
+ membersInjectors.add(new MembersInjector(o));
+ }
+
+ public void validate(InjectorImpl injector) {
+ for (MembersInjector membersInjector : membersInjectors) {
+ membersInjector.checkDependencies(injector);
+ }
+ }
+
+ public void injectMembers(InjectorImpl injector) {
+ for (MembersInjector membersInjector : membersInjectors) {
+ membersInjector.injectMembers(injector);
+ }
+ }
+
+ private static class MembersInjector {
+ final Object o;
+
+ MembersInjector(Object o) {
+ this.o = o;
+ }
+
+ void checkDependencies(InjectorImpl injector) {
+ injector.injectors.get(o.getClass());
+ }
+
+ void injectMembers(InjectorImpl injector) {
+ injector.injectMembers(o);
+ }
+ }
+
+ @Override public Boolean visitBindConstant(BindConstantCommand command) {
+ Object value = command.getTarget().get();
+ if (value == null) {
+ addError(command.getSource(), ErrorMessages.MISSING_CONSTANT_VALUE);
+ }
+
+ validateKey(command.getSource(), command.getKey());
+ ConstantFactory<Object> factory = new ConstantFactory<Object>(value);
+ putBinding(new ContantBindingImpl<Object>(
+ injector, command.getKey(), command.getSource(), factory, value));
+
+ return true;
+ }
+
+ private <T> void createBinding(Object source, boolean shouldPreload,
+ BindingImpl<T> binding) {
+ putBinding(binding);
+
+ // Register to preload if necessary.
+ if (binding.getScope() == Scopes.SINGLETON) {
+ if (stage == Stage.PRODUCTION || shouldPreload) {
+ preloaders.add(new BindingPreloader(binding.key, binding.internalFactory));
+ }
+ } else {
+ if (shouldPreload) {
+ addError(source, ErrorMessages.PRELOAD_NOT_ALLOWED);
+ }
+ }
+ }
+
+ public void runPreloaders(InjectorImpl injector) {
+ injector.callInContext(new ContextualCallable<Void>() {
+ public Void call(InternalContext context) {
+ for (ContextualCallable<Void> preloader : preloaders) {
+ preloader.call(context);
+ }
+ return null;
+ }
+ });
+ }
+
+ public void runCreationListeners(InjectorImpl injector) {
+ for (CreationListener creationListener : creationListeners) {
+ creationListener.notify(injector);
+ }
+ }
+
+ private static class BindingPreloader implements ContextualCallable<Void> {
+ private final Key<?> key;
+ private final InternalFactory<?> factory;
+
+ public BindingPreloader(Key<?> key, InternalFactory<?> factory) {
+ this.key = key;
+ this.factory = Objects.nonNull(factory, "factory");
+ }
+
+ public Void call(InternalContext context) {
+ InjectionPoint<?> injectionPoint
+ = InjectionPoint.newInstance(key, context.getInjectorImpl());
+ context.setInjectionPoint(injectionPoint);
+ try {
+ factory.get(context, injectionPoint);
+ return null;
+ } catch(ProvisionException provisionException) {
+ provisionException.addContext(injectionPoint);
+ throw provisionException;
+ } finally {
+ context.setInjectionPoint(null);
+ }
+ }
+ }
+
+ private void putBinding(BindingImpl<?> binding) {
+ Key<?> key = binding.getKey();
+ Binding<?> original = bindings.get(key);
+
+ Class<?> rawType = key.getRawType();
+ if (FORBIDDEN_TYPES.contains(rawType)) {
+ addError(binding.getSource(), ErrorMessages.CANNOT_BIND_TO_GUICE_TYPE,
+ rawType.getSimpleName());
+ return;
+ }
+
+ if (bindings.containsKey(key)) {
+ addError(binding.getSource(), ErrorMessages.BINDING_ALREADY_SET, key,
+ original.getSource());
+ } else {
+ bindings.put(key, binding);
+ }
+ }
+
+ private static Set<Class<?>> FORBIDDEN_TYPES = forbiddenTypes();
+
+ @SuppressWarnings("unchecked") // For generic array creation.
+ private static Set<Class<?>> forbiddenTypes() {
+ Set<Class<?>> set = new HashSet<Class<?>>();
+
+ Collections.addAll(set,
+
+ // It's unfortunate that we have to maintain a blacklist of specific
+ // classes, but we can't easily block the whole package because of
+ // all our unit tests.
+
+ AbstractModule.class,
+ Binder.class,
+ Binding.class,
+ Key.class,
+ Module.class,
+ Provider.class,
+ Scope.class,
+ TypeLiteral.class);
+ return Collections.unmodifiableSet(set);
+ }
+
+ interface CreationListener {
+ void notify(InjectorImpl injector);
+ }
+}
diff --git a/src/com/google/inject/BindInterceptorCommandProcessor.java b/src/com/google/inject/BindInterceptorCommandProcessor.java
new file mode 100644
index 0000000..6ae838a
--- /dev/null
+++ b/src/com/google/inject/BindInterceptorCommandProcessor.java
@@ -0,0 +1,40 @@
+/**
+ * Copyright (C) 2008 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;
+
+import com.google.inject.commands.BindInterceptorCommand;
+
+/**
+ * Handles {@link Binder#bindInterceptor} commands.
+ *
+ * @author crazybob@google.com (Bob Lee)
+ * @author jessewilson@google.com (Jesse Wilson)
+ */
+class BindInterceptorCommandProcessor extends CommandProcessor {
+
+ private final ProxyFactoryBuilder proxyFactoryBuilder = new ProxyFactoryBuilder();
+
+ @Override public Boolean visitBindInterceptor(BindInterceptorCommand command) {
+ proxyFactoryBuilder.intercept(
+ command.getClassMatcher(), command.getMethodMatcher(), command.getInterceptors());
+ return true;
+ }
+
+ ProxyFactory createProxyFactory() {
+ return proxyFactoryBuilder.create();
+ }
+}
diff --git a/src/com/google/inject/BindingBuilderImpl.java b/src/com/google/inject/BindingBuilderImpl.java
deleted file mode 100644
index 451f943..0000000
--- a/src/com/google/inject/BindingBuilderImpl.java
+++ /dev/null
@@ -1,398 +0,0 @@
-/*
- * Copyright (C) 2007 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;
-
-import com.google.inject.BinderImpl.CreationListener;
-import com.google.inject.BinderImpl.MembersInjector;
-import com.google.inject.binder.AnnotatedBindingBuilder;
-import com.google.inject.binder.ScopedBindingBuilder;
-import com.google.inject.internal.Annotations;
-import com.google.inject.internal.Objects;
-import com.google.inject.internal.StackTraceElements;
-import com.google.inject.internal.ToStringBuilder;
-import com.google.inject.spi.BindingVisitor;
-import com.google.inject.spi.Dependency;
-import com.google.inject.spi.InstanceBinding;
-import com.google.inject.util.Providers;
-import java.lang.annotation.Annotation;
-import java.lang.reflect.Type;
-import java.util.logging.Logger;
-import java.util.Collection;
-
-/**
- * Binds a {@link com.google.inject.Key} to an implementation in a given scope.
- */
-class BindingBuilderImpl<T> implements AnnotatedBindingBuilder<T> {
-
- private static final Logger logger
- = Logger.getLogger(BindingBuilderImpl.class.getName());
-
- final Object source;
- Key<T> key;
- InternalFactory<? extends T> factory;
- Scope scope;
- boolean preload = false;
- private BinderImpl binder;
-
- // These fields keep track of the raw implementation for later use in the
- // Binding API.
- T instance;
- Key<? extends T> targetKey;
- Provider<? extends T> providerInstance;
- Key<? extends Provider<? extends T>> providerKey;
-
- BindingBuilderImpl(BinderImpl binder, Key<T> key, Object source) {
- this.binder = binder;
- this.key = Objects.nonNull(key, "key");
- this.source = source;
- }
-
- Object getSource() {
- return source;
- }
-
- Key<T> getKey() {
- return key;
- }
-
- public BindingBuilderImpl<T> annotatedWith(
- Class<? extends Annotation> annotationType) {
- if (this.key.hasAnnotationType()) {
- binder.addError(source, ErrorMessages.ANNOTATION_ALREADY_SPECIFIED);
- } else {
- boolean retainedAtRuntime =
- Annotations.isRetainedAtRuntime(annotationType);
- boolean bindingAnnotation = Key.isBindingAnnotation(annotationType);
-
- if (!retainedAtRuntime) {
- binder.addError(StackTraceElements.forType(annotationType),
- ErrorMessages.MISSING_RUNTIME_RETENTION, binder.source());
- }
-
- if (!bindingAnnotation) {
- binder.addError(StackTraceElements.forType(annotationType),
- ErrorMessages.MISSING_BINDING_ANNOTATION, binder.source());
- }
-
- if (retainedAtRuntime && bindingAnnotation) {
- this.key = Key.get(this.key.getTypeLiteral(), annotationType);
- }
- }
- return this;
- }
-
- public BindingBuilderImpl<T> annotatedWith(Annotation annotation) {
- if (this.key.hasAnnotationType()) {
- binder.addError(source, ErrorMessages.ANNOTATION_ALREADY_SPECIFIED);
- } else {
- Class<? extends Annotation> annotationType = annotation.annotationType();
-
- boolean retainedAtRuntime =
- Annotations.isRetainedAtRuntime(annotationType);
- boolean bindingAnnotation = Key.isBindingAnnotation(annotationType);
-
- if (!retainedAtRuntime) {
- binder.addError(StackTraceElements.forType(annotationType),
- ErrorMessages.MISSING_RUNTIME_RETENTION, binder.source());
- }
-
- if (!bindingAnnotation) {
- binder.addError(StackTraceElements.forType(annotationType),
- ErrorMessages.MISSING_BINDING_ANNOTATION, binder.source());
- }
-
- if (retainedAtRuntime && bindingAnnotation) {
- this.key = Key.get(this.key.getTypeLiteral(), annotation);
- }
- }
- return this;
- }
-
- public ScopedBindingBuilder to(Class<? extends T> implementation) {
- return to(TypeLiteral.get(implementation));
- }
-
- public ScopedBindingBuilder to(TypeLiteral<? extends T> implementation) {
- return to(Key.get(implementation));
- }
-
- public ScopedBindingBuilder to(Key<? extends T> targetKey) {
- ensureImplementationIsNotSet();
-
- if (key.equals(targetKey)) {
- binder.addError(source, ErrorMessages.RECURSIVE_BINDING);
- }
-
- final FactoryProxy<? extends T> factoryProxy =
- new FactoryProxy<T>(key, targetKey, source);
- this.factory = factoryProxy;
- binder.creationListeners.add(factoryProxy);
- this.targetKey = targetKey;
- return this;
- }
-
- public void toInstance(T instance) {
- ensureImplementationIsNotSet();
- this.instance = instance;
- this.factory = new ConstantFactory<T>(instance);
- registerInstanceForInjection(instance);
-
- // TODO: I don't think this can happen anymore.
- if (this.scope != null) {
- binder.addError(source, ErrorMessages.SINGLE_INSTANCE_AND_SCOPE);
- }
- }
-
- public ScopedBindingBuilder toProvider(Provider<? extends T> provider) {
- ensureImplementationIsNotSet();
- this.factory = new InternalFactoryToProviderAdapter<T>(provider, source);
- this.providerInstance = provider;
- registerInstanceForInjection(provider);
- return this;
- }
-
- public BindingBuilderImpl<T> toInternalFactory(InternalFactory<T> internalFactory) {
- ensureImplementationIsNotSet();
- this.factory = internalFactory;
- this.providerInstance = new Provider<T>() {
- public T get() {
- throw new UnsupportedOperationException("?");
- }
- };
- return this;
- }
-
- public BindingBuilderImpl<T> toProvider(
- Class<? extends Provider<? extends T>> providerType) {
- return toProvider(Key.get(providerType));
- }
-
- public BindingBuilderImpl<T> toProvider(
- Key<? extends Provider<? extends T>> providerKey) {
- ensureImplementationIsNotSet();
-
- final BoundProviderFactory<T> boundProviderFactory =
- new BoundProviderFactory<T>(providerKey, source);
- binder.creationListeners.add(boundProviderFactory);
- this.factory = boundProviderFactory;
- this.providerKey = providerKey;
-
- return this;
- }
-
- /**
- * Adds an error message if the implementation has already been bound.
- */
- private void ensureImplementationIsNotSet() {
- if (factory != null) {
- binder.addError(source, ErrorMessages.IMPLEMENTATION_ALREADY_SET);
- }
- }
-
- public void in(Class<? extends Annotation> scopeAnnotation) {
- // this method not test-covered
- ensureScopeNotSet();
-
- // We could defer this lookup to when we create the Injector, but this
- // is fine for now.
- this.scope = binder.scopes.get(
- Objects.nonNull(scopeAnnotation, "scope annotation"));
- if (this.scope == null) {
- binder.addError(source, ErrorMessages.SCOPE_NOT_FOUND,
- "@" + scopeAnnotation.getSimpleName());
- }
- }
-
- public void in(Scope scope) {
- ensureScopeNotSet();
- this.scope = Objects.nonNull(scope, "scope");
- }
-
- private void ensureScopeNotSet() {
- // Scoping isn't allowed when we have only one instance.
- if (this.instance != null) {
- binder.addError(source, ErrorMessages.SINGLE_INSTANCE_AND_SCOPE);
- return;
- }
-
- if (this.scope != null) {
- binder.addError(source, ErrorMessages.SCOPE_ALREADY_SET);
- }
- }
-
- public void asEagerSingleton() {
- in(Scopes.SINGLETON);
- this.preload = true;
- }
-
- boolean shouldPreload() {
- return preload;
- }
-
- BindingImpl<T> build(InjectorImpl injector) {
- if (this.factory != null) {
- Scope scope = this.scope == null ? Scopes.NO_SCOPE : this.scope;
-
- InternalFactory<? extends T> scopedFactory
- = Scopes.scope(this.key, injector, this.factory, scope);
-
- // Instance binding.
- if (instance != null) {
- return new InstanceBindingImpl<T>(
- injector, key, source, scopedFactory, instance);
- }
-
- // Linked binding.
- if (this.targetKey != null) {
- return new LinkedBindingImpl<T>(
- injector, key, source, scopedFactory, scope, targetKey);
- }
-
- // Provider instance binding.
- if (this.providerInstance != null) {
- return new ProviderInstanceBindingImpl<T>(
- injector, key, source, scopedFactory, scope, providerInstance);
- }
-
- // Provider binding.
- if (this.providerKey != null) {
- return new LinkedProviderBindingImpl<T>(
- injector, key, source, scopedFactory, scope, providerKey);
- }
-
- throw new AssertionError();
- } else {
- // If we're here, the type we bound to is also the implementation.
- // Example: bind(FooImpl.class).in(Scopes.SINGLETON);
-
- Type type = key.getTypeLiteral().getType();
-
- // Error: Missing implementation.
- // Example: bind(Date.class).annotatedWith(Red.class);
- // We can't assume abstract types aren't injectable. They may have an
- // @ImplementedBy annotation or something.
- if (key.hasAnnotationType() || !(type instanceof Class<?>)) {
- injector.errorHandler.handle(source,
- ErrorMessages.MISSING_IMPLEMENTATION);
- return invalidBinding(injector);
- }
-
- // This cast is safe after the preceeding check.
- @SuppressWarnings("unchecked")
- Class<T> clazz = (Class<T>) type;
-
- BindingImpl<T> binding = injector.createBindingFromType(
- clazz, scope, source);
- // TODO: Should we clean up the binding left behind in jitBindings?
-
- if (binding == null) {
- injector.errorHandler.handle(source,
- ErrorMessages.CANNOT_INJECT_ABSTRACT_TYPE, clazz);
- return invalidBinding(injector);
- }
-
- return binding;
- }
- }
-
- InvalidBindingImpl<T> invalidBinding(InjectorImpl injector) {
- return new InvalidBindingImpl<T>(injector, key, source);
- }
-
- private static class InstanceBindingImpl<T> extends BindingImpl<T>
- implements InstanceBinding<T> {
-
- final T instance;
- final Provider<T> provider;
-
- InstanceBindingImpl(InjectorImpl injector, Key<T> key, Object source,
- InternalFactory<? extends T> internalFactory, T instance) {
- super(injector, key, source, internalFactory, Scopes.NO_SCOPE);
- this.instance = instance;
- this.provider = Providers.of(instance);
- }
-
- @Override
- public Provider<T> getProvider() {
- return this.provider;
- }
-
- public void accept(BindingVisitor<? super T> bindingVisitor) {
- bindingVisitor.visit(this);
- }
-
- public T getInstance() {
- return this.instance;
- }
-
- public Collection<Dependency<?>> getDependencies() {
- return injector.getFieldAndMethodDependenciesFor(instance.getClass());
- }
-
- @Override
- public String toString() {
- return new ToStringBuilder(InstanceBinding.class)
- .add("key", key)
- .add("instance", instance)
- .add("source", source)
- .toString();
- }
- }
-
- void registerInstanceForInjection(final Object o) {
- binder.membersInjectors.add(new MembersInjector(o));
- }
-
- /**
- * A placeholder which enables us to swap in the real factory once the
- * container is created.
- */
- private static class FactoryProxy<T> implements InternalFactory<T>,
- CreationListener {
-
- private final Key<T> key;
- private final Key<? extends T> targetKey;
- private final Object source;
-
- InternalFactory<? extends T> targetFactory;
-
- FactoryProxy(Key<T> key, Key<? extends T> targetKey, Object source) {
- this.key = key;
- this.targetKey = targetKey;
- this.source = source;
- }
-
- public void notify(final InjectorImpl injector) {
- injector.withDefaultSource(source, new Runnable() {
- public void run() {
- targetFactory = injector.getInternalFactory(targetKey);
- }
- });
- }
-
- public T get(InternalContext context, InjectionPoint<?> injectionPoint) {
- return targetFactory.get(context, injectionPoint);
- }
-
- public String toString() {
- return new ToStringBuilder(FactoryProxy.class)
- .add("key", key)
- .add("provider", targetFactory)
- .toString();
- }
- }
-}
diff --git a/src/com/google/inject/BoundProviderFactory.java b/src/com/google/inject/BoundProviderFactory.java
index f0708e0..77fe909 100644
--- a/src/com/google/inject/BoundProviderFactory.java
+++ b/src/com/google/inject/BoundProviderFactory.java
@@ -16,7 +16,7 @@
package com.google.inject;
-import com.google.inject.BinderImpl.CreationListener;
+import com.google.inject.BindCommandProcessor.CreationListener;
/**
* Delegates to a custom factory which is also bound in the injector.
diff --git a/src/com/google/inject/CommandProcessor.java b/src/com/google/inject/CommandProcessor.java
new file mode 100644
index 0000000..e3f4eb7
--- /dev/null
+++ b/src/com/google/inject/CommandProcessor.java
@@ -0,0 +1,94 @@
+/**
+ * Copyright (C) 2008 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;
+
+import com.google.inject.commands.*;
+
+import java.util.Iterator;
+import java.util.List;
+
+/**
+ * Abstract base class for executing commands to creating an injector.
+ *
+ * <p>Extending classes must return {@code true} from any overridden
+ * {@code visit*()} methods, in order for the command processor to remove the
+ * handled command.
+ *
+ * @author jessewilson@google.com (Jesse Wilson)
+ */
+abstract class CommandProcessor implements Command.Visitor<Boolean> {
+
+ private ErrorHandler errorHandler;
+
+ public void processCommands(List<Command> commands, ErrorHandler errorHandler) {
+ this.errorHandler = errorHandler;
+ try {
+ for (Iterator<Command> i = commands.iterator(); i.hasNext(); ) {
+ Boolean allDone = i.next().acceptVisitor(this);
+ if (allDone) {
+ i.remove();
+ }
+ }
+ } finally {
+ this.errorHandler = null;
+ }
+ }
+
+ protected void addError(Object source, String message, Object... arguments) {
+ errorHandler.handle(source, message, arguments);
+ }
+
+ protected void addError(Object source, String message) {
+ errorHandler.handle(source, message);
+ }
+
+ public Boolean visitAddMessageError(AddMessageErrorCommand command) {
+ return false;
+ }
+
+ public Boolean visitAddError(AddThrowableErrorCommand command) {
+ return false;
+ }
+
+ public Boolean visitBindInterceptor(BindInterceptorCommand command) {
+ return false;
+ }
+
+ public Boolean visitBindScope(BindScopeCommand command) {
+ return false;
+ }
+
+ public Boolean visitRequestStaticInjection(RequestStaticInjectionCommand command) {
+ return false;
+ }
+
+ public Boolean visitBindConstant(BindConstantCommand command) {
+ return false;
+ }
+
+ public Boolean visitConvertToTypes(ConvertToTypesCommand command) {
+ return false;
+ }
+
+ public <T> Boolean visitBind(BindCommand<T> command) {
+ return false;
+ }
+
+ public <T> Boolean visitGetProvider(GetProviderCommand<T> command) {
+ return false;
+ }
+}
diff --git a/src/com/google/inject/ConfigurationException.java b/src/com/google/inject/ConfigurationException.java
index ceac337..d73ebd5 100644
--- a/src/com/google/inject/ConfigurationException.java
+++ b/src/com/google/inject/ConfigurationException.java
@@ -17,7 +17,7 @@
package com.google.inject;
/**
- * Thrown when the {@link BinderImpl} is misconfigured.
+ * Thrown when the {@link InjectorBuilder} is misconfigured.
*
* @author crazybob@google.com (Bob Lee)
*/
diff --git a/src/com/google/inject/ConstantBindingBuilderImpl.java b/src/com/google/inject/ConstantBindingBuilderImpl.java
deleted file mode 100644
index 6ff1037..0000000
--- a/src/com/google/inject/ConstantBindingBuilderImpl.java
+++ /dev/null
@@ -1,204 +0,0 @@
-/*
- * Copyright (C) 2007 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;
-
-import com.google.inject.Key.AnnotationStrategy;
-import com.google.inject.binder.AnnotatedConstantBindingBuilder;
-import com.google.inject.binder.ConstantBindingBuilder;
-import com.google.inject.internal.Annotations;
-import com.google.inject.internal.Objects;
-import com.google.inject.internal.StackTraceElements;
-import com.google.inject.internal.ToStringBuilder;
-import com.google.inject.spi.BindingVisitor;
-import com.google.inject.spi.ConstantBinding;
-import com.google.inject.util.Providers;
-import java.lang.annotation.Annotation;
-
-/**
- * Builds a constant binding.
- */
-class ConstantBindingBuilderImpl implements AnnotatedConstantBindingBuilder,
- ConstantBindingBuilder {
-
- BindingInfo<?> bindingInfo;
- AnnotationStrategy annotationStrategy;
- final Object source;
- private BinderImpl binder;
-
- ConstantBindingBuilderImpl(BinderImpl binder, Object source) {
- this.binder = binder;
- this.source = source;
- }
-
- public ConstantBindingBuilder annotatedWith(
- Class<? extends Annotation> annotationType) {
- Objects.nonNull(annotationType, "annotation type");
- validateAnnotation(annotationType);
- annotationStrategy = Key.strategyFor(annotationType);
- return this;
- }
-
- public ConstantBindingBuilder annotatedWith(Annotation annotation) {
- Objects.nonNull(annotation, "annotation");
- validateAnnotation(annotation.annotationType());
- annotationStrategy = Key.strategyFor(annotation);
- return this;
- }
-
- void validateAnnotation(Class<? extends Annotation> annotationType) {
- if (annotationStrategy != null) {
- binder.addError(source, ErrorMessages.ANNOTATION_ALREADY_SPECIFIED);
- return;
- }
-
- boolean retainedAtRuntime =
- Annotations.isRetainedAtRuntime(annotationType);
- boolean bindingAnnotation = Key.isBindingAnnotation(annotationType);
-
- if (!retainedAtRuntime) {
- binder.addError(StackTraceElements.forType(annotationType),
- ErrorMessages.MISSING_RUNTIME_RETENTION, source);
- }
-
- if (!bindingAnnotation) {
- binder.addError(StackTraceElements.forType(annotationType),
- ErrorMessages.MISSING_BINDING_ANNOTATION, source);
- }
- }
-
- boolean hasValue() {
- return bindingInfo != null;
- }
-
- Object getSource() {
- return source;
- }
-
- public void to(String value) {
- to(String.class, value);
- }
-
- public void to(int value) {
- to(int.class, value);
- }
-
- public void to(long value) {
- to(long.class, value);
- }
-
- public void to(boolean value) {
- to(boolean.class, value);
- }
-
- public void to(double value) {
- to(double.class, value);
- }
-
- public void to(float value) {
- to(float.class, value);
- }
-
- public void to(short value) {
- to(short.class, value);
- }
-
- public void to(char value) {
- to(char.class, value);
- }
-
- public void to(Class<?> value) {
- to(Class.class, value);
- }
-
- public <E extends Enum<E>> void to(E value) {
- to(value.getDeclaringClass(), value);
- }
-
- /**
- * Maps a constant value to the given type and name.
- */
- <T> void to(final Class<T> type, final T value) {
- if (this.bindingInfo != null) {
- binder.addError(source, ErrorMessages.CONSTANT_VALUE_ALREADY_SET);
- } else {
- this.bindingInfo
- = new BindingInfo<T>(type, value, annotationStrategy, source);
- }
- }
-
- BindingImpl<?> createBinding(InjectorImpl injector) {
- return bindingInfo.createBinding(injector);
- }
-
- private static class BindingInfo<T> {
-
- final Class<T> type;
- final T value;
- final AnnotationStrategy annotationStrategy;
- final Object source;
-
- BindingInfo(Class<T> type, T value,
- AnnotationStrategy annotationStrategy, Object source) {
- this.type = type;
- this.value = value;
- this.annotationStrategy = annotationStrategy;
- this.source = source;
- }
-
- BindingImpl<T> createBinding(InjectorImpl injector) {
- Key<T> key = Key.get(type, annotationStrategy);
- ConstantFactory<T> factory = new ConstantFactory<T>(value);
- return new ContantBindingImpl<T>(injector, key, source, factory, value);
- }
- }
-
- private static class ContantBindingImpl<T> extends BindingImpl<T>
- implements ConstantBinding<T> {
-
- final T value;
- final Provider<T> provider;
-
- ContantBindingImpl(InjectorImpl injector, Key<T> key, Object source,
- InternalFactory<T> internalFactory, T value) {
- super(injector, key, source, internalFactory, Scopes.NO_SCOPE);
- this.value = value;
- this.provider = Providers.of(value);
- }
-
- @Override
- public Provider<T> getProvider() {
- return this.provider;
- }
-
- public void accept(BindingVisitor<? super T> bindingVisitor) {
- bindingVisitor.visit(this);
- }
-
- public T getValue() {
- return this.value;
- }
-
- @Override
- public String toString() {
- return new ToStringBuilder(ConstantBinding.class)
- .add("key", key)
- .add("value", value)
- .add("source", source)
- .toString();
- }
- }
-}
diff --git a/src/com/google/inject/ContantBindingImpl.java b/src/com/google/inject/ContantBindingImpl.java
new file mode 100644
index 0000000..6157a06
--- /dev/null
+++ b/src/com/google/inject/ContantBindingImpl.java
@@ -0,0 +1,62 @@
+/**
+ * Copyright (C) 2008 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;
+
+import com.google.inject.spi.ConstantBinding;
+import com.google.inject.spi.BindingVisitor;
+import com.google.inject.util.Providers;
+import com.google.inject.internal.ToStringBuilder;
+
+/**
+ * A constant binding.
+ */
+class ContantBindingImpl<T> extends BindingImpl<T>
+ implements ConstantBinding<T> {
+
+ final T value;
+ final Provider<T> provider;
+
+ ContantBindingImpl(InjectorImpl injector, Key<T> key, Object source,
+ InternalFactory<T> internalFactory, T value) {
+ super(injector, key, source, internalFactory, Scopes.NO_SCOPE);
+ this.value = value;
+ this.provider = Providers.of(value);
+ }
+
+ @Override
+ public Provider<T> getProvider() {
+ return this.provider;
+ }
+
+ public void accept(BindingVisitor<? super T> bindingVisitor) {
+ bindingVisitor.visit(this);
+ }
+
+ public T getValue() {
+ return this.value;
+ }
+
+ @Override
+ public String toString() {
+ return new ToStringBuilder(ConstantBinding.class)
+ .add("key", key)
+ .add("value", value)
+ .add("source", source)
+ .toString();
+ }
+}
diff --git a/src/com/google/inject/ConvertToTypesCommandProcessor.java b/src/com/google/inject/ConvertToTypesCommandProcessor.java
new file mode 100644
index 0000000..af9e592
--- /dev/null
+++ b/src/com/google/inject/ConvertToTypesCommandProcessor.java
@@ -0,0 +1,177 @@
+/**
+ * Copyright (C) 2008 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;
+
+import com.google.inject.commands.ConvertToTypesCommand;
+import com.google.inject.internal.Strings;
+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.TypeConverter;
+
+import java.lang.reflect.InvocationTargetException;
+import java.lang.reflect.Method;
+import java.lang.reflect.Type;
+import java.util.List;
+
+/**
+ * Handles {@link Binder#convertToTypes} commands.
+ *
+ * @author crazybob@google.com (Bob Lee)
+ * @author jessewilson@google.com (Jesse Wilson)
+ */
+class ConvertToTypesCommandProcessor extends CommandProcessor {
+
+ private final List<MatcherAndConverter<?>> converters;
+
+ ConvertToTypesCommandProcessor(List<MatcherAndConverter<?>> converters) {
+ this.converters = converters;
+
+ // Configure type converters.
+ convertToPrimitiveType(int.class, Integer.class);
+ convertToPrimitiveType(long.class, Long.class);
+ convertToPrimitiveType(boolean.class, Boolean.class);
+ convertToPrimitiveType(byte.class, Byte.class);
+ convertToPrimitiveType(short.class, Short.class);
+ convertToPrimitiveType(float.class, Float.class);
+ convertToPrimitiveType(double.class, Double.class);
+
+ TypeConverter characterConverter = new TypeConverter() {
+ public Object convert(String value, TypeLiteral<?> toType) {
+ value = value.trim();
+ if (value.length() != 1) {
+ throw new RuntimeException("Length != 1.");
+ }
+ return value.charAt(0);
+ }
+
+ @Override public String toString() {
+ return "TypeConverter<Character>";
+ }
+ };
+
+ convertToClass(char.class, characterConverter);
+ convertToClass(Character.class, characterConverter);
+
+ convertToClasses(Matchers.subclassesOf(Enum.class), new TypeConverter() {
+ @SuppressWarnings("unchecked")
+ public Object convert(String value, TypeLiteral<?> toType) {
+ return Enum.valueOf((Class) toType.getRawType(), value);
+ }
+
+ @Override public String toString() {
+ return "TypeConverter<E extends Enum<E>>";
+ }
+ });
+
+ internalConvertToTypes(
+ new AbstractMatcher<TypeLiteral<?>>() {
+ public boolean matches(TypeLiteral<?> typeLiteral) {
+ return typeLiteral.getRawType() == Class.class;
+ }
+
+ @Override public String toString() {
+ return "Class<?>";
+ }
+ },
+ new TypeConverter() {
+ @SuppressWarnings("unchecked")
+ public Object convert(String value, TypeLiteral<?> toType) {
+ try {
+ return Class.forName(value);
+ }
+ catch (ClassNotFoundException e) {
+ throw new RuntimeException(e.getMessage());
+ }
+ }
+
+ @Override public String toString() {
+ return "TypeConverter<Class<?>>";
+ }
+ }
+ );
+ }
+
+ private <T> void convertToPrimitiveType(Class<T> primitiveType,
+ final Class<T> wrapperType) {
+ try {
+ final Method parser = wrapperType.getMethod(
+ "parse" + Strings.capitalize(primitiveType.getName()), String.class);
+
+ TypeConverter typeConverter = new TypeConverter() {
+ @SuppressWarnings("unchecked")
+ public Object convert(String value, TypeLiteral<?> toType) {
+ try {
+ return parser.invoke(null, value);
+ }
+ catch (IllegalAccessException e) {
+ throw new AssertionError(e);
+ }
+ catch (InvocationTargetException e) {
+ throw new RuntimeException(e.getTargetException().getMessage());
+ }
+ }
+
+ @Override public String toString() {
+ return "TypeConverter<" + wrapperType.getSimpleName() + ">";
+ }
+ };
+
+ convertToClass(primitiveType, typeConverter);
+ convertToClass(wrapperType, typeConverter);
+ }
+ catch (NoSuchMethodException e) {
+ throw new AssertionError(e);
+ }
+ }
+
+ private <T> void convertToClass(Class<T> type, TypeConverter converter) {
+ convertToClasses(Matchers.identicalTo(type), converter);
+ }
+
+ private void convertToClasses(final Matcher<? super Class<?>> typeMatcher,
+ TypeConverter converter) {
+ internalConvertToTypes(new AbstractMatcher<TypeLiteral<?>>() {
+ public boolean matches(TypeLiteral<?> typeLiteral) {
+ Type type = typeLiteral.getType();
+ if (!(type instanceof Class)) {
+ return false;
+ }
+ Class<?> clazz = (Class<?>) type;
+ return typeMatcher.matches(clazz);
+ }
+
+ public String toString() {
+ return typeMatcher.toString();
+ }
+ }, converter);
+ }
+
+ private void internalConvertToTypes(Matcher<? super TypeLiteral<?>> typeMatcher,
+ TypeConverter converter) {
+ converters.add(MatcherAndConverter.newInstance(typeMatcher, converter,
+ SourceProviders.UNKNOWN_SOURCE));
+ }
+
+ @Override public Boolean visitConvertToTypes(ConvertToTypesCommand command) {
+ converters.add(MatcherAndConverter.newInstance(
+ command.getTypeMatcher(), command.getTypeConverter()));
+ return true;
+ }
+}
diff --git a/src/com/google/inject/ErrorMessages.java b/src/com/google/inject/ErrorMessages.java
index 47cddf4..321d2c8 100644
--- a/src/com/google/inject/ErrorMessages.java
+++ b/src/com/google/inject/ErrorMessages.java
@@ -123,9 +123,6 @@
static final String SCOPE_NOT_FOUND = "No scope is bound to %s.";
- static final String SINGLE_INSTANCE_AND_SCOPE = "Setting the scope is not"
- + " permitted when binding to a single instance.";
-
static final String CONSTRUCTOR_RULES = "Classes must have either one (and"
+ " only one) constructor annotated with @Inject or a zero-argument"
+ " constructor.";
@@ -149,14 +146,6 @@
+ " classes is not supported. Please use a 'static' class (top-level or"
+ " nested) instead.";
- static final String ANNOTATION_ALREADY_SPECIFIED = "More than one annotation"
- + " is specified for this binding.";
-
- static final String IMPLEMENTATION_ALREADY_SET = "Implementation is set more"
- + " than once.";
-
- static final String SCOPE_ALREADY_SET = "Scope is set more than once.";
-
static final String DUPLICATE_BINDING_ANNOTATIONS =
"Found more than one annotation annotated with @BindingAnnotation:"
+ " %s and %s";
@@ -164,9 +153,6 @@
static final String DUPLICATE_SCOPE_ANNOTATIONS = "More than one scope"
+ " annotation was found: %s and %s";
- static final String CONSTANT_VALUE_ALREADY_SET = "Constant value is set more"
- + " than once.";
-
static final String RECURSIVE_BINDING = "Binding points to itself.";
static final String BINDING_ALREADY_SET = "A binding to %s was already"
diff --git a/src/com/google/inject/ErrorsCommandProcessor.java b/src/com/google/inject/ErrorsCommandProcessor.java
new file mode 100644
index 0000000..c83c59b
--- /dev/null
+++ b/src/com/google/inject/ErrorsCommandProcessor.java
@@ -0,0 +1,50 @@
+/**
+ * Copyright (C) 2008 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;
+
+import com.google.inject.commands.AddMessageErrorCommand;
+import com.google.inject.commands.AddThrowableErrorCommand;
+
+import java.util.logging.Level;
+import java.util.logging.Logger;
+
+/**
+ * Handles {@link Binder#addError} commands.
+ *
+ * @author crazybob@google.com (Bob Lee)
+ * @author jessewilson@google.com (Jesse Wilson)
+ */
+class ErrorsCommandProcessor extends CommandProcessor {
+
+ private static final Logger logger
+ = Logger.getLogger(ErrorsCommandProcessor.class.getName());
+
+ @Override public Boolean visitAddMessageError(AddMessageErrorCommand command) {
+ addError(command.getSource(), command.getMessage(), command.getArguments());
+ return true;
+ }
+
+ @Override public Boolean visitAddError(AddThrowableErrorCommand command) {
+ Object source = command.getSource();
+ String message = ErrorMessages.getRootMessage(command.getThrowable());
+ String logMessage = String.format(
+ ErrorMessages.EXCEPTION_REPORTED_BY_MODULE, message);
+ logger.log(Level.INFO, logMessage, command.getThrowable());
+ addError(source, ErrorMessages.EXCEPTION_REPORTED_BY_MODULE_SEE_LOG, message);
+ return true;
+ }
+}
diff --git a/src/com/google/inject/FactoryProxy.java b/src/com/google/inject/FactoryProxy.java
new file mode 100644
index 0000000..f6767b1
--- /dev/null
+++ b/src/com/google/inject/FactoryProxy.java
@@ -0,0 +1,59 @@
+/**
+ * Copyright (C) 2008 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;
+
+import com.google.inject.internal.ToStringBuilder;
+
+/**
+ * A placeholder which enables us to swap in the real factory once the
+ * container is created.
+ */
+class FactoryProxy<T> implements InternalFactory<T>,
+ BindCommandProcessor.CreationListener {
+
+ private final Key<T> key;
+ private final Key<? extends T> targetKey;
+ private final Object source;
+
+ InternalFactory<? extends T> targetFactory;
+
+ FactoryProxy(Key<T> key, Key<? extends T> targetKey, Object source) {
+ this.key = key;
+ this.targetKey = targetKey;
+ this.source = source;
+ }
+
+ public void notify(final InjectorImpl injector) {
+ injector.withDefaultSource(source, new Runnable() {
+ public void run() {
+ targetFactory = injector.getInternalFactory(targetKey);
+ }
+ });
+ }
+
+ public T get(InternalContext context, InjectionPoint<?> injectionPoint) {
+ return targetFactory.get(context, injectionPoint);
+ }
+
+ public String toString() {
+ return new ToStringBuilder(FactoryProxy.class)
+ .add("key", key)
+ .add("provider", targetFactory)
+ .toString();
+ }
+}
diff --git a/src/com/google/inject/GetProviderProcessor.java b/src/com/google/inject/GetProviderProcessor.java
new file mode 100644
index 0000000..73a9a6d
--- /dev/null
+++ b/src/com/google/inject/GetProviderProcessor.java
@@ -0,0 +1,45 @@
+/**
+ * Copyright (C) 2008 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;
+
+import com.google.inject.commands.GetProviderCommand;
+
+/**
+ * Handles {@link Binder#getProvider} commands.
+ *
+ * @author crazybob@google.com (Bob Lee)
+ * @author jessewilson@google.com (Jesse Wilson)
+ */
+class GetProviderProcessor extends CommandProcessor {
+
+ private final InjectorImpl injector;
+
+ GetProviderProcessor(InjectorImpl injector) {
+ this.injector = injector;
+ }
+
+ @Override public <T> Boolean visitGetProvider(GetProviderCommand<T> command) {
+ try {
+ // ensure the provider can be created
+ injector.getProvider(command.getKey());
+ } catch (ConfigurationException e) {
+ ErrorMessages.handleMissingBinding(injector, command.getSource(), command.getKey());
+ }
+
+ return true;
+ }
+}
diff --git a/src/com/google/inject/Guice.java b/src/com/google/inject/Guice.java
index 900fea5..7c23e72 100644
--- a/src/com/google/inject/Guice.java
+++ b/src/com/google/inject/Guice.java
@@ -128,11 +128,11 @@
public static Injector createInjector(
Injector parent, Stage stage,
Iterable<? extends Module> modules) {
- BinderImpl binder = new BinderImpl(stage);
- for (Module module : modules) {
- binder.install(module);
- }
- return binder.createInjector(parent);
+ return new InjectorBuilder()
+ .stage(stage)
+ .parentInjector(parent)
+ .addModules(modules)
+ .build();
}
}
diff --git a/src/com/google/inject/InjectorBuilder.java b/src/com/google/inject/InjectorBuilder.java
new file mode 100644
index 0000000..cf02d38
--- /dev/null
+++ b/src/com/google/inject/InjectorBuilder.java
@@ -0,0 +1,271 @@
+/**
+ * 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;
+
+import static com.google.inject.Scopes.SINGLETON;
+import com.google.inject.commands.Command;
+import com.google.inject.commands.CommandRecorder;
+import com.google.inject.commands.FutureInjector;
+import com.google.inject.internal.Stopwatch;
+import com.google.inject.spi.Message;
+import com.google.inject.spi.SourceProviders;
+
+import java.lang.reflect.Member;
+import java.util.ArrayList;
+import java.util.Collection;
+import java.util.List;
+import java.util.LinkedList;
+import java.util.logging.Logger;
+
+/**
+ * Builds a dependency injection {@link Injector}.
+ *
+ * @author crazybob@google.com (Bob Lee)
+ * @author jessewilson@google.com (Jesse Wilson)
+ */
+class InjectorBuilder {
+
+ private final Stopwatch stopwatch = new Stopwatch();
+
+ private Injector parent;
+ private Stage stage;
+ private final List<Module> modules = new LinkedList<Module>();
+
+ private final ConfigurationErrorHandler configurationErrorHandler
+ = new ConfigurationErrorHandler();
+
+ private InjectorImpl injector;
+
+ private final FutureInjector futureInjector = new FutureInjector();
+ private final List<Command> commands = new ArrayList<Command>();
+
+ private BindCommandProcessor bindCommandProcesor;
+ private RequestStaticInjectionCommandProcessor requestStaticInjectionCommandProcessor;
+
+ /**
+ * @param stage we're running in. If the stage is {@link Stage#PRODUCTION},
+ * we will eagerly load singletons.
+ */
+ InjectorBuilder stage(Stage stage) {
+ this.stage = stage;
+ return this;
+ }
+
+ InjectorBuilder parentInjector(Injector parent) {
+ this.parent = parent;
+ return this;
+ }
+
+ InjectorBuilder addModules(Iterable<? extends Module> modules) {
+ for (Module module : modules) {
+ this.modules.add(module);
+ }
+ return this;
+ }
+
+ Injector build() {
+ if (injector != null) {
+ throw new AssertionError("Already built, builders are not reusable.");
+ }
+
+ modules.add(0, new BuiltInModule(injector, stage));
+
+ CommandRecorder commandRecorder = new CommandRecorder(futureInjector);
+ commandRecorder.setCurrentStage(stage);
+ commands.addAll(commandRecorder.recordCommands(modules));
+
+ injector = new InjectorImpl(parent);
+ injector.setErrorHandler(configurationErrorHandler);
+
+ buildCoreInjector();
+
+ validate();
+
+ injector.setErrorHandler(RuntimeErrorHandler.INSTANCE);
+
+ // If we're in the tool stage, stop here. Don't eagerly inject or load
+ // anything.
+ if (stage == Stage.TOOL) {
+ // TODO: Wrap this and prevent usage of anything besides getBindings().
+ return injector;
+ }
+
+ fulfillInjectionRequests();
+
+ if (!commands.isEmpty()) {
+ throw new AssertionError("Failed to execute " + commands);
+ }
+
+ return injector;
+ }
+
+ /**
+ * Builds the injector.
+ */
+ private void buildCoreInjector() {
+ new ErrorsCommandProcessor()
+ .processCommands(commands, configurationErrorHandler);
+
+ BindInterceptorCommandProcessor bindInterceptorCommandProcessor
+ = new BindInterceptorCommandProcessor();
+ bindInterceptorCommandProcessor.processCommands(commands, configurationErrorHandler);
+ injector.constructionProxyFactory = bindInterceptorCommandProcessor.createProxyFactory();
+ stopwatch.resetAndLog("Interceptors creation");
+
+ new ScopesCommandProcessor(injector.scopes)
+ .processCommands(commands, configurationErrorHandler);
+ stopwatch.resetAndLog("Scopes creation");
+
+ new ConvertToTypesCommandProcessor(injector.converters)
+ .processCommands(commands, configurationErrorHandler);
+ stopwatch.resetAndLog("Converters creation");
+
+ bindCommandProcesor = new BindCommandProcessor(
+ injector, injector.scopes, stage, injector.explicitBindings);
+ bindCommandProcesor.processCommands(commands, configurationErrorHandler);
+ stopwatch.resetAndLog("Binding creation");
+
+ injector.index();
+ stopwatch.resetAndLog("Binding indexing");
+
+ requestStaticInjectionCommandProcessor = new RequestStaticInjectionCommandProcessor();
+ requestStaticInjectionCommandProcessor
+ .processCommands(commands, configurationErrorHandler);
+ stopwatch.resetAndLog("Static injection");
+ }
+
+ /**
+ * Validate everything that we can validate now that the injector is ready
+ * for use.
+ */
+ private void validate() {
+ bindCommandProcesor.runCreationListeners(injector);
+ stopwatch.resetAndLog("Validation");
+
+ requestStaticInjectionCommandProcessor.validate(injector);
+ stopwatch.resetAndLog("Static validation");
+
+ bindCommandProcesor.validate(injector);
+ stopwatch.resetAndLog("Instance member validation");
+
+ new GetProviderProcessor(injector)
+ .processCommands(commands, configurationErrorHandler);
+ stopwatch.resetAndLog("Provider verification");
+
+ configurationErrorHandler.blowUpIfErrorsExist();
+ }
+
+ /**
+ * Inject everything that can be injected. This uses runtime error handling.
+ */
+ private void fulfillInjectionRequests() {
+ futureInjector.initialize(injector);
+
+ // TODO(jessewilson): sort these injections by their dependencies
+ requestStaticInjectionCommandProcessor.injectMembers(injector);
+ stopwatch.resetAndLog("Static member injection");
+ bindCommandProcesor.injectMembers(injector);
+ stopwatch.resetAndLog("Instance injection");
+
+ bindCommandProcesor.runPreloaders(injector);
+ stopwatch.resetAndLog("Preloading");
+ }
+
+ private static class BuiltInModule extends AbstractModule {
+ final Injector injector;
+ final Stage stage;
+
+ private BuiltInModule(Injector injector, Stage stage) {
+ this.injector = injector;
+ this.stage = stage;
+ }
+
+ protected void configure() {
+ SourceProviders.withDefault(SourceProviders.UNKNOWN_SOURCE, new Runnable() {
+ public void run() {
+ // TODO(jessewilson): use a real logger
+ // bind(Logger.class).toInternalFactory(new LoggerFactory());
+ bind(Logger.class).toInstance(Logger.getLogger(""));
+ 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));
+
+ }
+ });
+ }
+
+ class InjectorProvider implements Provider<Injector> {
+ final Injector injector;
+
+ InjectorProvider(Injector injector) {
+ this.injector = injector;
+ }
+
+ public Injector get() {
+ return injector;
+ }
+
+ public String toString() {
+ return "Provider<Injector>";
+ }
+ }
+
+ class LoggerFactory implements InternalFactory<Logger> {
+ public Logger get(InternalContext context, InjectionPoint<?> injectionPoint) {
+ Member member = injectionPoint.getMember();
+ return member == null
+ ? Logger.getAnonymousLogger()
+ : Logger.getLogger(member.getDeclaringClass().getName());
+ }
+
+ public String toString() {
+ return "Provider<Logger>";
+ }
+ }
+ }
+
+ /**
+ * Handles errors while the injector is being created.
+ */
+ private class ConfigurationErrorHandler extends AbstractErrorHandler {
+ final Collection<Message> errorMessages = new ArrayList<Message>();
+
+ public void handle(Object source, String message) {
+ errorMessages.add(new Message(source, message));
+ }
+
+ void blowUpIfErrorsExist() {
+ if (!errorMessages.isEmpty()) {
+ throw new CreationException(errorMessages);
+ }
+ }
+ }
+
+ /**
+ * Handles errors after the injector is created.
+ */
+ private static class RuntimeErrorHandler extends AbstractErrorHandler {
+ static ErrorHandler INSTANCE = new RuntimeErrorHandler();
+
+ public void handle(Object source, String message) {
+ throw new ConfigurationException("Error at " + source + " " + message);
+ }
+ }
+}
diff --git a/src/com/google/inject/InjectorImpl.java b/src/com/google/inject/InjectorImpl.java
index 72bf939..ed34caf 100644
--- a/src/com/google/inject/InjectorImpl.java
+++ b/src/com/google/inject/InjectorImpl.java
@@ -53,7 +53,7 @@
* Default {@link Injector} implementation.
*
* @author crazybob@google.com (Bob Lee)
- * @see BinderImpl
+ * @see InjectorBuilder
*/
class InjectorImpl implements Injector {
@@ -85,27 +85,22 @@
PRIMITIVE_COUNTERPARTS = Collections.unmodifiableMap(counterparts);
}
- final ConstructionProxyFactory constructionProxyFactory;
- final Map<Key<?>, BindingImpl<?>> explicitBindings;
- final BindingsMultimap bindingsMultimap = new BindingsMultimap();
- final Map<Class<? extends Annotation>, Scope> scopes;
- final List<MatcherAndConverter<?>> converters;
final Injector parentInjector;
+ ConstructionProxyFactory constructionProxyFactory;
+ final Map<Key<?>, BindingImpl<?>> explicitBindings
+ = new HashMap<Key<?>, BindingImpl<?>>();
+ final BindingsMultimap bindingsMultimap = new BindingsMultimap();
+ final Map<Class<? extends Annotation>, Scope> scopes
+ = new HashMap<Class<? extends Annotation>, Scope>();
+ final List<MatcherAndConverter<?>> converters
+ = new ArrayList<MatcherAndConverter<?>>();
final Map<Key<?>, BindingImpl<?>> parentBindings
= new HashMap<Key<?>, BindingImpl<?>>();
ErrorHandler errorHandler = new InvalidErrorHandler();
- InjectorImpl(Injector parentInjector,
- ConstructionProxyFactory constructionProxyFactory,
- Map<Key<?>, BindingImpl<?>> bindings,
- Map<Class<? extends Annotation>, Scope> scopes,
- List<MatcherAndConverter<?>> converters) {
+ InjectorImpl(Injector parentInjector) {
this.parentInjector = parentInjector;
- this.constructionProxyFactory = constructionProxyFactory;
- this.explicitBindings = bindings;
- this.scopes = scopes;
- this.converters = converters;
}
/**
diff --git a/src/com/google/inject/InstanceBindingImpl.java b/src/com/google/inject/InstanceBindingImpl.java
new file mode 100644
index 0000000..f6ab05f
--- /dev/null
+++ b/src/com/google/inject/InstanceBindingImpl.java
@@ -0,0 +1,66 @@
+/**
+ * Copyright (C) 2008 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;
+
+import com.google.inject.spi.InstanceBinding;
+import com.google.inject.spi.BindingVisitor;
+import com.google.inject.spi.Dependency;
+import com.google.inject.util.Providers;
+import com.google.inject.internal.ToStringBuilder;
+
+import java.util.Collection;
+
+class InstanceBindingImpl<T> extends BindingImpl<T>
+ implements InstanceBinding<T> {
+
+ final T instance;
+ final Provider<T> provider;
+
+ InstanceBindingImpl(InjectorImpl injector, Key<T> key, Object source,
+ InternalFactory<? extends T> internalFactory, T instance) {
+ super(injector, key, source, internalFactory, Scopes.NO_SCOPE);
+ this.instance = instance;
+ this.provider = Providers.of(instance);
+ }
+
+ @Override
+ public Provider<T> getProvider() {
+ return this.provider;
+ }
+
+ public void accept(BindingVisitor<? super T> bindingVisitor) {
+ bindingVisitor.visit(this);
+ }
+
+ public T getInstance() {
+ return this.instance;
+ }
+
+ public Collection<Dependency<?>> getDependencies() {
+ return injector.getFieldAndMethodDependenciesFor(instance.getClass());
+ }
+
+ @Override
+ public String toString() {
+ return new ToStringBuilder(InstanceBinding.class)
+ .add("key", key)
+ .add("instance", instance)
+ .add("source", source)
+ .toString();
+ }
+}
diff --git a/src/com/google/inject/MethodAspect.java b/src/com/google/inject/MethodAspect.java
index 948aef3..26e0e75 100644
--- a/src/com/google/inject/MethodAspect.java
+++ b/src/com/google/inject/MethodAspect.java
@@ -21,6 +21,9 @@
import java.lang.reflect.Method;
import java.util.Arrays;
import java.util.List;
+import java.util.Collection;
+import java.util.ArrayList;
+
import org.aopalliance.intercept.MethodInterceptor;
/**
@@ -35,11 +38,10 @@
final List<MethodInterceptor> interceptors;
MethodAspect(Matcher<? super Class<?>> classMatcher,
- Matcher<? super Method> methodMatcher, MethodInterceptor... interceptors) {
+ Matcher<? super Method> methodMatcher, List<MethodInterceptor> interceptors) {
this.classMatcher = Objects.nonNull(classMatcher, "class matcher");
this.methodMatcher = Objects.nonNull(methodMatcher, "method matcher");
- this.interceptors
- = Arrays.asList(Objects.nonNull(interceptors, "interceptors"));
+ this.interceptors = Objects.nonNull(interceptors, "interceptors");
}
boolean matches(Class<?> clazz) {
diff --git a/src/com/google/inject/ProxyFactoryBuilder.java b/src/com/google/inject/ProxyFactoryBuilder.java
index bb915bc..62c1cff 100644
--- a/src/com/google/inject/ProxyFactoryBuilder.java
+++ b/src/com/google/inject/ProxyFactoryBuilder.java
@@ -20,6 +20,9 @@
import java.lang.reflect.Method;
import java.util.ArrayList;
import java.util.List;
+import java.util.Collection;
+import java.util.Arrays;
+
import org.aopalliance.intercept.MethodInterceptor;
/**
@@ -43,12 +46,17 @@
*/
public ProxyFactoryBuilder intercept(Matcher<? super Class<?>> classMatcher,
Matcher<? super Method> methodMatcher,
- MethodInterceptor... interceptors) {
- methodAspects.add(
- new MethodAspect(classMatcher, methodMatcher, interceptors));
+ List<MethodInterceptor> interceptors) {
+ methodAspects.add(new MethodAspect(classMatcher, methodMatcher, interceptors));
return this;
}
+ public ProxyFactoryBuilder intercept(Matcher<? super Class<?>> classMatcher,
+ Matcher<? super Method> methodMatcher,
+ MethodInterceptor... interceptors) {
+ return intercept(classMatcher, methodMatcher, Arrays.asList(interceptors));
+ }
+
/**
* Creates a {@code ProxyFactory}.
*/
diff --git a/src/com/google/inject/RequestStaticInjectionCommandProcessor.java b/src/com/google/inject/RequestStaticInjectionCommandProcessor.java
new file mode 100644
index 0000000..401cb6a
--- /dev/null
+++ b/src/com/google/inject/RequestStaticInjectionCommandProcessor.java
@@ -0,0 +1,91 @@
+/**
+ * Copyright (C) 2008 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;
+
+import com.google.inject.commands.RequestStaticInjectionCommand;
+
+import java.util.ArrayList;
+import java.util.List;
+
+/**
+ * Handles {@link Binder#requestStaticInjection} commands.
+ *
+ * @author crazybob@google.com (Bob Lee)
+ * @author jessewilson@google.com (Jesse Wilson)
+ */
+class RequestStaticInjectionCommandProcessor extends CommandProcessor {
+
+ private final List<StaticInjection> staticInjections
+ = new ArrayList<StaticInjection>();
+
+ @Override public Boolean visitRequestStaticInjection(RequestStaticInjectionCommand command) {
+ for (Class<?> type : command.getTypes()) {
+ staticInjections.add(new StaticInjection(command.getSource(), type));
+ }
+ return true;
+ }
+
+ public void validate(InjectorImpl injector) {
+ for (StaticInjection staticInjection : staticInjections) {
+ staticInjection.validate(injector);
+ }
+ }
+
+ public void injectMembers(InjectorImpl injector) {
+ for (StaticInjection staticInjection : staticInjections) {
+ staticInjection.injectMembers(injector);
+ }
+ }
+
+ /**
+ * A requested static injection.
+ */
+ private class StaticInjection {
+ final Object source;
+ final Class<?> type;
+ final List<InjectorImpl.SingleMemberInjector> memberInjectors
+ = new ArrayList<InjectorImpl.SingleMemberInjector>();
+
+ public StaticInjection(Object source, Class type) {
+ this.source = source;
+ this.type = type;
+ }
+
+ void validate(final InjectorImpl injector) {
+ injector.withDefaultSource(source,
+ new Runnable() {
+ public void run() {
+ injector.addSingleInjectorsForFields(
+ type.getDeclaredFields(), true, memberInjectors);
+ injector.addSingleInjectorsForMethods(
+ type.getDeclaredMethods(), true, memberInjectors);
+ }
+ });
+ }
+
+ void injectMembers(InjectorImpl injector) {
+ injector.callInContext(new ContextualCallable<Void>() {
+ public Void call(InternalContext context) {
+ for (InjectorImpl.SingleMemberInjector injector : memberInjectors) {
+ injector.inject(context, null);
+ }
+ return null;
+ }
+ });
+ }
+ }
+}
\ No newline at end of file
diff --git a/src/com/google/inject/ScopesCommandProcessor.java b/src/com/google/inject/ScopesCommandProcessor.java
new file mode 100644
index 0000000..317e914
--- /dev/null
+++ b/src/com/google/inject/ScopesCommandProcessor.java
@@ -0,0 +1,67 @@
+/**
+ * Copyright (C) 2008 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;
+
+import com.google.inject.commands.BindScopeCommand;
+import com.google.inject.internal.Annotations;
+import static com.google.inject.internal.Objects.nonNull;
+import com.google.inject.internal.StackTraceElements;
+
+import java.lang.annotation.Annotation;
+import java.util.Map;
+
+/**
+ * Handles {@link Binder#bindScope} commands.
+ *
+ * @author crazybob@google.com (Bob Lee)
+ * @author jessewilson@google.com (Jesse Wilson)
+ */
+class ScopesCommandProcessor extends CommandProcessor {
+
+ private final Map<Class<? extends Annotation>, Scope> scopes;
+
+ ScopesCommandProcessor(Map<Class<? extends Annotation>, Scope> scopes) {
+ this.scopes = scopes;
+ }
+
+ @Override public Boolean visitBindScope(BindScopeCommand command) {
+ Scope scope = command.getScope();
+ Class<? extends Annotation> annotationType = command.getAnnotationType();
+
+ if (!Scopes.isScopeAnnotation(annotationType)) {
+ addError(StackTraceElements.forType(annotationType),
+ ErrorMessages.MISSING_SCOPE_ANNOTATION);
+ // Go ahead and bind anyway so we don't get collateral errors.
+ }
+
+ if (!Annotations.isRetainedAtRuntime(annotationType)) {
+ addError(StackTraceElements.forType(annotationType),
+ ErrorMessages.MISSING_RUNTIME_RETENTION, command.getSource());
+ // Go ahead and bind anyway so we don't get collateral errors.
+ }
+
+ Scope existing = scopes.get(nonNull(annotationType, "annotation type"));
+ if (existing != null) {
+ addError(command.getSource(), ErrorMessages.DUPLICATE_SCOPES, existing,
+ annotationType, scope);
+ } else {
+ scopes.put(annotationType, nonNull(scope, "scope"));
+ }
+
+ return true;
+ }
+}
\ No newline at end of file
diff --git a/src/com/google/inject/internal/Stopwatch.java b/src/com/google/inject/internal/Stopwatch.java
index 07e4b05..268f913 100644
--- a/src/com/google/inject/internal/Stopwatch.java
+++ b/src/com/google/inject/internal/Stopwatch.java
@@ -24,8 +24,9 @@
* @author crazybob@google.com (Bob Lee)
*/
public class Stopwatch {
+ private static final Logger logger = Logger.getLogger(Stopwatch.class.getName());
- long start = System.currentTimeMillis();
+ private long start = System.currentTimeMillis();
/**
* Resets and returns elapsed time in milliseconds.
@@ -42,7 +43,7 @@
/**
* Resets and logs elapsed time in milliseconds.
*/
- public void resetAndLog(Logger logger, String label) {
+ public void resetAndLog(String label) {
logger.fine(label + ": " + reset() + "ms");
}
}
diff --git a/test/com/google/inject/BoundProviderTest.java b/test/com/google/inject/BoundProviderTest.java
index df20ba7..5fc46f4 100644
--- a/test/com/google/inject/BoundProviderTest.java
+++ b/test/com/google/inject/BoundProviderTest.java
@@ -24,12 +24,14 @@
public class BoundProviderTest extends TestCase {
public void testFooProvider() throws CreationException {
- BinderImpl cb = new BinderImpl();
- cb.bind(Foo.class).toProvider(FooProvider.class);
- Injector c = cb.createInjector();
+ Injector injector = Guice.createInjector(new AbstractModule() {
+ protected void configure() {
+ bind(Foo.class).toProvider(FooProvider.class);
+ }
+ });
- Foo a = c.getInstance(Foo.class);
- Foo b = c.getInstance(Foo.class);
+ Foo a = injector.getInstance(Foo.class);
+ Foo b = injector.getInstance(Foo.class);
assertEquals(0, a.i);
assertEquals(0, b.i);
@@ -39,12 +41,14 @@
}
public void testSingletonFooProvider() throws CreationException {
- BinderImpl cb = new BinderImpl();
- cb.bind(Foo.class).toProvider(SingletonFooProvider.class);
- Injector c = cb.createInjector();
+ Injector injector = Guice.createInjector(new AbstractModule() {
+ protected void configure() {
+ bind(Foo.class).toProvider(SingletonFooProvider.class);
+ }
+ });
- Foo a = c.getInstance(Foo.class);
- Foo b = c.getInstance(Foo.class);
+ Foo a = injector.getInstance(Foo.class);
+ Foo b = injector.getInstance(Foo.class);
assertEquals(0, a.i);
assertEquals(1, b.i);
diff --git a/test/com/google/inject/CircularDependencyTest.java b/test/com/google/inject/CircularDependencyTest.java
index ad50b31..018be1d 100644
--- a/test/com/google/inject/CircularDependencyTest.java
+++ b/test/com/google/inject/CircularDependencyTest.java
@@ -25,11 +25,13 @@
public void testCircularlyDependentConstructors()
throws CreationException {
- BinderImpl builder = new BinderImpl();
- builder.bind(A.class).to(AImpl.class);
- builder.bind(B.class).to(BImpl.class);
+ Injector injector = Guice.createInjector(new AbstractModule() {
+ protected void configure() {
+ bind(A.class).to(AImpl.class);
+ bind(B.class).to(BImpl.class);
+ }
+ });
- Injector injector = builder.createInjector();
A a = injector.getInstance(A.class);
assertNotNull(a.getB().getA());
}
diff --git a/test/com/google/inject/ConstantConversionTest.java b/test/com/google/inject/ConstantConversionTest.java
index 660608d..78b3227 100644
--- a/test/com/google/inject/ConstantConversionTest.java
+++ b/test/com/google/inject/ConstantConversionTest.java
@@ -61,10 +61,13 @@
}
public void testOneConstantInjection() throws CreationException {
- BinderImpl builder = new BinderImpl();
- builder.bindConstant().annotatedWith(NumericValue.class).to("5");
- builder.bind(Simple.class);
- Injector injector = builder.createInjector();
+ Injector injector = Guice.createInjector(new AbstractModule() {
+ protected void configure() {
+ bindConstant().annotatedWith(NumericValue.class).to("5");
+ bind(Simple.class);
+ }
+ });
+
Simple simple = injector.getInstance(Simple.class);
assertEquals(5, simple.i);
}
@@ -74,13 +77,16 @@
}
public void testConstantInjection() throws CreationException {
- BinderImpl b = new BinderImpl();
- b.bindConstant().annotatedWith(NumericValue.class).to("5");
- b.bindConstant().annotatedWith(BooleanValue.class).to("true");
- b.bindConstant().annotatedWith(EnumValue.class).to("TEE");
- b.bindConstant().annotatedWith(ClassName.class).to(Foo.class.getName());
- Injector c = b.createInjector();
- Foo foo = c.getInstance(Foo.class);
+ Injector injector = Guice.createInjector(new AbstractModule() {
+ protected void configure() {
+ bindConstant().annotatedWith(NumericValue.class).to("5");
+ bindConstant().annotatedWith(BooleanValue.class).to("true");
+ bindConstant().annotatedWith(EnumValue.class).to("TEE");
+ bindConstant().annotatedWith(ClassName.class).to(Foo.class.getName());
+ }
+ });
+
+ Foo foo = injector.getInstance(Foo.class);
checkNumbers(
foo.integerField,
@@ -108,11 +114,14 @@
}
public void testInvalidInteger() throws CreationException {
- BinderImpl b = new BinderImpl();
- b.bindConstant().annotatedWith(NumericValue.class).to("invalid");
- Injector c = b.createInjector();
+ Injector injector = Guice.createInjector(new AbstractModule() {
+ protected void configure() {
+ bindConstant().annotatedWith(NumericValue.class).to("invalid");
+ }
+ });
+
try {
- c.getInstance(InvalidInteger.class);
+ injector.getInstance(InvalidInteger.class);
fail();
} catch (ConfigurationException e) { /* expected */ }
}
@@ -122,11 +131,14 @@
}
public void testInvalidCharacter() throws CreationException {
- BinderImpl b = new BinderImpl();
- b.bindConstant().annotatedWith(NumericValue.class).to("invalid");
- Injector c = b.createInjector();
+ Injector injector = Guice.createInjector(new AbstractModule() {
+ protected void configure() {
+ bindConstant().annotatedWith(NumericValue.class).to("invalid");
+ }
+ });
+
try {
- c.getInstance(InvalidCharacter.class);
+ injector.getInstance(InvalidCharacter.class);
fail();
} catch (ConfigurationException e) { /* expected */ }
}
@@ -136,11 +148,14 @@
}
public void testInvalidEnum() throws CreationException {
- BinderImpl b = new BinderImpl();
- b.bindConstant().annotatedWith(NumericValue.class).to("invalid");
- Injector c = b.createInjector();
+ Injector injector = Guice.createInjector(new AbstractModule() {
+ protected void configure() {
+ bindConstant().annotatedWith(NumericValue.class).to("invalid");
+ }
+ });
+
try {
- c.getInstance(InvalidEnum.class);
+ injector.getInstance(InvalidEnum.class);
fail();
} catch (ConfigurationException e) { /* expected */ }
}
@@ -150,10 +165,12 @@
}
public void testToInstanceIsTreatedLikeConstant() throws CreationException {
- BinderImpl b = new BinderImpl();
- b.bind(String.class).toInstance("5");
- b.bind(LongHolder.class);
- Injector c = b.createInjector();
+ Guice.createInjector(new AbstractModule() {
+ protected void configure() {
+ bind(String.class).toInstance("5");
+ bind(LongHolder.class);
+ }
+ });
}
static class LongHolder {
diff --git a/test/com/google/inject/GenericInjectionTest.java b/test/com/google/inject/GenericInjectionTest.java
index 2281b59..74bfc0e 100644
--- a/test/com/google/inject/GenericInjectionTest.java
+++ b/test/com/google/inject/GenericInjectionTest.java
@@ -26,10 +26,14 @@
public class GenericInjectionTest extends TestCase {
public void testGenericInjection() throws CreationException {
- List<String> names = Arrays.asList("foo", "bar", "bob");
- BinderImpl builder = new BinderImpl();
- builder.bind(new TypeLiteral<List<String>>() {}).toInstance(names);
- Injector injector = builder.createInjector();
+ final List<String> names = Arrays.asList("foo", "bar", "bob");
+
+ Injector injector = Guice.createInjector((Module) new AbstractModule() {
+ protected void configure() {
+ bind(new TypeLiteral<List<String>>() {}).toInstance(names);
+ }
+ });
+
Foo foo = injector.getInstance(Foo.class);
assertEquals(names, foo.names);
}
diff --git a/test/com/google/inject/InjectorTest.java b/test/com/google/inject/InjectorTest.java
index cbaa9f4..40a3dc7 100644
--- a/test/com/google/inject/InjectorTest.java
+++ b/test/com/google/inject/InjectorTest.java
@@ -41,15 +41,17 @@
}
public void testProviderMethods() throws CreationException {
- SampleSingleton singleton = new SampleSingleton();
- SampleSingleton other = new SampleSingleton();
+ final SampleSingleton singleton = new SampleSingleton();
+ final SampleSingleton other = new SampleSingleton();
- BinderImpl builder = new BinderImpl();
- builder.bind(SampleSingleton.class).toInstance(singleton);
- builder.bind(SampleSingleton.class)
- .annotatedWith(Other.class)
- .toInstance(other);
- Injector injector = builder.createInjector();
+ Injector injector = Guice.createInjector(new AbstractModule() {
+ protected void configure() {
+ bind(SampleSingleton.class).toInstance(singleton);
+ bind(SampleSingleton.class)
+ .annotatedWith(Other.class)
+ .toInstance(other);
+ }
+ });
assertSame(singleton,
injector.getInstance(Key.get(SampleSingleton.class)));
@@ -96,9 +98,12 @@
public void testIntAndIntegerAreInterchangeable()
throws CreationException {
- BinderImpl builder = new BinderImpl();
- builder.bindConstant().annotatedWith(I.class).to(5);
- Injector injector = builder.createInjector();
+ Injector injector = Guice.createInjector(new AbstractModule() {
+ protected void configure() {
+ bindConstant().annotatedWith(I.class).to(5);
+ }
+ });
+
IntegerWrapper iw = injector.getInstance(IntegerWrapper.class);
assertEquals(5, (int) iw.i);
}
@@ -175,11 +180,13 @@
}
public void testInjectStatics() throws CreationException {
- BinderImpl builder = new BinderImpl();
- builder.bindConstant().annotatedWith(S.class).to("test");
- builder.bindConstant().annotatedWith(I.class).to(5);
- builder.requestStaticInjection(Static.class);
- builder.createInjector();
+ Guice.createInjector(new AbstractModule() {
+ protected void configure() {
+ bindConstant().annotatedWith(S.class).to("test");
+ bindConstant().annotatedWith(I.class).to(5);
+ requestStaticInjection(Static.class);
+ }
+ });
assertEquals("test", Static.s);
assertEquals(5, Static.i);
diff --git a/test/com/google/inject/IntegrationTest.java b/test/com/google/inject/IntegrationTest.java
index 91923b8..2132898 100644
--- a/test/com/google/inject/IntegrationTest.java
+++ b/test/com/google/inject/IntegrationTest.java
@@ -27,12 +27,14 @@
public class IntegrationTest extends TestCase {
public void testIntegration() throws CreationException {
- CountingInterceptor counter = new CountingInterceptor();
+ final CountingInterceptor counter = new CountingInterceptor();
- BinderImpl binder = new BinderImpl();
- binder.bind(Foo.class);
- binder.bindInterceptor(any(), any(), counter);
- Injector injector = binder.createInjector();
+ Injector injector = Guice.createInjector(new AbstractModule() {
+ protected void configure() {
+ bind(Foo.class);
+ bindInterceptor(any(), any(), counter);
+ }
+ });
Foo foo = injector.getInstance(Key.get(Foo.class));
foo.foo();
diff --git a/test/com/google/inject/NotRequiredTest.java b/test/com/google/inject/NotRequiredTest.java
index 6cf6067..234518d 100644
--- a/test/com/google/inject/NotRequiredTest.java
+++ b/test/com/google/inject/NotRequiredTest.java
@@ -24,10 +24,13 @@
public class NotRequiredTest extends TestCase {
public void testProvided() throws CreationException {
- BinderImpl builder = new BinderImpl();
- builder.bind(Bar.class).to(BarImpl.class);
- Injector c = builder.createInjector();
- Foo foo = c.getInstance(Foo.class);
+ Injector injector = Guice.createInjector(new AbstractModule() {
+ protected void configure() {
+ bind(Bar.class).to(BarImpl.class);
+ }
+ });
+
+ Foo foo = injector.getInstance(Foo.class);
assertNotNull(foo.bar);
assertNotNull(foo.fromMethod);
}
diff --git a/test/com/google/inject/PreloadingTest.java b/test/com/google/inject/PreloadingTest.java
index e8b92dc..51f618f 100644
--- a/test/com/google/inject/PreloadingTest.java
+++ b/test/com/google/inject/PreloadingTest.java
@@ -29,24 +29,24 @@
}
public void testPreloadSome() throws CreationException {
- BinderImpl builder = createBinder(Stage.DEVELOPMENT);
- builder.createInjector();
+ createBinder(Stage.DEVELOPMENT);
assertEquals(1, Foo.count);
assertEquals(0, Bar.count);
}
public void testPreloadAll() throws CreationException {
- BinderImpl builder = createBinder(Stage.PRODUCTION);
- builder.createInjector();
+ createBinder(Stage.PRODUCTION);
assertEquals(1, Foo.count);
assertEquals(1, Bar.count);
}
- private BinderImpl createBinder(Stage stage) {
- BinderImpl builder = new BinderImpl(stage);
- builder.bind(Foo.class).asEagerSingleton();
- builder.bind(Bar.class);
- return builder;
+ private Injector createBinder(Stage stage) {
+ return Guice.createInjector(stage, new AbstractModule() {
+ protected void configure() {
+ bind(Foo.class).asEagerSingleton();
+ bind(Bar.class);
+ }
+ });
}
static class Foo {
diff --git a/test/com/google/inject/ProviderInjectionTest.java b/test/com/google/inject/ProviderInjectionTest.java
index abc172c..449ba7c 100644
--- a/test/com/google/inject/ProviderInjectionTest.java
+++ b/test/com/google/inject/ProviderInjectionTest.java
@@ -27,12 +27,12 @@
public class ProviderInjectionTest extends TestCase {
public void testProviderInjection() throws CreationException {
- BinderImpl builder = new BinderImpl();
-
- builder.bind(Bar.class);
- builder.bind(SampleSingleton.class).in(Scopes.SINGLETON);
-
- Injector injector = builder.createInjector();
+ Injector injector = Guice.createInjector(new AbstractModule() {
+ protected void configure() {
+ bind(Bar.class);
+ bind(SampleSingleton.class).in(Scopes.SINGLETON);
+ }
+ });
Foo foo = injector.getInstance(Foo.class);
diff --git a/test/com/google/inject/ReflectionTest.java b/test/com/google/inject/ReflectionTest.java
index 4bd971c..0d0fa1a 100644
--- a/test/com/google/inject/ReflectionTest.java
+++ b/test/com/google/inject/ReflectionTest.java
@@ -29,10 +29,15 @@
@BindingAnnotation @interface I {}
public void testNormalBinding() throws CreationException {
- BinderImpl builder = new BinderImpl();
- Foo foo = new Foo();
- builder.bind(Foo.class).toInstance(foo);
- Injector injector = builder.createInjector();
+ InjectorBuilder builder = new InjectorBuilder();
+ final Foo foo = new Foo();
+
+ Injector injector = Guice.createInjector(new AbstractModule() {
+ protected void configure() {
+ bind(Foo.class).toInstance(foo);
+ }
+ });
+
Binding<Foo> fooBinding = injector.getBinding(Key.get(Foo.class));
assertSame(foo, fooBinding.getProvider().get());
assertNotNull(fooBinding.getSource());
@@ -40,9 +45,12 @@
}
public void testConstantBinding() throws CreationException {
- BinderImpl builder = new BinderImpl();
- builder.bindConstant().annotatedWith(I.class).to(5);
- Injector injector = builder.createInjector();
+ Injector injector = Guice.createInjector(new AbstractModule() {
+ protected void configure() {
+ bindConstant().annotatedWith(I.class).to(5);
+ }
+ });
+
Binding<?> i = injector.getBinding(Key.get(int.class, I.class));
assertEquals(5, i.getProvider().get());
assertNotNull(i.getSource());
@@ -50,11 +58,16 @@
}
public void testLinkedBinding() throws CreationException {
- BinderImpl builder = new BinderImpl();
- Bar bar = new Bar();
- builder.bind(Bar.class).toInstance(bar);
- builder.bind(Key.get(Foo.class)).to(Key.get(Bar.class));
- Injector injector = builder.createInjector();
+ InjectorBuilder builder = new InjectorBuilder();
+ final Bar bar = new Bar();
+
+ Injector injector = Guice.createInjector(new AbstractModule() {
+ protected void configure() {
+ bind(Bar.class).toInstance(bar);
+ bind(Key.get(Foo.class)).to(Key.get(Bar.class));
+ }
+ });
+
Binding<Foo> fooBinding = injector.getBinding(Key.get(Foo.class));
assertSame(bar, fooBinding.getProvider().get());
assertNotNull(fooBinding.getSource());
diff --git a/test/com/google/inject/ScopesTest.java b/test/com/google/inject/ScopesTest.java
index 1603b1d..29236d7 100644
--- a/test/com/google/inject/ScopesTest.java
+++ b/test/com/google/inject/ScopesTest.java
@@ -24,10 +24,12 @@
public class ScopesTest extends TestCase {
public void testSingletonAnnotation() throws CreationException {
- BinderImpl binder = new BinderImpl();
- BindingBuilderImpl<SampleSingleton> bindingBuilder
- = binder.bind(SampleSingleton.class);
- Injector injector = binder.createInjector();
+ Injector injector = Guice.createInjector(new AbstractModule() {
+ protected void configure() {
+ bind(SampleSingleton.class);
+ }
+ });
+
assertSame(
injector.getInstance(SampleSingleton.class),
injector.getInstance(SampleSingleton.class));
@@ -38,9 +40,12 @@
public void testOverriddingAnnotation()
throws CreationException {
- BinderImpl binder = new BinderImpl();
- binder.bind(SampleSingleton.class).in(Scopes.NO_SCOPE);
- Injector injector = binder.createInjector();
+ Injector injector = Guice.createInjector(new AbstractModule() {
+ protected void configure() {
+ bind(SampleSingleton.class).in(Scopes.NO_SCOPE);
+ }
+ });
+
assertNotSame(
injector.getInstance(SampleSingleton.class),
injector.getInstance(SampleSingleton.class));
diff --git a/test/com/google/inject/StaticInjectionTest.java b/test/com/google/inject/StaticInjectionTest.java
index 187360d..6f1ac5f 100644
--- a/test/com/google/inject/StaticInjectionTest.java
+++ b/test/com/google/inject/StaticInjectionTest.java
@@ -32,12 +32,13 @@
@BindingAnnotation @interface S {}
public void testInjectStatics() throws CreationException {
- BinderImpl builder = new BinderImpl();
- builder.bindConstant().annotatedWith(S.class).to("test");
- builder.bindConstant().annotatedWith(I.class).to(5);
- builder.requestStaticInjection(StaticInjectionTest.Static.class);
-
- Injector c = builder.createInjector();
+ Guice.createInjector(new AbstractModule() {
+ protected void configure() {
+ bindConstant().annotatedWith(S.class).to("test");
+ bindConstant().annotatedWith(I.class).to(5);
+ requestStaticInjection(StaticInjectionTest.Static.class);
+ }
+ });
assertEquals("test", StaticInjectionTest.Static.s);
assertEquals(5, StaticInjectionTest.Static.i);
diff --git a/test/com/google/inject/SuperclassTest.java b/test/com/google/inject/SuperclassTest.java
index d39a56c..3dda585 100644
--- a/test/com/google/inject/SuperclassTest.java
+++ b/test/com/google/inject/SuperclassTest.java
@@ -24,9 +24,12 @@
public class SuperclassTest extends TestCase {
public void testSuperclassInjection() throws CreationException {
- BinderImpl builder = new BinderImpl();
- builder.bind(Foo.class);
- Injector injector = builder.createInjector();
+ Injector injector = Guice.createInjector(new AbstractModule() {
+ protected void configure() {
+ bind(Foo.class);
+ }
+ });
+
Provider<Sub> creator = injector.getProvider(Sub.class);
Sub sub = creator.get();
sub = creator.get();