MentaContainer

Rev

Rev 92 | Rev 94 | Go to most recent revision | Only display areas with differences | Ignore whitespace | Details | Blame | Last modification | View Log | RSS feed

Rev 92 Rev 93
1
package org.mentacontainer.impl;
1
package org.mentacontainer.impl;
2
2
3
import java.lang.reflect.Constructor;
3
import java.lang.reflect.Constructor;
4
import java.lang.reflect.Method;
4
import java.lang.reflect.Method;
5
import java.util.HashMap;
5
import java.util.HashMap;
6
import java.util.Iterator;
6
import java.util.Iterator;
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
10
11
import org.mentacontainer.ConfigurableFactory;
11
import org.mentacontainer.ConfigurableFactory;
12
import org.mentacontainer.Container;
12
import org.mentacontainer.Container;
13
import org.mentacontainer.util.FindMethod;
13
import org.mentacontainer.util.FindMethod;
14
14
15
/**
15
/**
16
 * A simple implementation of the Component interface.
-
 
-
 
16
 * The implementation of the Configurable Factory.
17
 *
17
 *
18
 * @author sergio.oliveira.jr@gmail.com
18
 * @author sergio.oliveira.jr@gmail.com
19
 */
19
 */
20
public class ClassFactory implements ConfigurableFactory {
-
 
-
 
20
class ClassFactory implements ConfigurableFactory {
21
       
21
       
22
                private final Container container;
22
                private final Container container;
23
       
23
       
24
            private final Class<? extends Object> klass;
24
            private final Class<? extends Object> klass;
25
           
25
           
26
            private Map<String, Object> props = null;
26
            private Map<String, Object> props = null;
27
           
27
           
28
            private List<Object> initValues = null;
28
            private List<Object> initValues = null;
29
           
29
           
30
            private List<Class<? extends Object>> initTypes = null;
30
            private List<Class<? extends Object>> initTypes = null;
31
           
31
           
32
            private Constructor<? extends Object> constructor = null;
32
            private Constructor<? extends Object> constructor = null;
33
           
33
           
34
            private Map<String, Method> cache = null;
34
            private Map<String, Method> cache = null;
35
           
-
 
36
            public ClassFactory(Class<? extends Object> klass) {
-
 
37
               
-
 
38
                this(null, klass);
-
 
39
            }
-
 
40
           
35
           
41
            public ClassFactory(Container container, Class<? extends Object> klass) {
36
            public ClassFactory(Container container, Class<? extends Object> klass) {
42
               
37
               
43
                this.container = container;
38
                this.container = container;
44
               
39
               
45
                this.klass = klass;
40
                this.klass = klass;
46
            }
41
            }
47
           
42
           
48
            @Override
43
            @Override
49
            public ConfigurableFactory addPropertyValue(String name, Object value) {
44
            public ConfigurableFactory addPropertyValue(String name, Object value) {
50
               
45
               
51
                if (props == null) {
46
                if (props == null) {
52
                       
47
                       
53
                    props = new HashMap<String, Object>();
48
                    props = new HashMap<String, Object>();
54
                   
49
                   
55
                    cache = new HashMap<String, Method>();
50
                    cache = new HashMap<String, Method>();
56
                }
51
                }
57
               
52
               
58
                props.put(name, value);
53
                props.put(name, value);
59
               
54
               
60
                return this;
55
                return this;
61
            }
56
            }
62
           
57
           
63
            @Override
58
            @Override
64
            public ConfigurableFactory addPropertyDependency(String property, String key) {
59
            public ConfigurableFactory addPropertyDependency(String property, String key) {
65
               
-
 
66
                if (container == null) throw new IllegalStateException("Cannot set property dependency because factory does not have container!");
-
 
67
               
60
               
68
                return addPropertyValue(property, new DependencyKey(key));
61
                return addPropertyValue(property, new DependencyKey(key));
69
            }
62
            }
70
           
63
           
71
            @Override
64
            @Override
72
            public ConfigurableFactory addInitDependency(String key) {
65
            public ConfigurableFactory addInitDependency(String key) {
73
               
-
 
74
                if (container == null) throw new IllegalStateException("Cannot set constructor dependency because factory does not have container!");
-
 
75
               
66
               
76
                return addInitValue(new DependencyKey(key), container.getType(key));
67
                return addInitValue(new DependencyKey(key), container.getType(key));
77
            }
68
            }
78
           
69
           
79
            private ConfigurableFactory addInitValue(Object value, Class<? extends Object> type) {
70
            private ConfigurableFactory addInitValue(Object value, Class<? extends Object> type) {
80
               
71
               
81
                if (initValues == null) {
72
                if (initValues == null) {
82
                       
73
                       
83
                    initValues = new LinkedList<Object>();
74
                    initValues = new LinkedList<Object>();
84
                   
75
                   
85
                    initTypes = new LinkedList<Class<? extends Object>>();
76
                    initTypes = new LinkedList<Class<? extends Object>>();
86
                }
77
                }
87
               
78
               
88
                initValues.add(value);
79
                initValues.add(value);
89
               
80
               
90
                initTypes.add(type);
81
                initTypes.add(type);
91
               
82
               
92
                return this;
83
                return this;
93
            }
84
            }
94
           
85
           
95
            @Override
86
            @Override
96
            public ConfigurableFactory addInitValue(Object value) {
87
            public ConfigurableFactory addInitValue(Object value) {
97
               
88
               
98
                return addInitValue(value, value.getClass());
89
                return addInitValue(value, value.getClass());
99
            }
90
            }
100
           
91
           
101
            @Override
92
            @Override
102
            public ConfigurableFactory addInitPrimitive(Object value) {
93
            public ConfigurableFactory addInitPrimitive(Object value) {
103
               
94
               
104
                Class<? extends Object> primitive = getPrimitiveFrom(value);
95
                Class<? extends Object> primitive = getPrimitiveFrom(value);
105
               
96
               
106
                if (primitive == null) throw new IllegalArgumentException("Value is not a primitive: " + value);
97
                if (primitive == null) throw new IllegalArgumentException("Value is not a primitive: " + value);
107
               
98
               
108
                return addInitValue(value, primitive);
99
                return addInitValue(value, primitive);
109
            }
100
            }
110
           
101
           
111
            private List<Class<? extends Object>> convertToPrimitives(List<Class<? extends Object>> list) {
102
            private List<Class<? extends Object>> convertToPrimitives(List<Class<? extends Object>> list) {
112
               
103
               
113
                Iterator<Class<? extends Object>> iter = list.iterator();
104
                Iterator<Class<? extends Object>> iter = list.iterator();
114
               
105
               
115
                List<Class<? extends Object>> results = new LinkedList<Class<? extends Object>>();
106
                List<Class<? extends Object>> results = new LinkedList<Class<? extends Object>>();
116
               
107
               
117
                while(iter.hasNext()) {
108
                while(iter.hasNext()) {
118
                       
109
                       
119
                        Class<? extends Object> klass = iter.next();
110
                        Class<? extends Object> klass = iter.next();
120
                       
111
                       
121
                        Class<? extends Object> primitive = getPrimitiveFrom(klass);
112
                        Class<? extends Object> primitive = getPrimitiveFrom(klass);
122
                       
113
                       
123
                        if (primitive != null) {
114
                        if (primitive != null) {
124
                               
115
                               
125
                                results.add(primitive);
116
                                results.add(primitive);
126
                               
117
                               
127
                        } else {
118
                        } else {
128
                               
119
                               
129
                                results.add(klass);
120
                                results.add(klass);
130
                        }
121
                        }
131
                }
122
                }
132
               
123
               
133
                return results;
124
                return results;
134
            }
125
            }
135
           
126
           
136
            private Class<? extends Object>[] getClasses(List<Class<? extends Object>> values) {
127
            private Class<? extends Object>[] getClasses(List<Class<? extends Object>> values) {
137
               
128
               
138
                Class<? extends Object>[] types = (Class<? extends Object>[]) new Class[values.size()];
129
                Class<? extends Object>[] types = (Class<? extends Object>[]) new Class[values.size()];
139
               
130
               
140
                return values.toArray(types);
131
                return values.toArray(types);
141
            }
132
            }
142
           
133
           
143
            private Object [] getValues(List<Object> values) throws InstantiationException {
134
            private Object [] getValues(List<Object> values) throws InstantiationException {
144
               
135
               
145
                Object [] array = new Object[values.size()];
136
                Object [] array = new Object[values.size()];
146
               
137
               
147
                int index = 0;
138
                int index = 0;
148
               
139
               
149
                Iterator<Object> iter = values.iterator();
140
                Iterator<Object> iter = values.iterator();
150
               
141
               
151
                while(iter.hasNext()) {
142
                while(iter.hasNext()) {
152
               
143
               
153
                        Object obj = iter.next();
144
                        Object obj = iter.next();
154
                       
145
                       
155
                        if (obj instanceof DependencyKey) {
146
                        if (obj instanceof DependencyKey) {
156
                               
147
                               
157
                                DependencyKey dk = (DependencyKey) obj;
148
                                DependencyKey dk = (DependencyKey) obj;
158
                               
149
                               
159
                                array[index++] = container.get(dk.getKey());
150
                                array[index++] = container.get(dk.getKey());
160
                               
151
                               
161
                        } else {
152
                        } else {
162
                   
153
                   
163
                                array[index++] = obj;
154
                                array[index++] = obj;
164
                        }
155
                        }
165
                }
156
                }
166
               
157
               
167
                return array;
158
                return array;
168
            }
159
            }
169
           
160
           
170
                /*
161
                /*
171
                 * Use reflection to set a property in the bean
162
                 * Use reflection to set a property in the bean
172
                 */
163
                 */
173
                private void setValue(Object bean, String name, Object value) {
164
                private void setValue(Object bean, String name, Object value) {
174
               
165
               
175
                        try {
166
                        try {
176
                               
167
                               
177
                                StringBuffer sb = new StringBuffer(30);
168
                                StringBuffer sb = new StringBuffer(30);
178
                                sb.append("set");
169
                                sb.append("set");
179
                                sb.append(name.substring(0,1).toUpperCase());
170
                                sb.append(name.substring(0,1).toUpperCase());
180
                               
171
                               
181
                                if (name.length() > 1) sb.append(name.substring(1));
172
                                if (name.length() > 1) sb.append(name.substring(1));
182
                   
173
                   
183
                    String methodName = sb.toString();
174
                    String methodName = sb.toString();
184
                   
175
                   
185
                    if (!cache.containsKey(name)) {
176
                    if (!cache.containsKey(name)) {
186
                       
177
                       
187
                        Method m = null;
178
                        Method m = null;
188
                       
179
                       
189
                        try {
180
                        try {
190
                               
181
                               
191
                            m = FindMethod.getMethod(klass, methodName, new Class[] { value.getClass() });
182
                            m = FindMethod.getMethod(klass, methodName, new Class[] { value.getClass() });
192
                           
183
                           
193
                        } catch(Exception e) {
184
                        } catch(Exception e) {
194
                               
185
                               
195
                            // try primitive...
186
                            // try primitive...
196
                               
187
                               
197
                            Class<? extends Object> primitive = getPrimitiveFrom(value);
188
                            Class<? extends Object> primitive = getPrimitiveFrom(value);
198
                           
189
                           
199
                            if (primitive != null) {
190
                            if (primitive != null) {
200
                               
191
                               
201
                                try {
192
                                try {
202
                                       
193
                                       
203
                                    m = klass.getMethod(methodName, new Class[] { primitive });
194
                                    m = klass.getMethod(methodName, new Class[] { primitive });
204
                                   
195
                                   
205
                                } catch(Exception ex) {
196
                                } catch(Exception ex) {
206
                                        // not found!
197
                                        // not found!
207
                                }
198
                                }
208
                            }
199
                            }
209
                           
200
                           
210
                            if (m == null) {
201
                            if (m == null) {
211
                               
202
                               
212
                                throw new InstantiationException("Cannot find method for property: " + name);
203
                                throw new InstantiationException("Cannot find method for property: " + name);
213
                            }
204
                            }
214
                        }
205
                        }
215
                       
206
                       
216
                        if (m != null) {
207
                        if (m != null) {
217
                               
208
                               
218
                            cache.put(name, m);
209
                            cache.put(name, m);
219
                           
210
                           
220
                            m.setAccessible(true);
211
                            m.setAccessible(true);
221
                        }
212
                        }
222
                    }    
213
                    }    
223
214
224
                    Method m = cache.get(name);
215
                    Method m = cache.get(name);
225
                   
216
                   
226
                    if (m != null) {
217
                    if (m != null) {
227
                       
218
                       
228
                        m.invoke(bean, new Object[] { value });
219
                        m.invoke(bean, new Object[] { value });
229
                    }                
220
                    }                
230
                   
221
                   
231
                        } catch(Exception e) {
222
                        } catch(Exception e) {
232
                               
223
                               
233
                                throw new RuntimeException("Error trying to set a property with reflection: " + name, e);
224
                                throw new RuntimeException("Error trying to set a property with reflection: " + name, e);
234
                        }
225
                        }
235
                }
226
                }
236
           
227
           
237
            private static Class<? extends Object> getPrimitiveFrom(Object w) {
228
            private static Class<? extends Object> getPrimitiveFrom(Object w) {
238
                if (w instanceof Boolean) { return Boolean.TYPE; }
229
                if (w instanceof Boolean) { return Boolean.TYPE; }
239
                else if (w instanceof Byte) { return Byte.TYPE; }
230
                else if (w instanceof Byte) { return Byte.TYPE; }
240
                else if (w instanceof Short) { return Short.TYPE; }
231
                else if (w instanceof Short) { return Short.TYPE; }
241
                else if (w instanceof Character) { return Character.TYPE; }
232
                else if (w instanceof Character) { return Character.TYPE; }
242
                else if (w instanceof Integer) { return Integer.TYPE; }
233
                else if (w instanceof Integer) { return Integer.TYPE; }
243
                else if (w instanceof Long) { return Long.TYPE; }
234
                else if (w instanceof Long) { return Long.TYPE; }
244
                else if (w instanceof Float) { return Float.TYPE; }
235
                else if (w instanceof Float) { return Float.TYPE; }
245
                else if (w instanceof Double) { return Double.TYPE; }
236
                else if (w instanceof Double) { return Double.TYPE; }
246
                return null;
237
                return null;
247
            }
238
            }
248
           
239
           
249
            private static Class<? extends Object> getPrimitiveFrom(Class<? extends Object> klass) {
240
            private static Class<? extends Object> getPrimitiveFrom(Class<? extends Object> klass) {
250
                if (klass.equals(Boolean.class)) { return Boolean.TYPE; }
241
                if (klass.equals(Boolean.class)) { return Boolean.TYPE; }
251
                else if (klass.equals(Byte.class)) { return Byte.TYPE; }
242
                else if (klass.equals(Byte.class)) { return Byte.TYPE; }
252
                else if (klass.equals(Short.class)) { return Short.TYPE; }
243
                else if (klass.equals(Short.class)) { return Short.TYPE; }
253
                else if (klass.equals(Character.class)) { return Character.TYPE; }
244
                else if (klass.equals(Character.class)) { return Character.TYPE; }
254
                else if (klass.equals(Integer.class)) { return Integer.TYPE; }
245
                else if (klass.equals(Integer.class)) { return Integer.TYPE; }
255
                else if (klass.equals(Long.class)) { return Long.TYPE; }
246
                else if (klass.equals(Long.class)) { return Long.TYPE; }
256
                else if (klass.equals(Float.class)) { return Float.TYPE; }
247
                else if (klass.equals(Float.class)) { return Float.TYPE; }
257
                else if (klass.equals(Double.class)) { return Double.TYPE; }
248
                else if (klass.equals(Double.class)) { return Double.TYPE; }
258
                return null;
249
                return null;
259
            }
250
            }
260
           
251
           
261
            @Override
252
            @Override
262
            public <T> T getInstance()  {
253
            public <T> T getInstance()  {
263
               
254
               
264
                Object obj = null;
255
                Object obj = null;
265
               
256
               
266
                if (initValues != null && initValues.size() > 0) {
257
                if (initValues != null && initValues.size() > 0) {
267
                       
258
                       
268
                    if (constructor == null) {
259
                    if (constructor == null) {
269
                       
260
                       
270
                        try {
261
                        try {
271
                               
262
                               
272
                            constructor = klass.getConstructor(getClasses(initTypes));
263
                            constructor = klass.getConstructor(getClasses(initTypes));
273
                           
264
                           
274
                        } catch(Exception e) {
265
                        } catch(Exception e) {
275
                               
266
                               
276
                                // try primitives...
267
                                // try primitives...
277
                               
268
                               
278
                                try {
269
                                try {
279
                               
270
                               
280
                                        constructor = klass.getConstructor(getClasses(convertToPrimitives(initTypes)));
271
                                        constructor = klass.getConstructor(getClasses(convertToPrimitives(initTypes)));
281
                                       
272
                                       
282
                                } catch(Exception ee) {
273
                                } catch(Exception ee) {
283
274
284
                                        throw new RuntimeException("Cannot find a constructor for class: " + klass);
275
                                        throw new RuntimeException("Cannot find a constructor for class: " + klass);
285
                                }
276
                                }
286
                        }
277
                        }
287
                    }
278
                    }
288
                   
279
                   
289
                    try {
280
                    try {
290
                       
281
                       
291
                        obj = constructor.newInstance(getValues(initValues));
282
                        obj = constructor.newInstance(getValues(initValues));
292
                       
283
                       
293
                    } catch(Exception e) {
284
                    } catch(Exception e) {
294
                       
285
                       
295
                        throw new RuntimeException("Cannot create instance from constructor: " + constructor, e);
286
                        throw new RuntimeException("Cannot create instance from constructor: " + constructor, e);
296
                    }
287
                    }
297
                   
288
                   
298
                } else {
289
                } else {
299
                       
290
                       
300
                    try {
291
                    try {
301
                       
292
                       
302
                        obj = klass.newInstance();
293
                        obj = klass.newInstance();
303
                       
294
                       
304
                    } catch(Exception e) {
295
                    } catch(Exception e) {
305
                       
296
                       
306
                        throw new RuntimeException("Cannot create instance from class: " + klass, e);
297
                        throw new RuntimeException("Cannot create instance from class: " + klass, e);
307
                    }
298
                    }
308
                }
299
                }
309
               
300
               
310
                if (props != null && props.size() > 0) {
301
                if (props != null && props.size() > 0) {
311
                       
302
                       
312
                    Iterator<String> iter = props.keySet().iterator();
303
                    Iterator<String> iter = props.keySet().iterator();
313
                   
304
                   
314
                    while(iter.hasNext()) {
305
                    while(iter.hasNext()) {
315
                       
306
                       
316
                        String name = iter.next();
307
                        String name = iter.next();
317
                       
308
                       
318
                        Object value = props.get(name);
309
                        Object value = props.get(name);
319
                       
310
                       
320
                        if (value instanceof DependencyKey) {
311
                        if (value instanceof DependencyKey) {
321
                               
312
                               
322
                                DependencyKey dk = (DependencyKey) value;
313
                                DependencyKey dk = (DependencyKey) value;
323
                               
314
                               
324
                                value = container.get(dk.getKey());
315
                                value = container.get(dk.getKey());
325
                        }
316
                        }
326
                       
317
                       
327
                        setValue(obj, name, value);
318
                        setValue(obj, name, value);
328
                    }
319
                    }
329
                }
320
                }
330
               
321
               
331
                return (T) obj;
322
                return (T) obj;
332
            }
323
            }
333
           
324
           
334
            private static class DependencyKey {
325
            private static class DependencyKey {
335
               
326
               
336
                private String key;
327
                private String key;
337
               
328
               
338
                public DependencyKey(String key) { this.key = key; }
329
                public DependencyKey(String key) { this.key = key; }
339
               
330
               
340
                private String getKey() { return key; }
331
                private String getKey() { return key; }
341
            }
332
            }
342
           
333
           
343
            @Override
334
            @Override
344
            public Class<? extends Object> getType() {
335
            public Class<? extends Object> getType() {
345
                return klass;
336
                return klass;
346
            }
337
            }
347
        }
338
        }