1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19 package com.puppycrawl.tools.checkstyle.api;
20
21 import com.google.common.collect.Lists;
22 import java.beans.PropertyDescriptor;
23 import java.lang.reflect.InvocationTargetException;
24 import java.util.Collection;
25 import java.util.List;
26 import java.util.StringTokenizer;
27 import org.apache.commons.beanutils.BeanUtilsBean;
28 import org.apache.commons.beanutils.ConversionException;
29 import org.apache.commons.beanutils.ConvertUtilsBean;
30 import org.apache.commons.beanutils.Converter;
31 import org.apache.commons.beanutils.PropertyUtils;
32 import org.apache.commons.beanutils.PropertyUtilsBean;
33 import org.apache.commons.beanutils.converters.ArrayConverter;
34 import org.apache.commons.beanutils.converters.BooleanConverter;
35 import org.apache.commons.beanutils.converters.ByteConverter;
36 import org.apache.commons.beanutils.converters.CharacterConverter;
37 import org.apache.commons.beanutils.converters.DoubleConverter;
38 import org.apache.commons.beanutils.converters.FloatConverter;
39 import org.apache.commons.beanutils.converters.IntegerConverter;
40 import org.apache.commons.beanutils.converters.LongConverter;
41 import org.apache.commons.beanutils.converters.ShortConverter;
42
43
44
45
46
47
48 public class AutomaticBean
49 implements Configurable, Contextualizable
50 {
51
52 private Configuration configuration;
53
54
55
56
57
58
59
60
61
62
63 private static BeanUtilsBean createBeanUtilsBean()
64 {
65 final ConvertUtilsBean cub = new ConvertUtilsBean();
66
67 cub.register(new BooleanConverter(), Boolean.TYPE);
68 cub.register(new BooleanConverter(), Boolean.class);
69 cub.register(new ArrayConverter(
70 boolean[].class, new BooleanConverter()), boolean[].class);
71 cub.register(new ByteConverter(), Byte.TYPE);
72 cub.register(new ByteConverter(), Byte.class);
73 cub.register(new ArrayConverter(byte[].class, new ByteConverter()),
74 byte[].class);
75 cub.register(new CharacterConverter(), Character.TYPE);
76 cub.register(new CharacterConverter(), Character.class);
77 cub.register(new ArrayConverter(char[].class, new CharacterConverter()),
78 char[].class);
79 cub.register(new DoubleConverter(), Double.TYPE);
80 cub.register(new DoubleConverter(), Double.class);
81 cub.register(new ArrayConverter(double[].class, new DoubleConverter()),
82 double[].class);
83 cub.register(new FloatConverter(), Float.TYPE);
84 cub.register(new FloatConverter(), Float.class);
85 cub.register(new ArrayConverter(float[].class, new FloatConverter()),
86 float[].class);
87 cub.register(new IntegerConverter(), Integer.TYPE);
88 cub.register(new IntegerConverter(), Integer.class);
89 cub.register(new ArrayConverter(int[].class, new IntegerConverter()),
90 int[].class);
91 cub.register(new LongConverter(), Long.TYPE);
92 cub.register(new LongConverter(), Long.class);
93 cub.register(new ArrayConverter(long[].class, new LongConverter()),
94 long[].class);
95 cub.register(new ShortConverter(), Short.TYPE);
96 cub.register(new ShortConverter(), Short.class);
97 cub.register(new ArrayConverter(short[].class, new ShortConverter()),
98 short[].class);
99 cub.register(new RelaxedStringArrayConverter(), String[].class);
100
101
102
103
104 return new BeanUtilsBean(cub, new PropertyUtilsBean());
105 }
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122 @Override
123 public final void configure(Configuration configuration)
124 throws CheckstyleException
125 {
126 this.configuration = configuration;
127
128 final BeanUtilsBean beanUtils = createBeanUtilsBean();
129
130
131 final String[] attributes = configuration.getAttributeNames();
132
133 for (final String key : attributes) {
134 final String value = configuration.getAttribute(key);
135
136 try {
137
138
139
140 final PropertyDescriptor pd =
141 PropertyUtils.getPropertyDescriptor(this, key);
142 if (pd == null || pd.getWriteMethod() == null) {
143 throw new CheckstyleException(
144 "Property '" + key + "' in module "
145 + configuration.getName()
146 + " does not exist, please check the documentation");
147 }
148
149
150 beanUtils.copyProperty(this, key, value);
151 }
152 catch (final InvocationTargetException e) {
153 throw new CheckstyleException(
154 "Cannot set property '" + key + "' in module "
155 + configuration.getName() + " to '" + value
156 + "': " + e.getTargetException().getMessage(), e);
157 }
158 catch (final IllegalAccessException e) {
159 throw new CheckstyleException(
160 "cannot access " + key + " in "
161 + this.getClass().getName(), e);
162 }
163 catch (final NoSuchMethodException e) {
164 throw new CheckstyleException(
165 "cannot access " + key + " in "
166 + this.getClass().getName(), e);
167 }
168 catch (final IllegalArgumentException e) {
169 throw new CheckstyleException(
170 "illegal value '" + value + "' for property '" + key
171 + "' of module " + configuration.getName(), e);
172 }
173 catch (final ConversionException e) {
174 throw new CheckstyleException(
175 "illegal value '" + value + "' for property '" + key
176 + "' of module " + configuration.getName(), e);
177 }
178
179 }
180
181 finishLocalSetup();
182
183 final Configuration[] childConfigs = configuration.getChildren();
184 for (final Configuration childConfig : childConfigs) {
185 setupChild(childConfig);
186 }
187 }
188
189
190
191
192
193
194
195 @Override
196 public final void contextualize(Context context)
197 throws CheckstyleException
198 {
199 final BeanUtilsBean beanUtils = createBeanUtilsBean();
200
201
202 final Collection<String> attributes = context.getAttributeNames();
203
204 for (final String key : attributes) {
205 final Object value = context.get(key);
206
207 try {
208 beanUtils.copyProperty(this, key, value);
209 }
210 catch (final InvocationTargetException e) {
211
212
213 throw new CheckstyleException("cannot set property "
214 + key + " to value " + value + " in bean "
215 + this.getClass().getName(), e);
216 }
217 catch (final IllegalAccessException e) {
218 throw new CheckstyleException(
219 "cannot access " + key + " in "
220 + this.getClass().getName(), e);
221 }
222 catch (final IllegalArgumentException e) {
223 throw new CheckstyleException(
224 "illegal value '" + value + "' for property '" + key
225 + "' of bean " + this.getClass().getName(), e);
226 }
227 catch (final ConversionException e) {
228 throw new CheckstyleException(
229 "illegal value '" + value + "' for property '" + key
230 + "' of bean " + this.getClass().getName(), e);
231 }
232 }
233 }
234
235
236
237
238
239 protected final Configuration getConfiguration()
240 {
241 return configuration;
242 }
243
244
245
246
247
248
249
250
251
252 protected void finishLocalSetup() throws CheckstyleException
253 {
254 }
255
256
257
258
259
260
261
262
263
264
265 protected void setupChild(Configuration childConf)
266 throws CheckstyleException
267 {
268 }
269
270
271
272
273
274
275 private static class RelaxedStringArrayConverter implements Converter
276 {
277
278 @Override
279 public Object convert(@SuppressWarnings("rawtypes") Class type,
280 Object value)
281 {
282 if (null == type) {
283 throw new ConversionException("Cannot convert from null.");
284 }
285
286
287 final StringTokenizer st = new StringTokenizer(
288 value.toString().trim(), ",");
289 final List<String> result = Lists.newArrayList();
290
291 while (st.hasMoreTokens()) {
292 final String token = st.nextToken();
293 result.add(token.trim());
294 }
295
296 return result.toArray(new String[result.size()]);
297 }
298 }
299 }