1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20 package org.grouplens.grapht;
21
22 import com.google.common.base.Preconditions;
23 import com.google.common.base.Throwables;
24 import org.grouplens.grapht.util.LogContext;
25 import org.grouplens.grapht.util.TypedProvider;
26 import org.grouplens.grapht.util.Types;
27 import javax.inject.Provider;
28 import org.slf4j.LoggerFactory;
29 import org.slf4j.Logger;
30 import org.grouplens.grapht.util.LogContext;
31
32
33
34
35
36
37
38 public final class Instantiators {
39 private static final Logger logger = LoggerFactory.getLogger(Instantiators.class);
40
41 private Instantiators() {}
42
43
44
45
46
47
48 public static Instantiator ofInstance(Object inst) {
49 Preconditions.checkNotNull(inst, "instance");
50 return new InstanceInstantiator(inst);
51 }
52
53
54
55
56
57
58 public static Instantiator ofNull(Class<?> type) {
59 Preconditions.checkNotNull(type, "instance");
60 return new InstanceInstantiator(null, type);
61 }
62
63
64
65
66
67
68
69 public static Instantiator ofProvider(Provider<?> provider) {
70 Preconditions.checkNotNull(provider, "provider");
71 return new ProviderInstantiator(ofInstance(provider));
72 }
73
74
75
76
77
78
79
80
81 public static Instantiator ofProviderInstantiator(Instantiator pinst) {
82 Preconditions.checkNotNull(pinst, "provider instantiator");
83 Preconditions.checkArgument(Provider.class.isAssignableFrom(pinst.getType()),
84 "instantiator is not of type Provider");
85
86 return new ProviderInstantiator(pinst);
87 }
88
89
90
91
92
93
94 public static Provider<?> toProvider(Instantiator instantiator) {
95
96 if (instantiator instanceof ProviderInstantiator) {
97 Instantiator itor = ((ProviderInstantiator) instantiator).providerInstantiator;
98 if (itor instanceof InstanceInstantiator) {
99 return (Provider) ((InstanceInstantiator) itor).instance;
100 }
101 }
102
103
104 return new InstantiatorProvider(instantiator);
105 }
106
107
108
109
110
111
112 public static Instantiator memoize(Instantiator instantiator) {
113 Preconditions.checkNotNull(instantiator, "instantiator");
114 return new MemoizingInstantiator(instantiator);
115 }
116 private static final class InstanceInstantiator implements Instantiator {
117 private final Object instance;
118 private final Class<?> type;
119
120 public InstanceInstantiator(Object inst) {
121 this(inst, (Class) inst.getClass());
122 }
123
124 public InstanceInstantiator(Object inst, Class<?> typ) {
125 instance = inst;
126 type = typ;
127 }
128
129 @Override
130 public Object instantiate() throws ConstructionException {
131 return instance;
132 }
133
134 @Override
135 public Class getType() {
136 return type;
137 }
138 }
139
140 private static class ProviderInstantiator implements Instantiator {
141 private final Instantiator providerInstantiator;
142 public ProviderInstantiator(Instantiator prov) {
143 providerInstantiator = prov;
144 }
145
146 @Override
147 public Object instantiate() throws ConstructionException {
148 Provider<?> provider = (Provider) providerInstantiator.instantiate();
149 LogContext mdcContextProvider = LogContext.create();
150 logger.trace("invoking provider {}",provider);
151 try {
152 mdcContextProvider.put("org.grouplens.grapht.currentProvider", provider.toString());
153 return provider.get();
154 } catch (Throwable th) {
155 throw new ConstructionException(getType(), "Error invoking provider " + providerInstantiator, th);
156 } finally {
157 mdcContextProvider.finish();
158 }
159 }
160 @SuppressWarnings("unchecked")
161 @Override
162 public Class<?> getType() {
163 return Types.getProvidedType(providerInstantiator.getType());
164 }
165 }
166
167
168 private static class MemoizingInstantiator implements Instantiator {
169 private final Instantiator delegate;
170 private volatile boolean instantiated = false;
171 private Object instance = null;
172 private Throwable error = null;
173
174 public MemoizingInstantiator(Instantiator inst) {
175 delegate = inst;
176 }
177
178 @Override
179 public Object instantiate() throws ConstructionException {
180 if (!instantiated) {
181 synchronized (this) {
182 if (!instantiated) {
183 try {
184 instance = delegate.instantiate();
185 } catch (Throwable th) {
186 error = th;
187 }
188 instantiated = true;
189 }
190 }
191 }
192
193 if (error != null) {
194 Throwables.propagateIfPossible(error, ConstructionException.class);
195
196 throw Throwables.propagate(error);
197 } else {
198 return instance;
199 }
200 }
201
202 @Override
203 public Class getType() {
204 return delegate.getType();
205 }
206 }
207
208 private static class InstantiatorProvider implements TypedProvider {
209 private final Instantiator instantiator;
210
211 public InstantiatorProvider(Instantiator itor) {
212 instantiator = itor;
213 }
214
215 @Override
216 public Class<?> getProvidedType() {
217 return instantiator.getType();
218 }
219
220 @Override
221 public Object get() {
222 try {
223 logger.trace("invoking instantiator {}", instantiator);
224 return getProvidedType().cast(instantiator.instantiate());
225 } catch (ConstructionException ex) {
226 throw new RuntimeException(ex);
227 }
228 }
229 }
230
231 }