Coverage Report - org.apache.ojb.broker.core.PersistenceBrokerAbstractImpl
 
Classes in this File Line Coverage Branch Coverage Complexity
PersistenceBrokerAbstractImpl
N/A
N/A
4.143
 
 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.Collections;
 19  
 import java.util.List;
 20  
 
 21  
 import org.apache.ojb.broker.PBLifeCycleEvent;
 22  
 import org.apache.ojb.broker.PBLifeCycleListener;
 23  
 import org.apache.ojb.broker.PBListener;
 24  
 import org.apache.ojb.broker.PBStateEvent;
 25  
 import org.apache.ojb.broker.PBStateListener;
 26  
 import org.apache.ojb.broker.PersistenceBrokerEvent;
 27  
 import org.apache.ojb.broker.PersistenceBrokerException;
 28  
 import org.apache.ojb.broker.PersistenceBrokerInternal;
 29  
 import org.apache.ojb.broker.util.IdentityArrayList;
 30  
 import org.apache.ojb.broker.util.configuration.Configuration;
 31  
 import org.apache.ojb.broker.util.configuration.ConfigurationException;
 32  
 import org.apache.ojb.broker.util.logging.LoggerFactory;
 33  
 
 34  
 /**
 35  
  * Abstract Implementation of the {@link org.apache.ojb.broker.PersistenceBroker}
 36  
  * encapsulating the used PB-event/listener concept.
 37  
  *
 38  
  * @see org.apache.ojb.broker.PersistenceBroker
 39  
  * @see org.apache.ojb.broker.PBLifeCycleListener
 40  
  * @see org.apache.ojb.broker.PersistenceBrokerAware
 41  
  * @see org.apache.ojb.broker.PBStateListener
 42  
  *
 43  
  * @version $Id: PersistenceBrokerAbstractImpl.java,v 1.1 2007-08-24 22:17:35 ewestfal Exp $
 44  
  */
 45  
 public abstract class PersistenceBrokerAbstractImpl implements PersistenceBrokerInternal
 46  
 {
 47  
     /**
 48  
      * Returns <em>true</em> if PB-transaction check is enabled.
 49  
      */
 50  
     private boolean txCheck;
 51  
 
 52  
     /**
 53  
      * List containing all permanent {@link org.apache.ojb.broker.PBStateListener}
 54  
      * instances.
 55  
      */
 56  
     private List permanentStateListeners = Collections.synchronizedList(new IdentityArrayList());
 57  
 
 58  
     /**
 59  
      * List containing all temporary {@link org.apache.ojb.broker.PBStateListener}
 60  
      * instances.
 61  
      */
 62  
     private List temporaryStateListeners = Collections.synchronizedList(new IdentityArrayList());
 63  
 
 64  
     /**
 65  
      * List containing all permanent {@link org.apache.ojb.broker.PBLifeCycleListener}
 66  
      * instances.
 67  
      */
 68  
     private List permanentLifeCycleListeners = Collections.synchronizedList(new IdentityArrayList(100));
 69  
 
 70  
     /**
 71  
      * List containing all temporary {@link org.apache.ojb.broker.PBLifeCycleListener}
 72  
      * instances.
 73  
      */
 74  
     private List temporaryLifeCycleListeners = Collections.synchronizedList(new IdentityArrayList(100));
 75  
 
 76  
     /**
 77  
      * Override if needed.
 78  
      *
 79  
      * @see org.apache.ojb.broker.util.configuration.Configurable#configure(Configuration)
 80  
      */
 81  
     public void configure(Configuration pConfig) throws ConfigurationException
 82  
     {
 83  
         txCheck = pConfig.getBoolean("TxCheck", false);
 84  
     }
 85  
 
 86  
     /**
 87  
      * Returns <em>true</em> if the development checks are enabled.
 88  
      *
 89  
      * @see #setTxCheck(boolean)
 90  
      */
 91  
     public boolean isTxCheck()
 92  
     {
 93  
         return txCheck;
 94  
     }
 95  
 
 96  
     /**
 97  
      * This setting can be helpful during development if the PersistenceBroker transaction
 98  
      * demarcation was used (this is true in most cases). If set 'true' on PB#store(...)
 99  
      * and PB#delete(...) methods calls OJB check for active PB-tx and if no active tx is
 100  
      * found a error is logged. This can help to avoid store/delete calls without a running
 101  
      * PB-tx while development. Default setting is 'false'.
 102  
      * <p/>
 103  
      * <strong>Note:</strong> When using OJB in a managed
 104  
      * environment <em>without</em> OJB-caching, it's valid to use store/delete
 105  
      * calls without a running PB-tx.
 106  
      *
 107  
      * @param txCheck Set <em>true</em> to enable the checks
 108  
      */
 109  
     public void setTxCheck(boolean txCheck)
 110  
     {
 111  
         this.txCheck = txCheck;
 112  
     }
 113  
 
 114  
     /**
 115  
      * @see org.apache.ojb.broker.PersistenceBroker#addListener(PBListener listener)
 116  
      */
 117  
     public void addListener(PBListener listener) throws PersistenceBrokerException
 118  
     {
 119  
         addListener(listener, false);
 120  
     }
 121  
 
 122  
     /**
 123  
      * @see org.apache.ojb.broker.PersistenceBroker#addListener(PBListener listener, boolean permanent)
 124  
      */
 125  
     public void addListener(PBListener listener, boolean permanent) throws PersistenceBrokerException
 126  
     {
 127  
         if (listener instanceof PBStateListener)
 128  
         {
 129  
             if (permanent)
 130  
             {
 131  
                 if (!permanentStateListeners.contains(listener))
 132  
                 {
 133  
                     permanentStateListeners.add(listener);
 134  
                 }
 135  
             }
 136  
             else
 137  
             {
 138  
                 if (!temporaryStateListeners.contains(listener))
 139  
                 {
 140  
                     temporaryStateListeners.add(listener);
 141  
                 }
 142  
             }
 143  
         }
 144  
 
 145  
         if (listener instanceof PBLifeCycleListener)
 146  
         {
 147  
             if (permanent)
 148  
             {
 149  
                 if (!permanentLifeCycleListeners.contains(listener))
 150  
                 {
 151  
                     permanentLifeCycleListeners.add(listener);
 152  
                 }
 153  
             }
 154  
             else
 155  
             {
 156  
                 if (!temporaryLifeCycleListeners.contains(listener))
 157  
                 {
 158  
                     temporaryLifeCycleListeners.add(listener);
 159  
                 }
 160  
             }
 161  
         }
 162  
     }
 163  
 
 164  
     /**
 165  
      * @see org.apache.ojb.broker.PersistenceBroker#removeListener(PBListener listener)
 166  
      */
 167  
     public void removeListener(PBListener listener) throws PersistenceBrokerException
 168  
     {
 169  
         if (listener instanceof PBStateListener)
 170  
         {
 171  
             permanentStateListeners.remove(listener);
 172  
             temporaryStateListeners.remove(listener);
 173  
         }
 174  
 
 175  
         if (listener instanceof PBLifeCycleListener)
 176  
         {
 177  
             permanentLifeCycleListeners.remove(listener);
 178  
             temporaryLifeCycleListeners.remove(listener);
 179  
         }
 180  
     }
 181  
 
 182  
     /**
 183  
      * @see org.apache.ojb.broker.PersistenceBroker#removeAllListeners(boolean)
 184  
      */
 185  
     public void removeAllListeners(boolean permanent) throws PersistenceBrokerException
 186  
     {
 187  
         if (permanent)
 188  
         {
 189  
             // remove permanent listeners as well
 190  
             permanentStateListeners.clear();
 191  
             // this could be huge, thus simply replace instance
 192  
             if(permanentLifeCycleListeners.size() > 10000)
 193  
             {
 194  
                 permanentLifeCycleListeners = Collections.synchronizedList(new IdentityArrayList(100));
 195  
             }
 196  
             else
 197  
             {
 198  
                 permanentLifeCycleListeners.clear();
 199  
             }
 200  
         }
 201  
 
 202  
         temporaryStateListeners.clear();
 203  
         // this could be huge, thus simply replace instance
 204  
         if(temporaryLifeCycleListeners.size() > 10000)
 205  
         {
 206  
             temporaryLifeCycleListeners = Collections.synchronizedList(new IdentityArrayList(100));
 207  
         }
 208  
         else
 209  
         {
 210  
             temporaryLifeCycleListeners.clear();
 211  
         }
 212  
     }
 213  
 
 214  
     /**
 215  
      * @see org.apache.ojb.broker.PersistenceBroker#removeAllListeners()
 216  
      */
 217  
     public void removeAllListeners() throws PersistenceBrokerException
 218  
     {
 219  
         removeAllListeners(false);
 220  
     }
 221  
 
 222  
     public void fireBrokerEvent(PersistenceBrokerEvent event)
 223  
     {
 224  
         if (event instanceof PBLifeCycleEvent)
 225  
         {
 226  
             fireBrokerEvent((PBLifeCycleEvent) event);
 227  
         }
 228  
         else if (event instanceof PBStateEvent)
 229  
         {
 230  
             fireBrokerEvent((PBStateEvent) event);
 231  
         }
 232  
         else
 233  
         {
 234  
             LoggerFactory.getDefaultLogger().error(
 235  
                     PersistenceBrokerAbstractImpl.class.getName() + ": Unkown PersistenceBrokerEvent was fired " + event);
 236  
         }
 237  
     }
 238  
 
 239  
     public void fireBrokerEvent(PBLifeCycleEvent event)
 240  
     {
 241  
         if (event.getPersitenceBrokerAware() != null)
 242  
         {
 243  
             // first we do the persistent object callback
 244  
             performCallBack(event);
 245  
         }
 246  
 
 247  
         // now we notify the listeners
 248  
         synchronized (permanentLifeCycleListeners) {
 249  
                 for (int i = permanentLifeCycleListeners.size() - 1; i >= 0; i--)
 250  
                 {
 251  
                     notifiyObjectLifeCycleListener((PBLifeCycleListener) permanentLifeCycleListeners.get(i), event);
 252  
                 }
 253  
                 }
 254  
 
 255  
                 synchronized (temporaryLifeCycleListeners) {
 256  
                 for(int i = temporaryLifeCycleListeners.size() - 1; i >= 0; i--)
 257  
                 {
 258  
                     notifiyObjectLifeCycleListener((PBLifeCycleListener) temporaryLifeCycleListeners.get(i), event);
 259  
                         }
 260  
         }
 261  
     }
 262  
 
 263  
     public void fireBrokerEvent(PBStateEvent event)
 264  
     {
 265  
                 synchronized (permanentStateListeners) {
 266  
                 for(int i = permanentStateListeners.size() - 1; i >= 0; i--)
 267  
                 {
 268  
                     notifiyStateListener((PBStateListener) permanentStateListeners.get(i), event);
 269  
                 }
 270  
                 }
 271  
 
 272  
                 synchronized (temporaryStateListeners) {
 273  
                 for(int i = temporaryStateListeners.size() - 1; i >= 0; i--)
 274  
                 {
 275  
                     notifiyStateListener((PBStateListener) temporaryStateListeners.get(i), event);
 276  
                 }
 277  
                 }
 278  
     }
 279  
 
 280  
     private void performCallBack(PBLifeCycleEvent event)
 281  
     {
 282  
         // Check for null
 283  
         if (event.getPersitenceBrokerAware() == null) return;
 284  
         switch (event.getEventType().typeId())
 285  
         {
 286  
             case PBLifeCycleEvent.TYPE_AFTER_LOOKUP:
 287  
                 event.getPersitenceBrokerAware().afterLookup(event.getTriggeringBroker());
 288  
                 break;
 289  
             case PBLifeCycleEvent.TYPE_BEFORE_UPDATE:
 290  
                 event.getPersitenceBrokerAware().beforeUpdate(event.getTriggeringBroker());
 291  
                 break;
 292  
             case PBLifeCycleEvent.TYPE_AFTER_UPDATE:
 293  
                 event.getPersitenceBrokerAware().afterUpdate(event.getTriggeringBroker());
 294  
                 break;
 295  
             case PBLifeCycleEvent.TYPE_BEFORE_INSERT:
 296  
                 event.getPersitenceBrokerAware().beforeInsert(event.getTriggeringBroker());
 297  
                 break;
 298  
             case PBLifeCycleEvent.TYPE_AFTER_INSERT:
 299  
                 event.getPersitenceBrokerAware().afterInsert(event.getTriggeringBroker());
 300  
                 break;
 301  
             case PBLifeCycleEvent.TYPE_BEFORE_DELETE:
 302  
                 event.getPersitenceBrokerAware().beforeDelete(event.getTriggeringBroker());
 303  
                 break;
 304  
             case PBLifeCycleEvent.TYPE_AFTER_DELETE:
 305  
                 event.getPersitenceBrokerAware().afterDelete(event.getTriggeringBroker());
 306  
                 break;
 307  
         }
 308  
     }
 309  
 
 310  
     private void notifiyStateListener(PBStateListener listener, PBStateEvent stateEvent)
 311  
     {
 312  
         switch (stateEvent.getEventType().typeId())
 313  
         {
 314  
             case PBStateEvent.KEY_BEFORE_COMMIT:
 315  
                 listener.beforeCommit(stateEvent);
 316  
                 break;
 317  
             case PBStateEvent.KEY_AFTER_COMMIT:
 318  
                 listener.afterCommit(stateEvent);
 319  
                 break;
 320  
             case PBStateEvent.KEY_BEFORE_BEGIN:
 321  
                 listener.beforeBegin(stateEvent);
 322  
                 break;
 323  
             case PBStateEvent.KEY_AFTER_BEGIN:
 324  
                 listener.afterBegin(stateEvent);
 325  
                 break;
 326  
             case PBStateEvent.KEY_BEFORE_CLOSE:
 327  
                 listener.beforeClose(stateEvent);
 328  
                 break;
 329  
             case PBStateEvent.KEY_AFTER_OPEN:
 330  
                 listener.afterOpen(stateEvent);
 331  
                 break;
 332  
             case PBStateEvent.KEY_AFTER_ROLLBACK:
 333  
                 listener.afterRollback(stateEvent);
 334  
                 break;
 335  
             case PBStateEvent.KEY_BEFORE_ROLLBACK:
 336  
                 listener.beforeRollback(stateEvent);
 337  
                 break;
 338  
         }
 339  
     }
 340  
 
 341  
     private void notifiyObjectLifeCycleListener(PBLifeCycleListener listener, PBLifeCycleEvent lifeEvent)
 342  
     {
 343  
         switch (lifeEvent.getEventType().typeId())
 344  
         {
 345  
             case PBLifeCycleEvent.TYPE_AFTER_LOOKUP:
 346  
                 listener.afterLookup(lifeEvent);
 347  
                 break;
 348  
             case PBLifeCycleEvent.TYPE_BEFORE_UPDATE:
 349  
                 listener.beforeUpdate(lifeEvent);
 350  
                 break;
 351  
             case PBLifeCycleEvent.TYPE_AFTER_UPDATE:
 352  
                 listener.afterUpdate(lifeEvent);
 353  
                 break;
 354  
             case PBLifeCycleEvent.TYPE_BEFORE_INSERT:
 355  
                 listener.beforeInsert(lifeEvent);
 356  
                 break;
 357  
             case PBLifeCycleEvent.TYPE_AFTER_INSERT:
 358  
                 listener.afterInsert(lifeEvent);
 359  
                 break;
 360  
             case PBLifeCycleEvent.TYPE_BEFORE_DELETE:
 361  
                 listener.beforeDelete(lifeEvent);
 362  
                 break;
 363  
             case PBLifeCycleEvent.TYPE_AFTER_DELETE:
 364  
                 listener.afterDelete(lifeEvent);
 365  
                 break;
 366  
         }
 367  
     }
 368  
 
 369  
     /*
 370  
     arminw:
 371  
     get the PB state event here, this helps to
 372  
     avoid object instantiation for any event call
 373  
     */
 374  
     protected final PBStateEvent AFTER_OPEN_EVENT = new PBStateEvent(this, PBStateEvent.Type.AFTER_OPEN);
 375  
     protected final PBStateEvent AFTER_BEGIN_EVENT = new PBStateEvent(this, PBStateEvent.Type.AFTER_BEGIN);
 376  
     protected final PBStateEvent AFTER_COMMIT_EVENT = new PBStateEvent(this, PBStateEvent.Type.AFTER_COMMIT);
 377  
     protected final PBStateEvent AFTER_ROLLBACK_EVENT = new PBStateEvent(this, PBStateEvent.Type.AFTER_ROLLBACK);
 378  
     protected final PBStateEvent BEFORE_BEGIN_EVENT = new PBStateEvent(this, PBStateEvent.Type.BEFORE_BEGIN);
 379  
     protected final PBStateEvent BEFORE_COMMIT_EVENT = new PBStateEvent(this, PBStateEvent.Type.BEFORE_COMMIT);
 380  
     protected final PBStateEvent BEFORE_ROLLBACK_EVENT = new PBStateEvent(this, PBStateEvent.Type.BEFORE_ROLLBACK);
 381  
     protected final PBStateEvent BEFORE_CLOSE_EVENT = new PBStateEvent(this, PBStateEvent.Type.BEFORE_CLOSE);
 382  
 
 383  
     /*
 384  
     arminw:
 385  
     here we could get the PB state event, this helps to
 386  
     avoid object instantiation on every event
 387  
     NOTE: It's a little critical, because caller shouldn't forget
 388  
     to set the target object using #setTargetObject(...) method.
 389  
     This means that we use the same event object with changed
 390  
     fields.
 391  
     TODO: find a better solution (and performant)
 392  
     */
 393  
     protected PBLifeCycleEvent BEFORE_STORE_EVENT =
 394  
             new PBLifeCycleEvent(this, PBLifeCycleEvent.Type.BEFORE_INSERT);
 395  
     protected PBLifeCycleEvent AFTER_STORE_EVENT =
 396  
             new PBLifeCycleEvent(this, PBLifeCycleEvent.Type.AFTER_INSERT);
 397  
     protected PBLifeCycleEvent BEFORE_DELETE_EVENT =
 398  
             new PBLifeCycleEvent(this, PBLifeCycleEvent.Type.BEFORE_DELETE);
 399  
     protected PBLifeCycleEvent AFTER_DELETE_EVENT =
 400  
             new PBLifeCycleEvent(this, PBLifeCycleEvent.Type.AFTER_DELETE);
 401  
     protected PBLifeCycleEvent AFTER_LOOKUP_EVENT =
 402  
             new PBLifeCycleEvent(this, PBLifeCycleEvent.Type.AFTER_LOOKUP);
 403  
     protected PBLifeCycleEvent BEFORE_UPDATE_EVENT =
 404  
             new PBLifeCycleEvent(this, PBLifeCycleEvent.Type.BEFORE_UPDATE);
 405  
     protected PBLifeCycleEvent AFTER_UPDATE_EVENT =
 406  
             new PBLifeCycleEvent(this, PBLifeCycleEvent.Type.AFTER_UPDATE);
 407  
 }
 408