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