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
 
 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  
 }