MentaContainer

Rev

Rev 119 | Rev 135 | Go to most recent revision | Only display areas with differences | Ignore whitespace | Details | Blame | Last modification | View Log | RSS feed

Rev 119 Rev 120
1
package org.mentacontainer.impl;
1
package org.mentacontainer.impl;
2
2
3
import java.lang.reflect.Method;
3
import java.lang.reflect.Method;
4
import java.util.Collections;
4
import java.util.Collections;
5
import java.util.HashSet;
5
import java.util.HashSet;
6
import java.util.Hashtable;
6
import java.util.Hashtable;
7
import java.util.LinkedList;
7
import java.util.LinkedList;
8
import java.util.List;
8
import java.util.List;
9
import java.util.Map;
9
import java.util.Map;
10
import java.util.Set;
10
import java.util.Set;
11
11
12
import org.mentacontainer.ConfigurableFactory;
12
import org.mentacontainer.ConfigurableFactory;
13
import org.mentacontainer.Container;
13
import org.mentacontainer.Container;
14
import org.mentacontainer.Factory;
14
import org.mentacontainer.Factory;
15
import org.mentacontainer.Interceptor;
15
import org.mentacontainer.Interceptor;
16
import org.mentacontainer.Scope;
16
import org.mentacontainer.Scope;
17
import org.mentacontainer.util.InjectionUtils;
17
import org.mentacontainer.util.InjectionUtils;
18
import org.mentacontainer.util.InjectionUtils.Provider;
18
import org.mentacontainer.util.InjectionUtils.Provider;
19
19
20
/**
20
/**
21
 * The implementation of the IoC container.
21
 * The implementation of the IoC container.
22
 *
22
 *
23
 * @author sergio.oliveira.jr@gmail.com
23
 * @author sergio.oliveira.jr@gmail.com
24
 */
24
 */
25
public class MentaContainer implements Container {
25
public class MentaContainer implements Container {
26
26
27
        private Map<String, Factory> factoriesByName = new Hashtable<String, Factory>();
27
        private Map<String, Factory> factoriesByName = new Hashtable<String, Factory>();
28
       
28
       
29
        private Map<String, Scope> scopes = new Hashtable<String, Scope>();
29
        private Map<String, Scope> scopes = new Hashtable<String, Scope>();
30
       
30
       
31
        private Map<String, Object> singletonsCache = new Hashtable<String, Object>();
31
        private Map<String, Object> singletonsCache = new Hashtable<String, Object>();
32
       
32
       
33
        private Map<String, ThreadLocal<Object>> threadLocalsCache = new Hashtable<String, ThreadLocal<Object>>();
33
        private Map<String, ThreadLocal<Object>> threadLocalsCache = new Hashtable<String, ThreadLocal<Object>>();
34
       
34
       
35
        private Set<SetterDependency> setterDependencies = Collections.synchronizedSet(new HashSet<SetterDependency>());
35
        private Set<SetterDependency> setterDependencies = Collections.synchronizedSet(new HashSet<SetterDependency>());
36
       
36
       
37
        private Set<ConstructorDependency> constructorDependencies = Collections.synchronizedSet(new HashSet<ConstructorDependency>());
37
        private Set<ConstructorDependency> constructorDependencies = Collections.synchronizedSet(new HashSet<ConstructorDependency>());
38
       
38
       
39
        private Set<ConstructorDependency> forConstructMethod = Collections.synchronizedSet(new HashSet<ConstructorDependency>());
39
        private Set<ConstructorDependency> forConstructMethod = Collections.synchronizedSet(new HashSet<ConstructorDependency>());
40
       
40
       
41
        @Override
41
        @Override
42
        public Class<? extends Object> getType(String key) {
42
        public Class<? extends Object> getType(String key) {
43
               
43
               
44
                Factory factory = factoriesByName.get(key);
44
                Factory factory = factoriesByName.get(key);
45
               
45
               
46
                if (factory == null) return null;
46
                if (factory == null) return null;
47
               
47
               
48
                return factory.getType();
48
                return factory.getType();
49
        }
49
        }
50
       
50
       
51
        @Override
51
        @Override
52
        public void clear(Scope scope) {
52
        public void clear(Scope scope) {
53
               
53
               
54
                if (scope == Scope.SINGLETON) {
54
                if (scope == Scope.SINGLETON) {
55
                       
55
                       
56
                        List<ClearableHolder> listToClear = new LinkedList<ClearableHolder>();
56
                        List<ClearableHolder> listToClear = new LinkedList<ClearableHolder>();
57
                       
57
                       
58
                        synchronized(this) {
58
                        synchronized(this) {
59
                       
59
                       
60
                        for(String key : singletonsCache.keySet()) {
60
                        for(String key : singletonsCache.keySet()) {
61
                               
61
                               
62
                                Factory factory = factoriesByName.get(key);
62
                                Factory factory = factoriesByName.get(key);
63
                               
63
                               
64
                                if (factory instanceof Interceptor) {
64
                                if (factory instanceof Interceptor) {
65
                                       
65
                                       
66
                                        Interceptor c = (Interceptor) factory;
66
                                        Interceptor c = (Interceptor) factory;
67
                               
67
                               
68
                                        Object value = singletonsCache.get(key);
68
                                        Object value = singletonsCache.get(key);
69
                                       
69
                                       
70
                                        listToClear.add(new ClearableHolder(c, value));
70
                                        listToClear.add(new ClearableHolder(c, value));
71
                                }
71
                                }
72
                        }
72
                        }
73
                       
73
                       
74
                        singletonsCache.clear();
74
                        singletonsCache.clear();
75
                        }
75
                        }
76
                       
76
                       
77
                        // clear everything inside a non-synchronized block...
77
                        // clear everything inside a non-synchronized block...
78
                       
78
                       
79
                        for(ClearableHolder cp : listToClear) cp.clear();
79
                        for(ClearableHolder cp : listToClear) cp.clear();
80
                       
80
                       
81
                } else if (scope == Scope.THREAD) {
81
                } else if (scope == Scope.THREAD) {
82
                       
82
                       
83
                        List<ClearableHolder> listToClear = new LinkedList<ClearableHolder>();
83
                        List<ClearableHolder> listToClear = new LinkedList<ClearableHolder>();
84
                       
84
                       
85
                        synchronized(this) {
85
                        synchronized(this) {
86
                       
86
                       
87
                        for(String key : threadLocalsCache.keySet()) {
87
                        for(String key : threadLocalsCache.keySet()) {
88
                               
88
                               
89
                                Factory factory = factoriesByName.get(key);
89
                                Factory factory = factoriesByName.get(key);
90
                               
90
                               
91
                                if (factory instanceof Interceptor) {
91
                                if (factory instanceof Interceptor) {
92
                                       
92
                                       
93
                                        Interceptor c = (Interceptor) factory;
93
                                        Interceptor c = (Interceptor) factory;
94
                               
94
                               
95
                                        ThreadLocal<Object> t = threadLocalsCache.get(key);
95
                                        ThreadLocal<Object> t = threadLocalsCache.get(key);
96
                                       
96
                                       
97
                                        Object value = t.get();
97
                                        Object value = t.get();
98
                                       
98
                                       
99
                                        if (value != null) listToClear.add(new ClearableHolder(c, value));
99
                                        if (value != null) listToClear.add(new ClearableHolder(c, value));
100
                                }
100
                                }
101
                        }
101
                        }
102
                       
102
                       
103
                        for(ThreadLocal<Object> t : threadLocalsCache.values()) {
103
                        for(ThreadLocal<Object> t : threadLocalsCache.values()) {
104
                               
104
                               
105
                                t.set(null);
-
 
-
 
105
                                t.remove();
106
                        }
106
                        }
107
                        }
107
                        }
108
                       
108
                       
109
                        // clear everything inside a non-synchronized block...
109
                        // clear everything inside a non-synchronized block...
110
                       
110
                       
111
                        for(ClearableHolder cp : listToClear) cp.clear();
111
                        for(ClearableHolder cp : listToClear) cp.clear();
112
                }
112
                }
113
        }
113
        }
114
       
114
       
115
        @Override
115
        @Override
116
        public <T> T clear(String key) {
116
        public <T> T clear(String key) {
117
               
117
               
118
                if (!factoriesByName.containsKey(key)) return null;
118
                if (!factoriesByName.containsKey(key)) return null;
119
               
119
               
120
                Scope scope = scopes.get(key);
120
                Scope scope = scopes.get(key);
121
               
121
               
122
                if (scope == Scope.SINGLETON) {
122
                if (scope == Scope.SINGLETON) {
123
                       
123
                       
124
                        ClearableHolder cp = null;
124
                        ClearableHolder cp = null;
125
                       
125
                       
126
                        Object value = null;
126
                        Object value = null;
127
                       
127
                       
128
                        synchronized(this) {
128
                        synchronized(this) {
129
                       
129
                       
130
                        value = singletonsCache.remove(key);
130
                        value = singletonsCache.remove(key);
131
                       
131
                       
132
                        if (value != null) {
132
                        if (value != null) {
133
                               
133
                               
134
                                Factory factory = factoriesByName.get(key);
134
                                Factory factory = factoriesByName.get(key);
135
                               
135
                               
136
                                if (factory instanceof Interceptor) {
136
                                if (factory instanceof Interceptor) {
137
                                       
137
                                       
138
                                        Interceptor c = (Interceptor) factory;
138
                                        Interceptor c = (Interceptor) factory;
139
                                       
139
                                       
140
                                        cp = new ClearableHolder(c, value);
140
                                        cp = new ClearableHolder(c, value);
141
                                }
141
                                }
142
                        }
142
                        }
143
                        }
143
                        }
144
                       
144
                       
145
                        if (cp != null) cp.c.onCleared(cp.value);
145
                        if (cp != null) cp.c.onCleared(cp.value);
146
                       
146
                       
147
                        return (T) value;
147
                        return (T) value;
148
                       
148
                       
149
                } else if (scope == Scope.THREAD) {
149
                } else if (scope == Scope.THREAD) {
150
                       
150
                       
151
                        ClearableHolder cp = null;
151
                        ClearableHolder cp = null;
152
                       
152
                       
153
                        Object retVal = null;
153
                        Object retVal = null;
154
                       
154
                       
155
                        synchronized(this) {
155
                        synchronized(this) {
156
                       
156
                       
157
                        ThreadLocal<Object> t = threadLocalsCache.get(key);
157
                        ThreadLocal<Object> t = threadLocalsCache.get(key);
158
                       
158
                       
159
                        if (t != null) {
159
                        if (t != null) {
160
                               
160
                               
161
                                Object o = t.get();
161
                                Object o = t.get();
162
                               
162
                               
163
                                if (o != null) {
163
                                if (o != null) {
164
                                       
164
                                       
165
                                        Factory factory = factoriesByName.get(key);
165
                                        Factory factory = factoriesByName.get(key);
166
                                       
166
                                       
167
                                        if (factory instanceof Interceptor) {
167
                                        if (factory instanceof Interceptor) {
168
                                               
168
                                               
169
                                                Interceptor c = (Interceptor) factory;
169
                                                Interceptor c = (Interceptor) factory;
170
                                               
170
                                               
171
                                                cp = new ClearableHolder(c, o);
171
                                                cp = new ClearableHolder(c, o);
172
                                        }
172
                                        }
173
                                       
173
                                       
174
                                        t.set(null);
-
 
-
 
174
                                        t.remove();
175
                                       
175
                                       
176
                                        retVal = o;
176
                                        retVal = o;
177
                                }
177
                                }
178
                        }
178
                        }
179
                        }
179
                        }
180
                       
180
                       
181
                        if (cp != null) cp.c.onCleared(cp.value);
181
                        if (cp != null) cp.c.onCleared(cp.value);
182
                       
182
                       
183
                        return (T) retVal;
183
                        return (T) retVal;
184
               
184
               
185
                } else if (scope == Scope.NONE) {
185
                } else if (scope == Scope.NONE) {
186
                       
186
                       
187
                        return null; // always...
187
                        return null; // always...
188
                       
188
                       
189
                } else {
189
                } else {
190
                       
190
                       
191
                        throw new UnsupportedOperationException("Scope not supported: " + scope);
191
                        throw new UnsupportedOperationException("Scope not supported: " + scope);
192
                }
192
                }
193
        }
193
        }
194
194
195
        @Override
195
        @Override
196
        public <T> T get(String key) {
196
        public <T> T get(String key) {
197
197
198
                if (!factoriesByName.containsKey(key)) return null;
198
                if (!factoriesByName.containsKey(key)) return null;
199
199
200
                Factory c = factoriesByName.get(key);
200
                Factory c = factoriesByName.get(key);
201
               
201
               
202
                Scope scope = scopes.get(key);
202
                Scope scope = scopes.get(key);
203
               
203
               
204
                Object target = null;
204
                Object target = null;
205
205
206
                try {
206
                try {
207
207
208
                        if (scope == Scope.SINGLETON) {
208
                        if (scope == Scope.SINGLETON) {
209
                               
209
                               
210
                                boolean needsToCreate = false;
210
                                boolean needsToCreate = false;
211
                               
211
                               
212
                                synchronized(this) {
212
                                synchronized(this) {
213
213
214
                                if (singletonsCache.containsKey(key)) {
214
                                if (singletonsCache.containsKey(key)) {
215
   
215
   
216
                                        target = singletonsCache.get(key);
216
                                        target = singletonsCache.get(key);
217
   
217
   
218
                                        return (T) target; // no need to wire again...
218
                                        return (T) target; // no need to wire again...
219
   
219
   
220
                                } else {
220
                                } else {
221
                                       
221
                                       
222
                                        needsToCreate = true;
222
                                        needsToCreate = true;
223
                                }
223
                                }
224
                                }
224
                                }
225
                               
225
                               
226
                                if (needsToCreate) {
226
                                if (needsToCreate) {
227
                                       
227
                                       
228
                                        // getInstance needs to be in a non-synchronized block
228
                                        // getInstance needs to be in a non-synchronized block
229
                                       
229
                                       
230
                                        target = c.getInstance();
230
                                        target = c.getInstance();
231
                                       
231
                                       
232
                                        checkInterceptable(c, target);
232
                                        checkInterceptable(c, target);
233
                                       
233
                                       
234
                                        synchronized(this) {
234
                                        synchronized(this) {
235
235
236
                                                singletonsCache.put(key, target);
236
                                                singletonsCache.put(key, target);
237
                                        }
237
                                        }
238
                                }
238
                                }
239
                               
239
                               
240
                        } else if (scope == Scope.THREAD) {
240
                        } else if (scope == Scope.THREAD) {
241
                               
241
                               
242
                                boolean needsToCreate = false;
242
                                boolean needsToCreate = false;
243
                               
243
                               
244
                                boolean needsToAddToCache = false;
244
                                boolean needsToAddToCache = false;
245
                               
245
                               
246
                                ThreadLocal<Object> t = null;
246
                                ThreadLocal<Object> t = null;
247
                               
247
                               
248
                                synchronized(this) {
248
                                synchronized(this) {
249
                               
249
                               
250
                                if (threadLocalsCache.containsKey(key)) {
250
                                if (threadLocalsCache.containsKey(key)) {
251
                                       
251
                                       
252
                                        t = threadLocalsCache.get(key);
252
                                        t = threadLocalsCache.get(key);
253
                                       
253
                                       
254
                                        target = t.get();
254
                                        target = t.get();
255
                                       
255
                                       
256
                                        if (target == null) { // different thread...
256
                                        if (target == null) { // different thread...
257
                                               
257
                                               
258
                                                needsToCreate = true;
258
                                                needsToCreate = true;
259
                                               
259
                                               
260
                                                // don't return... let it be wired...
260
                                                // don't return... let it be wired...
261
                                               
261
                                               
262
                                        } else {
262
                                        } else {
263
                                       
263
                                       
264
                                                return (T) target; // no need to wire again...
264
                                                return (T) target; // no need to wire again...
265
                                               
265
                                               
266
                                        }
266
                                        }
267
                                       
267
                                       
268
                                } else {
268
                                } else {
269
                                       
269
                                       
270
                                        t = new ThreadLocal<Object>();
270
                                        t = new ThreadLocal<Object>();
271
                                       
271
                                       
272
                                        needsToCreate = true;
272
                                        needsToCreate = true;
273
                                       
273
                                       
274
                                                needsToAddToCache = true;
274
                                                needsToAddToCache = true;
275
                                       
275
                                       
276
                                        // let it be wired...
276
                                        // let it be wired...
277
                                }
277
                                }
278
                                }
278
                                }
279
                               
279
                               
280
                                if (needsToCreate) {
280
                                if (needsToCreate) {
281
                                       
281
                                       
282
                                        // getInstance needs to be in a non-synchronized block
282
                                        // getInstance needs to be in a non-synchronized block
283
                                       
283
                                       
284
                                        target = c.getInstance();
284
                                        target = c.getInstance();
285
                                       
285
                                       
286
                                        checkInterceptable(c, target);
286
                                        checkInterceptable(c, target);
287
                                       
287
                                       
288
                                        t.set(target);
288
                                        t.set(target);
289
                                }
289
                                }
290
                               
290
                               
291
                                if (needsToAddToCache) {
291
                                if (needsToAddToCache) {
292
                                       
292
                                       
293
                                        synchronized(this) {
293
                                        synchronized(this) {
294
                                       
294
                                       
295
                                                threadLocalsCache.put(key, t);
295
                                                threadLocalsCache.put(key, t);
296
                                        }
296
                                        }
297
                                }
297
                                }
298
                               
298
                               
299
                        } else if (scope == Scope.NONE) {
299
                        } else if (scope == Scope.NONE) {
300
300
301
                                target = c.getInstance();
301
                                target = c.getInstance();
302
                               
302
                               
303
                                checkInterceptable(c, target);
303
                                checkInterceptable(c, target);
304
                               
304
                               
305
                        } else {
305
                        } else {
306
                               
306
                               
307
                                throw new UnsupportedOperationException("Don't know how to handle scope: " + scope);
307
                                throw new UnsupportedOperationException("Don't know how to handle scope: " + scope);
308
                        }
308
                        }
309
309
310
                        if (target != null) {
310
                        if (target != null) {
311
311
312
                                for (SetterDependency d : setterDependencies) {
312
                                for (SetterDependency d : setterDependencies) {
313
313
314
                                        // has dependency ?
314
                                        // has dependency ?
315
                                        Method m = d.check(target.getClass());
315
                                        Method m = d.check(target.getClass());
316
316
317
                                        if (m != null) {
317
                                        if (m != null) {
318
318
319
                                                String sourceKey = d.getSource();
319
                                                String sourceKey = d.getSource();
320
320
321
                                                if (sourceKey.equals(key)) {
321
                                                if (sourceKey.equals(key)) {
322
322
323
                                                        // cannot depend on itself... also avoid recursive StackOverflow...
323
                                                        // cannot depend on itself... also avoid recursive StackOverflow...
324
324
325
                                                        continue;
325
                                                        continue;
326
326
327
                                                }
327
                                                }
328
328
329
                                                Object source = get(sourceKey);
329
                                                Object source = get(sourceKey);
330
330
331
                                                try {
331
                                                try {
332
332
333
                                                        // inject
333
                                                        // inject
334
                                                        m.invoke(target, source);
334
                                                        m.invoke(target, source);
335
335
336
                                                } catch (Exception e) {
336
                                                } catch (Exception e) {
337
337
338
                                                        throw new RuntimeException("Cannot inject dependency: method = " + (m != null ? m.getName() : "NULL") + " / source = "
338
                                                        throw new RuntimeException("Cannot inject dependency: method = " + (m != null ? m.getName() : "NULL") + " / source = "
339
                                                                + (source != null ? source : "NULL") + " / target = " + target, e);
339
                                                                + (source != null ? source : "NULL") + " / target = " + target, e);
340
340
341
                                                }
341
                                                }
342
                                        }
342
                                        }
343
                                }
343
                                }
344
                        }
344
                        }
345
345
346
                        return (T) target; // return target nicely with all the dependencies
346
                        return (T) target; // return target nicely with all the dependencies
347
347
348
                } catch (Exception e) {
348
                } catch (Exception e) {
349
349
350
                        throw new RuntimeException(e);
350
                        throw new RuntimeException(e);
351
                }
351
                }
352
        }
352
        }
353
       
353
       
354
        private final void checkInterceptable(Factory f, Object value) {
354
        private final void checkInterceptable(Factory f, Object value) {
355
               
355
               
356
                if (f instanceof Interceptor) {
356
                if (f instanceof Interceptor) {
357
                       
357
                       
358
                        Interceptor i = (Interceptor) f;
358
                        Interceptor i = (Interceptor) f;
359
                       
359
                       
360
                        ((Interceptor) f).onCreated(value);
360
                        ((Interceptor) f).onCreated(value);
361
                }
361
                }
362
        }
362
        }
363
       
363
       
364
        @Override
364
        @Override
365
        public Factory ioc(String key, Factory factory, Scope scope) {
365
        public Factory ioc(String key, Factory factory, Scope scope) {
366
               
366
               
367
                factoriesByName.put(key, factory);
367
                factoriesByName.put(key, factory);
368
               
368
               
369
                singletonsCache.remove(key); // just in case we are overriding a previous singleton bean...
369
                singletonsCache.remove(key); // just in case we are overriding a previous singleton bean...
370
               
370
               
371
                threadLocalsCache.remove(key); // just in case we are overriding a previous thread local...
-
 
-
 
371
                ThreadLocal<Object> threadLocal = threadLocalsCache.remove(key); // just in case we are overriding a previous thread local...
-
 
372
                if (threadLocal != null) {
-
 
373
                        threadLocal.remove();
-
 
374
                }
372
               
375
               
373
                scopes.put(key, scope);
376
                scopes.put(key, scope);
374
               
377
               
375
                forConstructMethod.add(new ConstructorDependency(key, factory.getType()));
378
                forConstructMethod.add(new ConstructorDependency(key, factory.getType()));
376
               
379
               
377
                return factory;
380
                return factory;
378
        }
381
        }
379
       
382
       
380
        @Override
383
        @Override
381
        public Factory ioc(String key, Factory factory) {
384
        public Factory ioc(String key, Factory factory) {
382
               
385
               
383
                return ioc(key, factory, Scope.NONE);
386
                return ioc(key, factory, Scope.NONE);
384
        }
387
        }
385
       
388
       
386
        @Override
389
        @Override
387
        public ConfigurableFactory ioc(String key, Class<? extends Object> klass) {
390
        public ConfigurableFactory ioc(String key, Class<? extends Object> klass) {
388
               
391
               
389
                ConfigurableFactory cc = new ClassFactory(this, klass);
392
                ConfigurableFactory cc = new ClassFactory(this, klass);
390
               
393
               
391
                ioc(key, cc);
394
                ioc(key, cc);
392
               
395
               
393
                return cc;
396
                return cc;
394
        }
397
        }
395
       
398
       
396
        @Override
399
        @Override
397
        public ConfigurableFactory ioc(String key, Class<? extends Object> klass, Scope scope) {
400
        public ConfigurableFactory ioc(String key, Class<? extends Object> klass, Scope scope) {
398
               
401
               
399
                ConfigurableFactory cc = new ClassFactory(this, klass);
402
                ConfigurableFactory cc = new ClassFactory(this, klass);
400
               
403
               
401
                ioc(key, cc, scope);
404
                ioc(key, cc, scope);
402
               
405
               
403
                return cc;
406
                return cc;
404
        }
407
        }
405
       
408
       
406
        @Override
409
        @Override
407
        public void autowire(String sourceFromContainer) {
410
        public void autowire(String sourceFromContainer) {
408
               
411
               
409
                // autowire by constructor and setter...
412
                // autowire by constructor and setter...
410
               
413
               
411
                autowireBySetter(sourceFromContainer);
414
                autowireBySetter(sourceFromContainer);
412
               
415
               
413
                autowireByConstructor(sourceFromContainer);
416
                autowireByConstructor(sourceFromContainer);
414
        }
417
        }
415
       
418
       
416
        @Override
419
        @Override
417
        public void autowire(String sourceFromContainer, String beanProperty) {
420
        public void autowire(String sourceFromContainer, String beanProperty) {
418
               
421
               
419
                // autowire by constructor and setter...
422
                // autowire by constructor and setter...
420
               
423
               
421
                autowireBySetter(beanProperty, sourceFromContainer);
424
                autowireBySetter(beanProperty, sourceFromContainer);
422
               
425
               
423
                autowireByConstructor(sourceFromContainer);
426
                autowireByConstructor(sourceFromContainer);
424
        }
427
        }
425
428
426
        private void autowireBySetter(String targetProperty, String sourceFromContainer) {
429
        private void autowireBySetter(String targetProperty, String sourceFromContainer) {
427
               
430
               
428
                Class<? extends Object> sourceType = getType(sourceFromContainer);
431
                Class<? extends Object> sourceType = getType(sourceFromContainer);
429
432
430
                SetterDependency d = new SetterDependency(targetProperty, sourceFromContainer, sourceType);
433
                SetterDependency d = new SetterDependency(targetProperty, sourceFromContainer, sourceType);
431
               
434
               
432
                setterDependencies.add(d);
435
                setterDependencies.add(d);
433
        }
436
        }
434
       
437
       
435
        private void autowireBySetter(String targetProperty) {
438
        private void autowireBySetter(String targetProperty) {
436
               
439
               
437
                autowireBySetter(targetProperty, targetProperty);
440
                autowireBySetter(targetProperty, targetProperty);
438
        }
441
        }
439
       
442
       
440
        private void autowireByConstructor(String sourceFromContainer) {
443
        private void autowireByConstructor(String sourceFromContainer) {
441
               
444
               
442
                Class<? extends Object> sourceType = getType(sourceFromContainer);
445
                Class<? extends Object> sourceType = getType(sourceFromContainer);
443
               
446
               
444
                ConstructorDependency d = new ConstructorDependency(sourceFromContainer, sourceType);
447
                ConstructorDependency d = new ConstructorDependency(sourceFromContainer, sourceType);
445
               
448
               
446
                constructorDependencies.add(d);
449
                constructorDependencies.add(d);
447
        }
450
        }
448
       
451
       
449
        Set<ConstructorDependency> getConstructorDependencies() {
452
        Set<ConstructorDependency> getConstructorDependencies() {
450
               
453
               
451
                return constructorDependencies;
454
                return constructorDependencies;
452
        }
455
        }
453
       
456
       
454
        @Override
457
        @Override
455
        public <T> T construct(Class<? extends Object> klass) {
458
        public <T> T construct(Class<? extends Object> klass) {
456
               
459
               
457
                ClassFactory f = new ClassFactory(this, klass, forConstructMethod);
460
                ClassFactory f = new ClassFactory(this, klass, forConstructMethod);
458
               
461
               
459
                return (T) f.getInstance();
462
                return (T) f.getInstance();
460
        }
463
        }
461
464
462
        @Override
465
        @Override
463
        public void inject(Object bean) {
466
        public void inject(Object bean) {
464
               
467
               
465
                Provider p = new Provider() {
468
                Provider p = new Provider() {
466
                       
469
                       
467
                        @Override
470
                        @Override
468
                        public Object get(String key) {
471
                        public Object get(String key) {
469
                               
472
                               
470
                                return MentaContainer.this.get(key);
473
                                return MentaContainer.this.get(key);
471
                        }
474
                        }
472
                       
475
                       
473
                        @Override
476
                        @Override
474
                        public boolean hasValue(String key) {
477
                        public boolean hasValue(String key) {
475
                               
478
                               
476
                                return MentaContainer.this.check(key);
479
                                return MentaContainer.this.check(key);
477
                        }
480
                        }
478
                       
481
                       
479
                };
482
                };
480
               
483
               
481
                try {
484
                try {
482
485
483
                        InjectionUtils.getObject(bean, p, false, null, true, false, true);
486
                        InjectionUtils.getObject(bean, p, false, null, true, false, true);
484
                       
487
                       
485
                } catch(Exception e) {
488
                } catch(Exception e) {
486
                       
489
                       
487
                        throw new RuntimeException("Error populating bean: " + bean, e);
490
                        throw new RuntimeException("Error populating bean: " + bean, e);
488
                }
491
                }
489
        }
492
        }
490
493
491
        @Override
494
        @Override
492
        public synchronized boolean check(String key) {
495
        public synchronized boolean check(String key) {
493
               
496
               
494
                if (!factoriesByName.containsKey(key)) return false;
497
                if (!factoriesByName.containsKey(key)) return false;
495
               
498
               
496
                Scope scope = scopes.get(key);
499
                Scope scope = scopes.get(key);
497
               
500
               
498
                if (scope == Scope.NONE) {
501
                if (scope == Scope.NONE) {
499
                       
502
                       
500
                        return false; // always...
503
                        return false; // always...
501
                       
504
                       
502
                } else if (scope == Scope.SINGLETON) {
505
                } else if (scope == Scope.SINGLETON) {
503
                       
506
                       
504
                        return singletonsCache.containsKey(key);
507
                        return singletonsCache.containsKey(key);
505
                       
508
                       
506
                } else if (scope == Scope.THREAD) {
509
                } else if (scope == Scope.THREAD) {
507
                       
510
                       
508
                        ThreadLocal<Object> t = threadLocalsCache.get(key);
511
                        ThreadLocal<Object> t = threadLocalsCache.get(key);
509
                       
512
                       
510
                        if (t != null) return t.get() != null;
513
                        if (t != null) return t.get() != null;
511
                       
514
                       
512
                        return false;
515
                        return false;
513
                       
516
                       
514
                } else {
517
                } else {
515
                       
518
                       
516
                        throw new UnsupportedOperationException("This scope is not supported: " + scope);
519
                        throw new UnsupportedOperationException("This scope is not supported: " + scope);
517
                }
520
                }
518
        }
521
        }
519
       
522
       
520
        private static class ClearableHolder {
523
        private static class ClearableHolder {
521
524
522
                private Interceptor c;
525
                private Interceptor c;
523
                private Object value;
526
                private Object value;
524
               
527
               
525
                public ClearableHolder(Interceptor c, Object value) {
528
                public ClearableHolder(Interceptor c, Object value) {
526
                        this.c = c;
529
                        this.c = c;
527
                        this.value = value;
530
                        this.value = value;
528
                }
531
                }
529
               
532
               
530
                public void clear() {
533
                public void clear() {
531
                        c.onCleared(value);
534
                        c.onCleared(value);
532
                }
535
                }
533
               
536
               
534
        }
537
        }
535
}
538
}