Clover coverage report - Code Coverage for hivemind release 1.1-alpha-2
Coverage timestamp: Wed Feb 23 2005 09:59:04 EST
file stats: LOC: 214   Methods: 8
NCLOC: 102   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
AbstractServiceModelImpl.java 78.6% 95.2% 100% 92.2%
coverage coverage
 1   
 // Copyright 2004, 2005 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.impl.servicemodel;
 16   
 
 17   
 import java.util.List;
 18   
 
 19   
 import org.apache.commons.logging.Log;
 20   
 import org.apache.commons.logging.LogFactory;
 21   
 import org.apache.hivemind.ApplicationRuntimeException;
 22   
 import org.apache.hivemind.HiveMind;
 23   
 import org.apache.hivemind.impl.ConstructableServicePoint;
 24   
 import org.apache.hivemind.impl.InterceptorStackImpl;
 25   
 import org.apache.hivemind.impl.ProxyBuilder;
 26   
 import org.apache.hivemind.internal.ServiceImplementationConstructor;
 27   
 import org.apache.hivemind.internal.ServiceInterceptorContribution;
 28   
 import org.apache.hivemind.internal.ServiceModel;
 29   
 import org.apache.hivemind.service.ClassFab;
 30   
 import org.apache.hivemind.util.ConstructorUtils;
 31   
 
 32   
 /**
 33   
  * Base class for implementing {@link org.apache.hivemind.internal.ServiceModel}.
 34   
  * 
 35   
  * @author Howard Lewis Ship
 36   
  */
 37   
 public abstract class AbstractServiceModelImpl implements ServiceModel
 38   
 {
 39   
     /**
 40   
      * This log is created from the log's service id, which is the appropriate place to log any
 41   
      * messages related to creating (or managing) the service implementation, proxy, etc. Subclasses
 42   
      * should make use of this Log as well.
 43   
      */
 44   
     protected final Log _log;
 45   
 
 46   
     private ConstructableServicePoint _servicePoint;
 47   
 
 48   
     /** @since 1.1 */
 49   
     private Class _bridgeProxyClass;
 50   
 
 51  1238
     public AbstractServiceModelImpl(ConstructableServicePoint servicePoint)
 52   
     {
 53  1238
         _log = LogFactory.getLog(servicePoint.getExtensionPointId());
 54   
 
 55  1238
         _servicePoint = servicePoint;
 56   
     }
 57   
 
 58  794
     protected Object addInterceptors(Object core)
 59   
     {
 60  794
         List interceptors = _servicePoint.getOrderedInterceptorContributions();
 61   
 
 62  794
         int count = interceptors == null ? 0 : interceptors.size();
 63   
 
 64  794
         if (count == 0)
 65  778
             return core;
 66   
 
 67  16
         InterceptorStackImpl stack = new InterceptorStackImpl(_log, _servicePoint, core);
 68   
 
 69   
         // They are sorted into runtime execution order. Since we build from the
 70   
         // core service impl outwarads, we have to reverse the runtime execution
 71   
         // order to get the build order.
 72   
         // That is, if user expects interceptors in order A B C (perhaps using
 73   
         // the rules: A before B, C after B).
 74   
         // Then that's the order for interceptors list: A B C
 75   
         // To get that runtime execution order, we wrap C around the core,
 76   
         // wrap B around C, and wrap A around B.
 77   
 
 78  16
         for (int i = count - 1; i >= 0; i--)
 79   
         {
 80  18
             ServiceInterceptorContribution ic = (ServiceInterceptorContribution) interceptors
 81   
                     .get(i);
 82   
 
 83  18
             stack.process(ic);
 84   
         }
 85   
 
 86   
         // Whatever's on top is the final service.
 87   
 
 88  13
         return stack.peek();
 89   
     }
 90   
 
 91   
     /**
 92   
      * Constructs the core service implementation (by invoking the
 93   
      * {@link ServiceImplementationConstructor}), and checks that the result is non-null and
 94   
      * assignable to the service interface.
 95   
      */
 96  831
     protected Object constructCoreServiceImplementation()
 97   
     {
 98  831
         if (_log.isDebugEnabled())
 99  18
             _log.debug("Constructing core service implementation for service "
 100   
                     + _servicePoint.getExtensionPointId());
 101   
 
 102  831
         Class serviceInterface = _servicePoint.getServiceInterface();
 103  831
         Class declaredInterface = _servicePoint.getDeclaredInterface();
 104   
 
 105  831
         ServiceImplementationConstructor constructor = _servicePoint.getServiceConstructor();
 106  831
         Object result = constructor.constructCoreServiceImplementation();
 107   
 
 108  831
         if (result == null)
 109  0
             throw new ApplicationRuntimeException(ServiceModelMessages
 110   
                     .factoryReturnedNull(_servicePoint), constructor.getLocation(), null);
 111   
 
 112   
         // The factory should provice something that either implements the service interface
 113   
         // or the declared interface. Again, they are normally the same, but with services
 114   
         // defined in terms of a class (not an interface), the service interface is
 115   
         // synthetic, and the declared interface is the actual class.
 116   
 
 117  831
         if (!(serviceInterface.isInstance(result) || declaredInterface.isInstance(result)))
 118  0
             throw new ApplicationRuntimeException(ServiceModelMessages.factoryWrongInterface(
 119   
                     _servicePoint,
 120   
                     result,
 121   
                     serviceInterface), constructor.getLocation(), null);
 122   
 
 123  831
         HiveMind.setLocation(result, constructor.getLocation());
 124   
 
 125  831
         return result;
 126   
     }
 127   
 
 128   
     /**
 129   
      * Constructs the service implementation; this is invoked from
 130   
      * {@link org.apache.hivemind.internal.ServicePoint#getService(Class)} (for singletons),
 131   
      * or from the generated deferrable proxy (for most service models). Primarily, invokes
 132   
      * {@link #constructNewServiceImplementation()}from within a block that checks for recursive
 133   
      * builds.
 134   
      */
 135   
 
 136  771
     protected Object constructServiceImplementation()
 137   
     {
 138  771
         Object result = constructNewServiceImplementation();
 139   
 
 140   
         // After succesfully building, we don't need
 141   
         // some of the definition stuff again.
 142   
 
 143  768
         _servicePoint.clearConstructorInformation();
 144   
 
 145  768
         return result;
 146   
     }
 147   
 
 148   
     /**
 149   
      * Constructs a new implementation of the service, starting with a core implementation, then
 150   
      * adding any interceptors.
 151   
      */
 152  771
     protected Object constructNewServiceImplementation()
 153   
     {
 154  771
         try
 155   
         {
 156  771
             Object core = constructCoreServiceImplementation();
 157   
 
 158  771
             Object intercepted = addInterceptors(core);
 159   
 
 160  768
             return intercepted;
 161   
         }
 162   
         catch (Exception ex)
 163   
         {
 164  3
             throw new ApplicationRuntimeException(ServiceModelMessages.unableToConstructService(
 165   
                     _servicePoint,
 166   
                     ex), ex);
 167   
         }
 168   
 
 169   
     }
 170   
 
 171  3107
     public ConstructableServicePoint getServicePoint()
 172   
     {
 173  3107
         return _servicePoint;
 174   
     }
 175   
 
 176   
     /**
 177   
      * Need to bridge from the service interface to the actual type.
 178   
      * 
 179   
      * @since 1.1
 180   
      */
 181  4
     protected synchronized Object constructBridgeProxy(Object service)
 182   
     {
 183  4
         if (_bridgeProxyClass == null)
 184  4
             _bridgeProxyClass = constructBridgeProxyClass(service);
 185   
 
 186  4
         return ConstructorUtils.invokeConstructor(_bridgeProxyClass, new Object[]
 187   
         { service });
 188   
     }
 189   
 
 190   
     /**
 191   
      * Assumes that the factory will keep cranking out instances of the same class.
 192   
      * 
 193   
      * @since 1.1
 194   
      */
 195   
 
 196  4
     private Class constructBridgeProxyClass(Object service)
 197   
     {
 198  4
         ProxyBuilder builder = new ProxyBuilder("BridgeProxy", getServicePoint());
 199   
 
 200  4
         ClassFab cf = builder.getClassFab();
 201   
 
 202  4
         Class serviceType = service.getClass();
 203   
 
 204  4
         cf.addField("_service", serviceType);
 205   
 
 206  4
         cf.addConstructor(new Class[]
 207   
         { serviceType }, null, "{ super(); _service = $1; }");
 208   
 
 209  4
         builder.addServiceMethods("_service");
 210   
 
 211  4
         return cf.createClass();
 212   
     }
 213   
 
 214   
 }