MentaContainer

Rev

Rev 145 | Rev 148 | Go to most recent revision | Show entire file | Ignore whitespace | Details | Blame | Last modification | View Log | RSS feed

Rev 145 Rev 146
Line 10... Line 10...
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.Pool;
-
 
-
 
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
/**
Line 22... Line 22...
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, Pool<?>> poolsByName = new Hashtable<String, Pool<?>>();
-
 
-
 
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
       
Line 37... Line 37...
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<? extends Object> getType(Object key) {
43
               
43
               
44
                String k = InjectionUtils.getKeyName(key);
44
                String k = InjectionUtils.getKeyName(key);
45
               
45
               
46
                Pool<?> factory = poolsByName.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
        }
Line 59... Line 59...
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
                                Pool<?> pool = poolsByName.get(key);
-
 
-
 
64
                                Factory factory = factoriesByName.get(key);
65
                               
65
                               
66
                                Object value = singletonsCache.get(key);
-
 
-
 
66
                                if (factory instanceof Interceptor) {
-
 
67
                                       
-
 
68
                                        Interceptor c = (Interceptor) factory;
67
                               
69
                               
68
                                listToClear.add(new ClearableHolder(pool, value));
-
 
-
 
70
                                        Object value = singletonsCache.get(key);
-
 
71
                                       
-
 
72
                                        listToClear.add(new ClearableHolder(c, value));
-
 
73
                                }
69
                        }
74
                        }
70
                       
75
                       
71
                        singletonsCache.clear();
76
                        singletonsCache.clear();
72
                        }
77
                        }
73
                       
78
                       
Line 81... Line 86...
81
                       
86
                       
82
                        synchronized(this) {
87
                        synchronized(this) {
83
                       
88
                       
84
                        for(String key : threadLocalsCache.keySet()) {
89
                        for(String key : threadLocalsCache.keySet()) {
85
                               
90
                               
86
                                Pool<?> factory = poolsByName.get(key);
-
 
-
 
91
                                Factory factory = factoriesByName.get(key);
87
                               
92
                               
88
                                ThreadLocal<Object> t = threadLocalsCache.get(key);
-
 
89
                                       
-
 
90
                                        Object value = t.get();
-
 
91
                                       
-
 
92
                                        if (value != null) listToClear.add(new ClearableHolder(factory, value));
-
 
-
 
93
                                if (factory instanceof Interceptor) {
-
 
94
                                       
-
 
95
                                        Interceptor c = (Interceptor) factory;
-
 
96
                               
-
 
97
                                        ThreadLocal<Object> t = threadLocalsCache.get(key);
-
 
98
                                       
-
 
99
                                        Object value = t.get();
-
 
100
                                       
-
 
101
                                        if (value != null) listToClear.add(new ClearableHolder(c, value));
-
 
102
                                }
93
                        }
103
                        }
94
                       
104
                       
95
                        for(ThreadLocal<Object> t : threadLocalsCache.values()) {
105
                        for(ThreadLocal<Object> t : threadLocalsCache.values()) {
96
                               
106
                               
97
                                t.remove();
107
                                t.remove();
Line 107... Line 117...
107
        @Override
117
        @Override
108
        public <T> T clear(Object key) {
118
        public <T> T clear(Object key) {
109
               
119
               
110
                String keyString = InjectionUtils.getKeyName(key);
120
                String keyString = InjectionUtils.getKeyName(key);
111
               
121
               
112
                if (!poolsByName.containsKey(keyString)) return null;
-
 
-
 
122
                if (!factoriesByName.containsKey(keyString)) return null;
113
               
123
               
114
                Scope scope = scopes.get(keyString);
124
                Scope scope = scopes.get(keyString);
115
               
125
               
116
                if (scope == Scope.SINGLETON) {
126
                if (scope == Scope.SINGLETON) {
117
                       
127
                       
Line 123... Line 133...
123
                       
133
                       
124
                        value = singletonsCache.remove(keyString);
134
                        value = singletonsCache.remove(keyString);
125
                       
135
                       
126
                        if (value != null) {
136
                        if (value != null) {
127
                               
137
                               
128
                                Pool<?> factory = poolsByName.get(keyString);
-
 
-
 
138
                                Factory factory = factoriesByName.get(keyString);
129
                               
139
                               
130
                                cp = new ClearableHolder(factory, value);
-
 
-
 
140
                                if (factory instanceof Interceptor) {
-
 
141
                                       
-
 
142
                                        Interceptor c = (Interceptor) factory;
-
 
143
                                       
-
 
144
                                        cp = new ClearableHolder(c, value);
-
 
145
                                }
131
                        }
146
                        }
132
                        }
147
                        }
133
                       
148
                       
134
                        if (cp != null) cp.clear();
-
 
-
 
149
                        if (cp != null) cp.c.onCleared(cp.value);
135
                       
150
                       
136
                        return (T) value;
151
                        return (T) value;
137
                       
152
                       
138
                } else if (scope == Scope.THREAD) {
153
                } else if (scope == Scope.THREAD) {
139
                       
154
                       
Line 149... Line 164...
149
                               
164
                               
150
                                Object o = t.get();
165
                                Object o = t.get();
151
                               
166
                               
152
                                if (o != null) {
167
                                if (o != null) {
153
                                       
168
                                       
154
                                        Pool<?> factory = poolsByName.get(keyString);
-
 
-
 
169
                                        Factory factory = factoriesByName.get(keyString);
155
                                       
170
                                       
156
                                        cp = new ClearableHolder(factory, o);
-
 
-
 
171
                                        if (factory instanceof Interceptor) {
-
 
172
                                               
-
 
173
                                                Interceptor c = (Interceptor) factory;
-
 
174
                                               
-
 
175
                                                cp = new ClearableHolder(c, o);
-
 
176
                                        }
157
                                       
177
                                       
158
                                        t.remove();
178
                                        t.remove();
159
                                       
179
                                       
160
                                        retVal = o;
180
                                        retVal = o;
161
                                }
181
                                }
162
                        }
182
                        }
163
                        }
183
                        }
164
                       
184
                       
165
                        if (cp != null) cp.clear();
-
 
-
 
185
                        if (cp != null) cp.c.onCleared(cp.value);
166
                       
186
                       
167
                        return (T) retVal;
187
                        return (T) retVal;
168
               
188
               
169
                } else if (scope == Scope.NONE) {
189
                } else if (scope == Scope.NONE) {
170
                       
190
                       
Line 179... Line 199...
179
        @Override
199
        @Override
180
        public <T> T get(Object key) {
200
        public <T> T get(Object key) {
181
               
201
               
182
                String keyString = InjectionUtils.getKeyName(key);
202
                String keyString = InjectionUtils.getKeyName(key);
183
203
184
                if (!poolsByName.containsKey(keyString)) return null;
-
 
-
 
204
                if (!factoriesByName.containsKey(keyString)) return null;
185
205
186
                Pool<?> c = poolsByName.get(keyString);
-
 
-
 
206
                Factory c = factoriesByName.get(keyString);
187
               
207
               
188
                Scope scope = scopes.get(keyString);
208
                Scope scope = scopes.get(keyString);
189
               
209
               
190
                Object target = null;
210
                Object target = null;
191
211
Line 212... Line 232...
212
                                if (needsToCreate) {
232
                                if (needsToCreate) {
213
                                       
233
                                       
214
                                        // getInstance needs to be in a non-synchronized block
234
                                        // getInstance needs to be in a non-synchronized block
215
                                       
235
                                       
216
                                        target = c.getInstance();
236
                                        target = c.getInstance();
-
 
237
                                       
-
 
238
                                        checkInterceptable(c, target);
217
                                       
239
                                       
218
                                        synchronized(this) {
240
                                        synchronized(this) {
219
241
220
                                                singletonsCache.put(keyString, target);
242
                                                singletonsCache.put(keyString, target);
221
                                        }
243
                                        }
Line 264... Line 286...
264
                                if (needsToCreate) {
286
                                if (needsToCreate) {
265
                                       
287
                                       
266
                                        // getInstance needs to be in a non-synchronized block
288
                                        // getInstance needs to be in a non-synchronized block
267
                                       
289
                                       
268
                                        target = c.getInstance();
290
                                        target = c.getInstance();
-
 
291
                                       
-
 
292
                                        checkInterceptable(c, target);
269
                                       
293
                                       
270
                                        t.set(target);
294
                                        t.set(target);
271
                                }
295
                                }
272
                               
296
                               
273
                                if (needsToAddToCache) {
297
                                if (needsToAddToCache) {
Line 279... Line 303...
279
                                }
303
                                }
280
                               
304
                               
281
                        } else if (scope == Scope.NONE) {
305
                        } else if (scope == Scope.NONE) {
282
306
283
                                target = c.getInstance();
307
                                target = c.getInstance();
-
 
308
                               
-
 
309
                                checkInterceptable(c, target);
284
                               
310
                               
285
                        } else {
311
                        } else {
286
                               
312
                               
287
                                throw new UnsupportedOperationException("Don't know how to handle scope: " + scope);
313
                                throw new UnsupportedOperationException("Don't know how to handle scope: " + scope);
288
                        }
314
                        }
Line 329... Line 355...
329
355
330
                        throw new RuntimeException(e);
356
                        throw new RuntimeException(e);
331
                }
357
                }
332
        }
358
        }
333
       
359
       
334
        private static <T> Pool<T> fromFactory(final Factory<T> creator) {
-
 
-
 
360
        private final void checkInterceptable(Factory f, Object value) {
335
               
361
               
336
                return new Pool<T>() {
-
 
337
-
 
338
                        @Override
-
 
339
            public T getInstance() {
-
 
340
                    return creator.getInstance();
-
 
341
            }
-
 
342
-
 
343
                        @Override
-
 
344
            public Class<T> getType() {
-
 
345
                    return creator.getType();
-
 
346
            }
-
 
347
-
 
348
                        @Override
-
 
349
            public void releaseInstance(T e) {
-
 
350
                                // do nothing!
-
 
351
            }
-
 
352
                };
-
 
-
 
362
                if (f instanceof Interceptor) {
-
 
363
                       
-
 
364
                        Interceptor i = (Interceptor) f;
-
 
365
                       
-
 
366
                        ((Interceptor) f).onCreated(value);
-
 
367
                }
353
        }
368
        }
354
       
369
       
355
        @Override
370
        @Override
356
        public void ioc(Object key, Factory<?> factory, Scope scope) {
-
 
357
               
-
 
358
                ioc(key, fromFactory(factory), scope);
-
 
359
        }
-
 
360
       
-
 
361
        @Override
-
 
362
        public void ioc(Object key, Pool<?> factory, Scope scope) {
-
 
-
 
371
        public Factory ioc(Object key, Factory factory, Scope scope) {
363
               
372
               
364
                String keyString = InjectionUtils.getKeyName(key);
373
                String keyString = InjectionUtils.getKeyName(key);
365
               
374
               
366
                poolsByName.put(keyString, factory);
-
 
-
 
375
                factoriesByName.put(keyString, factory);
367
               
376
               
368
                singletonsCache.remove(keyString); // just in case we are overriding a previous singleton bean...
377
                singletonsCache.remove(keyString); // just in case we are overriding a previous singleton bean...
369
               
378
               
370
                ThreadLocal<Object> threadLocal = threadLocalsCache.remove(keyString); // just in case we are overriding a previous thread local...
379
                ThreadLocal<Object> threadLocal = threadLocalsCache.remove(keyString); // just in case we are overriding a previous thread local...
371
                if (threadLocal != null) {
380
                if (threadLocal != null) {
Line 373... Line 382...
373
                }
382
                }
374
               
383
               
375
                scopes.put(keyString, scope);
384
                scopes.put(keyString, scope);
376
               
385
               
377
                forConstructMethod.add(new ConstructorDependency(keyString, factory.getType()));
386
                forConstructMethod.add(new ConstructorDependency(keyString, factory.getType()));
378
        }
-
 
379
       
-
 
380
        @Override
-
 
381
        public void ioc(Object key, Factory<?> factory) {
-
 
382
               
387
               
383
                ioc(key, fromFactory(factory));
-
 
-
 
388
                return factory;
384
        }
389
        }
385
       
390
       
386
        @Override
391
        @Override
387
        public void ioc(Object key, Pool<?> pool) {
-
 
-
 
392
        public Factory ioc(Object key, Factory factory) {
388
               
393
               
389
                ioc(key, pool, Scope.NONE);
-
 
-
 
394
                return ioc(key, factory, Scope.NONE);
390
        }
395
        }
391
       
396
       
392
        @Override
397
        @Override
393
        public <T> ConfigurableFactory<T> ioc(Object key, Class<T> klass) {
-
 
-
 
398
        public ConfigurableFactory ioc(Object key, Class<? extends Object> klass) {
394
               
399
               
395
                ConfigurableFactory<T> cc = new ClassFactory<T>(this, klass);
-
 
-
 
400
                ConfigurableFactory cc = new ClassFactory(this, klass);
396
               
401
               
397
                ioc(key, cc);
402
                ioc(key, cc);
398
               
403
               
399
                return cc;
404
                return cc;
400
        }
405
        }
401
       
406
       
402
        @Override
407
        @Override
403
        public <T> ConfigurableFactory<T> ioc(Object key, Class<T> klass, Scope scope) {
-
 
-
 
408
        public ConfigurableFactory ioc(Object key, Class<? extends Object> klass, Scope scope) {
404
               
409
               
405
                ConfigurableFactory<T> cc = new ClassFactory<T>(this, klass);
-
 
-
 
410
                ConfigurableFactory cc = new ClassFactory(this, klass);
406
               
411
               
407
                ioc(key, cc, scope);
412
                ioc(key, cc, scope);
408
               
413
               
409
                return cc;
414
                return cc;
410
        }
415
        }
Line 460... Line 465...
460
               
465
               
461
                return constructorDependencies;
466
                return constructorDependencies;
462
        }
467
        }
463
       
468
       
464
        @Override
469
        @Override
465
        public <T> T construct(Class<T> klass) {
-
 
-
 
470
        public <T> T construct(Class<? extends Object> klass) {
466
               
471
               
467
                ClassFactory<T> f = new ClassFactory<T>(this, klass, forConstructMethod);
-
 
-
 
472
                ClassFactory f = new ClassFactory(this, klass, forConstructMethod);
468
               
473
               
469
                return f.getInstance();
-
 
-
 
474
                return (T) f.getInstance();
470
        }
475
        }
471
476
472
        @Override
477
        @Override
473
        public void inject(Object bean) {
478
        public void inject(Object bean) {
474
               
479
               
Line 501... Line 506...
501
        @Override
506
        @Override
502
        public synchronized boolean check(Object obj) {
507
        public synchronized boolean check(Object obj) {
503
               
508
               
504
                String key = InjectionUtils.getKeyName(obj);
509
                String key = InjectionUtils.getKeyName(obj);
505
               
510
               
506
                if (!poolsByName.containsKey(key)) return false;
-
 
-
 
511
                if (!factoriesByName.containsKey(key)) return false;
507
               
512
               
508
                Scope scope = scopes.get(key);
513
                Scope scope = scopes.get(key);
509
               
514
               
510
                if (scope == Scope.NONE) {
515
                if (scope == Scope.NONE) {
511
                       
516
                       
Line 529... Line 534...
529
                }
534
                }
530
        }
535
        }
531
       
536
       
532
        private static class ClearableHolder {
537
        private static class ClearableHolder {
533
538
534
                private Pool<Object> c;
-
 
-
 
539
                private Interceptor c;
535
                private Object value;
540
                private Object value;
536
               
541
               
537
                public ClearableHolder(Pool<?> c, Object value) {
-
 
538
                        this.c = (Pool<Object>) c;
-
 
-
 
542
                public ClearableHolder(Interceptor c, Object value) {
-
 
543
                        this.c = c;
539
                        this.value = value;
544
                        this.value = value;
540
                }
545
                }
541
               
546
               
542
                public void clear() {
547
                public void clear() {
543
                        c.releaseInstance(value);
-
 
-
 
548
                        c.onCleared(value);
544
                }
549
                }
545
               
550
               
546
        }
551
        }
547
}
552
}