1 package org.apache.turbine.annotation;
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22 import java.lang.annotation.Annotation;
23 import java.lang.reflect.AccessibleObject;
24 import java.lang.reflect.Field;
25 import java.util.List;
26 import java.util.concurrent.ConcurrentHashMap;
27 import java.util.concurrent.ConcurrentMap;
28
29 import org.apache.commons.configuration2.Configuration;
30 import org.apache.commons.lang3.StringUtils;
31 import org.apache.fulcrum.security.model.turbine.TurbineAccessControlList;
32 import org.apache.logging.log4j.LogManager;
33 import org.apache.logging.log4j.Logger;
34 import org.apache.turbine.Turbine;
35 import org.apache.turbine.modules.Loader;
36 import org.apache.turbine.services.ServiceManager;
37 import org.apache.turbine.services.TurbineServices;
38 import org.apache.turbine.services.assemblerbroker.AssemblerBrokerService;
39 import org.apache.turbine.util.TurbineException;
40
41
42
43
44
45
46
47
48 public class AnnotationProcessor
49 {
50
51 private static Logger log = LogManager.getLogger(AnnotationProcessor.class);
52
53
54 private static ConcurrentMap<String, Annotation[]> annotationCache = new ConcurrentHashMap<String, Annotation[]>();
55
56
57
58
59
60
61
62
63 public static Annotation[] getAnnotations(AccessibleObject object)
64 {
65 String key = object.getClass() + object.toString();
66 Annotation[] annotations = annotationCache.get(key);
67 if (annotations == null)
68 {
69 Annotation[] newAnnotations = object.getDeclaredAnnotations();
70 annotations = annotationCache.putIfAbsent(key, newAnnotations);
71 if (annotations == null)
72 {
73 annotations = newAnnotations;
74 }
75 }
76 return annotations;
77 }
78
79 public enum ConditionType
80 {
81 COMPOUND, ANY;
82 }
83
84
85
86
87
88
89
90
91
92
93
94
95
96 public static <A extends TurbineAccessControlList<?>> boolean isAuthorized(AccessibleObject object, A acl)
97 {
98 return isAuthorized( object, acl, ConditionType.COMPOUND );
99 }
100
101
102
103
104
105
106
107
108
109
110
111
112 public static <A extends TurbineAccessControlList<?>> boolean isAuthorized(AccessibleObject object, A acl, ConditionType conditonType)
113 {
114 Annotation[] annotations = getAnnotations(object);
115
116 for (Annotation annotation : annotations)
117 {
118 if (annotation instanceof TurbineRequiredRole)
119 {
120 TurbineRequiredRole trr = (TurbineRequiredRole) annotation;
121 String[] roleNames = trr.value();
122 String group = trr.group();
123
124 if (StringUtils.isEmpty(group))
125 {
126 for (String roleName : roleNames)
127 {
128 switch ( conditonType ) {
129 case COMPOUND: default:
130 if (!acl.hasRole(roleName))
131 {
132 return false;
133 }
134 break;
135 case ANY:
136 if (acl.hasRole(roleName))
137 {
138 return true;
139 }
140 break;
141 }
142 }
143 if (conditonType == ConditionType.ANY) {
144 return false;
145 }
146 }
147 else
148 {
149 for (String roleName : roleNames)
150 {
151 switch ( conditonType ) {
152 case COMPOUND: default:
153 if (!acl.hasRole(roleName, group))
154 {
155 return false;
156 }
157 break;
158 case ANY:
159 if (acl.hasRole(roleName, group))
160 {
161 return true;
162 }
163 break;
164 }
165 }
166 }
167 }
168 else if (annotation instanceof TurbineRequiredPermission)
169 {
170 TurbineRequiredPermission trp = (TurbineRequiredPermission) annotation;
171 String[] permissionNames = trp.value();
172 String group = trp.group();
173
174 if (StringUtils.isEmpty(group))
175 {
176 for (String permissionName : permissionNames)
177 {
178 switch ( conditonType ) {
179 case COMPOUND: default:
180 if (!acl.hasPermission(permissionName))
181 {
182 return false;
183 }
184 break;
185 case ANY:
186 if (acl.hasPermission(permissionName))
187 {
188 return true;
189 }
190 break;
191 }
192 }
193 }
194 else
195 {
196 for (String permissionName : permissionNames)
197 {
198 switch ( conditonType ) {
199 case COMPOUND: default:
200 if (!acl.hasPermission(permissionName, group))
201 {
202 return false;
203 }
204 break;
205 case ANY:
206 if (acl.hasPermission(permissionName, group))
207 {
208 return true;
209 }
210 break;
211 }
212
213 }
214 }
215 }
216 }
217
218 return true;
219 }
220
221
222
223
224
225
226
227
228 public static void process(Object object) throws TurbineException
229 {
230 ServiceManager manager = null;
231 Configuration config = null;
232 AssemblerBrokerService assembler = null;
233 Class<?> clazz = object.getClass();
234
235 while (clazz != null)
236 {
237 Field[] fields = clazz.getDeclaredFields();
238
239 for (Field field : fields)
240 {
241 Annotation[] annotations = getAnnotations(field);
242
243 for (Annotation a : annotations)
244 {
245 if (a instanceof TurbineService)
246 {
247 if (manager == null)
248 {
249 manager = TurbineServices.getInstance();
250 }
251 injectTurbineService(object, manager, field, (TurbineService) a);
252 }
253 else if (a instanceof TurbineConfiguration)
254 {
255 if (config == null)
256 {
257 config = Turbine.getConfiguration();
258 }
259 injectTurbineConfiguration(object, config, field, (TurbineConfiguration) a);
260 }
261 else if (a instanceof TurbineLoader)
262 {
263 if (assembler == null)
264 {
265 assembler = (AssemblerBrokerService) TurbineServices.getInstance().
266 getService(AssemblerBrokerService.SERVICE_NAME);
267 }
268 injectTurbineLoader(object, assembler, field, (TurbineLoader) a);
269 }
270 }
271 }
272
273 clazz = clazz.getSuperclass();
274 }
275 }
276
277
278
279
280
281
282
283
284
285
286
287 private static void injectTurbineLoader(Object object, AssemblerBrokerService assembler, Field field, TurbineLoader annotation) throws TurbineException
288 {
289 Loader<?> loader = assembler.getLoader(annotation.value());
290 field.setAccessible(true);
291
292 try
293 {
294 log.debug("Injection of {} into object {}", loader, object);
295
296 field.set(object, loader);
297 }
298 catch (IllegalArgumentException | IllegalAccessException e)
299 {
300 throw new TurbineException("Could not inject loader "
301 + loader + " into object " + object, e);
302 }
303 }
304
305
306
307
308
309
310
311
312
313
314
315 @SuppressWarnings("boxing")
316 private static void injectTurbineConfiguration(Object object, Configuration conf, Field field, TurbineConfiguration annotation) throws TurbineException
317 {
318 Class<?> type = field.getType();
319 String key = annotation.value();
320
321 try
322 {
323 if (Configuration.class.isAssignableFrom(type))
324 {
325 final Configuration injectConfiguration;
326
327 if (StringUtils.isNotEmpty(key))
328 {
329 injectConfiguration = conf.subset(key);
330 }
331 else
332 {
333 injectConfiguration = conf;
334 }
335
336 log.debug("Injection of {} into object {}", injectConfiguration, object);
337
338 field.setAccessible(true);
339 field.set(object, injectConfiguration);
340 }
341 else if (conf.containsKey(key))
342 {
343 if ( String.class.isAssignableFrom( type ) )
344 {
345 String value = conf.getString(key);
346 log.debug("Injection of {} into object {}", value, object);
347
348 field.setAccessible(true);
349 field.set(object, value);
350 }
351 else if ( Boolean.TYPE.isAssignableFrom( type ) )
352 {
353 boolean value = conf.getBoolean(key);
354 log.debug("Injection of {} into object {}", value, object);
355
356 field.setAccessible(true);
357 field.setBoolean(object, value);
358 }
359 else if ( Integer.TYPE.isAssignableFrom( type ) )
360 {
361 int value = conf.getInt(key);
362 log.debug("Injection of {} into object {}", value, object);
363
364 field.setAccessible(true);
365 field.setInt(object, value);
366 }
367 else if ( Long.TYPE.isAssignableFrom( type ) )
368 {
369 long value = conf.getLong(key);
370 log.debug("Injection of {} into object {}", value, object);
371
372 field.setAccessible(true);
373 field.setLong(object, value);
374 }
375 else if ( Short.TYPE.isAssignableFrom( type ) )
376 {
377 short value = conf.getShort(key);
378 log.debug("Injection of {} into object {}", value, object);
379
380 field.setAccessible(true);
381 field.setShort(object, value);
382 }
383 else if ( Long.TYPE.isAssignableFrom( type ) )
384 {
385 long value = conf.getLong(key);
386 log.debug("Injection of {} into object {}", value, object);
387
388 field.setAccessible(true);
389 field.setLong(object, value);
390 }
391 else if ( Float.TYPE.isAssignableFrom( type ) )
392 {
393 float value = conf.getFloat(key);
394 log.debug("Injection of {} into object {}", value, object);
395
396 field.setAccessible(true);
397 field.setFloat(object, value);
398 }
399 else if ( Double.TYPE.isAssignableFrom( type ) )
400 {
401 double value = conf.getDouble(key);
402 log.debug("Injection of {} into object {}", value, object);
403
404 field.setAccessible(true);
405 field.setDouble(object, value);
406 }
407 else if ( Byte.TYPE.isAssignableFrom( type ) )
408 {
409 byte value = conf.getByte(key);
410 log.debug("Injection of {} into object {}", value, object);
411
412 field.setAccessible(true);
413 field.setByte(object, value);
414 }
415 else if ( List.class.isAssignableFrom( type ) )
416 {
417 List<Object> values = conf.getList(key);
418 log.debug("Injection of {} into object {}", values, object);
419
420 field.setAccessible(true);
421 field.set(object, values);
422 }
423 }
424 }
425 catch (IllegalArgumentException | IllegalAccessException e)
426 {
427 throw new TurbineException("Could not inject configuration "
428 + conf + " into object " + object, e);
429 }
430 }
431
432
433
434
435
436
437
438
439
440
441
442 private static void injectTurbineService(Object object, ServiceManager manager, Field field, TurbineService annotation) throws TurbineException
443 {
444 String serviceName = null;
445
446 if (StringUtils.isNotEmpty(annotation.value()))
447 {
448 serviceName = annotation.value();
449 }
450
451 else
452 {
453 Field[] typeFields = field.getType().getFields();
454 for (Field f : typeFields)
455 {
456 if (TurbineService.SERVICE_NAME.equals(f.getName()))
457 {
458 try
459 {
460 serviceName = (String)f.get(null);
461 }
462 catch (IllegalArgumentException | IllegalAccessException e)
463 {
464 continue;
465 }
466 break;
467 }
468 else if (TurbineService.ROLE.equals(f.getName()))
469 {
470 try
471 {
472 serviceName = (String)f.get(null);
473 }
474 catch (IllegalArgumentException | IllegalAccessException e)
475 {
476 continue;
477 }
478 break;
479 }
480 }
481 }
482
483 if (StringUtils.isEmpty(serviceName))
484 {
485
486 serviceName = field.getType().getName();
487 }
488
489 log.debug("Looking up service for injection: {} for object {}", serviceName, object);
490
491 Object service = manager.getService(serviceName);
492 field.setAccessible(true);
493
494 try
495 {
496 log.debug("Injection of {} into object {}", serviceName, object);
497
498 field.set(object, service);
499 }
500 catch (IllegalArgumentException | IllegalAccessException e)
501 {
502 throw new TurbineException("Could not inject service "
503 + serviceName + " into object " + object, e);
504 }
505 }
506 }