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 | }
|