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