Clover coverage report -
Coverage timestamp: do jan 22 2004 21:12:32 CET
file stats: LOC: 312   Methods: 16
NCLOC: 113   Classes: 1
 
 Source file Conditionals Statements Methods TOTAL
CacheEntry.java 58,3% 68% 81,2% 67,8%
coverage coverage
 1   
 /*
 2   
  * Copyright (c) 2002-2003 by OpenSymphony
 3   
  * All rights reserved.
 4   
  */
 5   
 package com.opensymphony.oscache.base;
 6   
 
 7   
 import com.opensymphony.oscache.web.filter.ResponseContent;
 8   
 
 9   
 import java.io.Serializable;
 10   
 
 11   
 import java.util.Collection;
 12   
 import java.util.HashSet;
 13   
 import java.util.Set;
 14   
 
 15   
 /**
 16   
  * A CacheEntry instance represents one entry in the cache. It holds the object that
 17   
  * is being cached, along with a host of information about that entry such as the
 18   
  * cache key, the time it was cached, whether the entry has been flushed or not and
 19   
  * the groups it belongs to.
 20   
  *
 21   
  * @version        $Revision: 1.1 $
 22   
  * @author        <a href="mailto:mike@atlassian.com">Mike Cannon-Brookes</a>
 23   
  * @author        <a href="mailto:tgochenour@peregrine.com">Todd Gochenour</a>
 24   
  * @author <a href="mailto:fbeauregard@pyxis-tech.com">Francois Beauregard</a>
 25   
  */
 26   
 public class CacheEntry implements Serializable {
 27   
     /**
 28   
      * Default initialization value for the creation time and the last
 29   
      * update time. This is a placeholder that indicates the value has
 30   
      * not been set yet.
 31   
      */
 32   
     private static final byte NOT_YET = -1;
 33   
 
 34   
     /**
 35   
      * Specifying this as the refresh period for the
 36   
      * {@link #needsRefresh(int)} method will ensure
 37   
      * an entry does not become stale until it is
 38   
      * either explicitly flushed or a custom refresh
 39   
      * policy causes the entry to expire.
 40   
      */
 41   
     public static final int INDEFINITE_EXPIRY = -1;
 42   
 
 43   
     /**
 44   
      * The entry refresh policy object to use for this cache entry. This is optional.
 45   
      */
 46   
     private EntryRefreshPolicy policy = null;
 47   
 
 48   
     /**
 49   
      * The actual content that is being cached. Wherever possible this object
 50   
      * should be serializable. This allows <code>PersistenceListener</code>s
 51   
      * to serialize the cache entries to disk or database.
 52   
      */
 53   
     private Object content = null;
 54   
 
 55   
     /**
 56   
      * The set of cache groups that this cache entry belongs to, if any.
 57   
      */
 58   
     private Set groups = null;
 59   
 
 60   
     /**
 61   
      *  The unique cache key for this entry
 62   
      */
 63   
     private String key;
 64   
 
 65   
     /**
 66   
      * <code>true</code> if this entry was flushed
 67   
      */
 68   
     private boolean wasFlushed = false;
 69   
 
 70   
     /**
 71   
      * The time this entry was created.
 72   
      */
 73   
     private long created = NOT_YET;
 74   
 
 75   
     /**
 76   
      * The time this emtry was last updated.
 77   
      */
 78   
     private long lastUpdate = NOT_YET;
 79   
 
 80   
     /**
 81   
      * Construct a new CacheEntry using the key provided.
 82   
      *
 83   
      * @param key    The key of this CacheEntry
 84   
      */
 85  21
     public CacheEntry(String key) {
 86  21
         this(key, null);
 87   
     }
 88   
 
 89   
     /**
 90   
      * Construct a CacheEntry.
 91   
      *
 92   
      * @param key      The unique key for this <code>CacheEntry</code>.
 93   
      * @param policy   Object that implements refresh policy logic. This parameter
 94   
      * is optional.
 95   
      */
 96  212
     public CacheEntry(String key, EntryRefreshPolicy policy) {
 97  212
         this(key, policy, null);
 98   
     }
 99   
 
 100   
     /**
 101   
      * Construct a CacheEntry.
 102   
      *
 103   
      * @param key     The unique key for this <code>CacheEntry</code>.
 104   
      * @param policy  The object that implements the refresh policy logic. This
 105   
      * parameter is optional.
 106   
      * @param groups  The groups that this <code>CacheEntry</code> belongs to. This
 107   
      * parameter is optional.
 108   
      */
 109  212
     public CacheEntry(String key, EntryRefreshPolicy policy, String[] groups) {
 110  212
         this.key = key;
 111   
 
 112  212
         if (groups != null) {
 113  0
             this.groups = new HashSet(groups.length);
 114   
 
 115  0
             for (int i = 0; i < groups.length; i++) {
 116  0
                 this.groups.add(groups[i]);
 117   
             }
 118   
         }
 119   
 
 120  212
         this.policy = policy;
 121  212
         this.created = System.currentTimeMillis();
 122   
     }
 123   
 
 124   
     /**
 125   
      * Sets the actual content that is being cached. Wherever possible this
 126   
      * object should be <code>Serializable</code>, however it is not an
 127   
      * absolute requirement when using a memory-only cache. Being <code>Serializable</code>
 128   
      * allows <code>PersistenceListener</code>s to serialize the cache entries to disk
 129   
      * or database.
 130   
      *
 131   
      * @param value The content to store in this CacheEntry.
 132   
      */
 133  213
     public synchronized void setContent(Object value) {
 134  213
         content = value;
 135  213
         lastUpdate = System.currentTimeMillis();
 136  213
         wasFlushed = false;
 137   
     }
 138   
 
 139   
     /**
 140   
      * Get the cached content from this CacheEntry.
 141   
      *
 142   
      * @return The content of this CacheEntry.
 143   
      */
 144  297
     public Object getContent() {
 145  297
         return content;
 146   
     }
 147   
 
 148   
     /**
 149   
      * Get the date this CacheEntry was created.
 150   
      *
 151   
      * @return The date this CacheEntry was created.
 152   
      */
 153  3
     public long getCreated() {
 154  3
         return created;
 155   
     }
 156   
 
 157   
     /**
 158   
      * Sets the cache groups for this entry.
 159   
      *
 160   
      * @param groups A string array containing all the group names
 161   
      */
 162  201
     public synchronized void setGroups(String[] groups) {
 163  201
         if (groups != null) {
 164  54
             this.groups = new HashSet(groups.length);
 165   
 
 166  54
             for (int i = 0; i < groups.length; i++) {
 167  87
                 this.groups.add(groups[i]);
 168   
             }
 169   
         } else {
 170  147
             this.groups = null;
 171   
         }
 172   
 
 173  201
         lastUpdate = System.currentTimeMillis();
 174   
     }
 175   
 
 176   
     /**
 177   
      * Sets the cache groups for this entry
 178   
      *
 179   
      * @param groups A collection containing all the group names
 180   
      */
 181  0
     public void setGroups(Collection groups) {
 182  0
         if (groups != null) {
 183  0
             this.groups = new HashSet(groups);
 184   
         } else {
 185  0
             this.groups = null;
 186   
         }
 187   
 
 188  0
         lastUpdate = System.currentTimeMillis();
 189   
     }
 190   
 
 191   
     /**
 192   
      * Gets the cache groups that this cache entry belongs to.
 193   
      * These returned groups should be treated as immuatable.
 194   
      *
 195   
      * @return A set containing the names of all the groups that
 196   
      * this cache entry belongs to.
 197   
      */
 198  324
     public Set getGroups() {
 199  324
         return groups;
 200   
     }
 201   
 
 202   
     /**
 203   
      * Get the key of this CacheEntry
 204   
      *
 205   
      * @return The key of this CacheEntry
 206   
      */
 207  191
     public String getKey() {
 208  191
         return key;
 209   
     }
 210   
 
 211   
     /**
 212   
      * Set the date this CacheEntry was last updated.
 213   
      *
 214   
      * @param update The time (in milliseconds) this CacheEntry was last updated.
 215   
      */
 216  0
     public void setLastUpdate(long update) {
 217  0
         lastUpdate = update;
 218   
     }
 219   
 
 220   
     /**
 221   
      * Get the date this CacheEntry was last updated.
 222   
      *
 223   
      * @return The date this CacheEntry was last updated.
 224   
      */
 225  3
     public long getLastUpdate() {
 226  3
         return lastUpdate;
 227   
     }
 228   
 
 229   
     /**
 230   
      * Indicates whether this CacheEntry is a freshly created one and
 231   
      * has not yet been assigned content or placed in a cache.
 232   
      *
 233   
      * @return <code>true</code> if this entry is newly created
 234   
      */
 235  360
     public boolean isNew() {
 236  360
         return lastUpdate == NOT_YET;
 237   
     }
 238   
 
 239   
     /**
 240   
      * Get the size of the cache entry in bytes (roughly).<p>
 241   
      *
 242   
      * Currently this method only handles <code>String<code>s and
 243   
      * {@link ResponseContent} objects.
 244   
      *
 245   
      * @return The approximate size of the entry in bytes, or -1 if the
 246   
      * size could not be estimated.
 247   
      */
 248  0
     public int getSize() {
 249   
         // a char is two bytes
 250  0
         int size = (key.length() * 2) + 4;
 251   
 
 252  0
         if (content.getClass() == String.class) {
 253  0
             size += ((content.toString().length() * 2) + 4);
 254  0
         } else if (content instanceof ResponseContent) {
 255  0
             size += ((ResponseContent) content).getSize();
 256   
         } else {
 257  0
             return -1;
 258   
         }
 259   
 
 260   
         //add created, lastUpdate, and wasFlushed field sizes (1, 8, and 8)
 261  0
         return size + 17;
 262   
     }
 263   
 
 264   
     /**
 265   
      * Flush the entry from cache.
 266   
      * note that flushing the cache doesn't actually remove the cache contents
 267   
      * it just tells the CacheEntry that it needs a refresh next time it is asked
 268   
      * this is so that the content is still there for a <usecached />.
 269   
      */
 270  48
     public void flush() {
 271  48
         wasFlushed = true;
 272   
     }
 273   
 
 274   
     /**
 275   
      * Check if this CacheEntry needs to be refreshed.
 276   
      *
 277   
      * @param refreshPeriod The period of refresh (in seconds). Passing in
 278   
      * {@link #INDEFINITE_EXPIRY} will result in the content never becoming
 279   
      * stale unless it is explicitly flushed, or expired by a custom
 280   
      * {@link EntryRefreshPolicy}. Passing in 0 will always result in a
 281   
      * refresh being required.
 282   
      *
 283   
      * @return Whether or not this CacheEntry needs refreshing.
 284   
      */
 285  386
     public boolean needsRefresh(int refreshPeriod) {
 286  386
         boolean needsRefresh;
 287   
 
 288   
         // needs a refresh if it has never been updated
 289  386
         if (lastUpdate == NOT_YET) {
 290  27
             needsRefresh = true;
 291   
         }
 292   
         // Was it flushed from cache?
 293  359
         else if (wasFlushed) {
 294  74
             needsRefresh = true;
 295  285
         } else if (refreshPeriod == 0) {
 296  63
             needsRefresh = true;
 297   
         }
 298   
         // check what the policy has to say if there is one
 299  222
         else if (policy != null) {
 300  6
             needsRefresh = policy.needsRefresh(this);
 301   
         }
 302   
         // check if the last update + update period is in the past
 303  216
         else if ((refreshPeriod >= 0) && (System.currentTimeMillis() >= (lastUpdate + (refreshPeriod * 1000L)))) {
 304  0
             needsRefresh = true;
 305   
         } else {
 306  216
             needsRefresh = false;
 307   
         }
 308   
 
 309  386
         return needsRefresh;
 310   
     }
 311   
 }
 312