1 package org.codehaus.plexus.component.configurator.converters;
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19 import java.lang.reflect.Field;
20 import java.lang.reflect.InvocationTargetException;
21 import java.lang.reflect.Method;
22
23 import org.codehaus.plexus.component.configurator.ComponentConfigurationException;
24 import org.codehaus.plexus.component.configurator.ConfigurationListener;
25 import org.codehaus.plexus.component.configurator.converters.lookup.ConverterLookup;
26 import org.codehaus.plexus.component.configurator.expression.ExpressionEvaluator;
27 import org.codehaus.plexus.configuration.PlexusConfiguration;
28 import org.codehaus.plexus.util.ReflectionUtils;
29
30
31 public class ComponentValueSetter {
32 private Object object;
33
34 private String fieldName;
35
36 private ConverterLookup lookup;
37
38 private Method setter;
39
40 private Class setterParamType;
41
42 private ConfigurationConverter setterTypeConverter;
43
44 private Field field;
45
46 private Class fieldType;
47
48 private ConfigurationConverter fieldTypeConverter;
49
50 private ConfigurationListener listener;
51
52 public ComponentValueSetter(String fieldName, Object object, ConverterLookup lookup)
53 throws ComponentConfigurationException {
54 this(fieldName, object, lookup, null);
55 }
56
57 public ComponentValueSetter(String fieldName, Object object, ConverterLookup lookup, ConfigurationListener listener)
58 throws ComponentConfigurationException {
59 this.fieldName = fieldName;
60 this.object = object;
61 this.lookup = lookup;
62 this.listener = listener;
63
64 if (object == null) {
65 throw new ComponentConfigurationException("Component is null");
66 }
67
68 initSetter();
69
70 initField();
71
72 if (setter == null && field == null) {
73 throw new ComponentConfigurationException(
74 "Cannot find setter nor field in " + object.getClass().getName() + " for '" + fieldName + "'");
75 }
76
77 if (setterTypeConverter == null && fieldTypeConverter == null) {
78 throw new ComponentConfigurationException("Cannot find converter for " + setterParamType.getName()
79 + (fieldType != null && !fieldType.equals(setterParamType) ? " or " + fieldType.getName() : ""));
80 }
81 }
82
83 private void initSetter() {
84 setter = ReflectionUtils.getSetter(fieldName, object.getClass());
85
86 if (setter == null) {
87 return;
88 }
89
90 setterParamType = setter.getParameterTypes()[0];
91
92 try {
93 setterTypeConverter = lookup.lookupConverterForType(setterParamType);
94 } catch (ComponentConfigurationException e) {
95
96 }
97 }
98
99 private void initField() {
100 field = ReflectionUtils.getFieldByNameIncludingSuperclasses(fieldName, object.getClass());
101
102 if (field == null) {
103 return;
104 }
105
106 fieldType = field.getType();
107
108 try {
109 fieldTypeConverter = lookup.lookupConverterForType(fieldType);
110 } catch (ComponentConfigurationException e) {
111
112 }
113 }
114
115 private void setValueUsingField(Object value) throws ComponentConfigurationException {
116 try {
117 boolean wasAccessible = field.isAccessible();
118
119 if (!wasAccessible) {
120 field.setAccessible(true);
121 }
122
123 if (listener != null) {
124 listener.notifyFieldChangeUsingReflection(fieldName, value, object);
125 }
126
127 field.set(object, value);
128
129 if (!wasAccessible) {
130 field.setAccessible(false);
131 }
132 } catch (IllegalAccessException e) {
133 throw new ComponentConfigurationException("Cannot access field: " + field, e);
134 } catch (IllegalArgumentException e) {
135 throw new ComponentConfigurationException(
136 "Cannot assign value '" + value + "' (type: " + value.getClass() + ") to " + field, e);
137 }
138 }
139
140 private void setValueUsingSetter(Object value) throws ComponentConfigurationException {
141 if (setterParamType == null || setter == null) {
142 throw new ComponentConfigurationException("No setter found");
143 }
144
145 String exceptionInfo = object.getClass().getName() + "." + setter.getName() + "( "
146 + setterParamType.getClass().getName() + " )";
147
148 if (listener != null) {
149 listener.notifyFieldChangeUsingSetter(fieldName, value, object);
150 }
151
152 try {
153 setter.invoke(object, new Object[] {value});
154 } catch (IllegalAccessException e) {
155 throw new ComponentConfigurationException("Cannot access method: " + exceptionInfo, e);
156 } catch (IllegalArgumentException e) {
157 throw new ComponentConfigurationException(
158 "Invalid parameter supplied while setting '" + value + "' to " + exceptionInfo, e);
159 } catch (InvocationTargetException e) {
160 throw new ComponentConfigurationException(
161 "Setter " + exceptionInfo + " threw exception when called with parameter '" + value + "': "
162 + e.getTargetException().getMessage(),
163 e);
164 }
165 }
166
167 public void configure(PlexusConfiguration config, ClassLoader classLoader, ExpressionEvaluator evaluator)
168 throws ComponentConfigurationException {
169 Object value = null;
170
171
172
173 if (setterTypeConverter != null) {
174 try {
175 value = setterTypeConverter.fromConfiguration(
176 lookup, config, setterParamType, object.getClass(), classLoader, evaluator, listener);
177
178 if (value != null) {
179 setValueUsingSetter(value);
180
181 return;
182 }
183 } catch (ComponentConfigurationException e) {
184 if (fieldTypeConverter == null
185 || fieldTypeConverter.getClass().equals(setterTypeConverter.getClass())) {
186 throw e;
187 }
188 }
189 }
190
191
192
193
194 ComponentConfigurationException savedEx = null;
195
196 if (value != null) {
197 try {
198 setValueUsingField(value);
199 return;
200 } catch (ComponentConfigurationException e) {
201 savedEx = e;
202 }
203 }
204
205
206
207
208 value = fieldTypeConverter.fromConfiguration(
209 lookup, config, fieldType, object.getClass(), classLoader, evaluator, listener);
210
211 if (value != null) {
212 setValueUsingField(value);
213 }
214
215 else if (savedEx != null) {
216 throw savedEx;
217 }
218 }
219 }