blob: 04388086a2383911d9bede19d830b34a4d73b99d [file] [log] [blame]
limpbizkit03b81a62009-03-18 05:34:39 +00001/*
2 * Copyright (C) 2007 Google Inc.
3 *
4 * Licensed under the Apache License, Version 2.0 (the "License");
5 * you may not use this file except in compliance with the License.
6 * You may obtain a copy of the License at
7 *
8 * http://www.apache.org/licenses/LICENSE-2.0
9 *
10 * Unless required by applicable law or agreed to in writing, software
11 * distributed under the License is distributed on an "AS IS" BASIS,
12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 * See the License for the specific language governing permissions and
14 * limitations under the License.
15 */
16
limpbizkit5ae41eb2009-06-06 17:51:27 +000017package com.google.inject.internal;
limpbizkit03b81a62009-03-18 05:34:39 +000018
limpbizkit5ae41eb2009-06-06 17:51:27 +000019import com.google.inject.Binder;
20import com.google.inject.Key;
limpbizkit03b81a62009-03-18 05:34:39 +000021import static com.google.inject.internal.Preconditions.checkState;
limpbizkit03b81a62009-03-18 05:34:39 +000022import com.google.inject.spi.BindingTargetVisitor;
23import com.google.inject.spi.ConstructorBinding;
24import com.google.inject.spi.Dependency;
limpbizkita843a952009-04-08 22:24:55 +000025import com.google.inject.spi.InjectionPoint;
26import java.lang.reflect.Method;
27import java.util.List;
28import java.util.Map;
limpbizkit03b81a62009-03-18 05:34:39 +000029import java.util.Set;
30
limpbizkit5ae41eb2009-06-06 17:51:27 +000031final class ConstructorBindingImpl<T> extends BindingImpl<T> implements ConstructorBinding<T> {
limpbizkit03b81a62009-03-18 05:34:39 +000032
33 private final Factory<T> factory;
limpbizkit03b81a62009-03-18 05:34:39 +000034
limpbizkit5ae41eb2009-06-06 17:51:27 +000035 private ConstructorBindingImpl(InjectorImpl injector, Key<T> key, Object source,
limpbizkit03b81a62009-03-18 05:34:39 +000036 InternalFactory<? extends T> scopedFactory, Scoping scoping, Factory<T> factory) {
37 super(injector, key, source, scopedFactory, scoping);
38 this.factory = factory;
39 }
40
41 static <T> ConstructorBindingImpl<T> create(
42 InjectorImpl injector, Key<T> key, Object source, Scoping scoping) {
43 Factory<T> factoryFactory = new Factory<T>();
44 InternalFactory<? extends T> scopedFactory
limpbizkit5ae41eb2009-06-06 17:51:27 +000045 = Scoping.scope(key, injector, factoryFactory, scoping);
limpbizkit03b81a62009-03-18 05:34:39 +000046 return new ConstructorBindingImpl<T>(
47 injector, key, source, scopedFactory, scoping, factoryFactory);
48 }
49
limpbizkit03b81a62009-03-18 05:34:39 +000050 public void initialize(InjectorImpl injector, Errors errors) throws ErrorsException {
limpbizkit7cef5b02009-03-29 21:16:51 +000051 factory.constructorInjector = injector.constructors.get(getKey().getTypeLiteral(), errors);
limpbizkit03b81a62009-03-18 05:34:39 +000052 }
53
54 public <V> V acceptTargetVisitor(BindingTargetVisitor<? super T, V> visitor) {
limpbizkita843a952009-04-08 22:24:55 +000055 checkState(factory.constructorInjector != null, "not initialized");
limpbizkit03b81a62009-03-18 05:34:39 +000056 return visitor.visit(this);
57 }
58
limpbizkita843a952009-04-08 22:24:55 +000059 public InjectionPoint getConstructor() {
60 checkState(factory.constructorInjector != null, "Binding is not ready");
61 return factory.constructorInjector.getConstructionProxy().getInjectionPoint();
limpbizkit03b81a62009-03-18 05:34:39 +000062 }
63
limpbizkita843a952009-04-08 22:24:55 +000064 public Set<InjectionPoint> getInjectableMembers() {
65 checkState(factory.constructorInjector != null, "Binding is not ready");
66 return factory.constructorInjector.getInjectableMembers();
67 }
68
limpbizkiteb405132009-04-14 00:50:25 +000069 /*if[AOP]*/
70 public Map<Method, List<org.aopalliance.intercept.MethodInterceptor>> getMethodInterceptors() {
limpbizkita843a952009-04-08 22:24:55 +000071 checkState(factory.constructorInjector != null, "Binding is not ready");
limpbizkiteb405132009-04-14 00:50:25 +000072 return factory.constructorInjector.getConstructionProxy().getMethodInterceptors();
limpbizkit03b81a62009-03-18 05:34:39 +000073 }
limpbizkiteb405132009-04-14 00:50:25 +000074 /*end[AOP]*/
limpbizkit03b81a62009-03-18 05:34:39 +000075
76 public Set<Dependency<?>> getDependencies() {
limpbizkita843a952009-04-08 22:24:55 +000077 return Dependency.forInjectionPoints(new ImmutableSet.Builder<InjectionPoint>()
78 .add(getConstructor())
79 .addAll(getInjectableMembers())
80 .build());
limpbizkit03b81a62009-03-18 05:34:39 +000081 }
82
83 public void applyTo(Binder binder) {
84 throw new UnsupportedOperationException("This element represents a synthetic binding.");
85 }
86
87 @Override public String toString() {
88 return new ToStringBuilder(ConstructorBinding.class)
89 .add("key", getKey())
90 .add("source", getSource())
91 .add("scope", getScoping())
92 .toString();
93 }
94
95 private static class Factory<T> implements InternalFactory<T> {
96 private ConstructorInjector<T> constructorInjector;
97
98 @SuppressWarnings("unchecked")
99 public T get(Errors errors, InternalContext context, Dependency<?> dependency)
100 throws ErrorsException {
101 checkState(constructorInjector != null, "Constructor not ready");
102
103 // This may not actually be safe because it could return a super type of T (if that's all the
104 // client needs), but it should be OK in practice thanks to the wonders of erasure.
limpbizkit5ae41eb2009-06-06 17:51:27 +0000105 return (T) constructorInjector.construct(errors, context,
106 dependency.getKey().getTypeLiteral().getRawType());
limpbizkit03b81a62009-03-18 05:34:39 +0000107 }
108 }
109}