1 package org.apache.velocity.tools.config;
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22 import java.lang.reflect.Method;
23 import org.apache.velocity.tools.OldToolInfo;
24 import org.apache.velocity.tools.ToolInfo;
25 import org.apache.velocity.tools.ClassUtils;
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41 public class ToolConfiguration extends Configuration
42 {
43 private enum Status {
44 VALID, OLD, NONE, MISSING, UNSUPPORTED, UNINSTANTIABLE;
45 }
46
47 private String key;
48 private String classname;
49 private String restrictTo;
50 private Boolean skipSetters;
51 private Status status;
52 private Throwable problem;
53
54 public void setKey(String key)
55 {
56 this.key = key;
57
58
59 if (key != null && !key.equals(getDefaultKey()))
60 {
61 setProperty("key", key);
62 }
63 }
64
65 public void setClass(Class clazz)
66 {
67 setClassname(clazz.getName());
68 }
69
70 public void setClassname(String classname)
71 {
72 this.classname = classname;
73 this.status = null;
74 }
75
76 public void setRestrictTo(String path)
77 {
78 this.restrictTo = path;
79 }
80
81 public void setSkipSetters(Boolean cfgOnly)
82 {
83 this.skipSetters = cfgOnly;
84 }
85
86
87
88
89
90 public String getKey()
91 {
92 if (this.key != null)
93 {
94 return this.key;
95 }
96 return getDefaultKey();
97 }
98
99
100
101
102
103
104
105
106
107 public String getDefaultKey()
108 {
109 if (getClassname() != null)
110 {
111 Class clazz = getToolClass();
112 DefaultKey defaultKey =
113 (DefaultKey)clazz.getAnnotation(DefaultKey.class);
114 if (defaultKey != null)
115 {
116 return defaultKey.value();
117 }
118 else
119 {
120
121 String name = clazz.getSimpleName();
122 if (name.endsWith("Tool")) {
123 int i = name.indexOf("Tool");
124 name = name.substring(0, i);
125 }
126 if (name.length() > 1) {
127 name = name.substring(0, 1).toLowerCase() +
128 name.substring(1, name.length());
129 } else {
130 name = name.toLowerCase();
131 }
132 return name;
133 }
134 }
135 return null;
136 }
137
138 public String getClassname()
139 {
140 return this.classname;
141 }
142
143 public Class getToolClass()
144 {
145 try
146 {
147 return ClassUtils.getClass(getClassname());
148 }
149 catch (ClassNotFoundException cnfe)
150 {
151 throw new ConfigurationException(this, cnfe);
152 }
153 }
154
155 public String[] getInvalidScopes()
156 {
157 InvalidScope invalid =
158 (InvalidScope)getToolClass().getAnnotation(InvalidScope.class);
159 if (invalid != null)
160 {
161 return invalid.value();
162 }
163 else
164 {
165 return new String[] {};
166 }
167 }
168
169 public String[] getValidScopes()
170 {
171 ValidScope valid =
172 (ValidScope)getToolClass().getAnnotation(ValidScope.class);
173 if (valid != null)
174 {
175 return valid.value();
176 }
177 else
178 {
179 return new String[] {};
180 }
181 }
182
183 private final Status getStatus()
184 {
185 if (this.status == null)
186 {
187 if (getClassname() == null)
188 {
189 this.status = Status.NONE;
190 }
191
192
193 try
194 {
195
196 Class clazz = ClassUtils.getClass(getClassname());
197
198
199 digForDependencies(clazz);
200
201
202 clazz.newInstance();
203
204
205 Method init =
206 clazz.getMethod("init", new Class[]{ Object.class });
207
208
209
210 Deprecated bc = init.getAnnotation(Deprecated.class);
211 if (bc == null)
212 {
213 this.status = Status.OLD;
214 this.problem = null;
215 }
216 else
217 {
218 this.status = Status.VALID;
219 this.problem = null;
220 }
221 }
222 catch (NoSuchMethodException nsme)
223 {
224
225 this.status = Status.VALID;
226 this.problem = null;
227 }
228 catch (ClassNotFoundException cnfe)
229 {
230 this.status = Status.MISSING;
231 this.problem = cnfe;
232 }
233 catch (NoClassDefFoundError ncdfe)
234 {
235 this.status = Status.UNSUPPORTED;
236 this.problem = ncdfe;
237 }
238 catch (Throwable t)
239 {
240
241 this.status = Status.UNINSTANTIABLE;
242 this.problem = t;
243 }
244 }
245 return this.status;
246 }
247
248 private void digForDependencies(Class clazz)
249 {
250 clazz.getDeclaredMethods();
251 clazz.getDeclaredFields();
252
253 Class superClass = clazz.getSuperclass();
254 if (superClass != null)
255 {
256 digForDependencies(superClass);
257 }
258 }
259
260 public String getRestrictTo()
261 {
262 return this.restrictTo;
263 }
264
265 public Boolean getSkipSetters()
266 {
267 return this.skipSetters;
268 }
269
270 public ToolInfo createInfo()
271 {
272 ToolInfo info = null;
273 Status status = getStatus();
274 switch (status)
275 {
276 case VALID:
277 info = new ToolInfo(getKey(), getToolClass());
278 break;
279 case OLD:
280 info = new OldToolInfo(getKey(), getToolClass());
281 break;
282 default:
283 throw new ConfigurationException(this, getError(status));
284 }
285
286 info.restrictTo(getRestrictTo());
287 if (getSkipSetters() != null)
288 {
289 info.setSkipSetters(getSkipSetters());
290 }
291
292
293 info.addProperties(getPropertyMap());
294 return info;
295 }
296
297 private final String getError(Status status)
298 {
299 switch (status)
300 {
301 case NONE:
302 return "No classname set for: "+this;
303 case MISSING:
304 return "Couldn't find tool class in the classpath for: "+this+
305 "("+this.problem+")";
306 case UNSUPPORTED:
307 return "Couldn't find necessary supporting classes for: "+this+
308 "("+this.problem+")";
309 case UNINSTANTIABLE:
310 return "Couldn't instantiate instance of tool for: "+this+
311 "("+this.problem+")";
312 default:
313 return "";
314 }
315 }
316
317 @Override
318 public void addConfiguration(Configuration config)
319 {
320
321 super.addConfiguration(config);
322
323
324 if (config instanceof ToolConfiguration)
325 {
326 ToolConfiguration that = (ToolConfiguration)config;
327 if (that.getClassname() != null)
328 {
329 setClassname(that.getClassname());
330 }
331 if (that.getRestrictTo() != null)
332 {
333 setRestrictTo(that.getRestrictTo());
334 }
335 }
336 }
337
338 @Override
339 public void validate()
340 {
341 super.validate();
342
343
344 if (getKey() == null)
345 {
346 throw new NullKeyException(this);
347 }
348
349 Status status = getStatus();
350 switch (status)
351 {
352 case VALID:
353 case OLD:
354 break;
355 default:
356 throw new ConfigurationException(this, getError(status));
357 }
358 }
359
360 @Override
361 public int compareTo(Configuration conf)
362 {
363 if (!(conf instanceof ToolConfiguration))
364 {
365 throw new UnsupportedOperationException("ToolConfigurations can only be compared to other ToolConfigurations");
366 }
367
368 ToolConfiguration tool = (ToolConfiguration)conf;
369 if (getKey() == null && tool.getKey() == null)
370 {
371 return 0;
372 }
373 else if (getKey() == null)
374 {
375 return -1;
376 }
377 else if (tool.getKey() == null)
378 {
379 return 1;
380 }
381 else
382 {
383 return getKey().compareTo(tool.getKey());
384 }
385 }
386
387 @Override
388 public int hashCode()
389 {
390 if (getKey() == null)
391 {
392 return super.hashCode();
393 }
394 return getKey().hashCode();
395 }
396
397 @Override
398 public boolean equals(Object obj)
399 {
400 if (getKey() == null || !(obj instanceof ToolConfiguration))
401 {
402 return super.equals(obj);
403 }
404 return getKey().equals(((ToolConfiguration)obj).getKey());
405 }
406
407 @Override
408 public String toString()
409 {
410 StringBuilder out = new StringBuilder();
411 if (getClassname() == null)
412 {
413 out.append("Tool '");
414 out.append(this.key);
415 }
416 else
417 {
418 switch (getStatus())
419 {
420 case VALID:
421 break;
422 case OLD:
423 out.append("Old ");
424 break;
425 case NONE:
426 case MISSING:
427 out.append("Invalid ");
428 break;
429 case UNSUPPORTED:
430 out.append("Unsupported ");
431 break;
432 case UNINSTANTIABLE:
433 out.append("Unusable ");
434 break;
435 default:
436 break;
437 }
438 out.append("Tool '");
439 out.append(getKey());
440 }
441 out.append("' ");
442 out.append("=> ");
443 out.append(getClassname());
444 if (getRestrictTo() != null)
445 {
446 out.append(" only for '");
447 out.append(getRestrictTo());
448 out.append('\'');
449 }
450 out.append(" ");
451 appendProperties(out);
452 return out.toString();
453 }
454
455 }