##### Coverage Report - org.apache.turbine.annotation.AnnotationProcessor

Classes in this File | Line Coverage | Branch Coverage | Complexity
AnnotationProcessor |
66% | 107/161
62% | 54/86
| 12.4;12,4

1 |  |
     package org.apache.turbine.annotation;
2 |  |
3 |  |
     /*
4 |  |
      * Licensed to the Apache Software Foundation (ASF) under one
5 |  |
      * or more contributor license agreements.  See the NOTICE file
6 |  |
      * distributed with this work for additional information
7 |  |
      * regarding copyright ownership.  The ASF licenses this file
8 |  |
      * to you under the Apache License, Version 2.0 (the
9 |  |
      * "License"); you may not use this file except in compliance
10 |  |
      * with the License.  You may obtain a copy of the License at
11 |  |
      *
12 |  |
      *   http://www.apache.org/licenses/LICENSE-2.0
13 |  |
      *
14 |  |
      * Unless required by applicable law or agreed to in writing,
15 |  |
      * software distributed under the License is distributed on an
16 |  |
      * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
17 |  |
      * KIND, either express or implied.  See the License for the
18 |  |
      * specific language governing permissions and limitations
19 |  |
      * under the License.
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.configuration.Configuration;
30 |  |
     import org.apache.commons.lang.StringUtils;
31 |  |
     import org.apache.commons.logging.Log;
32 |  |
     import org.apache.commons.logging.LogFactory;
33 |  |
     import org.apache.turbine.Turbine;
34 |  |
     import org.apache.turbine.modules.Loader;
35 |  |
     import org.apache.turbine.services.ServiceManager;
36 |  |
     import org.apache.turbine.services.TurbineServices;
37 |  |
     import org.apache.turbine.services.assemblerbroker.AssemblerBrokerService;
38 |  |
     import org.apache.turbine.util.TurbineException;
39 |  |
40 |  |
     /**
41 |  |
      * AnnotationProcessor contains static helper methods that handle the
42 |  |
      * Turbine annotations for objects
43 |  |
      *
44 |  |
      * @author <a href="mailto:tv@apache.org">Thomas Vandahl</a>
45 |  |
      * @version $Id: TurbineAssemblerBrokerService.java 1521103 2013-09-09 13:38:07Z tv $
46 |  |
      */
47 | 0 |
     public class AnnotationProcessor
48 |  |
     {
49 |  |
         /** Logging */
50 | 33 |
         private static Log log = LogFactory.getLog(AnnotationProcessor.class);
51 |  |
52 |  |
         /** Annotation cache */
53 | 33 |
         private static ConcurrentMap<String, Annotation[]> annotationCache = new ConcurrentHashMap<String, Annotation[]>();
54 |  |
55 |  |
         /**
56 |  |
          * Get cached annotations for field, class or method
57 |  |
          *
58 |  |
          * @param object a field, class or method
59 |  |
          *
60 |  |
          * @return the declared annotations for the object
61 |  |
          */
62 |  |
         public static Annotation[] getAnnotations(AccessibleObject object)
63 |  |
         {
64 | 3139 |
             String key = object.getClass() + object.toString();
65 | 3139 |
             Annotation[] annotations = annotationCache.get(key);
66 | 3139 |
             if (annotations == null)
67 |  |
             {
68 | 1562 |
                 Annotation[] newAnnotations = object.getDeclaredAnnotations();
69 | 1562 |
                 annotations = annotationCache.putIfAbsent(key, newAnnotations);
70 | 1562 |
                 if (annotations == null)
71 |  |
                 {
72 | 1562 |
                     annotations = newAnnotations;
73 |  |
                 }
74 |  |
             }
75 | 3139 |
             return annotations;
76 |  |
         }
77 |  |
78 |  |
         /**
79 |  |
          * Search for annotated fields of the object and inject the appropriate
80 |  |
          * objects
81 |  |
          *
82 |  |
          * @param object the object
83 |  |
          * @throws TurbineException if the objects could not be injected
84 |  |
          */
85 |  |
         public static void process(Object object) throws TurbineException
86 |  |
         {
87 | 565 |
             ServiceManager manager = null;
88 | 565 |
             Configuration config = null;
89 | 565 |
             AssemblerBrokerService assembler = null;
90 | 565 |
             Class<?> clazz = object.getClass();
91 |  |
92 | 2336 |
             while (clazz != null)
93 |  |
             {
94 | 1775 |
                 Field[] fields = clazz.getDeclaredFields();
95 |  |
96 | 4770 |
                 for (Field field : fields)
97 |  |
                 {
98 | 2999 |
                     Annotation[] annotations = getAnnotations(field);
99 |  |
100 | 3708 |
                     for (Annotation a : annotations)
101 |  |
                     {
102 | 713 |
                         if (a instanceof TurbineService)
103 |  |
                         {
104 | 156 |
                             if (manager == null)
105 |  |
                             {
106 | 124 |
                                 manager = TurbineServices.getInstance();
107 |  |
                             }
108 | 156 |
                             injectTurbineService(object, manager, field, (TurbineService) a);
109 |  |
                         }
110 | 557 |
                         else if (a instanceof TurbineConfiguration)
111 |  |
                         {
112 | 349 |
                             if (config == null)
113 |  |
                             {
114 | 256 |
                                 config = Turbine.getConfiguration();
115 |  |
                             }
116 | 349 |
                             injectTurbineConfiguration(object, config, field, (TurbineConfiguration) a);
117 |  |
                         }
118 | 208 |
                         else if (a instanceof TurbineLoader)
119 |  |
                         {
120 | 208 |
                             if (assembler == null)
121 |  |
                             {
122 | 200 |
                                 assembler = (AssemblerBrokerService) TurbineServices.getInstance().
123 |  |
                                     getService(AssemblerBrokerService.SERVICE_NAME);
124 |  |
                             }
125 | 208 |
                             injectTurbineLoader(object, assembler, field, (TurbineLoader) a);
126 |  |
                         }
127 |  |
                     }
128 |  |
                 }
129 |  |
130 | 1771 |
                 clazz = clazz.getSuperclass();
131 | 1771 |
             }
132 | 561 |
         }
133 |  |
134 |  |
         /**
135 |  |
          * Inject Turbine configuration into field of object
136 |  |
          *
137 |  |
          * @param object the object to process
138 |  |
          * @param assembler AssemblerBrokerService, provides the loader
139 |  |
          * @param field the field
140 |  |
          * @param annotation the value of the annotation
141 |  |
          *
142 |  |
          * @throws TurbineException if loader cannot be set
143 |  |
          */
144 |  |
         private static void injectTurbineLoader(Object object, AssemblerBrokerService assembler, Field field, TurbineLoader annotation) throws TurbineException
145 |  |
         {
146 | 208 |
             Loader<?> loader = assembler.getLoader(annotation.value());
147 | 208 |
             field.setAccessible(true);
148 |  |
149 |  |
             try
150 |  |
             {
151 | 208 |
                 if (log.isDebugEnabled())
152 |  |
                 {
153 | 208 |
                     log.debug("Injection of " + loader + " into object " + object);
154 |  |
                 }
155 |  |
156 | 208 |
                 field.set(object, loader);
157 |  |
             }
158 | 0 |
             catch (IllegalArgumentException e)
159 |  |
             {
160 | 0 |
                 throw new TurbineException("Could not inject loader "
161 |  |
                         + loader + " into object " + object, e);
162 |  |
             }
163 | 0 |
             catch (IllegalAccessException e)
164 |  |
             {
165 | 0 |
                 throw new TurbineException("Could not inject loader "
166 |  |
                         + loader + " into object " + object, e);
167 | 208 |
             }
168 | 208 |
         }
169 |  |
170 |  |
         /**
171 |  |
          * Inject Turbine configuration into field of object
172 |  |
          *
173 |  |
          * @param object the object to process
174 |  |
          * @param conf the configuration to use
175 |  |
          * @param field the field
176 |  |
          * @param annotation the value of the annotation
177 |  |
          *
178 |  |
          * @throws TurbineException if configuration cannot be set
179 |  |
          */
180 |  |
         private static void injectTurbineConfiguration(Object object, Configuration conf, Field field, TurbineConfiguration annotation) throws TurbineException
181 |  |
         {
182 | 349 |
             Class<?> type = field.getType();
183 | 349 |
             String key = annotation.value();
184 |  |
185 |  |
             try
186 |  |
             {
187 | 349 |
                 if (Configuration.class.isAssignableFrom(type))
188 |  |
                 {
189 |  |
                     // Check for annotation value
190 | 2 |
                     if (StringUtils.isNotEmpty(key))
191 |  |
                     {
192 | 1 |
                         conf = conf.subset(key);
193 |  |
                     }
194 |  |
195 | 2 |
                     if (log.isDebugEnabled())
196 |  |
                     {
197 | 2 |
                         log.debug("Injection of " + conf + " into object " + object);
198 |  |
                     }
199 |  |
200 | 2 |
                     field.setAccessible(true);
201 | 2 |
                     field.set(object, conf);
202 |  |
                 }
203 | 347 |
                 else if (conf.containsKey(key))
204 |  |
                 {
205 | 156 |
                     if ( String.class.isAssignableFrom( type ) )
206 |  |
                     {
207 | 134 |
                         String value = conf.getString(key);
208 | 134 |
                         if (log.isDebugEnabled())
209 |  |
                         {
210 | 134 |
                             log.debug("Injection of " + value + " into object " + object);
211 |  |
                         }
212 |  |
213 | 134 |
                         field.setAccessible(true);
214 | 134 |
                         field.set(object, value);
215 | 134 |
                     }
216 | 22 |
                     else if ( Boolean.TYPE.isAssignableFrom( type ) )
217 |  |
                     {
218 | 19 |
                         boolean value = conf.getBoolean(key);
219 | 19 |
                         if (log.isDebugEnabled())
220 |  |
                         {
221 | 19 |
                             log.debug("Injection of " + value + " into object " + object);
222 |  |
                         }
223 |  |
224 | 19 |
                         field.setAccessible(true);
225 | 19 |
                         field.setBoolean(object, value);
226 | 19 |
                     }
227 | 3 |
                     else if ( Integer.TYPE.isAssignableFrom( type ) )
228 |  |
                     {
229 | 2 |
                         int value = conf.getInt(key);
230 | 2 |
                         if (log.isDebugEnabled())
231 |  |
                         {
232 | 2 |
                             log.debug("Injection of " + value + " into object " + object);
233 |  |
                         }
234 |  |
235 | 2 |
                         field.setAccessible(true);
236 | 2 |
                         field.setInt(object, value);
237 | 2 |
                     }
238 | 1 |
                     else if ( Long.TYPE.isAssignableFrom( type ) )
239 |  |
                     {
240 | 0 |
                         long value = conf.getLong(key);
241 | 0 |
                         if (log.isDebugEnabled())
242 |  |
                         {
243 | 0 |
                             log.debug("Injection of " + value + " into object " + object);
244 |  |
                         }
245 |  |
246 | 0 |
                         field.setAccessible(true);
247 | 0 |
                         field.setLong(object, value);
248 | 0 |
                     }
249 | 1 |
                     else if ( Short.TYPE.isAssignableFrom( type ) )
250 |  |
                     {
251 | 0 |
                         short value = conf.getShort(key);
252 | 0 |
                         if (log.isDebugEnabled())
253 |  |
                         {
254 | 0 |
                             log.debug("Injection of " + value + " into object " + object);
255 |  |
                         }
256 |  |
257 | 0 |
                         field.setAccessible(true);
258 | 0 |
                         field.setShort(object, value);
259 | 0 |
                     }
260 | 1 |
                     else if ( Long.TYPE.isAssignableFrom( type ) )
261 |  |
                     {
262 | 0 |
                         long value = conf.getLong(key);
263 | 0 |
                         if (log.isDebugEnabled())
264 |  |
                         {
265 | 0 |
                             log.debug("Injection of " + value + " into object " + object);
266 |  |
                         }
267 |  |
268 | 0 |
                         field.setAccessible(true);
269 | 0 |
                         field.setLong(object, value);
270 | 0 |
                     }
271 | 1 |
                     else if ( Float.TYPE.isAssignableFrom( type ) )
272 |  |
                     {
273 | 0 |
                         float value = conf.getFloat(key);
274 | 0 |
                         if (log.isDebugEnabled())
275 |  |
                         {
276 | 0 |
                             log.debug("Injection of " + value + " into object " + object);
277 |  |
                         }
278 |  |
279 | 0 |
                         field.setAccessible(true);
280 | 0 |
                         field.setFloat(object, value);
281 | 0 |
                     }
282 | 1 |
                     else if ( Double.TYPE.isAssignableFrom( type ) )
283 |  |
                     {
284 | 0 |
                         double value = conf.getDouble(key);
285 | 0 |
                         if (log.isDebugEnabled())
286 |  |
                         {
287 | 0 |
                             log.debug("Injection of " + value + " into object " + object);
288 |  |
                         }
289 |  |
290 | 0 |
                         field.setAccessible(true);
291 | 0 |
                         field.setDouble(object, value);
292 | 0 |
                     }
293 | 1 |
                     else if ( Byte.TYPE.isAssignableFrom( type ) )
294 |  |
                     {
295 | 0 |
                         byte value = conf.getByte(key);
296 | 0 |
                         if (log.isDebugEnabled())
297 |  |
                         {
298 | 0 |
                             log.debug("Injection of " + value + " into object " + object);
299 |  |
                         }
300 |  |
301 | 0 |
                         field.setAccessible(true);
302 | 0 |
                         field.setByte(object, value);
303 | 0 |
                     }
304 | 1 |
                     else if ( List.class.isAssignableFrom( type ) )
305 |  |
                     {
306 | 1 |
                         List<Object> values = conf.getList(key);
307 | 1 |
                         if (log.isDebugEnabled())
308 |  |
                         {
309 | 1 |
                             log.debug("Injection of " + values + " into object " + object);
310 |  |
                         }
311 |  |
312 | 1 |
                         field.setAccessible(true);
313 | 1 |
                         field.set(object, values);
314 |  |
                     }
315 |  |
                 }
316 |  |
             }
317 | 0 |
             catch (IllegalArgumentException e)
318 |  |
             {
319 | 0 |
                 throw new TurbineException("Could not inject configuration "
320 |  |
                         + conf + " into object " + object, e);
321 |  |
             }
322 | 0 |
             catch (IllegalAccessException e)
323 |  |
             {
324 | 0 |
                 throw new TurbineException("Could not inject configuration "
325 |  |
                         + conf + " into object " + object, e);
326 | 349 |
             }
327 | 349 |
         }
328 |  |
329 |  |
         /**
330 |  |
          * Inject Turbine service into field of object
331 |  |
          *
332 |  |
          * @param object the object to process
333 |  |
          * @param manager the service manager
334 |  |
          * @param field the field
335 |  |
          * @param annotation the value of the annotation
336 |  |
          *
337 |  |
          * @throws TurbineException if service is not available
338 |  |
          */
339 |  |
         private static void injectTurbineService(Object object, ServiceManager manager, Field field, TurbineService annotation) throws TurbineException
340 |  |
         {
341 | 156 |
             String serviceName = null;
342 |  |
             // Check for annotation value
343 | 156 |
             if (StringUtils.isNotEmpty(annotation.value()))
344 |  |
             {
345 | 1 |
                 serviceName = annotation.value();
346 |  |
             }
347 |  |
             // Check for fields SERVICE_NAME and ROLE
348 |  |
             else
349 |  |
             {
350 | 155 |
                 Field[] typeFields = field.getType().getFields();
351 | 155 |
                 for (Field f : typeFields)
352 |  |
                 {
353 | 155 |
                     if (TurbineService.SERVICE_NAME.equals(f.getName()))
354 |  |
                     {
355 |  |
                         try
356 |  |
                         {
357 | 138 |
                             serviceName = (String)f.get(null);
358 |  |
                         }
359 | 0 |
                         catch (Exception e)
360 |  |
                         {
361 | 0 |
                             continue;
362 | 138 |
                         }
363 |  |
                         break;
364 |  |
                     }
365 | 17 |
                     else if (TurbineService.ROLE.equals(f.getName()))
366 |  |
                     {
367 |  |
                         try
368 |  |
                         {
369 | 17 |
                             serviceName = (String)f.get(null);
370 |  |
                         }
371 | 0 |
                         catch (Exception e)
372 |  |
                         {
373 | 0 |
                             continue;
374 | 17 |
                         }
375 |  |
                         break;
376 |  |
                     }
377 |  |
                 }
378 |  |
             }
379 |  |
380 | 156 |
             if (StringUtils.isEmpty(serviceName))
381 |  |
             {
382 |  |
                 // Try interface class name
383 | 0 |
                 serviceName = field.getType().getName();
384 |  |
             }
385 |  |
386 | 156 |
             if (log.isDebugEnabled())
387 |  |
             {
388 | 156 |
                 log.debug("Looking up service for injection: " + serviceName + " for object " + object);
389 |  |
             }
390 |  |
391 | 156 |
             Object service = manager.getService(serviceName); // throws Exception on unknown service
392 | 152 |
             field.setAccessible(true);
393 |  |
394 |  |
             try
395 |  |
             {
396 | 152 |
                 if (log.isDebugEnabled())
397 |  |
                 {
398 | 152 |
                     log.debug("Injection of " + serviceName + " into object " + object);
399 |  |
                 }
400 |  |
401 | 152 |
                 field.set(object, service);
402 |  |
             }
403 | 0 |
             catch (IllegalArgumentException e)
404 |  |
             {
405 | 0 |
                 throw new TurbineException("Could not inject service "
406 |  |
                         + serviceName + " into object " + object, e);
407 |  |
             }
408 | 0 |
             catch (IllegalAccessException e)
409 |  |
             {
410 | 0 |
                 throw new TurbineException("Could not inject service "
411 |  |
                         + serviceName + " into object " + object, e);
412 | 152 |
             }
413 | 152 |
         }
414 |  |
     }