Clover coverage report - Code Coverage for hivemind release 1.1-beta-3
Coverage timestamp: Mon Aug 22 2005 21:38:15 EDT
file stats: LOC: 220   Methods: 9
NCLOC: 107   Classes: 1
 
 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  1413 public AbstractServiceModelImpl(ConstructableServicePoint servicePoint)
 53    {
 54  1413 _log = LogFactory.getLog(servicePoint.getExtensionPointId());
 55   
 56  1413 _servicePoint = servicePoint;
 57    }
 58   
 59  913 protected Object addInterceptors(Object core)
 60    {
 61  913 List interceptors = _servicePoint.getOrderedInterceptorContributions();
 62   
 63  913 int count = interceptors == null ? 0 : interceptors.size();
 64   
 65  913 if (count == 0)
 66  897 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  950 protected Object constructCoreServiceImplementation()
 98    {
 99  950 if (_log.isDebugEnabled())
 100  18 _log.debug("Constructing core service implementation for service "
 101    + _servicePoint.getExtensionPointId());
 102   
 103  950 Class serviceInterface = _servicePoint.getServiceInterface();
 104  950 Class declaredInterface = _servicePoint.getDeclaredInterface();
 105   
 106  950 ServiceImplementationConstructor constructor = _servicePoint.getServiceConstructor();
 107  950 Object result = constructor.constructCoreServiceImplementation();
 108   
 109  950 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  950 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  950 HiveMind.setLocation(result, constructor.getLocation());
 125   
 126  950 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  885 protected Object constructServiceImplementation()
 138    {
 139  885 Object result = constructNewServiceImplementation();
 140   
 141    // After succesfully building, we don't need
 142    // some of the definition stuff again.
 143   
 144  882 _servicePoint.clearConstructorInformation();
 145   
 146  882 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  885 protected Object constructNewServiceImplementation()
 154    {
 155  885 try
 156    {
 157  885 Object core = constructCoreServiceImplementation();
 158   
 159  885 Object intercepted = addInterceptors(core);
 160   
 161  882 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  3579 public ConstructableServicePoint getServicePoint()
 173    {
 174  3579 return _servicePoint;
 175    }
 176   
 177    /**
 178    * Need to bridge from the service interface to the actual type.
 179    *
 180    * @since 1.1
 181    */
 182  10 protected synchronized Object constructBridgeProxy(Object service)
 183    {
 184  10 if (_bridgeProxyClass == null)
 185  10 _bridgeProxyClass = constructBridgeProxyClass(service);
 186   
 187  10 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  10 private Class constructBridgeProxyClass(Object service)
 198    {
 199  10 ProxyBuilder builder = new ProxyBuilder("BridgeProxy", getServicePoint());
 200   
 201  10 ClassFab cf = builder.getClassFab();
 202   
 203  10 Class serviceType = service.getClass();
 204   
 205  10 cf.addField("_service", serviceType);
 206   
 207  10 cf.addConstructor(new Class[]
 208    { serviceType }, null, "{ super(); _service = $1; }");
 209   
 210  10 builder.addServiceMethods("_service");
 211   
 212  10 return cf.createClass();
 213    }
 214   
 215  11 protected ShutdownCoordinator getShutdownCoordinatorService()
 216    {
 217  11 return ( ( ShutdownCoordinator )getServicePoint().getModule().getService( ShutdownCoordinator.class ) );
 218    }
 219   
 220    }