1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20 package org.grouplens.grapht.reflect.internal;
21
22 import org.grouplens.grapht.*;
23 import org.grouplens.grapht.reflect.*;
24 import org.grouplens.grapht.util.ClassProxy;
25 import org.grouplens.grapht.util.Preconditions;
26 import org.grouplens.grapht.util.Types;
27
28 import javax.inject.Provider;
29 import javax.inject.Singleton;
30 import java.io.InvalidObjectException;
31 import java.io.ObjectInputStream;
32 import java.io.ObjectStreamException;
33 import java.io.Serializable;
34 import java.lang.reflect.Modifier;
35 import java.lang.reflect.Type;
36 import java.util.List;
37 import java.util.Map;
38
39
40
41
42
43
44
45 public class ProviderClassSatisfaction implements Satisfaction, Serializable {
46 private static final long serialVersionUID = -1L;
47 private final transient Class<? extends Provider<?>> providerType;
48
49
50
51
52
53
54
55
56 public ProviderClassSatisfaction(Class<? extends Provider<?>> providerType) {
57 Preconditions.notNull("provider type", providerType);
58 Preconditions.isAssignable(Provider.class, providerType);
59 int mods = providerType.getModifiers();
60 if (Modifier.isAbstract(mods) || Modifier.isInterface(mods)) {
61 throw new IllegalArgumentException("Provider satisfaction " + providerType + " is abstract");
62 }
63 if (!Types.isInstantiable(providerType)) {
64 throw new IllegalArgumentException("Provider satisfaction " + providerType + " is not instantiable");
65 }
66
67 this.providerType = providerType;
68 }
69
70 @Override
71 public CachePolicy getDefaultCachePolicy() {
72 return (getErasedType().getAnnotation(Singleton.class) != null ? CachePolicy.MEMOIZE : CachePolicy.NO_PREFERENCE);
73 }
74
75
76
77
78
79 public Class<? extends Provider<?>> getProviderType() {
80 return providerType;
81 }
82
83 @Override
84 public List<Desire> getDependencies() {
85 return ReflectionDesire.getDesires(providerType);
86 }
87
88 @Override
89 public Type getType() {
90 return Types.getProvidedType(providerType);
91 }
92
93 @Override
94 public Class<?> getErasedType() {
95 return Types.erase(getType());
96 }
97
98 @Override
99 public boolean hasInstance() {
100 return false;
101 }
102
103 @Override
104 public <T> T visit(SatisfactionVisitor<T> visitor) {
105 return visitor.visitProviderClass(providerType);
106 }
107
108 @Override
109 @SuppressWarnings({ "unchecked", "rawtypes" })
110 public Instantiator makeInstantiator(Map<Desire,Instantiator> dependencies,
111 LifecycleManager lm) {
112
113
114 ClassInstantiator providerBuilder = new ClassInstantiator(providerType, getDependencies(),
115 dependencies, lm);
116 return Instantiators.ofProviderInstantiator(providerBuilder);
117 }
118
119 @Override
120 public boolean equals(Object o) {
121 if (!(o instanceof ProviderClassSatisfaction)) {
122 return false;
123 }
124 return ((ProviderClassSatisfaction) o).providerType.equals(providerType);
125 }
126
127 @Override
128 public int hashCode() {
129 return providerType.hashCode();
130 }
131
132 @Override
133 public String toString() {
134 return "Provider(" + providerType.getName() + ")";
135 }
136
137 private Object writeReplace() {
138 return new SerialProxy(providerType);
139 }
140
141 private void readObject(ObjectInputStream stream) throws ObjectStreamException {
142 throw new InvalidObjectException("must use serialization proxy");
143 }
144
145 private static class SerialProxy implements Serializable {
146 private static final long serialVersionUID = 1L;
147
148 private final ClassProxy providerType;
149
150 public SerialProxy(Class<?> cls) {
151 providerType = ClassProxy.of(cls);
152 }
153
154 @SuppressWarnings("unchecked")
155 private Object readResolve() throws ObjectStreamException {
156 try {
157 return new ProviderClassSatisfaction((Class<? extends Provider<?>>) providerType.resolve().asSubclass(Provider.class));
158 } catch (ClassNotFoundException e) {
159 InvalidObjectException ex = new InvalidObjectException("cannot resolve " + providerType);
160 ex.initCause(e);
161 throw ex;
162 } catch (ClassCastException e) {
163 InvalidObjectException ex = new InvalidObjectException("class " + providerType + " is not a provider");
164 ex.initCause(e);
165 throw ex;
166 }
167 }
168 }
169 }