Clover coverage report - Code Coverage for hivemind release 1.1
Coverage timestamp: Tue Oct 25 2005 10:47:07 EDT
file stats: LOC: 263   Methods: 17
NCLOC: 159   Classes: 2
 
 Source file Conditionals Statements Methods TOTAL
PooledServiceModel.java 91.7% 98.3% 100% 97%
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.ArrayList;
 18    import java.util.List;
 19   
 20    import org.apache.hivemind.ApplicationRuntimeException;
 21    import org.apache.hivemind.HiveMind;
 22    import org.apache.hivemind.PoolManageable;
 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.ProxyUtils;
 27    import org.apache.hivemind.internal.Module;
 28    import org.apache.hivemind.service.ThreadCleanupListener;
 29    import org.apache.hivemind.service.ThreadEventNotifier;
 30   
 31    /**
 32    * Similar to the
 33    * {@link org.apache.hivemind.impl.servicemodel.ThreadedServiceModel threaded service model},
 34    * except that, once created, services are pooled for later use.
 35    *
 36    * @author Howard Lewis Ship
 37    */
 38    public class PooledServiceModel extends AbstractServiceModelImpl
 39    {
 40    /**
 41    * Name of a method in the deferred proxy that is used to obtain the constructed service.
 42    */
 43    protected static final String SERVICE_ACCESSOR_METHOD_NAME = "_service";
 44   
 45    private Object _serviceProxy;
 46   
 47    private ThreadEventNotifier _notifier;
 48   
 49    private ThreadLocal _activeService;
 50   
 51    private List _servicePool;
 52   
 53    /** @since 1.1 */
 54   
 55    private Class _serviceInterface;
 56   
 57    /**
 58    * Shared, null implementation of PoolManageable.
 59    */
 60    private static final PoolManageable NULL_MANAGEABLE = new PoolManageable()
 61    {
 62  407 public void activateService()
 63    {
 64    }
 65   
 66  401 public void passivateService()
 67    {
 68    }
 69    };
 70   
 71    private class PooledService implements ThreadCleanupListener
 72    {
 73    private Object _core;
 74   
 75    private PoolManageable _managed;
 76   
 77    /**
 78    * @param service
 79    * the full service implementation, including any interceptors
 80    * @param core
 81    * the core service implementation, which may optionally implement
 82    * {@link PoolManageable}
 83    */
 84  47 PooledService(Object core)
 85    {
 86  47 _core = core;
 87   
 88  47 if (core instanceof PoolManageable)
 89  1 _managed = (PoolManageable) core;
 90    else
 91  46 _managed = NULL_MANAGEABLE;
 92    }
 93   
 94  402 public void threadDidCleanup()
 95    {
 96  402 unbindPooledServiceFromCurrentThread(this);
 97    }
 98   
 99  409 void activate()
 100    {
 101  409 _managed.activateService();
 102    }
 103   
 104  402 void passivate()
 105    {
 106  402 _managed.passivateService();
 107    }
 108   
 109    /**
 110    * Returns the configured service implementation.
 111    */
 112  414 public Object getService()
 113    {
 114  414 return _core;
 115    }
 116   
 117    }
 118   
 119  9 public PooledServiceModel(ConstructableServicePoint servicePoint)
 120    {
 121  9 super(servicePoint);
 122   
 123  9 _serviceInterface = servicePoint.getServiceInterface();
 124    }
 125   
 126  9 public synchronized Object getService()
 127    {
 128  9 if (_notifier == null)
 129    {
 130  9 Module module = getServicePoint().getModule();
 131   
 132  9 _notifier = (ThreadEventNotifier) module.getService(
 133    HiveMind.THREAD_EVENT_NOTIFIER_SERVICE,
 134    ThreadEventNotifier.class);
 135    }
 136   
 137  9 if (_serviceProxy == null)
 138  9 _serviceProxy = constructServiceProxy();
 139   
 140  9 return _serviceProxy;
 141    }
 142   
 143    /**
 144    * Constructs the service proxy and returns it, wrapped in any interceptors.
 145    */
 146  9 private Object constructServiceProxy()
 147    {
 148  9 ConstructableServicePoint servicePoint = getServicePoint();
 149   
 150  9 if (_log.isDebugEnabled())
 151  1 _log.debug("Creating PooledProxy for service " + servicePoint.getExtensionPointId());
 152   
 153  9 Object proxy = ProxyUtils.createDelegatingProxy(
 154    "PooledProxy",
 155    this,
 156    "getServiceImplementationForCurrentThread",
 157    servicePoint);
 158   
 159  9 Object intercepted = addInterceptors(proxy);
 160   
 161  9 RegistryShutdownListener outerProxy = ProxyUtils
 162    .createOuterProxy(intercepted, servicePoint);
 163   
 164  9 ShutdownCoordinator coordinator = servicePoint.getShutdownCoordinator();
 165   
 166  9 coordinator.addRegistryShutdownListener(outerProxy);
 167   
 168  9 return outerProxy;
 169    }
 170   
 171  414 public synchronized Object getServiceImplementationForCurrentThread()
 172    {
 173  414 if (_activeService == null)
 174  9 _activeService = new ThreadLocal();
 175   
 176  414 PooledService pooled = (PooledService) _activeService.get();
 177   
 178  414 if (pooled == null)
 179    {
 180  409 pooled = obtainPooledService();
 181   
 182  409 pooled.activate();
 183   
 184  409 _notifier.addThreadCleanupListener(pooled);
 185  409 _activeService.set(pooled);
 186    }
 187   
 188  414 return pooled.getService();
 189    }
 190   
 191  409 private PooledService obtainPooledService()
 192    {
 193  409 PooledService result = getServiceFromPool();
 194   
 195  409 if (result == null)
 196  47 result = constructPooledService();
 197   
 198  409 return result;
 199    }
 200   
 201  409 private synchronized PooledService getServiceFromPool()
 202    {
 203  409 int count = _servicePool == null ? 0 : _servicePool.size();
 204   
 205  409 if (count == 0)
 206  47 return null;
 207   
 208  362 return (PooledService) _servicePool.remove(count - 1);
 209    }
 210   
 211  402 private synchronized void returnServiceToPool(PooledService pooled)
 212    {
 213  402 if (_servicePool == null)
 214  4 _servicePool = new ArrayList();
 215   
 216  402 _servicePool.add(pooled);
 217    }
 218   
 219  47 private synchronized PooledService constructPooledService()
 220    {
 221  47 try
 222    {
 223  47 Object core = constructCoreServiceImplementation();
 224   
 225    // This is related to bean services.
 226   
 227  47 if (!_serviceInterface.isInstance(core))
 228  2 core = constructBridgeProxy(core);
 229  47 if( core instanceof RegistryShutdownListener )
 230    {
 231  3 getShutdownCoordinatorService().addRegistryShutdownListener( ( RegistryShutdownListener )core );
 232    }
 233  47 return new PooledService(core);
 234    }
 235    catch (Exception ex)
 236    {
 237  0 throw new ApplicationRuntimeException(ServiceModelMessages.unableToConstructService(
 238    getServicePoint(),
 239    ex), ex);
 240    }
 241    }
 242   
 243  402 private void unbindPooledServiceFromCurrentThread(PooledService pooled)
 244    {
 245  402 _notifier.removeThreadCleanupListener(pooled);
 246   
 247  402 _activeService.set(null);
 248   
 249  402 pooled.passivate();
 250   
 251  402 returnServiceToPool(pooled);
 252    }
 253   
 254    /**
 255    * Invokes {@link #getServiceImplementationForCurrentThread()} to instantiate an instance of the
 256    * service.
 257    */
 258  1 public void instantiateService()
 259    {
 260  1 getServiceImplementationForCurrentThread();
 261    }
 262   
 263    }