Clover coverage report - Code Coverage for hivemind release 1.0-beta-2
Coverage timestamp: Sun Aug 1 2004 14:03:45 EDT
file stats: LOC: 329   Methods: 12
NCLOC: 221   Classes: 1
30 day Evaluation Version distributed via the Maven Jar Repository. Clover is not free. You have 30 days to evaluate it. Please visit http://www.thecortex.net/clover to obtain a licensed version of Clover
 
 Source file Conditionals Statements Methods TOTAL
BuilderFactoryLogic.java 94.1% 96.7% 100% 96.4%
coverage coverage
 1   
 //  Copyright 2004 The Apache Software Foundation
 2   
 //
 3   
 // Licensed under the Apache License, Version 2.0 (the "License");
 4   
 // you may not use this file except in compliance with the License.
 5   
 // You may obtain a copy of the License at
 6   
 //
 7   
 //     http://www.apache.org/licenses/LICENSE-2.0
 8   
 //
 9   
 // Unless required by applicable law or agreed to in writing, software
 10   
 // distributed under the License is distributed on an "AS IS" BASIS,
 11   
 // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 12   
 // See the License for the specific language governing permissions and
 13   
 // limitations under the License.
 14   
 
 15   
 package org.apache.hivemind.service.impl;
 16   
 
 17   
 import java.lang.reflect.InvocationTargetException;
 18   
 import java.lang.reflect.Method;
 19   
 import java.util.Collection;
 20   
 import java.util.HashSet;
 21   
 import java.util.Iterator;
 22   
 import java.util.List;
 23   
 import java.util.Set;
 24   
 
 25   
 import org.apache.commons.logging.Log;
 26   
 import org.apache.hivemind.ClassResolver;
 27   
 import org.apache.hivemind.ErrorHandler;
 28   
 import org.apache.hivemind.HiveMind;
 29   
 import org.apache.hivemind.Location;
 30   
 import org.apache.hivemind.internal.Module;
 31   
 import org.apache.hivemind.service.EventLinker;
 32   
 import org.apache.hivemind.util.ConstructorUtils;
 33   
 import org.apache.hivemind.util.PropertyUtils;
 34   
 
 35   
 /**
 36   
  * Created by {@link org.apache.hivemind.service.impl.BuilderFactory} for each
 37   
  * service to be created; encapsulates all the direct and indirect parameters
 38   
  * used to construct a service.
 39   
  *
 40   
  * @author Howard Lewis Ship
 41   
  */
 42   
 public class BuilderFactoryLogic
 43   
 {
 44   
     private Module _contributingModule;
 45   
     private Log _log;
 46   
     private String _serviceId;
 47   
     private BuilderParameter _parameter;
 48   
     private ErrorHandler _errorHandler;
 49   
 
 50  235
     public BuilderFactoryLogic(
 51   
         Module contributingModule,
 52   
         Log log,
 53   
         String serviceId,
 54   
         BuilderParameter parameter)
 55   
     {
 56  235
         _contributingModule = contributingModule;
 57  235
         _log = log;
 58  235
         _serviceId = serviceId;
 59  235
         _parameter = parameter;
 60   
     }
 61   
 
 62  235
     public Object createService()
 63   
     {
 64  235
         Object result = null;
 65   
 
 66  235
         try
 67   
         {
 68  235
             result = instantiateCoreServiceInstance();
 69   
 
 70  235
             setProperties(result);
 71   
 
 72  235
             registerForEvents(result);
 73   
 
 74  235
             invokeInitializer(result);
 75   
         }
 76   
         catch (Exception ex)
 77   
         {
 78  0
             getErrorHandler().error(
 79   
                 _log,
 80   
                 ServiceMessages.failureBuildingService(_serviceId, ex),
 81   
                 _parameter.getLocation(),
 82   
                 ex);
 83   
         }
 84   
 
 85  235
         return result;
 86   
     }
 87   
 
 88  235
     private Object instantiateCoreServiceInstance()
 89   
     {
 90  235
         ClassResolver resolver = _contributingModule.getClassResolver();
 91  235
         Class serviceClass = resolver.findClass(_parameter.getClassName());
 92   
 
 93  235
         Object[] constructorParameters = buildConstructorParameters();
 94   
 
 95  235
         return ConstructorUtils.invokeConstructor(serviceClass, constructorParameters);
 96   
     }
 97   
 
 98  235
     private Object[] buildConstructorParameters()
 99   
     {
 100  235
         List parameters = _parameter.getParameters();
 101  235
         int count = parameters.size();
 102   
 
 103  235
         if (count == 0)
 104  216
             return null;
 105   
 
 106  19
         Object[] result = new Object[count];
 107   
 
 108  19
         for (int i = 0; i < count; i++)
 109   
         {
 110  21
             BuilderFacet facet = (BuilderFacet) parameters.get(i);
 111   
 
 112  21
             try
 113   
             {
 114  21
                 result[i] = facet.getFacetValue(_serviceId, _contributingModule, Object.class);
 115   
 
 116  21
                 HiveMind.setLocation(result[i], HiveMind.getLocation(facet));
 117   
             }
 118   
             catch (Exception ex)
 119   
             {
 120  0
                 getErrorHandler().error(_log, ex.getMessage(), facet.getLocation(), ex);
 121   
             }
 122   
         }
 123   
 
 124  19
         return result;
 125   
     }
 126   
 
 127  235
     private void invokeInitializer(Object service)
 128   
     {
 129  235
         String methodName = _parameter.getInitializeMethod();
 130   
 
 131  235
         boolean allowMissing = HiveMind.isBlank(methodName);
 132   
 
 133  235
         String searchMethodName = allowMissing ? "initializeService" : methodName;
 134   
 
 135  235
         try
 136   
         {
 137  235
             findAndInvokeInitializerMethod(service, searchMethodName, allowMissing);
 138   
         }
 139   
         catch (Exception ex)
 140   
         {
 141  1
             getErrorHandler().error(
 142   
                 _log,
 143   
                 ServiceMessages.unableToInitializeService(
 144   
                     _serviceId,
 145   
                     methodName,
 146   
                     service.getClass(),
 147   
                     ex),
 148   
                 _parameter.getLocation(),
 149   
                 ex);
 150   
         }
 151   
     }
 152   
 
 153  235
     private void findAndInvokeInitializerMethod(
 154   
         Object service,
 155   
         String methodName,
 156   
         boolean allowMissing)
 157   
         throws IllegalAccessException, InvocationTargetException, NoSuchMethodException
 158   
     {
 159  235
         Class serviceClass = service.getClass();
 160   
 
 161  235
         try
 162   
         {
 163  235
             Method m = serviceClass.getMethod(methodName, null);
 164   
 
 165  10
             m.invoke(service, null);
 166   
         }
 167   
         catch (NoSuchMethodException ex)
 168   
         {
 169  225
             if (allowMissing)
 170  224
                 return;
 171   
 
 172  1
             throw ex;
 173   
         }
 174   
     }
 175   
 
 176  235
     private void registerForEvents(Object result)
 177   
     {
 178  235
         List eventRegistrations = _parameter.getEventRegistrations();
 179   
 
 180  235
         if (eventRegistrations.isEmpty())
 181  232
             return;
 182   
 
 183  3
         EventLinker linker = new EventLinkerImpl(_log, getErrorHandler());
 184   
 
 185  3
         Iterator i = eventRegistrations.iterator();
 186  3
         while (i.hasNext())
 187   
         {
 188  3
             EventRegistration er = (EventRegistration) i.next();
 189   
 
 190   
             // Will log any errors to the errorHandler
 191   
 
 192  3
             linker.addEventListener(
 193   
                 er.getProducer(),
 194   
                 er.getEventSetName(),
 195   
                 result,
 196   
                 er.getLocation());
 197   
         }
 198   
     }
 199   
 
 200  235
     private void setProperties(Object service)
 201   
     {
 202  235
         List properties = _parameter.getProperties();
 203  235
         int count = properties.size();
 204   
 
 205   
         // Track the writeable properties, removing names as they are wired or autowired.
 206   
 
 207  235
         Set writeableProperties = new HashSet(PropertyUtils.getWriteableProperties(service));
 208   
 
 209  235
         for (int i = 0; i < count; i++)
 210   
         {
 211  1354
             BuilderFacet facet = (BuilderFacet) properties.get(i);
 212   
 
 213  1354
             String propertyName = wireProperty(service, facet);
 214   
 
 215  1354
             if (propertyName != null)
 216  237
                 writeableProperties.remove(propertyName);
 217   
         }
 218   
 
 219  235
         if (_parameter.getAutowireServices())
 220  232
             autowireServices(service, writeableProperties);
 221   
 
 222   
     }
 223   
 
 224   
     /**
 225   
      * Wire (or auto-wire) the property; return the name of the property actually set
 226   
      * (if a property is set, which is not always the case).
 227   
      */
 228  1354
     private String wireProperty(Object service, BuilderFacet facet)
 229   
     {
 230  1354
         String propertyName = facet.getPropertyName();
 231   
 
 232  1354
         try
 233   
         {
 234   
             // Autowire the property (if possible).
 235   
 
 236  1354
             String autowirePropertyName =
 237   
                 facet.autowire(service, _serviceId, _contributingModule, _log);
 238   
 
 239  1354
             if (autowirePropertyName != null)
 240  22
                 return autowirePropertyName;
 241   
 
 242   
             // There will be a facet for log, messages, service-id, etc. even if no
 243   
             // property name is specified, so we skip it here.  In many cases, those
 244   
             // facets will have just done an autowire.                
 245   
 
 246  1332
             if (propertyName == null)
 247  1116
                 return null;
 248   
 
 249  216
             Class targetType = PropertyUtils.getPropertyType(service, propertyName);
 250   
 
 251  215
             Object value = facet.getFacetValue(_serviceId, _contributingModule, targetType);
 252   
 
 253  215
             PropertyUtils.write(service, propertyName, value);
 254   
 
 255  215
             if (_log.isDebugEnabled())
 256  16
                 _log.debug("Set property " + propertyName + " to " + value);
 257   
 
 258  215
             return propertyName;
 259   
         }
 260   
         catch (Exception ex)
 261   
         {
 262  1
             getErrorHandler().error(_log, ex.getMessage(), facet.getLocation(), ex);
 263   
 
 264  1
             return null;
 265   
         }
 266   
     }
 267   
 
 268  232
     private void autowireServices(Object service, Collection propertyNames)
 269   
     {
 270  232
         Iterator i = propertyNames.iterator();
 271  232
         while (i.hasNext())
 272   
         {
 273  109
             String propertyName = (String) i.next();
 274   
 
 275  109
             autowireProperty(service, propertyName);
 276   
         }
 277   
     }
 278   
 
 279  109
     private void autowireProperty(Object service, String propertyName)
 280   
     {
 281  109
         Class propertyType = PropertyUtils.getPropertyType(service, propertyName);
 282   
 
 283   
         // Yes, not all interfaces are services, but there's no real way to be sure.
 284   
         // Moral of the story: don't leave around writeable properties that are interfaces
 285   
         // (and therefore look like services)! A future improvement may be to ignore
 286   
         // properties for which there are no service points. This is why autowiring
 287   
         // can be turned off. 
 288   
 
 289  109
         if (!propertyType.isInterface())
 290  10
             return;
 291   
 
 292   
         // Here's the problem with autowiring; there can be other stuff besides
 293   
         // services that are writable; since lots of classes inherite from
 294   
         // BaseLocatable, Location is one of those property types.
 295   
         
 296  99
         if (propertyType.equals(Location.class))
 297  95
             return;
 298   
 
 299  4
         try
 300   
         {
 301  4
             Object collaboratingService = _contributingModule.getService(propertyType);
 302   
 
 303  3
             PropertyUtils.write(service, propertyName, collaboratingService);
 304   
 
 305  3
             if (_log.isDebugEnabled())
 306  0
                 _log.debug(
 307   
                     "Autowired service property " + propertyName + " to " + collaboratingService);
 308   
 
 309   
         }
 310   
         catch (Exception ex)
 311   
         {
 312  1
             getErrorHandler().error(
 313   
                 _log,
 314   
                 ServiceMessages.autowirePropertyFailure(propertyName, _serviceId, ex),
 315   
                 _parameter.getLocation(),
 316   
                 ex);
 317   
         }
 318   
     }
 319   
 
 320  6
     private ErrorHandler getErrorHandler()
 321   
     {
 322  6
         if (_errorHandler == null)
 323  6
             _errorHandler = _contributingModule.getErrorHandler();
 324   
 
 325  6
         return _errorHandler;
 326   
     }
 327   
 
 328   
 }
 329