2009/04/15 - Apache HiveMind has been retired.

For more information, please explore the Attic.

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