1 package org.apache.ojb.broker.metadata.fieldaccess;
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18 import java.beans.BeanInfo;
19 import java.beans.IntrospectionException;
20 import java.beans.Introspector;
21 import java.beans.PropertyDescriptor;
22 import java.lang.reflect.Method;
23 import java.util.ArrayList;
24 import java.util.List;
25
26 import org.apache.commons.lang.StringUtils;
27 import org.apache.ojb.broker.core.proxy.ProxyHelper;
28 import org.apache.ojb.broker.metadata.MetadataException;
29 import org.apache.ojb.broker.util.ClassHelper;
30 import org.apache.ojb.broker.util.logging.Logger;
31
32
33
34
35
36
37
38
39
40
41 public class PersistentFieldIntrospectorImpl extends PersistentFieldBase
42 {
43 private static final long serialVersionUID = 8805309492150404444L;
44 private Class type;
45 private transient List propertyGraph;
46
47 public PersistentFieldIntrospectorImpl()
48 {
49 super();
50 }
51
52 public PersistentFieldIntrospectorImpl(Class aClass, String aPropertyName)
53 {
54 super(aClass, aPropertyName);
55 }
56
57 public Class getType()
58 {
59 if (type == null)
60 {
61 type = getPropertyDescriptor().getPropertyType();
62 }
63 return type;
64 }
65
66 public void set(Object target, Object value) throws MetadataException
67 {
68 if(target == null) return;
69 List propertyDescriptors = getPropertyGraph();
70 int size = propertyDescriptors.size() - 1;
71 PropertyDescriptor pd;
72 for (int i = 0; i < size; i++)
73 {
74 Object attribute;
75 pd = (PropertyDescriptor) propertyDescriptors.get(i);
76 attribute = getValueFrom(pd, target);
77 if (attribute != null || value != null)
78 {
79 if (attribute == null)
80 {
81 try
82 {
83 attribute = ClassHelper.newInstance(pd.getPropertyType());
84 }
85 catch (Exception e)
86 {
87 throw new MetadataException("Can't instantiate nested object of type '"
88 + pd.getPropertyType() + "' for field '"
89 + pd.getName() + "'", e);
90 }
91 }
92 setValueFor(pd, target, attribute);
93 }
94 else
95 {
96 return;
97 }
98 target = attribute;
99 }
100 pd = (PropertyDescriptor) propertyDescriptors.get(size);
101 setValueFor(pd, target, value);
102 }
103
104 public Object get(Object target) throws MetadataException
105 {
106 List propertyDescriptors = getPropertyGraph();
107 for (int i = 0; i < propertyDescriptors.size(); i++)
108 {
109 PropertyDescriptor pd = (PropertyDescriptor) propertyDescriptors.get(i);
110 target = getValueFrom(pd, target);
111 if (target == null) break;
112 }
113 return target;
114 }
115
116 private Object getValueFrom(PropertyDescriptor pd, Object target)
117 {
118 if (target == null) return null;
119 Method m = pd.getReadMethod();
120 if (m != null)
121 {
122 try
123 {
124 return m.invoke(ProxyHelper.getRealObject(target), null);
125 }
126 catch (Throwable e)
127 {
128 logProblem(pd, target, null, "Can't read value from given object");
129 throw new MetadataException("Error invoking method:" + m.getName() + " in object " + target.getClass().getName(), e);
130 }
131 }
132 else
133 {
134 throw new MetadataException("Can't get ReadMethod for property:" + pd.getName() + " in object " + target.getClass().getName());
135 }
136 }
137
138 private void setValueFor(PropertyDescriptor pd, Object target, Object value)
139 {
140 Method m = pd.getWriteMethod();
141 Object[] args = {value};
142 if (m != null)
143 {
144 try
145 {
146
147
148
149
150
151
152 if ((value != null) || !m.getParameterTypes()[0].isPrimitive())
153 {
154 m.invoke(ProxyHelper.getRealObject(target), args);
155 }
156 }
157 catch (Throwable e)
158 {
159 logProblem(pd, target, value, "Can't set value on given object.");
160 throw new MetadataException("Error invoking method:" + m.getName() + " in object:" + target.getClass().getName(), e);
161 }
162 }
163 else
164 {
165 throw new MetadataException("Can't get WriteMethod for property:" + pd.getName() + " in object:" + target.getClass().getName());
166 }
167 }
168
169 private List getPropertyGraph()
170 {
171 if (propertyGraph == null)
172 {
173 propertyGraph = buildPropertyGraph();
174 }
175 return propertyGraph;
176 }
177
178 private List buildPropertyGraph()
179 {
180 List result = new ArrayList();
181 String[] fields = StringUtils.split(getName(), PATH_TOKEN);
182 PropertyDescriptor pd = null;
183 for (int i = 0; i < fields.length; i++)
184 {
185 String fieldName = fields[i];
186 if (pd == null)
187 {
188 pd = findPropertyDescriptor(getDeclaringClass(), fieldName);
189 }
190 else
191 {
192 pd = findPropertyDescriptor(pd.getPropertyType(), fieldName);
193 }
194 result.add(pd);
195 }
196 return result;
197 }
198
199
200
201
202 protected static PropertyDescriptor findPropertyDescriptor(Class aClass, String aPropertyName)
203 {
204 BeanInfo info;
205 PropertyDescriptor[] pd;
206 PropertyDescriptor descriptor = null;
207
208 try
209 {
210 info = Introspector.getBeanInfo(aClass);
211 pd = info.getPropertyDescriptors();
212 for (int i = 0; i < pd.length; i++)
213 {
214 if (pd[i].getName().equals(aPropertyName))
215 {
216 descriptor = pd[i];
217 break;
218 }
219 }
220 if (descriptor == null)
221 {
222
223
224
225
226 throw new MetadataException("Can't find property " + aPropertyName + " in " + aClass.getName());
227 }
228 return descriptor;
229 }
230 catch (IntrospectionException ex)
231 {
232
233
234
235
236 throw new MetadataException("Can't find property " + aPropertyName + " in " + aClass.getName(), ex);
237 }
238 }
239
240
241
242
243
244
245 protected PropertyDescriptor getPropertyDescriptor()
246 {
247 return (PropertyDescriptor) getPropertyGraph().get(getPropertyGraph().size() - 1);
248 }
249
250
251
252
253 public boolean makeAccessible()
254 {
255 return false;
256 }
257
258
259
260
261
262
263 public boolean usesAccessorsAndMutators()
264 {
265 return true;
266 }
267
268
269
270
271 protected void logProblem(PropertyDescriptor pd, Object anObject, Object aValue, String msg)
272 {
273 Logger logger = getLog();
274 logger.error("Error in [PersistentFieldPropertyImpl], " + msg);
275 logger.error("Declaring class [" + getDeclaringClass().getName() + "]");
276 logger.error("Property Name [" + getName() + "]");
277 logger.error("Property Type [" + pd.getPropertyType().getName() + "]");
278
279 if (anObject != null)
280 {
281 logger.error("anObject was class [" + anObject.getClass().getName() + "]");
282 }
283 else
284 {
285 logger.error("anObject was null");
286 }
287 if (aValue != null)
288 {
289 logger.error("aValue was class [" + aValue.getClass().getName() + "]");
290 }
291 else
292 {
293 logger.error("aValue was null");
294 }
295 }
296 }