MentaContainer

Rev

Rev 149 | Only display areas with differences | Ignore whitespace | Details | Blame | Last modification | View Log | RSS feed

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