MentaContainer

Rev

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

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