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