Coverage Report - org.apache.ojb.broker.core.PersistenceBrokerFactoryDefaultImpl
 
Classes in this File Line Coverage Branch Coverage Complexity
PersistenceBrokerFactoryDefaultImpl
N/A
N/A
1.688
PersistenceBrokerFactoryDefaultImpl$PBKeyedPoolableObjectFactory
N/A
N/A
1.688
 
 1  
 package org.apache.ojb.broker.core;
 2  
 
 3  
 /* Copyright 2003-2005 The Apache Software Foundation
 4  
  *
 5  
  * Licensed under the Apache License, Version 2.0 (the "License");
 6  
  * you may not use this file except in compliance with the License.
 7  
  * You may obtain a copy of the License at
 8  
  *
 9  
  *     http://www.apache.org/licenses/LICENSE-2.0
 10  
  *
 11  
  * Unless required by applicable law or agreed to in writing, software
 12  
  * distributed under the License is distributed on an "AS IS" BASIS,
 13  
  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 14  
  * See the License for the specific language governing permissions and
 15  
  * limitations under the License.
 16  
  */
 17  
 
 18  
 import java.util.Properties;
 19  
 
 20  
 import org.apache.commons.lang.builder.ToStringBuilder;
 21  
 import org.apache.commons.lang.builder.ToStringStyle;
 22  
 import org.apache.commons.pool.KeyedObjectPool;
 23  
 import org.apache.commons.pool.KeyedPoolableObjectFactory;
 24  
 import org.apache.commons.pool.impl.GenericKeyedObjectPool;
 25  
 import org.apache.ojb.broker.PBFactoryException;
 26  
 import org.apache.ojb.broker.PBKey;
 27  
 import org.apache.ojb.broker.PBState;
 28  
 import org.apache.ojb.broker.PersistenceBroker;
 29  
 import org.apache.ojb.broker.PersistenceBrokerInternal;
 30  
 import org.apache.ojb.broker.util.BrokerHelper;
 31  
 import org.apache.ojb.broker.util.logging.Logger;
 32  
 import org.apache.ojb.broker.util.logging.LoggerFactory;
 33  
 
 34  
 /**
 35  
  * This is the default implementation of the {@link PersistenceBrokerFactoryIF}
 36  
  * interface.
 37  
  * <p>
 38  
  * This implementation use a pool of {@link org.apache.ojb.broker.PersistenceBroker}
 39  
  * instances [abbr. PB]. Each pooled PB instance (the implementation class was specified
 40  
  * in OJB configuration file) is wrapped by {@link PoolablePersistenceBroker} class
 41  
  * before add to pool.
 42  
  * </p>
 43  
  * <p>
 44  
  * When calling {@link #createPersistenceBroker} or {@link #defaultPersistenceBroker} the pooled-PB
 45  
  * instance (<tt>PoolablePersistenceBroker</tt>) on its part was wrapped with {@link PersistenceBrokerHandle}
 46  
  * handle.
 47  
  * </p>
 48  
  * <p>
 49  
  * When a client do a PB.close() call on the handle the wrapped <tt>PoolablePersistenceBroker</tt> will
 50  
  * be closed and returned to pool. All further method calls on the handle
 51  
  * (except <tt>PB.isClosed()</tt> and <tt>PB.isInTransaction()</tt>) result in an exception.
 52  
  * </p>
 53  
  * Each different {@link org.apache.ojb.broker.PBKey} (based on <code>PBKey.equals(...)</code> method)
 54  
  * get its own PB-pool.
 55  
  *
 56  
  * @see PersistenceBrokerFactoryBaseImpl
 57  
  *
 58  
  * @author <a href="mailto:thma@apache.org">Thomas Mahler<a>
 59  
  * @author <a href="mailto:armin@codeAuLait.de">Armin Waibel</a>
 60  
  * @version $Id: PersistenceBrokerFactoryDefaultImpl.java,v 1.1 2007-08-24 22:17:35 ewestfal Exp $
 61  
  */
 62  
 public class PersistenceBrokerFactoryDefaultImpl extends PersistenceBrokerFactoryBaseImpl
 63  
 {
 64  
     private static Logger log = LoggerFactory.getLogger(PersistenceBrokerFactoryDefaultImpl.class);
 65  
     private GenericKeyedObjectPool brokerPool;
 66  
     private PBPoolInfo poolConfig;
 67  
 
 68  
     public PersistenceBrokerFactoryDefaultImpl()
 69  
     {
 70  
         super();
 71  
         // get PB-pool configuration properties from OJB.properties
 72  
         poolConfig = new PBPoolInfo();
 73  
         // setup pool for PB instances
 74  
         brokerPool = this.createPool();
 75  
         log.info("Create PersistenceBroker instance pool, pool configuration was " + getPoolConfiguration());
 76  
     }
 77  
 
 78  
     /**
 79  
      * Return broker instance from pool. If given {@link PBKey} was not found in pool
 80  
      * a new pool for given
 81  
      * @param pbKey
 82  
      * @return
 83  
      * @throws PBFactoryException
 84  
      */
 85  
     public PersistenceBrokerInternal createPersistenceBroker(PBKey pbKey) throws PBFactoryException
 86  
     {
 87  
         if (log.isDebugEnabled()) log.debug("Obtain broker from pool, used PBKey is " + pbKey);
 88  
         PersistenceBrokerInternal broker = null;
 89  
 
 90  
         /*
 91  
         try to find a valid PBKey, if given key does not full match
 92  
         */
 93  
         pbKey = BrokerHelper.crossCheckPBKey(pbKey);
 94  
 
 95  
         try
 96  
         {
 97  
             /*
 98  
             get a pooled PB instance, the pool is reponsible to create new
 99  
             PB instances if not found in pool
 100  
             */
 101  
             broker = ((PersistenceBrokerInternal) brokerPool.borrowObject(pbKey));
 102  
             /*
 103  
             now warp pooled PB instance with a handle to avoid PB corruption
 104  
             of closed PB instances.
 105  
             */
 106  
             broker = wrapRequestedBrokerInstance(broker);
 107  
 
 108  
         }
 109  
         catch (Exception e)
 110  
         {
 111  
             try
 112  
             {
 113  
                 // if something going wrong, tryto close broker
 114  
                 if(broker != null) broker.close();
 115  
             }
 116  
             catch (Exception ignore)
 117  
             {
 118  
                 //ignore it
 119  
             }
 120  
             throw new PBFactoryException("Borrow broker from pool failed, using PBKey " + pbKey, e);
 121  
         }
 122  
         return broker;
 123  
     }
 124  
 
 125  
     /**
 126  
      * Each real pooled {@link PersistenceBroker} instance was wrapped by a
 127  
      * pooling handle when a new instance was created.
 128  
      *
 129  
      * @see PoolablePersistenceBroker
 130  
      * @param broker real {@link PersistenceBroker} instance
 131  
      * @param pool use {@link KeyedObjectPool}
 132  
      * @return wrapped broker instance
 133  
      */
 134  
     protected PersistenceBrokerInternal wrapBrokerWithPoolingHandle(PersistenceBrokerInternal broker, KeyedObjectPool pool)
 135  
     {
 136  
         return new PoolablePersistenceBroker(broker, pool);
 137  
     }
 138  
 
 139  
     /**
 140  
      * Wraps the requested pooled broker instance. The returned handle
 141  
      * warps a pooled broker instance to avoid corruption
 142  
      * of already closed broker instances.
 143  
      *
 144  
      * @see PersistenceBrokerHandle
 145  
      * @param broker
 146  
      * @return The broker handle.
 147  
      */
 148  
     protected PersistenceBrokerInternal wrapRequestedBrokerInstance(PersistenceBrokerInternal broker)
 149  
     {
 150  
         return new PersistenceBrokerHandle(broker);
 151  
     }
 152  
 
 153  
     /**
 154  
      * @see PersistenceBrokerFactoryIF#releaseAllInstances()
 155  
      */
 156  
     public synchronized void releaseAllInstances()
 157  
     {
 158  
         log.warn("Release all instances referenced by this object");
 159  
         super.releaseAllInstances();
 160  
         try
 161  
         {
 162  
             brokerPool.close();
 163  
             brokerPool = this.createPool();
 164  
         }
 165  
         catch (Exception e)
 166  
         {
 167  
             log.error("Error while release all pooled broker instances and refresh pool", e);
 168  
         }
 169  
     }
 170  
 
 171  
     public void shutdown()
 172  
     {
 173  
         try
 174  
         {
 175  
             brokerPool.close();
 176  
             brokerPool = null;
 177  
         }
 178  
         catch(Exception e)
 179  
         {
 180  
             log.error("Error while shutdown of broker pool", e);
 181  
         }
 182  
         super.shutdown();
 183  
     }
 184  
 
 185  
     public int activePersistenceBroker()
 186  
     {
 187  
         return brokerPool.getNumActive();
 188  
     }
 189  
 
 190  
     /**
 191  
      * could be used for monitoring
 192  
      * TODO: is this useful?
 193  
      */
 194  
     public Properties getPoolConfiguration()
 195  
     {
 196  
         return poolConfig;
 197  
     }
 198  
 
 199  
     /**
 200  
      * could be used for runtime configuration
 201  
      * TODO: is this useful?
 202  
      */
 203  
     public void setPoolConfiguration(Properties prop)
 204  
     {
 205  
         poolConfig = new PBPoolInfo(prop);
 206  
         log.info("Change pooling configuration properties: " + poolConfig.getKeyedObjectPoolConfig());
 207  
         brokerPool.setConfig(poolConfig.getKeyedObjectPoolConfig());
 208  
     }
 209  
 
 210  
 
 211  
     /**
 212  
      * Create the {@link org.apache.commons.pool.KeyedObjectPool}, pooling
 213  
      * the {@link PersistenceBroker} instances - override this method to
 214  
      * implement your own pool and {@link org.apache.commons.pool.KeyedPoolableObjectFactory}.
 215  
      */
 216  
     private GenericKeyedObjectPool createPool()
 217  
     {
 218  
         GenericKeyedObjectPool.Config conf = poolConfig.getKeyedObjectPoolConfig();
 219  
         if (log.isDebugEnabled())
 220  
             log.debug("PersistenceBroker pool will be setup with the following configuration " +
 221  
                     ToStringBuilder.reflectionToString(conf, ToStringStyle.MULTI_LINE_STYLE));
 222  
         GenericKeyedObjectPool pool = new GenericKeyedObjectPool(null, conf);
 223  
         pool.setFactory(new PersistenceBrokerFactoryDefaultImpl.PBKeyedPoolableObjectFactory(this, pool));
 224  
         return pool;
 225  
     }
 226  
 
 227  
 //**************************************************************************************
 228  
 // Inner classes
 229  
 //**************************************************************************************
 230  
 //
 231  
 
 232  
     /**
 233  
      * This is a {@link org.apache.commons.pool.KeyedPoolableObjectFactory} implementation,
 234  
      * manage the life-cycle of {@link PersistenceBroker} instances
 235  
      * hold in an {@link org.apache.commons.pool.KeyedObjectPool}.
 236  
      *
 237  
      * @author <a href="mailto:armin@codeAuLait.de">Armin Waibel</a>
 238  
      */
 239  
     class PBKeyedPoolableObjectFactory implements KeyedPoolableObjectFactory
 240  
     {
 241  
         private PersistenceBrokerFactoryDefaultImpl pbf;
 242  
         private KeyedObjectPool pool;
 243  
 
 244  
         public PBKeyedPoolableObjectFactory(PersistenceBrokerFactoryDefaultImpl pbf, KeyedObjectPool pool)
 245  
         {
 246  
             this.pbf = pbf;
 247  
             this.pool = pool;
 248  
         }
 249  
 
 250  
         public Object makeObject(Object key) throws Exception
 251  
         {
 252  
             return wrapBrokerWithPoolingHandle(pbf.createNewBrokerInstance((PBKey) key), pool);
 253  
         }
 254  
 
 255  
         /**
 256  
          * Do all cleanup stuff here.
 257  
          */
 258  
         public void destroyObject(Object key, Object obj) throws Exception
 259  
         {
 260  
             PoolablePersistenceBroker pb = (PoolablePersistenceBroker) obj;
 261  
             PersistenceBroker broker = pb.getInnermostDelegate();
 262  
             if (broker instanceof PersistenceBrokerImpl)
 263  
             {
 264  
                 log.info("Destroy PersistenceBroker instance " + obj);
 265  
                 ((PersistenceBrokerImpl) broker).destroy();
 266  
             }
 267  
             pb.destroy();
 268  
         }
 269  
 
 270  
         /**
 271  
          * Check if the given PersistenceBroker instance
 272  
          * was already in transaction.
 273  
          * Was called when
 274  
          * {@link PBPoolInfo#init}
 275  
          * method does set <code>testOnBorrow(true)</code>.
 276  
          * (Default was false, thus this method wasn't called)
 277  
          * See documentation jakarta-connons-pool api.
 278  
          */
 279  
         public boolean validateObject(Object key, Object obj)
 280  
         {
 281  
             // here we could validate the PB instance
 282  
             // if corresponding configuration properties are set
 283  
             if (((PersistenceBroker) obj).isInTransaction())
 284  
             {
 285  
                 log.error("Illegal broker state! This broker instance was already in transaction.");
 286  
                 return false;
 287  
             }
 288  
             return true;
 289  
         }
 290  
 
 291  
         /**
 292  
          * Called before borrow object from pool.
 293  
          */
 294  
         public void activateObject(Object key, Object obj) throws Exception
 295  
         {
 296  
             ((PBState) obj).setClosed(false);
 297  
         }
 298  
 
 299  
         /**
 300  
          * Called before return object to pool.
 301  
          */
 302  
         public void passivateObject(Object key, Object obj) throws Exception
 303  
         {
 304  
             ((PBState) obj).setClosed(true);
 305  
         }
 306  
     }
 307  
 }