MentaContainer

Rev

Rev 44 | Rev 51 | 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>();
2 soliveira 24
 
20 soliveira 25
        private Map<String, Object> singletons = new HashMap<String, Object>();
4 soliveira 26
 
20 soliveira 27
        private Set<Dependency> dependencies = new HashSet<Dependency>();
4 soliveira 28
 
41 soliveira 29
        public <T> T get(String key) {
4 soliveira 30
 
43 soliveira 31
                if (!beans.containsKey(key)) return null;
4 soliveira 32
 
20 soliveira 33
                Component c = beans.get(key);
4 soliveira 34
 
20 soliveira 35
                Object target = null;
4 soliveira 36
 
20 soliveira 37
                try {
4 soliveira 38
 
20 soliveira 39
                        if (c.isSingleton()) {
4 soliveira 40
 
20 soliveira 41
                                if (singletons.containsKey(key)) {
4 soliveira 42
 
20 soliveira 43
                                        target = singletons.get(key);
4 soliveira 44
 
41 soliveira 45
                                        return (T) target;
4 soliveira 46
 
20 soliveira 47
                                } else {
4 soliveira 48
 
20 soliveira 49
                                        target = c.getInstance();
4 soliveira 50
 
20 soliveira 51
                                        singletons.put(key, target);
52
                                }
4 soliveira 53
 
20 soliveira 54
                        } else {
4 soliveira 55
 
20 soliveira 56
                                target = c.getInstance();
4 soliveira 57
 
20 soliveira 58
                        }
4 soliveira 59
 
20 soliveira 60
                        if (target != null) {
4 soliveira 61
 
20 soliveira 62
                                for (Dependency d : dependencies) {
4 soliveira 63
 
20 soliveira 64
                                        // has dependency ?
65
                                        Method m = d.check(target.getClass());
4 soliveira 66
 
20 soliveira 67
                                        if (m != null) {
4 soliveira 68
 
20 soliveira 69
                                                String sourceKey = d.getSource();
4 soliveira 70
 
20 soliveira 71
                                                if (sourceKey.equals(key)) {
4 soliveira 72
 
20 soliveira 73
                                                        // cannot depend on itself... also avoid recursive StackOverflow...
4 soliveira 74
 
20 soliveira 75
                                                        continue;
4 soliveira 76
 
20 soliveira 77
                                                }
2 soliveira 78
 
20 soliveira 79
                                                Object source = get(sourceKey);
2 soliveira 80
 
20 soliveira 81
                                                boolean isAssignable = source != null && d.getType().isAssignableFrom(source.getClass());
4 soliveira 82
 
20 soliveira 83
                                                // check if we can find the dependency and if it is
84
                                                // assignable to the target dependency
85
                                                if (isAssignable) {
4 soliveira 86
 
20 soliveira 87
                                                        try {
4 soliveira 88
 
20 soliveira 89
                                                                // inject
90
                                                                m.invoke(target, source);
4 soliveira 91
 
20 soliveira 92
                                                        } catch (Exception e) {
4 soliveira 93
 
20 soliveira 94
                                                                throw new RuntimeException("Cannot inject dependency: method = " + (m != null ? m.getName() : "NULL") + " / source = "
95
                                                                        + (source != null ? source : "NULL") + " / target = " + target, e);
4 soliveira 96
 
20 soliveira 97
                                                        }
4 soliveira 98
 
20 soliveira 99
                                                }
100
                                        }
101
                                }
4 soliveira 102
                        }
2 soliveira 103
 
41 soliveira 104
                        return (T) target; // return target nicely with all the dependencies
4 soliveira 105
 
20 soliveira 106
                } catch (Exception e) {
4 soliveira 107
 
20 soliveira 108
                        throw new RuntimeException(e);
109
                }
2 soliveira 110
        }
4 soliveira 111
 
39 soliveira 112
        public Component ioc(String key, Component component) {
20 soliveira 113
 
114
                beans.put(key, component);
44 soliveira 115
 
116
                // clear the singleton cache in case of adding again...
117
                singletons.remove(key);
4 soliveira 118
 
20 soliveira 119
                return component;
120
        }
121
 
45 soliveira 122
        public ConfigurableComponent ioc(String key, Class<? extends Object> klass) {
20 soliveira 123
 
45 soliveira 124
                ConfigurableComponent cc = new MentaComponent(klass);
125
 
126
                ioc(key, cc);
127
 
128
                return cc;
20 soliveira 129
        }
130
 
45 soliveira 131
        public ConfigurableComponent ioc(String key, Class<? extends Object> klass, boolean singleton) {
20 soliveira 132
 
45 soliveira 133
                ConfigurableComponent cc = new MentaComponent(klass, singleton);
134
 
135
                ioc(key, cc);
136
 
137
                return cc;
20 soliveira 138
        }
4 soliveira 139
 
20 soliveira 140
        public Dependency autowire(Dependency d) {
4 soliveira 141
 
20 soliveira 142
                dependencies.add(d);
4 soliveira 143
 
20 soliveira 144
                return d;
145
        }
4 soliveira 146
 
20 soliveira 147
        public Dependency autowire(String property, Class<? extends Object> klass) {
148
 
149
                return autowire(property, klass, property);
150
        }
2 soliveira 151
 
20 soliveira 152
        public Dependency autowire(String property, Class<? extends Object> klass, String source) {
153
 
154
                return autowire(new MentaDependency(property, klass, source));
155
        }
2 soliveira 156
 
40 soliveira 157
        public Container populate(Object bean) {
22 soliveira 158
 
159
                Provider p = new Provider() {
160
 
161
                        public Object get(String key) {
162
 
163
                                return MentaContainer.this.get(key);
164
                        }
165
 
166
                        public boolean contains(String key) {
167
 
168
                                return MentaContainer.this.contains(key);
169
                        }
170
 
171
                };
40 soliveira 172
 
173
                try {
2 soliveira 174
 
40 soliveira 175
                        InjectionUtils.getObject(bean, p, false, null, true, false, true);
176
 
177
                } catch(Exception e) {
178
 
179
                        throw new RuntimeException("Error populating bean: " + bean, e);
180
                }
2 soliveira 181
 
20 soliveira 182
                return this;
183
        }
2 soliveira 184
 
20 soliveira 185
        public boolean contains(String key) {
2 soliveira 186
 
20 soliveira 187
                return beans.containsKey(key);
188
        }
2 soliveira 189
}