MentaContainer

Rev

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

Rev 66 Rev 71
Line 2... Line 2...
2
2
3
import java.lang.reflect.Method;
3
import java.lang.reflect.Method;
4
import java.util.HashMap;
-
 
-
 
4
import java.util.Collections;
5
import java.util.HashSet;
5
import java.util.HashSet;
-
 
6
import java.util.Hashtable;
-
 
7
import java.util.LinkedList;
-
 
8
import java.util.List;
6
import java.util.Map;
9
import java.util.Map;
7
import java.util.Set;
10
import java.util.Set;
8
11
9
import org.mentacontainer.Clearable;
12
import org.mentacontainer.Clearable;
10
import org.mentacontainer.Component;
13
import org.mentacontainer.Component;
Line 20... Line 23...
20
 *
23
 *
21
 * @author sergio.oliveira.jr@gmail.com
24
 * @author sergio.oliveira.jr@gmail.com
22
 */
25
 */
23
public class MentaContainer implements Container {
26
public class MentaContainer implements Container {
24
27
25
        private Map<String, Component> beans = new HashMap<String, Component>();
-
 
-
 
28
        private Map<String, Component> beans = new Hashtable<String, Component>();
26
       
29
       
27
        private Map<String, Scope> scopes = new HashMap<String, Scope>();
-
 
-
 
30
        private Map<String, Scope> scopes = new Hashtable<String, Scope>();
28
       
31
       
29
        private Map<String, Object> singletonsCache = new HashMap<String, Object>();
-
 
-
 
32
        private Map<String, Object> singletonsCache = new Hashtable<String, Object>();
30
       
33
       
31
        private Map<String, ThreadLocal<Object>> threadLocalsCache = new HashMap<String, ThreadLocal<Object>>();
-
 
-
 
34
        private Map<String, ThreadLocal<Object>> threadLocalsCache = new Hashtable<String, ThreadLocal<Object>>();
32
35
33
        private Set<Dependency> dependencies = new HashSet<Dependency>();
-
 
-
 
36
        private Set<Dependency> dependencies = Collections.synchronizedSet(new HashSet<Dependency>());
34
       
37
       
35
        public synchronized void clear(Scope scope) {
-
 
-
 
38
        public void clear(Scope scope) {
36
               
39
               
37
                if (scope == Scope.SINGLETON) {
40
                if (scope == Scope.SINGLETON) {
38
                       
41
                       
39
                        for(String key : singletonsCache.keySet()) {
-
 
40
                               
-
 
41
                                Component comp = beans.get(key);
-
 
42
                               
-
 
43
                                if (comp instanceof Clearable) {
-
 
44
                                       
-
 
45
                                        Clearable<Object> c = (Clearable<Object>) comp;
-
 
46
                               
-
 
47
                                        Object value = singletonsCache.get(key);
-
 
48
                                       
-
 
49
                                        c.onCleared(value);
-
 
50
                                }
-
 
-
 
42
                        List<ClearablePair> listToClear = new LinkedList<ClearablePair>();
-
 
43
                       
-
 
44
                        synchronized(this) {
-
 
45
                       
-
 
46
                        for(String key : singletonsCache.keySet()) {
-
 
47
                               
-
 
48
                                Component comp = beans.get(key);
-
 
49
                               
-
 
50
                                if (comp instanceof Clearable) {
-
 
51
                                       
-
 
52
                                        Clearable<Object> c = (Clearable<Object>) comp;
-
 
53
                               
-
 
54
                                        Object value = singletonsCache.get(key);
-
 
55
                                       
-
 
56
                                        listToClear.add(new ClearablePair(c, value));
-
 
57
                                }
-
 
58
                        }
-
 
59
                       
-
 
60
                        singletonsCache.clear();
51
                        }
61
                        }
52
                       
62
                       
53
                        singletonsCache.clear();
-
 
-
 
63
                        // clear everything inside a non-synchronized block...
-
 
64
                       
-
 
65
                        for(ClearablePair cp : listToClear) cp.c.onCleared(cp.value);
54
                       
66
                       
55
                } else if (scope == Scope.THREAD) {
67
                } else if (scope == Scope.THREAD) {
56
                       
68
                       
57
                        for(String key : threadLocalsCache.keySet()) {
-
 
58
                               
-
 
59
                                Component comp = beans.get(key);
-
 
60
                               
-
 
61
                                if (comp instanceof Clearable) {
-
 
62
                                       
-
 
63
                                        Clearable<Object> c = (Clearable<Object>) comp;
-
 
64
                               
-
 
65
                                        ThreadLocal<Object> t = threadLocalsCache.get(key);
-
 
66
                                       
-
 
67
                                        Object value = t.get();
-
 
68
                                       
-
 
69
                                        if (value != null) c.onCleared(value);
-
 
70
                                }
-
 
-
 
69
                        List<ClearablePair> listToClear = new LinkedList<ClearablePair>();
-
 
70
                       
-
 
71
                        synchronized(this) {
-
 
72
                       
-
 
73
                        for(String key : threadLocalsCache.keySet()) {
-
 
74
                               
-
 
75
                                Component comp = beans.get(key);
-
 
76
                               
-
 
77
                                if (comp instanceof Clearable) {
-
 
78
                                       
-
 
79
                                        Clearable<Object> c = (Clearable<Object>) comp;
-
 
80
                               
-
 
81
                                        ThreadLocal<Object> t = threadLocalsCache.get(key);
-
 
82
                                       
-
 
83
                                        Object value = t.get();
-
 
84
                                       
-
 
85
                                        if (value != null) listToClear.add(new ClearablePair(c, value));
-
 
86
                                }
-
 
87
                        }
-
 
88
                       
-
 
89
                        for(ThreadLocal<Object> t : threadLocalsCache.values()) {
-
 
90
                               
-
 
91
                                t.set(null);
-
 
92
                        }
71
                        }
93
                        }
72
                       
94
                       
73
                        for(ThreadLocal<Object> t : threadLocalsCache.values()) {
-
 
74
                               
-
 
75
                                t.set(null);
-
 
76
                        }
-
 
-
 
95
                        // clear everything inside a non-synchronized block...
-
 
96
                       
-
 
97
                        for(ClearablePair cp : listToClear) cp.c.onCleared(cp.value);
77
                }
98
                }
78
        }
99
        }
79
       
100
       
80
        public synchronized <T> T clear(String key) {
-
 
-
 
101
        public <T> T clear(String key) {
81
               
102
               
82
                if (!beans.containsKey(key)) return null;
103
                if (!beans.containsKey(key)) return null;
83
               
104
               
84
                Scope scope = scopes.get(key);
105
                Scope scope = scopes.get(key);
85
               
106
               
86
                if (scope == Scope.SINGLETON) {
107
                if (scope == Scope.SINGLETON) {
87
                       
108
                       
88
                        Object value = singletonsCache.remove(key);
-
 
-
 
109
                        ClearablePair cp = null;
89
                       
110
                       
90
                        if (value != null) {
-
 
91
                               
-
 
92
                                Component comp = beans.get(key);
-
 
93
                               
-
 
94
                                if (comp instanceof Clearable) {
-
 
95
                                       
-
 
96
                                        Clearable<Object> c = (Clearable<Object>) comp;
-
 
97
                                       
-
 
98
                                        c.onCleared(value);
-
 
99
                                }
-
 
-
 
111
                        Object value = null;
-
 
112
                       
-
 
113
                        synchronized(this) {
-
 
114
                       
-
 
115
                        value = singletonsCache.remove(key);
-
 
116
                       
-
 
117
                        if (value != null) {
-
 
118
                               
-
 
119
                                Component comp = beans.get(key);
-
 
120
                               
-
 
121
                                if (comp instanceof Clearable) {
-
 
122
                                       
-
 
123
                                        Clearable<Object> c = (Clearable<Object>) comp;
-
 
124
                                       
-
 
125
                                        cp = new ClearablePair(c, value);
-
 
126
                                }
-
 
127
                        }
100
                        }
128
                        }
-
 
129
                       
-
 
130
                        if (cp != null) cp.c.onCleared(cp.value);
101
                       
131
                       
102
                        return (T) value;
132
                        return (T) value;
103
                       
133
                       
104
                } else if (scope == Scope.THREAD) {
134
                } else if (scope == Scope.THREAD) {
105
                       
135
                       
106
                        ThreadLocal<Object> t = threadLocalsCache.get(key);
-
 
-
 
136
                        ClearablePair cp = null;
107
                       
137
                       
108
                        if (t != null) {
-
 
109
                               
-
 
110
                                Object o = t.get();
-
 
111
                               
-
 
112
                                if (o != null) {
-
 
113
                                       
-
 
114
                                        Component comp = beans.get(key);
-
 
115
                                       
-
 
116
                                        if (comp instanceof Clearable) {
-
 
117
                                               
-
 
118
                                                Clearable<Object> c = (Clearable<Object>) comp;
-
 
119
                                               
-
 
120
                                                c.onCleared(o);
-
 
121
                                        }
-
 
122
                                       
-
 
123
                                        t.set(null);
-
 
124
                                       
-
 
125
                                        return (T) o;
-
 
126
                                }
-
 
-
 
138
                        Object retVal = null;
-
 
139
                       
-
 
140
                        synchronized(this) {
-
 
141
                       
-
 
142
                        ThreadLocal<Object> t = threadLocalsCache.get(key);
-
 
143
                       
-
 
144
                        if (t != null) {
-
 
145
                               
-
 
146
                                Object o = t.get();
-
 
147
                               
-
 
148
                                if (o != null) {
-
 
149
                                       
-
 
150
                                        Component comp = beans.get(key);
-
 
151
                                       
-
 
152
                                        if (comp instanceof Clearable) {
-
 
153
                                               
-
 
154
                                                Clearable<Object> c = (Clearable<Object>) comp;
-
 
155
                                               
-
 
156
                                                cp = new ClearablePair(c, o);
-
 
157
                                        }
-
 
158
                                       
-
 
159
                                        t.set(null);
-
 
160
                                       
-
 
161
                                        retVal = o;
-
 
162
                                }
-
 
163
                        }
127
                        }
164
                        }
128
                       
165
                       
129
                        return null;
-
 
-
 
166
                        if (cp != null) cp.c.onCleared(cp.value);
-
 
167
                       
-
 
168
                        return (T) retVal;
130
               
169
               
131
                } else if (scope == Scope.NONE) {
170
                } else if (scope == Scope.NONE) {
132
                       
171
                       
133
                        return null; // always...
172
                        return null; // always...
134
                       
173
                       
Line 136... Line 175...
136
                       
175
                       
137
                        throw new UnsupportedOperationException("Scope not supported: " + scope);
176
                        throw new UnsupportedOperationException("Scope not supported: " + scope);
138
                }
177
                }
139
        }
178
        }
140
179
141
        public synchronized <T> T get(String key) {
-
 
-
 
180
        public <T> T get(String key) {
142
181
143
                if (!beans.containsKey(key)) return null;
182
                if (!beans.containsKey(key)) return null;
144
183
145
                Component c = beans.get(key);
184
                Component c = beans.get(key);
146
               
185
               
Line 149... Line 188...
149
                Object target = null;
188
                Object target = null;
150
189
151
                try {
190
                try {
152
191
153
                        if (scope == Scope.SINGLETON) {
192
                        if (scope == Scope.SINGLETON) {
-
 
193
                               
-
 
194
                                boolean needsToCreate = false;
-
 
195
                               
-
 
196
                                synchronized(this) {
154
197
155
                                if (singletonsCache.containsKey(key)) {
-
 
156
-
 
157
                                        target = singletonsCache.get(key);
-
 
158
-
 
159
                                        return (T) target; // no need to wire again...
-
 
160
-
 
161
                                } else {
-
 
162
-
 
-
 
198
                                if (singletonsCache.containsKey(key)) {
-
 
199
   
-
 
200
                                        target = singletonsCache.get(key);
-
 
201
   
-
 
202
                                        return (T) target; // no need to wire again...
-
 
203
   
-
 
204
                                } else {
-
 
205
                                       
-
 
206
                                        needsToCreate = true;
-
 
207
                                }
-
 
208
                                }
-
 
209
                               
-
 
210
                                if (needsToCreate) {
-
 
211
                                       
-
 
212
                                        // getInstance needs to be in a non-synchronized block
-
 
213
                                       
163
                                        target = c.getInstance();
214
                                        target = c.getInstance();
-
 
215
                                       
-
 
216
                                        synchronized(this) {
164
217
165
                                        singletonsCache.put(key, target);
-
 
-
 
218
                                                singletonsCache.put(key, target);
-
 
219
                                        }
166
                                }
220
                                }
167
                               
221
                               
168
                        } else if (scope == Scope.THREAD) {
222
                        } else if (scope == Scope.THREAD) {
169
                               
223
                               
170
                                if (threadLocalsCache.containsKey(key)) {
-
 
-
 
224
                                boolean needsToCreate = false;
-
 
225
                               
-
 
226
                                boolean needsToAddToCache = false;
-
 
227
                               
-
 
228
                                ThreadLocal<Object> t = null;
-
 
229
                               
-
 
230
                                synchronized(this) {
-
 
231
                               
-
 
232
                                if (threadLocalsCache.containsKey(key)) {
-
 
233
                                       
-
 
234
                                        t = threadLocalsCache.get(key);
-
 
235
                                       
-
 
236
                                        target = t.get();
-
 
237
                                       
-
 
238
                                        if (target == null) { // different thread...
-
 
239
                                               
-
 
240
                                                needsToCreate = true;
-
 
241
                                               
-
 
242
                                                // don't return... let it be wired...
-
 
243
                                               
-
 
244
                                        } else {
-
 
245
                                       
-
 
246
                                                return (T) target; // no need to wire again...
-
 
247
                                               
-
 
248
                                        }
-
 
249
                                       
-
 
250
                                } else {
-
 
251
                                       
-
 
252
                                        t = new ThreadLocal<Object>();
-
 
253
                                       
-
 
254
                                        needsToCreate = true;
-
 
255
                                       
-
 
256
                                                needsToAddToCache = true;
-
 
257
                                       
-
 
258
                                        // let it be wired...
-
 
259
                                }
-
 
260
                                }
-
 
261
                               
-
 
262
                                if (needsToCreate) {
171
                                       
263
                                       
172
                                        ThreadLocal<Object> t = threadLocalsCache.get(key);
-
 
173
                                       
-
 
174
                                        target = t.get();
-
 
175
                                       
-
 
176
                                        if (target == null) { // different thread...
-
 
177
                                               
-
 
178
                                                target = c.getInstance();
-
 
179
                                               
-
 
180
                                                t.set(target);
-
 
181
                                               
-
 
182
                                                // don't return... let it be wired...
-
 
183
                                               
-
 
184
                                        } else {
-
 
185
                                       
-
 
186
                                                return (T) target; // no need to wire again...
-
 
187
                                               
-
 
188
                                        }
-
 
189
                                       
-
 
190
                                } else {
-
 
191
                                       
-
 
192
                                        ThreadLocal<Object> t = new ThreadLocal<Object>();
-
 
-
 
264
                                        // getInstance needs to be in a non-synchronized block
193
                                       
265
                                       
194
                                        target = c.getInstance();
266
                                        target = c.getInstance();
195
                                       
267
                                       
196
                                        t.set(target);
268
                                        t.set(target);
-
 
269
                                }
-
 
270
                               
-
 
271
                                if (needsToAddToCache) {
197
                                       
272
                                       
198
                                        threadLocalsCache.put(key, t);
-
 
-
 
273
                                        synchronized(this) {
199
                                       
274
                                       
200
                                        // let it be wired...
-
 
-
 
275
                                                threadLocalsCache.put(key, t);
-
 
276
                                        }
201
                                }
277
                                }
202
                               
278
                               
203
                        } else if (scope == Scope.NONE) {
279
                        } else if (scope == Scope.NONE) {
204
280
205
                                target = c.getInstance();
281
                                target = c.getInstance();
Line 367... Line 443...
367
                       
443
                       
368
                } else {
444
                } else {
369
                       
445
                       
370
                        throw new UnsupportedOperationException("This scope is not supported: " + scope);
446
                        throw new UnsupportedOperationException("This scope is not supported: " + scope);
371
                }
447
                }
-
 
448
        }
-
 
449
       
-
 
450
        private static class ClearablePair {
-
 
451
               
-
 
452
                public ClearablePair(Clearable<Object> c, Object value) {
-
 
453
                        this.c = c;
-
 
454
                        this.value = value;
-
 
455
                }
-
 
456
               
-
 
457
                Clearable<Object> c;
-
 
458
               
-
 
459
                Object value;
372
        }
460
        }
373
}
461
}