MentaContainer

Rev

Rev 45 | Rev 57 | Go to most recent revision | Details | Compare with Previous | Last modification | View Log | RSS feed

Rev Author Line No. Line
2 soliveira 1
package org.mentacontainer.impl;
2
 
3
import java.lang.reflect.Method;
4
import java.util.HashMap;
5
import java.util.HashSet;
6
import java.util.Map;
7
import java.util.Set;
8
 
20 soliveira 9
import org.mentacontainer.Component;
45 soliveira 10
import org.mentacontainer.ConfigurableComponent;
2 soliveira 11
import org.mentacontainer.Container;
20 soliveira 12
import org.mentacontainer.Dependency;
4 soliveira 13
import org.mentacontainer.util.InjectionUtils;
22 soliveira 14
import org.mentacontainer.util.InjectionUtils.Provider;
2 soliveira 15
 
20 soliveira 16
/**
17
 * The implementation of the IoC container.
18
 *
19
 * @author sergio.oliveira.jr@gmail.com
20
 */
2 soliveira 21
public class MentaContainer implements Container {
22
 
20 soliveira 23
        private Map<String, Component> beans = new HashMap<String, Component>();
51 soliveira 24
 
25
        private Set<String> singletons = new HashSet<String>();
26
 
27
        private Map<String, Object> singletonsCache = new HashMap<String, Object>();
2 soliveira 28
 
20 soliveira 29
        private Set<Dependency> dependencies = new HashSet<Dependency>();
4 soliveira 30
 
41 soliveira 31
        public <T> T get(String key) {
4 soliveira 32
 
43 soliveira 33
                if (!beans.containsKey(key)) return null;
4 soliveira 34
 
20 soliveira 35
                Component c = beans.get(key);
51 soliveira 36
 
37
                boolean isSingleton = singletons.contains(key);
4 soliveira 38
 
20 soliveira 39
                Object target = null;
4 soliveira 40
 
20 soliveira 41
                try {
4 soliveira 42
 
51 soliveira 43
                        if (isSingleton) {
4 soliveira 44
 
51 soliveira 45
                                if (singletonsCache.containsKey(key)) {
4 soliveira 46
 
51 soliveira 47
                                        target = singletonsCache.get(key);
4 soliveira 48
 
41 soliveira 49
                                        return (T) target;
4 soliveira 50
 
20 soliveira 51
                                } else {
4 soliveira 52
 
20 soliveira 53
                                        target = c.getInstance();
4 soliveira 54
 
51 soliveira 55
                                        singletonsCache.put(key, target);
20 soliveira 56
                                }
4 soliveira 57
 
20 soliveira 58
                        } else {
4 soliveira 59
 
20 soliveira 60
                                target = c.getInstance();
4 soliveira 61
 
20 soliveira 62
                        }
4 soliveira 63
 
20 soliveira 64
                        if (target != null) {
4 soliveira 65
 
20 soliveira 66
                                for (Dependency d : dependencies) {
4 soliveira 67
 
20 soliveira 68
                                        // has dependency ?
69
                                        Method m = d.check(target.getClass());
4 soliveira 70
 
20 soliveira 71
                                        if (m != null) {
4 soliveira 72
 
20 soliveira 73
                                                String sourceKey = d.getSource();
4 soliveira 74
 
20 soliveira 75
                                                if (sourceKey.equals(key)) {
4 soliveira 76
 
20 soliveira 77
                                                        // cannot depend on itself... also avoid recursive StackOverflow...
4 soliveira 78
 
20 soliveira 79
                                                        continue;
4 soliveira 80
 
20 soliveira 81
                                                }
2 soliveira 82
 
20 soliveira 83
                                                Object source = get(sourceKey);
2 soliveira 84
 
20 soliveira 85
                                                boolean isAssignable = source != null && d.getType().isAssignableFrom(source.getClass());
4 soliveira 86
 
20 soliveira 87
                                                // check if we can find the dependency and if it is
88
                                                // assignable to the target dependency
89
                                                if (isAssignable) {
4 soliveira 90
 
20 soliveira 91
                                                        try {
4 soliveira 92
 
20 soliveira 93
                                                                // inject
94
                                                                m.invoke(target, source);
4 soliveira 95
 
20 soliveira 96
                                                        } catch (Exception e) {
4 soliveira 97
 
20 soliveira 98
                                                                throw new RuntimeException("Cannot inject dependency: method = " + (m != null ? m.getName() : "NULL") + " / source = "
99
                                                                        + (source != null ? source : "NULL") + " / target = " + target, e);
4 soliveira 100
 
20 soliveira 101
                                                        }
4 soliveira 102
 
20 soliveira 103
                                                }
104
                                        }
105
                                }
4 soliveira 106
                        }
2 soliveira 107
 
41 soliveira 108
                        return (T) target; // return target nicely with all the dependencies
4 soliveira 109
 
20 soliveira 110
                } catch (Exception e) {
4 soliveira 111
 
20 soliveira 112
                        throw new RuntimeException(e);
113
                }
2 soliveira 114
        }
4 soliveira 115
 
51 soliveira 116
        public Component ioc(String key, Component component, boolean isSingleton) {
20 soliveira 117
 
118
                beans.put(key, component);
44 soliveira 119
 
51 soliveira 120
                singletonsCache.remove(key); // just in case we are overriding a previous singleton bean...
121
 
122
                if (isSingleton) {
123
 
124
                        singletons.add(key);
125
 
126
                } else {
127
 
128
                        singletons.remove(key); // just in case...
129
                }
4 soliveira 130
 
20 soliveira 131
                return component;
132
        }
133
 
51 soliveira 134
        public Component ioc(String key, Component component) {
135
 
136
                return ioc(key, component, false);
137
        }
138
 
45 soliveira 139
        public ConfigurableComponent ioc(String key, Class<? extends Object> klass) {
20 soliveira 140
 
45 soliveira 141
                ConfigurableComponent cc = new MentaComponent(klass);
142
 
143
                ioc(key, cc);
144
 
145
                return cc;
20 soliveira 146
        }
147
 
45 soliveira 148
        public ConfigurableComponent ioc(String key, Class<? extends Object> klass, boolean singleton) {
20 soliveira 149
 
51 soliveira 150
                ConfigurableComponent cc = new MentaComponent(klass);
45 soliveira 151
 
51 soliveira 152
                ioc(key, cc, singleton);
45 soliveira 153
 
154
                return cc;
20 soliveira 155
        }
4 soliveira 156
 
20 soliveira 157
        public Dependency autowire(Dependency d) {
4 soliveira 158
 
20 soliveira 159
                dependencies.add(d);
4 soliveira 160
 
20 soliveira 161
                return d;
162
        }
4 soliveira 163
 
20 soliveira 164
        public Dependency autowire(String property, Class<? extends Object> klass) {
165
 
166
                return autowire(property, klass, property);
167
        }
2 soliveira 168
 
20 soliveira 169
        public Dependency autowire(String property, Class<? extends Object> klass, String source) {
170
 
171
                return autowire(new MentaDependency(property, klass, source));
172
        }
2 soliveira 173
 
40 soliveira 174
        public Container populate(Object bean) {
22 soliveira 175
 
176
                Provider p = new Provider() {
177
 
178
                        public Object get(String key) {
179
 
180
                                return MentaContainer.this.get(key);
181
                        }
182
 
183
                        public boolean contains(String key) {
184
 
185
                                return MentaContainer.this.contains(key);
186
                        }
187
 
188
                };
40 soliveira 189
 
190
                try {
2 soliveira 191
 
40 soliveira 192
                        InjectionUtils.getObject(bean, p, false, null, true, false, true);
193
 
194
                } catch(Exception e) {
195
 
196
                        throw new RuntimeException("Error populating bean: " + bean, e);
197
                }
2 soliveira 198
 
20 soliveira 199
                return this;
200
        }
2 soliveira 201
 
20 soliveira 202
        public boolean contains(String key) {
2 soliveira 203
 
20 soliveira 204
                return beans.containsKey(key);
205
        }
2 soliveira 206
}