1
2
3
4
5
6
7
8
9
10
11
12
13
14
15 package ch.qos.logback.core.joran.util;
16
17 import ch.qos.logback.core.Context;
18 import ch.qos.logback.core.joran.spi.DefaultNestedComponentRegistry;
19 import ch.qos.logback.core.joran.util.beans.BeanDescription;
20 import ch.qos.logback.core.joran.util.beans.BeanDescriptionCache;
21 import ch.qos.logback.core.spi.ContextAwareBase;
22 import ch.qos.logback.core.util.AggregationType;
23 import ch.qos.logback.core.util.PropertySetterException;
24 import ch.qos.logback.core.util.StringUtil;
25
26 import java.lang.reflect.Method;
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51 public class PropertySetter extends ContextAwareBase {
52
53 protected final Object obj;
54 protected final Class<?> objClass;
55 protected final BeanDescription beanDescription;
56 protected final AggregationAssessor aggregationAssessor;
57
58
59
60
61
62
63
64 public PropertySetter(BeanDescriptionCache beanDescriptionCache, Object obj) {
65 this.obj = obj;
66 this.objClass = obj.getClass();
67 this.beanDescription = beanDescriptionCache.getBeanDescription(objClass);
68 this.aggregationAssessor = new AggregationAssessor(beanDescriptionCache, this.objClass);
69 }
70
71 @Override
72 public void setContext(Context context) {
73 super.setContext(context);
74 aggregationAssessor.setContext(context);
75 }
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94 public void setProperty(String name, String value) {
95 if (value == null) {
96 return;
97 }
98 Method setter = aggregationAssessor.findSetterMethod(name);
99 if (setter == null) {
100 addWarn("No setter for property [" + name + "] in " + objClass.getName() + ".");
101 } else {
102 try {
103 setProperty(setter, value);
104 } catch (PropertySetterException ex) {
105 addWarn("Failed to set property [" + name + "] to value \"" + value + "\". ", ex);
106 }
107 }
108 }
109
110
111
112
113
114
115
116
117 private void setProperty(Method setter, String value) throws PropertySetterException {
118 Class<?>[] paramTypes = setter.getParameterTypes();
119
120 Object arg;
121
122 try {
123 arg = StringToObjectConverter.convertArg(this, value, paramTypes[0]);
124 } catch (Throwable t) {
125 throw new PropertySetterException("Conversion to type [" + paramTypes[0] + "] failed. ", t);
126 }
127
128 if (arg == null) {
129 throw new PropertySetterException("Conversion to type [" + paramTypes[0] + "] failed.");
130 }
131 try {
132 setter.invoke(obj, arg);
133 } catch (Exception ex) {
134 throw new PropertySetterException(ex);
135 }
136 }
137
138 public AggregationType computeAggregationType(String name) {
139 return this.aggregationAssessor.computeAggregationType(name);
140 }
141
142
143 public Class<?> getObjClass() {
144 return objClass;
145 }
146
147 public void addComplexProperty(String name, Object complexProperty) {
148 Method adderMethod = aggregationAssessor.findAdderMethod(name);
149
150 if (adderMethod != null) {
151 Class<?>[] paramTypes = adderMethod.getParameterTypes();
152 if (!isSanityCheckSuccessful(name, adderMethod, paramTypes, complexProperty)) {
153 return;
154 }
155 invokeMethodWithSingleParameterOnThisObject(adderMethod, complexProperty);
156 } else {
157 addError("Could not find method [" + "add" + name + "] in class [" + objClass.getName() + "].");
158 }
159 }
160
161 void invokeMethodWithSingleParameterOnThisObject(Method method, Object parameter) {
162 Class<?> ccc = parameter.getClass();
163 try {
164 method.invoke(this.obj, parameter);
165 } catch (Exception e) {
166 addError("Could not invoke method " + method.getName() + " in class " + obj.getClass().getName()
167 + " with parameter of type " + ccc.getName(), e);
168 }
169 }
170
171 public void addBasicProperty(String name, String strValue) {
172
173 if (strValue == null) {
174 return;
175 }
176
177 name = StringUtil.capitalizeFirstLetter(name);
178 Method adderMethod = aggregationAssessor.findAdderMethod(name);
179
180 if (adderMethod == null) {
181 addError("No adder for property [" + name + "].");
182 return;
183 }
184
185 Class<?>[] paramTypes = adderMethod.getParameterTypes();
186 isSanityCheckSuccessful(name, adderMethod, paramTypes, strValue);
187
188 Object arg;
189 try {
190 arg = StringToObjectConverter.convertArg(this, strValue, paramTypes[0]);
191 } catch (Throwable t) {
192 addError("Conversion to type [" + paramTypes[0] + "] failed. ", t);
193 return;
194 }
195 if (arg != null) {
196 invokeMethodWithSingleParameterOnThisObject(adderMethod, arg);
197 }
198 }
199
200 public void setComplexProperty(String name, Object complexProperty) {
201 Method setter = aggregationAssessor.findSetterMethod(name);
202
203 if (setter == null) {
204 addWarn("Not setter method for property [" + name + "] in " + obj.getClass().getName());
205
206 return;
207 }
208
209 Class<?>[] paramTypes = setter.getParameterTypes();
210
211 if (!isSanityCheckSuccessful(name, setter, paramTypes, complexProperty)) {
212 return;
213 }
214 try {
215 invokeMethodWithSingleParameterOnThisObject(setter, complexProperty);
216
217 } catch (Exception e) {
218 addError("Could not set component " + obj + " for parent component " + obj, e);
219 }
220 }
221
222 private boolean isSanityCheckSuccessful(String name, Method method, Class<?>[] params, Object complexProperty) {
223 Class<?> ccc = complexProperty.getClass();
224 if (params.length != 1) {
225 addError("Wrong number of parameters in setter method for property [" + name + "] in "
226 + obj.getClass().getName());
227
228 return false;
229 }
230
231 if (!params[0].isAssignableFrom(complexProperty.getClass())) {
232 addError("A \"" + ccc.getName() + "\" object is not assignable to a \"" + params[0].getName()
233 + "\" variable.");
234 addError("The class \"" + params[0].getName() + "\" was loaded by ");
235 addError("[" + params[0].getClassLoader() + "] whereas object of type ");
236 addError("\"" + ccc.getName() + "\" was loaded by [" + ccc.getClassLoader() + "].");
237 return false;
238 }
239
240 return true;
241 }
242
243 public Object getObj() {
244 return obj;
245 }
246
247
248 public Class<?> getClassNameViaImplicitRules(String name, AggregationType aggregationType,
249 DefaultNestedComponentRegistry registry) {
250 return aggregationAssessor.getClassNameViaImplicitRules(name, aggregationType, registry);
251 }
252
253 public Class<?> getTypeForComplexProperty(String nestedElementTagName, AggregationType aggregationType) {
254
255 Method aMethod = null;
256 switch (aggregationType) {
257 case AS_COMPLEX_PROPERTY:
258 aMethod = aggregationAssessor.findSetterMethod(nestedElementTagName);
259 break;
260 case AS_COMPLEX_PROPERTY_COLLECTION:
261 aMethod = aggregationAssessor.findAdderMethod(nestedElementTagName);
262 }
263
264
265 checkParameterCount(aMethod, nestedElementTagName);
266
267 Class<?>[] paramTypes = aMethod.getParameterTypes();
268 return paramTypes[0];
269
270 }
271
272 private void checkParameterCount(Method aMethod, String nestedElementTagName) {
273 if(aMethod == null) {
274 String msg = "Could not find method for property [" + nestedElementTagName + "].";
275 addError(msg);
276 throw new IllegalStateException(msg);
277 }
278 int parameterCount = aMethod.getParameterCount();
279 if (parameterCount != 1) {
280 String msg = "Expected ["+aMethod.getName()+"] for property [" + nestedElementTagName + "] to have exactly one parameter.";
281 addError(msg);
282 throw new IllegalStateException(msg);
283 }
284 }
285 }