Rev 41 | 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.Constructor; |
||
4 | import java.lang.reflect.Method; |
||
5 | import java.util.HashMap; |
||
6 | import java.util.Iterator; |
||
7 | import java.util.LinkedList; |
||
8 | import java.util.List; |
||
9 | import java.util.Map; |
||
10 | |||
45 | soliveira | 11 | import org.mentacontainer.ConfigurableComponent; |
2 | soliveira | 12 | import org.mentacontainer.util.FindMethod; |
13 | |||
20 | soliveira | 14 | /** |
15 | * A simple implementation of the Component interface. |
||
16 | * |
||
17 | * @author sergio.oliveira.jr@gmail.com |
||
18 | */ |
||
45 | soliveira | 19 | public class MentaComponent implements ConfigurableComponent { |
20 | soliveira | 20 | |
21 | private final Class<? extends Object> klass; |
||
2 | soliveira | 22 | |
23 | private Map<String, Object> props = null; |
||
24 | |||
25 | private List<Object> initValues = null; |
||
26 | |||
27 | private Constructor<? extends Object> constructor = null; |
||
28 | |||
29 | private Map<String, Method> cache = null; |
||
30 | |||
31 | private final boolean singleton; |
||
23 | soliveira | 32 | |
33 | private Object singletonValue = null; |
||
2 | soliveira | 34 | |
39 | soliveira | 35 | public MentaComponent(Class<? extends Object> klass, boolean singleton) { |
20 | soliveira | 36 | |
2 | soliveira | 37 | this.klass = klass; |
38 | |||
39 | this.singleton = singleton; |
||
40 | } |
||
41 | |||
39 | soliveira | 42 | public MentaComponent(Class<? extends Object> klass) { |
20 | soliveira | 43 | |
39 | soliveira | 44 | this(klass, false); |
20 | soliveira | 45 | } |
46 | |||
2 | soliveira | 47 | public boolean isSingleton() { return singleton; } |
48 | |||
45 | soliveira | 49 | public ConfigurableComponent addProperty(String name, Object value) { |
2 | soliveira | 50 | |
51 | if (props == null) { |
||
52 | |||
53 | props = new HashMap<String, Object>(); |
||
54 | |||
55 | cache = new HashMap<String, Method>(); |
||
56 | } |
||
57 | |||
58 | props.put(name, value); |
||
20 | soliveira | 59 | |
60 | return this; |
||
2 | soliveira | 61 | } |
62 | |||
45 | soliveira | 63 | public ConfigurableComponent addInitValue(Object value) { |
2 | soliveira | 64 | |
65 | if (initValues == null) { |
||
66 | |||
67 | initValues = new LinkedList<Object>(); |
||
68 | } |
||
69 | |||
70 | initValues.add(value); |
||
20 | soliveira | 71 | |
72 | return this; |
||
2 | soliveira | 73 | } |
74 | |||
75 | private Class<? extends Object>[] getClasses(List<Object> values) { |
||
76 | |||
77 | Class<? extends Object>[] types = (Class<? extends Object>[]) new Class[values.size()]; |
||
78 | |||
79 | Iterator<Object> iter = values.iterator(); |
||
80 | |||
81 | int index = 0; |
||
82 | |||
83 | while(iter.hasNext()) { |
||
84 | |||
85 | Object value = iter.next(); |
||
86 | |||
87 | if (value != null) { |
||
88 | |||
89 | types[index++] = value.getClass(); |
||
90 | |||
91 | } else { |
||
92 | |||
93 | types[index++] = null; |
||
94 | } |
||
95 | } |
||
96 | |||
97 | return types; |
||
98 | } |
||
99 | |||
100 | private Object [] getValues(List<Object> values) throws InstantiationException { |
||
101 | |||
102 | Object [] array = new Object[values.size()]; |
||
103 | |||
104 | int index = 0; |
||
105 | |||
106 | Iterator<Object> iter = values.iterator(); |
||
107 | |||
108 | while(iter.hasNext()) { |
||
109 | |||
110 | Object obj = iter.next(); |
||
111 | |||
112 | array[index++] = obj; |
||
113 | } |
||
114 | |||
115 | return array; |
||
116 | } |
||
117 | |||
118 | /* |
||
119 | * Use reflection to set a property in the bean |
||
120 | */ |
||
40 | soliveira | 121 | private void setValue(Object bean, String name, Object value) { |
2 | soliveira | 122 | |
123 | try { |
||
20 | soliveira | 124 | |
2 | soliveira | 125 | StringBuffer sb = new StringBuffer(30); |
126 | sb.append("set"); |
||
127 | sb.append(name.substring(0,1).toUpperCase()); |
||
20 | soliveira | 128 | |
2 | soliveira | 129 | if (name.length() > 1) sb.append(name.substring(1)); |
130 | |||
131 | String methodName = sb.toString(); |
||
132 | |||
133 | if (!cache.containsKey(name)) { |
||
20 | soliveira | 134 | |
2 | soliveira | 135 | Method m = null; |
20 | soliveira | 136 | |
2 | soliveira | 137 | try { |
20 | soliveira | 138 | |
2 | soliveira | 139 | m = FindMethod.getMethod(klass, methodName, new Class[] { value.getClass() }); |
20 | soliveira | 140 | |
2 | soliveira | 141 | } catch(Exception e) { |
20 | soliveira | 142 | |
2 | soliveira | 143 | // try primitive... |
20 | soliveira | 144 | |
2 | soliveira | 145 | Class<? extends Object> primitive = getPrimitiveFrom(value); |
20 | soliveira | 146 | |
2 | soliveira | 147 | if (primitive != null) { |
20 | soliveira | 148 | |
2 | soliveira | 149 | try { |
20 | soliveira | 150 | |
2 | soliveira | 151 | m = klass.getMethod(methodName, new Class[] { primitive }); |
20 | soliveira | 152 | |
2 | soliveira | 153 | } catch(Exception ex) { |
154 | // not found! |
||
155 | } |
||
156 | } |
||
157 | |||
158 | if (m == null) { |
||
20 | soliveira | 159 | |
2 | soliveira | 160 | throw new InstantiationException("Cannot find method or field for property: " + name); |
161 | } |
||
162 | } |
||
163 | |||
164 | if (m != null) { |
||
20 | soliveira | 165 | |
2 | soliveira | 166 | cache.put(name, m); |
20 | soliveira | 167 | |
2 | soliveira | 168 | m.setAccessible(true); |
169 | } |
||
170 | } |
||
171 | |||
172 | Method m = cache.get(name); |
||
20 | soliveira | 173 | |
2 | soliveira | 174 | if (m != null) { |
20 | soliveira | 175 | |
2 | soliveira | 176 | m.invoke(bean, new Object[] { value }); |
177 | } |
||
20 | soliveira | 178 | |
2 | soliveira | 179 | } catch(Exception e) { |
20 | soliveira | 180 | |
40 | soliveira | 181 | throw new RuntimeException("Error trying to set a property with reflection: " + name, e); |
2 | soliveira | 182 | } |
183 | } |
||
184 | |||
185 | private static Class<? extends Object> getPrimitiveFrom(Object w) { |
||
186 | if (w instanceof Boolean) { return Boolean.TYPE; } |
||
187 | else if (w instanceof Byte) { return Byte.TYPE; } |
||
188 | else if (w instanceof Short) { return Short.TYPE; } |
||
189 | else if (w instanceof Character) { return Character.TYPE; } |
||
190 | else if (w instanceof Integer) { return Integer.TYPE; } |
||
191 | else if (w instanceof Long) { return Long.TYPE; } |
||
192 | else if (w instanceof Float) { return Float.TYPE; } |
||
193 | else if (w instanceof Double) { return Double.TYPE; } |
||
194 | return null; |
||
195 | } |
||
196 | |||
41 | soliveira | 197 | public <T> T getInstance() { |
20 | soliveira | 198 | |
41 | soliveira | 199 | if (singleton && singletonValue != null) return (T) singletonValue; |
23 | soliveira | 200 | |
2 | soliveira | 201 | Object obj = null; |
20 | soliveira | 202 | |
2 | soliveira | 203 | if (initValues != null && initValues.size() > 0) { |
20 | soliveira | 204 | |
2 | soliveira | 205 | if (constructor == null) { |
20 | soliveira | 206 | |
2 | soliveira | 207 | try { |
20 | soliveira | 208 | |
2 | soliveira | 209 | constructor = klass.getConstructor(getClasses(initValues)); |
20 | soliveira | 210 | |
2 | soliveira | 211 | } catch(Exception e) { |
20 | soliveira | 212 | |
40 | soliveira | 213 | throw new RuntimeException("Cannot find a constructor for class: " + klass, e); |
2 | soliveira | 214 | } |
215 | } |
||
20 | soliveira | 216 | |
2 | soliveira | 217 | try { |
20 | soliveira | 218 | |
2 | soliveira | 219 | obj = constructor.newInstance(getValues(initValues)); |
20 | soliveira | 220 | |
2 | soliveira | 221 | } catch(Exception e) { |
20 | soliveira | 222 | |
40 | soliveira | 223 | throw new RuntimeException("Cannot create instance from constructor: " + constructor, e); |
2 | soliveira | 224 | } |
20 | soliveira | 225 | |
2 | soliveira | 226 | } else { |
20 | soliveira | 227 | |
2 | soliveira | 228 | try { |
20 | soliveira | 229 | |
2 | soliveira | 230 | obj = klass.newInstance(); |
20 | soliveira | 231 | |
2 | soliveira | 232 | } catch(Exception e) { |
20 | soliveira | 233 | |
40 | soliveira | 234 | throw new RuntimeException("Cannot create instance from class: " + klass, e); |
2 | soliveira | 235 | } |
236 | } |
||
20 | soliveira | 237 | |
2 | soliveira | 238 | if (props != null && props.size() > 0) { |
20 | soliveira | 239 | |
2 | soliveira | 240 | Iterator<String> iter = props.keySet().iterator(); |
20 | soliveira | 241 | |
2 | soliveira | 242 | while(iter.hasNext()) { |
20 | soliveira | 243 | |
2 | soliveira | 244 | String name = iter.next(); |
20 | soliveira | 245 | |
2 | soliveira | 246 | Object value = props.get(name); |
20 | soliveira | 247 | |
2 | soliveira | 248 | setValue(obj, name, value); |
249 | } |
||
250 | } |
||
20 | soliveira | 251 | |
23 | soliveira | 252 | if (obj != null && singleton) singletonValue = obj; |
253 | |||
41 | soliveira | 254 | return (T) obj; |
2 | soliveira | 255 | } |
256 | } |