Revision: 1293
Author: sberlin
Date: Sat Oct 16 18:28:06 2010
Log: patch from ramakrishna (with very minor changes from me) for an
extension SPI for assisted inject.
http://code.google.com/p/google-guice/source/detail?r=1293
Added:
/trunk/extensions/assistedinject/src/com/google/inject/assistedinject/AssistedInjectBinding.java
/trunk/extensions/assistedinject/src/com/google/inject/assistedinject/AssistedInjectTargetVisitor.java
/trunk/extensions/assistedinject/src/com/google/inject/assistedinject/AssistedMethod.java
/trunk/extensions/assistedinject/test/com/google/inject/assistedinject/ExtensionSpiTest.java
Modified:
/trunk/extensions/assistedinject/src/com/google/inject/assistedinject/FactoryModuleBuilder.java
/trunk/extensions/assistedinject/src/com/google/inject/assistedinject/FactoryProvider.java
/trunk/extensions/assistedinject/src/com/google/inject/assistedinject/FactoryProvider2.java
=======================================
--- /dev/null
+++
/trunk/extensions/assistedinject/src/com/google/inject/assistedinject/AssistedInjectBinding.java
Sat Oct 16 18:28:06 2010
@@ -0,0 +1,37 @@
+/**
+ * Copyright (C) 2010 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.assistedinject;
+
+import com.google.inject.Key;
+
+import java.util.Collection;
+
+/**
+ * A binding for a factory created by FactoryModuleBuilder.
+ *
+ * @param <T> The fully qualified type of the factory.
+ *
+ * @author ramakris...@google.com (Ramakrishna Rajanna)
+ */
+public interface AssistedInjectBinding<T> {
+
+ /** Returns the {...@link Key} for the factory binding. */
+ Key<T> getKey();
+
+ /** Returns an {...@link AssistedMethod} for each method in the factory. */
+ Collection<AssistedMethod> getAssistedMethods();
+}
=======================================
--- /dev/null
+++
/trunk/extensions/assistedinject/src/com/google/inject/assistedinject/AssistedInjectTargetVisitor.java
Sat Oct 16 18:28:06 2010
@@ -0,0 +1,35 @@
+/**
+ * Copyright (C) 2010 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.assistedinject;
+
+import com.google.inject.spi.BindingTargetVisitor;
+
+/**
+ * A visitor for the AssistedInject extension.
+ * <p>
+ * If your {...@link BindingTargetVisitor} implements this interface,
bindings created by using
+ * {...@link FactoryModuleBuilder} will be visited through this interface.
+ *
+ * @author ramakris...@google.com (Ramakrishna Rajanna)
+ */
+public interface AssistedInjectTargetVisitor<T, V> extends
BindingTargetVisitor<T, V> {
+
+ /**
+ * Visits an {...@link AssistedInjectBinding} created through {...@link
FactoryModuleBuilder}.
+ */
+ V visit(AssistedInjectBinding<? extends T> assistedInjectBinding);
+}
=======================================
--- /dev/null
+++
/trunk/extensions/assistedinject/src/com/google/inject/assistedinject/AssistedMethod.java
Sat Oct 16 18:28:06 2010
@@ -0,0 +1,55 @@
+/**
+ * Copyright (C) 2010 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.assistedinject;
+
+import com.google.inject.TypeLiteral;
+import com.google.inject.spi.Dependency;
+
+import java.lang.reflect.Constructor;
+import java.lang.reflect.Method;
+import java.util.Set;
+
+/**
+ * Details about how a method in an assisted inject factory will be
assisted.
+ *
+ * @author ramakris...@google.com (Ramakrishna Rajanna)
+ */
+public interface AssistedMethod {
+
+ /**
+ * Returns the factory method that is being assisted.
+ */
+ Method getFactoryMethod();
+
+ /**
+ * Returns the implementation type that will be created when the method
is
+ * used.
+ */
+ TypeLiteral<?> getImplementationType();
+
+ /**
+ * Returns the constructor that will be used to construct instances of
the
+ * implementation.
+ */
+ Constructor<?> getImplementationConstructor();
+
+ /**
+ * Returns all non-assisted dependencies required to construct and inject
+ * the implementation.
+ */
+ Set<Dependency<?>> getDependencies();
+}
=======================================
--- /dev/null
+++
/trunk/extensions/assistedinject/test/com/google/inject/assistedinject/ExtensionSpiTest.java
Sat Oct 16 18:28:06 2010
@@ -0,0 +1,221 @@
+/**
+ * Copyright (C) 2010 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.assistedinject;
+
+import static com.google.inject.name.Names.named;
+
+import com.google.inject.AbstractModule;
+import com.google.inject.Binding;
+import com.google.inject.Guice;
+import com.google.inject.Inject;
+import com.google.inject.Injector;
+import com.google.inject.Key;
+import com.google.inject.Stage;
+import com.google.inject.internal.util.ImmutableList;
+import com.google.inject.internal.util.ImmutableSet;
+import com.google.inject.internal.util.Iterables;
+import com.google.inject.internal.util.Lists;
+import com.google.inject.name.Named;
+import com.google.inject.spi.DefaultBindingTargetVisitor;
+import com.google.inject.spi.Dependency;
+import com.google.inject.spi.Element;
+import com.google.inject.spi.Elements;
+
+import junit.framework.AssertionFailedError;
+import junit.framework.TestCase;
+
+import java.util.List;
+import java.util.Set;
+import java.util.logging.Logger;
+
+/**
+ * Tests for AssistedInject Spi.
+ *
+ * @author ramakris...@google.com (Ramakrishna Rajanna)
+ */
+public class ExtensionSpiTest extends TestCase {
+
+ public final void testSpiOnElements() throws Exception {
+ AssistedInjectSpiVisitor visitor = new AssistedInjectSpiVisitor();
+ Integer count = 0;
+ for(Element element : Elements.getElements(new Module())) {
+ if(element instanceof Binding) {
+ assertEquals(count++,
((Binding<?>)element).acceptTargetVisitor(visitor));
+ }
+ }
+ validateVisitor(visitor);
+ }
+
+ public void testSpiOnVisitor() throws Exception {
+ AssistedInjectSpiVisitor visitor = new AssistedInjectSpiVisitor();
+ Integer count = 0;
+ Injector injector = Guice.createInjector(new Module());
+ for(Binding<?> binding : injector.getBindings().values()) {
+ assertEquals(count++, binding.acceptTargetVisitor(visitor));
+ }
+ validateVisitor(visitor);
+ }
+
+ private void validateVisitor(AssistedInjectSpiVisitor visitor) throws
Exception {
+ assertEquals(1, visitor.assistedBindingCount);
+ List<AssistedMethod> assistedMethods =
+ Lists.newArrayList(Iterables.getOnlyElement(
+ visitor.assistedInjectBindings).getAssistedMethods());
+ assertEquals(7, assistedMethods.size());
+ assertEquals(1, visitor.assistedBindingCount);
+ assertEquals(1, visitor.assistedInjectBindings.size());
+
+ // Validate for each of the methods in AnimalFactory
+ validateCreateAStrangeCatAsAnimal(assistedMethods.get(0));
+
validatecreateStrangeCatWithConstructorForOwner(assistedMethods.get(1));
+ validatecreateStrangeCatWithConstructorForAge(assistedMethods.get(2));
+ validateCreateCatWithANonAssistedDependency(assistedMethods.get(3));
+ validateCreateCat(assistedMethods.get(4));
+ validateCreateASimpleCatAsAnimal(assistedMethods.get(5));
+ validateCreateCatWithNonAssistedDependencies(assistedMethods.get(6));
+
+ }
+
+ private void validateCreateAStrangeCatAsAnimal(AssistedMethod
assistedMethod) {
+ validateAssistedMethod(assistedMethod, "createAStrangeCatAsAnimal",
+ StrangeCat.class, ImmutableList.<Key<?>>of());
+ }
+
+ private void
validatecreateStrangeCatWithConstructorForOwner(AssistedMethod
assistedMethod) {
+
validateAssistedMethod(assistedMethod, "createStrangeCatWithConstructorForOwner",
+ StrangeCat.class, ImmutableList.<Key<?>>of());
+ }
+
+ private void
validatecreateStrangeCatWithConstructorForAge(AssistedMethod
assistedMethod) {
+
validateAssistedMethod(assistedMethod, "createStrangeCatWithConstructorForAge",
+ StrangeCat.class, ImmutableList.<Key<?>>of());
+ }
+
+ private void validateCreateCatWithANonAssistedDependency(AssistedMethod
assistedMethod)
+ throws Exception {
+
validateAssistedMethod(assistedMethod, "createCatWithANonAssistedDependency",
+ CatWithAName.class, ImmutableList.<Key<?>>of(Key.get(String.class,
named("catName2"))));
+ }
+
+ private void validateCreateCat(AssistedMethod assistedMethod) throws
Exception {
+ validateAssistedMethod(assistedMethod, "createCat", Cat.class,
ImmutableList.<Key<?>>of());
+ }
+
+ private void validateCreateASimpleCatAsAnimal(AssistedMethod
assistedMethod) {
+ validateAssistedMethod(assistedMethod, "createASimpleCatAsAnimal",
SimpleCat.class,
+ ImmutableList.<Key<?>>of());
+ }
+
+ private void validateCreateCatWithNonAssistedDependencies(AssistedMethod
assistedMethod) {
+ List<Key<?>> dependencyKeys = ImmutableList.<Key<?>>of(
+ Key.get(String.class, named("catName1")),
+ Key.get(String.class, named("petName")),
+ Key.get(Integer.class, named("age")));
+
validateAssistedMethod(assistedMethod, "createCatWithNonAssistedDependencies",
+ ExplodingCat.class, dependencyKeys);
+ }
+
+ private void validateAssistedMethod(AssistedMethod assistedMethod,
String factoryMethodName,
+ Class clazz, List<Key<?>>
dependencyKeys){
+ assertEquals(factoryMethodName,
assistedMethod.getFactoryMethod().getName());
+ assertEquals(clazz,
assistedMethod.getImplementationConstructor().getDeclaringClass());
+ assertEquals(dependencyKeys.size(),
assistedMethod.getDependencies().size());
+ for (Dependency<?> dependency : assistedMethod.getDependencies()) {
+ assertTrue(dependencyKeys.contains(dependency.getKey()));
+ }
+ assertEquals(clazz, assistedMethod.getImplementationType().getType());
+ }
+
+
+ interface AnimalFactory {
+ Cat createCat(String owner);
+ CatWithAName createCatWithANonAssistedDependency(String owner);
+ @Named("SimpleCat") Animal createASimpleCatAsAnimal(String owner);
+ Animal createAStrangeCatAsAnimal(String owner);
+ StrangeCat createStrangeCatWithConstructorForOwner(String owner);
+ StrangeCat createStrangeCatWithConstructorForAge(Integer age);
+ ExplodingCat createCatWithNonAssistedDependencies(String owner);
+ }
+
+ interface Animal {}
+
+ private static class Cat implements Animal {
+ @Inject Cat(@Assisted String owner) {}
+ }
+
+ private static class SimpleCat implements Animal {
+ @Inject SimpleCat(@Assisted String owner) {
+ }
+ }
+
+ private static class StrangeCat implements Animal {
+ @AssistedInject StrangeCat(@Assisted String owner) {}
+ @AssistedInject StrangeCat(@Assisted Integer age) {}
+ }
+
+ private static class ExplodingCat implements Animal {
+ @Inject public ExplodingCat(@Named("catName1") String name, @Assisted
String owner,
+ @Named("age") Integer age,
@Named("petName") String petName) {}
+ }
+
+ private static class CatWithAName extends Cat {
+ @Inject CatWithAName(@Assisted String owner, @Named("catName2") String
name) {
+ super(owner);
+ }
+ }
+
+ public class Module extends AbstractModule{
+ @Override
+ protected void configure() {
+
bind(String.class).annotatedWith(named("catName1")).toInstance("kitty1");
+
bind(String.class).annotatedWith(named("catName2")).toInstance("kitty2");
+
bind(String.class).annotatedWith(named("petName")).toInstance("pussy");
+ bind(Integer.class).annotatedWith(named("age")).toInstance(12);
+ install(new FactoryModuleBuilder()
+ .implement(Animal.class, StrangeCat.class)
+ .implement(Animal.class, named("SimpleCat"), SimpleCat.class)
+ .build(AnimalFactory.class));
+ }
+ }
+
+ public class AssistedInjectSpiVisitor extends
DefaultBindingTargetVisitor<Object, Integer>
+ implements AssistedInjectTargetVisitor<Object, Integer> {
+
+ private final Set<Class> allowedClasses =
+ ImmutableSet.<Class> of(
+ Injector.class, Stage.class, Logger.class,
+ String.class, Integer.class);
+
+ private int assistedBindingCount = 0;
+ private int currentCount = 0;
+ private List<AssistedInjectBinding<?>> assistedInjectBindings =
Lists.newArrayList();
+
+ public Integer visit(AssistedInjectBinding assistedInjectBinding) {
+ assistedInjectBindings.add(assistedInjectBinding);
+ assistedBindingCount++;
+ return currentCount++;
+ }
+
+ @Override
+ protected Integer visitOther(Binding<? extends Object> binding) {
+
if(!allowedClasses.contains(binding.getKey().getTypeLiteral().getRawType()))
{
+ throw new AssertionFailedError("invalid other binding: " +
binding);
+ }
+ return currentCount++;
+ }
+ }
+}
=======================================
---
/trunk/extensions/assistedinject/src/com/google/inject/assistedinject/FactoryModuleBuilder.java
Sat Jul 31 09:08:27 2010
+++
/trunk/extensions/assistedinject/src/com/google/inject/assistedinject/FactoryModuleBuilder.java
Sat Oct 16 18:28:06 2010
@@ -310,7 +310,7 @@
public <F> Module build(final Key<F> factoryInterface) {
return new AbstractModule() {
@Override protected void configure() {
- Provider<F> provider = new
FactoryProvider2<F>(factoryInterface.getTypeLiteral(), bindings);
+ Provider<F> provider = new FactoryProvider2<F>(factoryInterface,
bindings);
bind(factoryInterface).toProvider(provider);
}
};
=======================================
---
/trunk/extensions/assistedinject/src/com/google/inject/assistedinject/FactoryProvider.java
Sat Jul 3 08:51:31 2010
+++
/trunk/extensions/assistedinject/src/com/google/inject/assistedinject/FactoryProvider.java
Sat Oct 16 18:28:06 2010
@@ -192,7 +192,7 @@
}
}
- return new FactoryProvider2<F>(factoryType, collector);
+ return new FactoryProvider2<F>(Key.get(factoryType), collector);
}
}
=======================================
---
/trunk/extensions/assistedinject/src/com/google/inject/assistedinject/FactoryProvider2.java
Wed Sep 22 20:16:22 2010
+++
/trunk/extensions/assistedinject/src/com/google/inject/assistedinject/FactoryProvider2.java
Sat Oct 16 18:28:06 2010
@@ -16,6 +16,9 @@
package com.google.inject.assistedinject;
+import static com.google.inject.internal.util.Iterables.getOnlyElement;
+import static com.google.inject.internal.util.Preconditions.checkState;
+
import com.google.inject.AbstractModule;
import com.google.inject.Binder;
import com.google.inject.Binding;
@@ -27,7 +30,7 @@
import com.google.inject.Provider;
import com.google.inject.ProvisionException;
import com.google.inject.TypeLiteral;
-import static com.google.inject.internal.Annotations.getKey;
+import com.google.inject.internal.Annotations;
import com.google.inject.internal.BytecodeGen;
import com.google.inject.internal.Errors;
import com.google.inject.internal.ErrorsException;
@@ -36,18 +39,18 @@
import com.google.inject.internal.util.ImmutableMap;
import com.google.inject.internal.util.ImmutableSet;
import com.google.inject.internal.util.Iterables;
-import com.google.inject.internal.util.ToStringBuilder;
-
-import static com.google.inject.internal.util.Iterables.getOnlyElement;
import com.google.inject.internal.util.Lists;
-import static com.google.inject.internal.util.Preconditions.checkState;
-
+import com.google.inject.internal.util.ToStringBuilder;
+import com.google.inject.spi.BindingTargetVisitor;
import com.google.inject.spi.Dependency;
import com.google.inject.spi.HasDependencies;
import com.google.inject.spi.InjectionPoint;
import com.google.inject.spi.Message;
+import com.google.inject.spi.ProviderInstanceBinding;
+import com.google.inject.spi.ProviderWithExtensionVisitor;
import com.google.inject.spi.Toolable;
import com.google.inject.util.Providers;
+
import java.lang.annotation.Annotation;
import java.lang.reflect.Constructor;
import java.lang.reflect.InvocationHandler;
@@ -71,7 +74,8 @@
* @author schm...@google.com (Peter Schmitt)
* @author sa...@google.com (Sam Berlin)
*/
-final class FactoryProvider2<F> implements InvocationHandler, Provider<F>,
HasDependencies {
+final class FactoryProvider2 <F> implements InvocationHandler,
+ ProviderWithExtensionVisitor<F>, HasDependencies,
AssistedInjectBinding<F> {
/** if a factory method parameter isn't annotated, it gets this
annotation. */
static final Assisted DEFAULT_ANNOTATION = new Assisted() {
@@ -96,36 +100,42 @@
return "@" + Assisted.class.getName() + "(value=)";
}
};
-
+
/** All the data necessary to perform an assisted inject. */
- private static class AssistData {
+ private static class AssistData implements AssistedMethod {
/** the constructor the implementation is constructed with. */
final Constructor<?> constructor;
/** the return type in the factory method that the constructor is
bound to. */
final Key<?> returnType;
/** the parameters in the factory method associated with this data. */
final ImmutableList<Key<?>> paramTypes;
-
+ /** the type of the implementation constructed */
+ final TypeLiteral<?> implementationType;
+
/** All non-assisted dependencies required by this method. */
final Set<Dependency<?>> dependencies;
-
+ /** The factory method associated with this data*/
+ final Method factoryMethod;
+
/** true if {...@link #validForOptimizedAssistedInject} returned true. */
final boolean optimized;
/** the list of optimized providers, empty if not optimized. */
final List<ThreadLocalProvider> providers;
/** used to perform optimized factory creations. */
volatile Binding<?> cachedBinding; // TODO: volatile necessary?
-
- AssistData(Constructor<?> constructor, Key<?> returnType,
- ImmutableList<Key<?>> paramTypes, boolean optimized,
- List<ThreadLocalProvider> providers,
- Set<Dependency<?>> dependencies) {
+
+ AssistData(Constructor<?> constructor, Key<?> returnType,
ImmutableList<Key<?>> paramTypes,
+ TypeLiteral<?> implementationType, Method factoryMethod,
+ Set<Dependency<?>> dependencies,
+ boolean optimized, List<ThreadLocalProvider> providers) {
this.constructor = constructor;
this.returnType = returnType;
this.paramTypes = paramTypes;
+ this.implementationType = implementationType;
+ this.factoryMethod = factoryMethod;
+ this.dependencies = dependencies;
this.optimized = optimized;
this.providers = providers;
- this.dependencies = dependencies;
}
@Override
@@ -134,33 +144,53 @@
.add("ctor", constructor)
.add("return type", returnType)
.add("param type", paramTypes)
+ .add("implementation type", implementationType)
+ .add("dependencies", dependencies)
+ .add("factory method", factoryMethod)
.add("optimized", optimized)
.add("providers", providers)
.add("cached binding", cachedBinding)
- .add("dependencies", dependencies)
.toString();
-
+ }
+
+ public Set<Dependency<?>> getDependencies() {
+ return dependencies;
+ }
+
+ public Method getFactoryMethod() {
+ return factoryMethod;
+ }
+
+ public Constructor<?> getImplementationConstructor() {
+ return constructor;
+ }
+
+ public TypeLiteral<?> getImplementationType() {
+ return implementationType;
}
}
- /** the produced type, or null if all methods return concrete types */
- private final BindingCollector collector;
- private final ImmutableMap<Method, AssistData> assistDataByMethod;
+ /** Mapping from method to the data about how the method will be
assisted. */
+ private final ImmutableMap<Method, AssistData> assistDataByMethod;
/** the hosting injector, or null if we haven't been initialized yet */
private Injector injector;
/** the factory interface, implemented and provided */
private final F factory;
+
+ /** The key that this is bound to. */
+ private final Key<F> factoryKey;
/**
* @param factoryType a Java interface that defines one or more create
methods.
* @param collector binding configuration that maps method return types
to
* implementation types.
*/
- FactoryProvider2(TypeLiteral<F> factoryType, BindingCollector collector)
{
- this.collector = collector;
-
+ FactoryProvider2(Key<F> factoryKey, BindingCollector collector) {
+ this.factoryKey = factoryKey;
+
+ TypeLiteral<F> factoryType = factoryKey.getTypeLiteral();
Errors errors = new Errors();
@SuppressWarnings("unchecked") // we imprecisely treat the class
literal of T as a Class<T>
@@ -173,7 +203,7 @@
TypeLiteral<?> returnTypeLiteral =
factoryType.getReturnType(method);
Key<?> returnType;
try {
- returnType = getKey(returnTypeLiteral, method,
method.getAnnotations(), errors);
+ returnType = Annotations.getKey(returnTypeLiteral, method,
method.getAnnotations(), errors);
} catch(ConfigurationException ce) {
// If this was an error due to returnTypeLiteral not being
specified, rephrase
// it as our factory not being specified, so it makes more sense
to users.
@@ -188,7 +218,7 @@
int p = 0;
List<Key<?>> keys = Lists.newArrayList();
for (TypeLiteral<?> param : params) {
- Key<?> paramKey = getKey(param, method, paramAnnotations[p++],
errors);
+ Key<?> paramKey = Annotations.getKey(param, method,
paramAnnotations[p++], errors);
Class<?> underlylingType =
paramKey.getTypeLiteral().getRawType();
if (underlylingType.equals(Provider.class)
|| underlylingType.equals(javax.inject.Provider.class)) {
@@ -199,7 +229,7 @@
keys.add(assistKey(method, paramKey, errors));
}
ImmutableList<Key<?>> immutableParamList =
ImmutableList.copyOf(keys);
-
+
// try to match up the method to the constructor
TypeLiteral<?> implementation =
collector.getBindings().get(returnType);
if(implementation == null) {
@@ -207,13 +237,13 @@
}
InjectionPoint ctorInjectionPoint;
try {
- ctorInjectionPoint =
+ ctorInjectionPoint =
findMatchingConstructorInjectionPoint(method, returnType,
implementation, immutableParamList);
} catch(ErrorsException ee) {
errors.merge(ee.getErrors());
continue;
}
-
+
Constructor<?> constructor =
(Constructor)ctorInjectionPoint.getMember();
List<ThreadLocalProvider> providers = Collections.emptyList();
Set<Dependency<?>> deps = getDependencies(ctorInjectionPoint,
implementation);
@@ -232,8 +262,8 @@
optimized = true;
}
assistDataBuilder.put(method,
- new AssistData(constructor, returnType, immutableParamList,
- optimized, providers, removeAssistedDeps(deps)));
+ new AssistData(constructor, returnType, immutableParamList,
implementation,
+ method, removeAssistedDeps(deps), optimized, providers));
}
// If we generated any errors (from finding matching constructors,
for instance), throw an exception.
@@ -245,7 +275,7 @@
} catch (ErrorsException e) {
throw new ConfigurationException(e.getErrors().getMessages());
}
-
+
factory =
factoryRawType.cast(Proxy.newProxyInstance(BytecodeGen.getClassLoader(factoryRawType),
new Class[] { factoryRawType }, this));
}
@@ -253,7 +283,7 @@
public F get() {
return factory;
}
-
+
public Set<Dependency<?>> getDependencies() {
Set<Dependency<?>> combinedDeps = new HashSet<Dependency<?>>();
for(AssistData data : assistDataByMethod.values()) {
@@ -261,6 +291,25 @@
}
return ImmutableSet.copyOf(combinedDeps);
}
+
+ public Key<F> getKey() {
+ return factoryKey;
+ }
+
+ // safe cast because values are typed to AssistedData, which is an
AssistedMethod
+ @SuppressWarnings("unchecked")
+ public Collection<AssistedMethod> getAssistedMethods() {
+ return (Collection)assistDataByMethod.values();
+ }
+
+ @SuppressWarnings("unchecked")
+ public <V, T> V acceptExtensionVisitor(BindingTargetVisitor<T, V>
visitor,
+ ProviderInstanceBinding<? extends T> binding) {
+ if (visitor instanceof AssistedInjectTargetVisitor) {
+ return ((AssistedInjectTargetVisitor<T,
V>)visitor).visit((AssistedInjectBinding<T>)this);
+ }
+ return visitor.visit(binding);
+ }
/**
* Returns true if the ConfigurationException is due to an error of
TypeLiteral not being fully
@@ -293,7 +342,7 @@
} else {
errors = errors.withSource(returnType).withSource(implementation);
}
-
+
Class<?> rawType = implementation.getRawType();
if (Modifier.isInterface(rawType.getModifiers())) {
errors.addMessage(
@@ -309,7 +358,7 @@
errors.cannotInjectInnerClass(rawType);
throw errors.toException();
}
-
+
Constructor<?> matchingConstructor = null;
boolean anyAssistedInjectConstructors = false;
// Look for AssistedInject constructors...
@@ -330,7 +379,7 @@
}
}
}
-
+
if(!anyAssistedInjectConstructors) {
// If none existed, use @Inject.
try {
@@ -371,7 +420,7 @@
int p = 0;
List<Key<?>> constructorKeys = Lists.newArrayList();
for (TypeLiteral<?> param : params) {
- Key<?> paramKey = getKey(param, constructor, paramAnnotations[p++],
+ Key<?> paramKey = Annotations.getKey(param, constructor,
paramAnnotations[p++],
errors);
constructorKeys.add(paramKey);
}
@@ -403,7 +452,7 @@
}
return builder.build();
}
-
+
/** Return all non-assisted dependencies. */
private Set<Dependency<?>> removeAssistedDeps(Set<Dependency<?>> deps) {
ImmutableSet.Builder<Dependency<?>> builder = ImmutableSet.builder();
@@ -415,7 +464,7 @@
}
return builder.build();
}
-
+
/**
* Returns true if all dependencies are suitable for the optimized
version of AssistedInject. The
* optimized version caches the binding & uses a ThreadLocal Provider,
so can only be applied if
@@ -430,7 +479,7 @@
}
return true;
}
-
+
/**
* Returns true if the dependency is for {...@link Injector} or if the
dependency
* is a {...@link Provider} for a parameter that is {...@literal @}...@link
Assisted}.
@@ -521,18 +570,14 @@
binder.bind((Key)
paramKey).toProvider(data.providers.get(p++));
}
}
-
+
Constructor constructor = data.constructor;
// Constructor *should* always be non-null here,
// but if it isn't, we'll end up throwing a fairly good error
// message for the user.
if(constructor != null) {
- TypeLiteral implementation =
collector.getBindings().get(returnType);
- if (implementation != null) {
- binder.bind(assistedReturnType).toConstructor(constructor,
implementation);
- } else {
- binder.bind(assistedReturnType).toConstructor(constructor,
(TypeLiteral) returnType.getTypeLiteral());
- }
+ binder.bind(assistedReturnType).toConstructor(
+ constructor, (TypeLiteral)data.implementationType);
}
}
};
@@ -541,7 +586,7 @@
Binding binding = forCreate.getBinding(assistedReturnType);
// If we have providers cached in data, cache the binding for future
optimizations.
if(data.optimized) {
- data.cachedBinding = binding;
+ data.cachedBinding = binding;
}
return binding;
}
@@ -607,9 +652,9 @@
return false;
}
-
+
// not <T> because we'll never know and this is easier than suppressing
warnings.
- private static class ThreadLocalProvider extends ThreadLocal<Object>
implements Provider<Object> {
+ private static class ThreadLocalProvider extends ThreadLocal<Object>
implements Provider<Object> {
@Override
protected Object initialValue() {
throw new IllegalStateException(
--
You received this message because you are subscribed to the Google Groups
"google-guice-dev" group.
To post to this group, send email to google-guice-...@googlegroups.com.
To unsubscribe from this group, send email to
google-guice-dev+unsubscr...@googlegroups.com.
For more options, visit this group at
http://groups.google.com/group/google-guice-dev?hl=en.