Coverage Report - org.apache.ojb.broker.cache.MaterializationCache
 
Classes in this File Line Coverage Branch Coverage Complexity
MaterializationCache
N/A
N/A
1.875
MaterializationCache$ObjectEntry
N/A
N/A
1.875
 
 1  
 package org.apache.ojb.broker.cache;
 2  
 
 3  
 /* Copyright 2004-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.HashMap;
 19  
 import java.util.Iterator;
 20  
 import java.util.Map;
 21  
 
 22  
 import org.apache.ojb.broker.Identity;
 23  
 import org.apache.ojb.broker.util.logging.Logger;
 24  
 import org.apache.ojb.broker.util.logging.LoggerFactory;
 25  
 
 26  
 /**
 27  
  * A wrapper class for {@link ObjectCache} implementations used to materialize object graphs and
 28  
  * push the fully materialized object to the real object cache.
 29  
  * To avoid passing of partial materialized objects to cache this class act as a temporary storage
 30  
  * for unmaterialized (new read or refreshed) objects.
 31  
  *
 32  
  * @author <a href="mailto:arminw@apache.org">Armin Waibel</a>
 33  
  * @version $Id: MaterializationCache.java,v 1.1 2007-08-24 22:17:29 ewestfal Exp $
 34  
  */
 35  
 public class MaterializationCache implements ObjectCacheInternal
 36  
 {
 37  
     private static Logger log = LoggerFactory.getLogger(MaterializationCache.class);
 38  
 
 39  
     private CacheDistributor cacheDistributor;
 40  
     private HashMap objectBuffer;
 41  
     private boolean enabledReadCache;
 42  
     private int invokeCounter;
 43  
 
 44  
     MaterializationCache(CacheDistributor cache)
 45  
     {
 46  
         this.cacheDistributor = cache;
 47  
         this.objectBuffer = new HashMap();
 48  
         enabledReadCache = false;
 49  
     }
 50  
 
 51  
     /**
 52  
      * Returns <em>true</em> if the materialisation cache is enabled, otherwise <em>false</em>.
 53  
      */
 54  
     public boolean isEnabledMaterialisationCache()
 55  
     {
 56  
         return enabledReadCache;
 57  
     }
 58  
 
 59  
     /**
 60  
      * For internal use only! Helper method to guarantee that only full materialized objects
 61  
      * will be pushed to the application cache regardless if an local PB transaction
 62  
      * is running or not. When a complex object is materialized there will be
 63  
      * nested calls to the same PB instance methods, e.g. materialization of a referenced
 64  
      * object which itself have several references, ...
 65  
      * <br/>
 66  
      * This method and {@link #disableMaterializationCache()} are used to delimit nested calls
 67  
      * and to detect the end of an object materialization and avoid endless loops on circular
 68  
      * references.
 69  
      * <br/>
 70  
      * If an code block with 'enabledMaterializationCache' throws an exception, in catch-block
 71  
      * method {@link #doLocalClear()} have to be called.
 72  
      */
 73  
     public void enableMaterializationCache()
 74  
     {
 75  
         ++invokeCounter;
 76  
         enabledReadCache = true;
 77  
     }
 78  
 
 79  
     /**
 80  
      * @see #enableMaterializationCache()
 81  
      */
 82  
     public void disableMaterializationCache()
 83  
     {
 84  
         if(!enabledReadCache) return;
 85  
 
 86  
         --invokeCounter;
 87  
         /*
 88  
         if materialization of the requested object was completed, the
 89  
         counter represents '0' and we push the object
 90  
         to the application cache
 91  
         */
 92  
         if(invokeCounter == 0)
 93  
         {
 94  
             try
 95  
             {
 96  
                 if(log.isDebugEnabled())
 97  
                 {
 98  
                     log.debug("Materialisation of object is finished, push "
 99  
                             + objectBuffer.size() + "objects to cache");
 100  
                 }
 101  
                 pushObjects();
 102  
             }
 103  
             finally
 104  
             {
 105  
                 doLocalClear();
 106  
             }
 107  
         }
 108  
     }
 109  
 
 110  
     public void doInternalCache(Identity oid, Object obj, int type)
 111  
     {
 112  
         // if OJB try to build an object graph put objects in local cache
 113  
         // else use the application cache
 114  
         if(enabledReadCache)
 115  
         {
 116  
             doLocalCache(oid, obj, type);
 117  
         }
 118  
         else
 119  
         {
 120  
             cacheDistributor.doInternalCache(oid, obj, type);
 121  
         }
 122  
     }
 123  
 
 124  
     public void cache(Identity oid, Object obj)
 125  
     {
 126  
         doInternalCache(oid, obj, TYPE_UNKNOWN);
 127  
     }
 128  
 
 129  
     /**
 130  
      * @see ObjectCacheInternal#cacheIfNew(org.apache.ojb.broker.Identity, Object)
 131  
      */ 
 132  
     public boolean cacheIfNew(Identity oid, Object obj)
 133  
     {
 134  
         boolean result = cacheDistributor.cacheIfNew(oid, obj);
 135  
         if(enabledReadCache)
 136  
         {
 137  
             doLocalCache(oid, obj, TYPE_CACHED_READ);
 138  
         }
 139  
         return result;
 140  
     }
 141  
 
 142  
     public Object lookup(Identity oid)
 143  
     {
 144  
         Object result = null;
 145  
         if(enabledReadCache)
 146  
         {
 147  
             result = doLocalLookup(oid);
 148  
         }
 149  
         if(result == null)
 150  
         {
 151  
             result = cacheDistributor.lookup(oid);
 152  
         }
 153  
         return result;
 154  
     }
 155  
 
 156  
     public Object doLocalLookup(Identity oid)
 157  
     {
 158  
         ObjectEntry entry = (ObjectEntry) objectBuffer.get(oid);
 159  
         return entry != null ? entry.obj : null;
 160  
     }
 161  
 
 162  
     public void remove(Identity oid)
 163  
     {
 164  
         doLocalRemove(oid);
 165  
         cacheDistributor.remove(oid);
 166  
     }
 167  
 
 168  
     public void doLocalRemove(Identity oid)
 169  
     {
 170  
         objectBuffer.remove(oid);
 171  
     }
 172  
 
 173  
     /**
 174  
      * Clears the internal used cache for object materialization.
 175  
      */
 176  
     public void doLocalClear()
 177  
     {
 178  
         if(log.isDebugEnabled()) log.debug("Clear materialization cache");
 179  
         invokeCounter = 0;
 180  
         enabledReadCache = false;
 181  
         objectBuffer.clear();
 182  
     }
 183  
 
 184  
     public void clear()
 185  
     {
 186  
         if(log.isDebugEnabled()) log.debug("Clear used caches");
 187  
         doLocalClear();
 188  
         cacheDistributor.clear();
 189  
     }
 190  
 
 191  
     private void doLocalCache(Identity oid, Object obj, int type)
 192  
     {
 193  
         objectBuffer.put(oid, new ObjectEntry(obj, type));
 194  
     }
 195  
 
 196  
     private void pushObjects()
 197  
     {
 198  
         Iterator it = objectBuffer.entrySet().iterator();
 199  
         Map.Entry entry;
 200  
         ObjectEntry oe;
 201  
         while(it.hasNext())
 202  
         {
 203  
             entry = (Map.Entry) it.next();
 204  
             oe = (ObjectEntry) entry.getValue();
 205  
             /*
 206  
             never push temporary object to a higher level cache
 207  
             */
 208  
             if(oe.type != TYPE_TEMP)
 209  
             {
 210  
                 if(log.isDebugEnabled()) log.debug("Push to cache: " + entry.getKey());
 211  
                 cacheDistributor.doInternalCache((Identity) entry.getKey(), oe.obj, oe.type);
 212  
             }
 213  
         }
 214  
     }
 215  
 
 216  
     //===========================================================
 217  
     // inner class
 218  
     //===========================================================
 219  
 
 220  
     static final class ObjectEntry
 221  
     {
 222  
         Object obj;
 223  
         int type;
 224  
 
 225  
         public ObjectEntry(Object obj, int type)
 226  
         {
 227  
             this.obj = obj;
 228  
             this.type = type;
 229  
         }
 230  
     }
 231  
 }