Coverage Report - org.apache.ojb.broker.cache.ObjectCacheSoftImpl
 
Classes in this File Line Coverage Branch Coverage Complexity
ObjectCacheSoftImpl
N/A
N/A
2
ObjectCacheSoftImpl$1
N/A
N/A
2
ObjectCacheSoftImpl$SoftHashMap
N/A
N/A
2
ObjectCacheSoftImpl$SoftHashMap$SoftValue
N/A
N/A
2
 
 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.lang.ref.ReferenceQueue;
 19  
 import java.lang.ref.SoftReference;
 20  
 import java.util.HashMap;
 21  
 import java.util.Properties;
 22  
 
 23  
 import org.apache.commons.collections.LRUMap;
 24  
 import org.apache.ojb.broker.Identity;
 25  
 import org.apache.ojb.broker.PersistenceBroker;
 26  
 import org.apache.ojb.broker.util.configuration.Configurable;
 27  
 import org.apache.ojb.broker.util.configuration.Configuration;
 28  
 import org.apache.ojb.broker.util.configuration.ConfigurationException;
 29  
 import org.apache.ojb.broker.util.configuration.impl.OjbConfigurator;
 30  
 
 31  
 /**
 32  
  * A global {@link ObjectCache} implementation.
 33  
  *
 34  
  * @author matthew.baird
 35  
  * @version $Id: ObjectCacheSoftImpl.java,v 1.1 2007-08-24 22:17:29 ewestfal Exp $
 36  
  */
 37  
 public class ObjectCacheSoftImpl implements ObjectCache, Configurable
 38  
 {
 39  
     /**
 40  
      * The static the cache map
 41  
      */
 42  
     private static SoftHashMap cache = null;
 43  
 
 44  
     /**
 45  
      * The size of the cache
 46  
      */
 47  
     private static int size = 10000;
 48  
 
 49  
     /**
 50  
      * Constructor called by ojb
 51  
      *
 52  
      * @param broker     ignored parameter
 53  
      * @param properties ignored parameter
 54  
      */
 55  
     public ObjectCacheSoftImpl(PersistenceBroker broker, Properties properties)
 56  
     {
 57  
         if (cache == null)
 58  
         {
 59  
             OjbConfigurator.getInstance().configure(this);
 60  
             cache = new SoftHashMap(size);
 61  
         }
 62  
     }
 63  
 
 64  
     /**
 65  
      * @see org.apache.ojb.broker.util.configuration.Configurable#configure(org.apache.ojb.broker.util.configuration.Configuration)
 66  
      */
 67  
     public void configure(Configuration configuration) throws ConfigurationException
 68  
     {
 69  
         size = configuration.getInteger("ObjectCacheSoftImpl", size);
 70  
     }
 71  
 
 72  
     /**
 73  
      * @see org.apache.ojb.broker.cache.ObjectCache#cache(org.apache.ojb.broker.Identity, java.lang.Object)
 74  
      */
 75  
     public void cache(Identity oid, Object obj)
 76  
     {
 77  
         synchronized(cache)
 78  
         {
 79  
             cache.put(oid, obj);
 80  
         }
 81  
     }
 82  
 
 83  
     public boolean cacheIfNew(Identity oid, Object obj)
 84  
     {
 85  
         synchronized(cache)
 86  
         {
 87  
             if(cache.get(oid) == null)
 88  
             {
 89  
                 cache.put(oid, obj);
 90  
                 return true;
 91  
             }
 92  
             return false;
 93  
         }
 94  
     }
 95  
 
 96  
     /**
 97  
      * @see org.apache.ojb.broker.cache.ObjectCache#lookup(org.apache.ojb.broker.Identity)
 98  
      */
 99  
     public Object lookup(Identity oid)
 100  
     {
 101  
         return cache.get(oid);
 102  
     }
 103  
 
 104  
     /**
 105  
      * @see org.apache.ojb.broker.cache.ObjectCache#remove(org.apache.ojb.broker.Identity)
 106  
      */
 107  
     public void remove(Identity oid)
 108  
     {
 109  
         synchronized(cache)
 110  
         {
 111  
             cache.remove(oid);
 112  
         }
 113  
     }
 114  
 
 115  
     /**
 116  
      * @see org.apache.ojb.broker.cache.ObjectCache#clear()
 117  
      */
 118  
     public void clear()
 119  
     {
 120  
         cache.clear();
 121  
     }
 122  
 
 123  
     /**
 124  
      * Kind of map using SoftReference to store values
 125  
      */
 126  
     public static final class SoftHashMap
 127  
     {
 128  
         /**
 129  
          * The internal HashMap that will hold the SoftReference.
 130  
          */
 131  
         private HashMap hash;
 132  
         /**
 133  
          * The FIFO list of hard references, order of last access.
 134  
          */
 135  
         private LRUMap hardCacheMap;
 136  
         /**
 137  
          * Reference queue for cleared SoftReference objects.
 138  
          */
 139  
         private ReferenceQueue queue;
 140  
 
 141  
         /**
 142  
          * Construct a new hash map with the specified size
 143  
          *
 144  
          * @param hardSize the maximum capacity of this map
 145  
          */
 146  
         public SoftHashMap(final int hardSize)
 147  
         {
 148  
             hash = new HashMap();
 149  
             hardCacheMap = new LRUMap(hardSize);
 150  
             queue = new ReferenceQueue();
 151  
         }
 152  
 
 153  
         /**
 154  
          * Put the key, value pair into the HashMap using a SoftValue object
 155  
          *
 156  
          * @param key   the key
 157  
          * @param value the value
 158  
          * @return the old value
 159  
          */
 160  
         public Object put(Object key, Object value)
 161  
         {
 162  
             //check null since hashtable doesn't support null key or null value
 163  
             if (key == null || value == null)
 164  
             {
 165  
                 return null;
 166  
             }
 167  
             processQueue(); // throw out garbage collected values first
 168  
             hardCacheMap.put(key, value);
 169  
             return hash.put(key, new SoftValue(value, key, queue));
 170  
         }
 171  
 
 172  
         /**
 173  
          * Retrieve the value associated to a given key
 174  
          *
 175  
          * @param key the key
 176  
          * @return the value associated to this key
 177  
          */
 178  
         public Object get(Object key)
 179  
         {
 180  
             // Check null since Hashtable doesn't support null key or null value
 181  
             if (key == null)
 182  
             {
 183  
                 return null;
 184  
             }
 185  
             Object result = null;
 186  
             // We get the SoftReference represented by that key
 187  
             SoftReference softRef = (SoftReference) hash.get(key);
 188  
             if (softRef != null)
 189  
             {
 190  
                 result = softRef.get();
 191  
                 if (result == null)
 192  
                 {
 193  
                     // If the value has been garbage collected, remove the
 194  
                     // entry from the HashMap.
 195  
                     hash.remove(key);
 196  
                 }
 197  
                 else
 198  
                 {
 199  
                     if (!hardCacheMap.containsKey(key))
 200  
                     {
 201  
                         hardCacheMap.put(key, result);
 202  
                     }
 203  
                     else
 204  
                     {
 205  
                         hardCacheMap.get(key);
 206  
                     }
 207  
                 }
 208  
             }
 209  
             return result;
 210  
         }
 211  
 
 212  
         /**
 213  
          * Remove the entry for this key
 214  
          *
 215  
          * @param key the key
 216  
          * @return the old value
 217  
          */
 218  
         public Object remove(Object key)
 219  
         {
 220  
             processQueue(); // throw out garbage collected values first
 221  
             Object retval = null;
 222  
             Object value = hash.remove(key);
 223  
             if (value != null)
 224  
             {
 225  
                 if (value instanceof SoftValue)
 226  
                 {
 227  
                     retval = ((SoftValue) value).get();
 228  
                 }
 229  
             }
 230  
             return retval;
 231  
         }
 232  
 
 233  
         /**
 234  
          * Clear the map
 235  
          */
 236  
         public void clear()
 237  
         {
 238  
             processQueue();
 239  
             hash.clear();
 240  
             hardCacheMap.clear();
 241  
         }
 242  
 
 243  
         /**
 244  
          * Class derived from SoftReference, used to
 245  
          * store the key of the map.
 246  
          */
 247  
         private class SoftValue extends SoftReference
 248  
         {
 249  
             /**
 250  
              * the key
 251  
              */
 252  
             private final Object key; // always make data member final
 253  
 
 254  
             /**
 255  
              * Create a SoftValue given the object, key and queue
 256  
              *
 257  
              * @param k   the object
 258  
              * @param key the key
 259  
              * @param q   the reference queue
 260  
              */
 261  
             private SoftValue(final Object k, final Object key, final ReferenceQueue q)
 262  
             {
 263  
                 super(k, q);
 264  
                 this.key = key;
 265  
             }
 266  
         }
 267  
 
 268  
         /**
 269  
          * Removes keys and objects that have been garbaged
 270  
          */
 271  
         private void processQueue()
 272  
         {
 273  
             SoftValue sv;
 274  
             while ((sv = (SoftValue) queue.poll()) != null)
 275  
             {
 276  
                 hash.remove(sv.key); // we can access private data!
 277  
             }
 278  
         }
 279  
 
 280  
     }
 281  
 }