1 package org.apache.velocity.tools;
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.InvocationTargetException;
23 import java.lang.reflect.Method;
24 import java.util.HashMap;
25 import java.util.Map;
26 import org.apache.commons.beanutils.PropertyUtils;
27 import org.apache.velocity.tools.ClassUtils;
28 import org.apache.velocity.tools.config.SkipSetters;
29
30
31
32
33
34
35
36
37
38 public class ToolInfo implements java.io.Serializable
39 {
40 private static final long serialVersionUID = -8145087882015742757L;
41 public static final String CONFIGURE_METHOD_NAME = "configure";
42
43 private String key;
44 private Class clazz;
45 private boolean restrictToIsExact;
46 private String restrictTo;
47 private Map<String,Object> properties;
48 private Boolean skipSetters;
49 private transient Method configure = null;
50
51
52
53
54
55 public ToolInfo(String key, Class clazz)
56 {
57 setKey(key);
58 setClass(clazz);
59 }
60
61
62
63
64 public void setKey(String key)
65 {
66 this.key = key;
67 if (this.key == null)
68 {
69 throw new NullPointerException("Key cannot be null");
70 }
71 }
72
73
74
75
76
77
78
79 public void setClass(Class clazz)
80 {
81 if (clazz == null)
82 {
83 throw new NullPointerException("Tool class must not be null");
84 }
85 this.clazz = clazz;
86
87
88
89
90
91
92 }
93
94
95
96
97 public void restrictTo(String path)
98 {
99 if (path != null && !path.startsWith("/"))
100 {
101 path = "/" + path;
102 }
103
104 if (path == null || path.equals("*"))
105 {
106
107 restrictToIsExact = false;
108 this.restrictTo = null;
109 }
110 else if(path.endsWith("*"))
111 {
112
113 restrictToIsExact = false;
114 this.restrictTo = path.substring(0, path.length() - 1);
115 }
116 else
117 {
118
119 restrictToIsExact = true;
120 this.restrictTo = path;
121 }
122 }
123
124 public void setSkipSetters(boolean cfgOnly)
125 {
126 this.skipSetters = cfgOnly;
127 }
128
129
130
131
132
133
134 public void addProperties(Map<String,Object> parentProps)
135 {
136
137
138 Map<String,Object> properties = getProps();
139 for (Map.Entry<String,Object> prop : parentProps.entrySet())
140 {
141 if (!properties.containsKey(prop.getKey()))
142 {
143 properties.put(prop.getKey(), prop.getValue());
144 }
145 }
146 }
147
148
149
150
151 public Object putProperty(String name, Object value)
152 {
153 return getProps().put(name, value);
154 }
155
156 protected synchronized Map<String,Object> getProps()
157 {
158 if (properties == null)
159 {
160 properties = new HashMap<String,Object>();
161 }
162 return properties;
163 }
164
165
166
167
168 public String getKey()
169 {
170 return key;
171 }
172
173 public String getClassname()
174 {
175 return clazz.getName();
176 }
177
178 public Class getToolClass()
179 {
180 return clazz;
181 }
182
183 public Map<String,Object> getProperties()
184 {
185 return getProps();
186 }
187
188 public boolean hasConfigure()
189 {
190 return (getConfigure() != null);
191 }
192
193 public boolean isSkipSetters()
194 {
195 if (skipSetters == null)
196 {
197 skipSetters = (clazz.getAnnotation(SkipSetters.class) != null);
198 }
199 return skipSetters;
200 }
201
202
203
204
205
206
207
208
209 public boolean hasPermission(String path)
210 {
211 if (this.restrictTo == null)
212 {
213 return true;
214 }
215 else if (restrictToIsExact)
216 {
217 return this.restrictTo.equals(path);
218 }
219 else if (path != null)
220 {
221 return path.startsWith(this.restrictTo);
222 }
223 return false;
224 }
225
226
227
228
229
230
231
232
233
234
235
236 public Object create(Map<String,Object> dynamicProperties)
237 {
238
239 Object tool = newInstance();
240
241
242
243
244 Map<String,Object> props;
245 if (properties == null)
246 {
247 props = dynamicProperties;
248 }
249 else
250 {
251 props = combine(dynamicProperties, properties);
252 }
253
254
255 configure(tool, props);
256 return tool;
257 }
258
259
260
261
262
263
264
265
266
267
268
269 protected void configure(Object tool, Map<String,Object> configuration)
270 {
271 if (!isSkipSetters() && configuration != null)
272 {
273 try
274 {
275
276 for (Map.Entry<String,Object> conf : configuration.entrySet())
277 {
278 setProperty(tool, conf.getKey(), conf.getValue());
279 }
280 }
281 catch (RuntimeException re)
282 {
283 throw re;
284 }
285 catch (Exception e)
286 {
287
288 throw new RuntimeException(e);
289 }
290 }
291
292 if (hasConfigure())
293 {
294 invoke(getConfigure(), tool, configuration);
295 }
296 }
297
298 protected Method getConfigure()
299 {
300 if (this.configure == null)
301 {
302
303 try
304 {
305 this.configure = ClassUtils.findMethod(clazz, CONFIGURE_METHOD_NAME,
306 new Class[]{ Map.class });
307 }
308 catch (SecurityException se)
309 {
310
311 String msg = "Unable to gain access to '" +
312 CONFIGURE_METHOD_NAME + "(Map)'" +
313 " method for '" + clazz.getName() +
314 "' under the current security manager."+
315 " This tool cannot be properly configured for use.";
316 throw new IllegalStateException(msg, se);
317 }
318 }
319 return this.configure;
320 }
321
322
323
324
325
326
327
328
329
330
331
332
333
334 protected Object newInstance()
335 {
336 try
337 {
338 return clazz.newInstance();
339 }
340
341
342
343 catch (IllegalAccessException iae)
344 {
345 String message = "Unable to instantiate instance of \"" +
346 getClassname() + "\"";
347 throw new IllegalStateException(message, iae);
348 }
349 catch (InstantiationException ie)
350 {
351 String message = "Exception while instantiating instance of \"" +
352 getClassname() + "\"";
353 throw new IllegalStateException(message, ie);
354 }
355 }
356
357
358 protected void invoke(Method method, Object tool, Object param)
359 {
360 try
361 {
362
363 method.invoke(tool, new Object[]{ param });
364 }
365 catch (IllegalAccessException iae)
366 {
367 String msg = "Unable to invoke " + method + " on " + tool;
368
369 throw new IllegalStateException(msg, iae);
370 }
371 catch (InvocationTargetException ite)
372 {
373 String msg = "Exception when invoking " + method + " on " + tool;
374
375 throw new RuntimeException(msg, ite.getCause());
376 }
377 }
378
379
380 protected void setProperty(Object tool, String name, Object value) throws Exception
381 {
382 if (PropertyUtils.isWriteable(tool, name))
383 {
384
385
386 PropertyUtils.setProperty(tool, name, value);
387 }
388 }
389
390
391 protected Map<String,Object> combine(Map<String,Object>... maps)
392 {
393 Map<String,Object> combined = new HashMap<String,Object>();
394 for (Map<String,Object> map : maps)
395 {
396 if (map != null)
397 {
398 combined.putAll(map);
399 }
400 }
401 return combined;
402 }
403
404 }