Docjar: A Java Source and Docuemnt Enginecom.*    java.*    javax.*    org.*    all    new    plug-in

Quick Search    Search Deep

Source code: javatools/util/Cache.java


1   /*
2       Javatools (modified version) - Some useful general classes.
3       Copyright (C) 2002-2003  Chris Bitmead (original) Antonio Petrelli (modified)
4   
5       This program is free software; you can redistribute it and/or modify
6       it under the terms of the GNU General Public License as published by
7       the Free Software Foundation; either version 2 of the License, or
8       (at your option) any later version.
9   
10      This program is distributed in the hope that it will be useful,
11      but WITHOUT ANY WARRANTY; without even the implied warranty of
12      MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
13      GNU General Public License for more details.
14  
15      You should have received a copy of the GNU General Public License
16      along with this program; if not, write to the Free Software
17      Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
18  
19      Contact me at: brenmcguire@users.sourceforge.net
20   */
21  package javatools.util;
22  import java.util.*;
23  
24  /**
25   * General purpose cache class. Acts basically like a weak reference dictionary
26   * except that it also returns null when asked to find an item whose use-by
27   * date has expired. It works with two main data structures: A Dictionary which
28   * provides fast access into the cache, and a Queue which keeps track of the
29   * least recently used items in the cache so that old items can be removed and
30   * limit the cache to a bounded size.
31   *
32   * Modified: 8th March 2003 11:41
33   *
34   * @author Chris Bitmead (Original) Antonio Petrelli (modified)
35   * @created December 13, 2001
36   * @version 0.1.10
37   * @commentedby Antonio Petrelli
38   */
39  
40  public class Cache {
41    /**
42     *  The fast access dictionary
43     */
44    private Dictionary dictionary;
45  
46    /**
47     *  The lru (least recently used) queue
48     */
49    private JQueue queue;
50  
51    /**
52     *  The maximum number of objects in the cache
53     */
54    private int cacheMaxObj = 100;
55  
56    /**
57     *  The maximum age of items in the cache in milliseconds.
58     */
59    private int cacheMaxAge = -1;
60  
61          /** Creates a new Cache object.
62           */        
63    public Cache() {
64      dictionary = new Hashtable();
65      queue = new JQueue();
66    }
67  
68    /**
69           * Constructor which takes an initial guesstimate of how many items we expect
70           * to store in it
71           *
72           * @param size The initial size.
73           */
74    public Cache(int size) {
75      dictionary = new Hashtable(size);
76      queue = new JQueue(size);
77    }
78  
79    /**
80     *  Set the maximum number of objects to cache.
81     *
82     * @param  n  The new cacheMaxObj value
83     * @n         the number of objects to cache.
84     */
85    public void setCacheMaxObj(int n) {
86      cacheMaxObj = n;
87    }
88  
89    /**
90     *  Change the maximum age of items in the cache. Can be changed at any time.
91     *
92     * @param  s  The new cacheMaxAgeSeconds value
93     * @s         maximum age in seconds
94     */
95    public void setCacheMaxAgeSeconds(int s) {
96      cacheMaxAge = s * 1000;
97    }
98  
99    /**
100    *  Turn off cache expiry based on age
101    */
102   public void setNoCacheMaxAge() {
103     cacheMaxAge = -1;
104   }
105 
106   /**
107          * Get an object from the cache. Returns null if the object is not in the
108          * cache.
109          *
110          * @param key The key to use to retrieve the object
111          * @return The needed value.
112          */
113   public Object get(Object key) {
114     CacheItem result = (CacheItem) dictionary.get(key);
115     Object rtn = null;
116     if (result != null) {
117       Date now = null;
118       Date expiration = null;
119       if (0 <= cacheMaxAge) {
120         now = new Date();
121         expiration = new Date(result.time.getTime() +
122             cacheMaxAge);
123       }
124       if (now == null || expiration.after(now)) {
125         // We just used it, so reset the date.
126         result.time = new Date();
127         // Since we just used this item
128         // put it at the front of the lru queue.
129         queue.remove(result.qkey);
130         result.qkey = queue.put(result);
131         rtn = result.item;
132       } else {
133         // It's out of date. Might as well throw it away.
134         // (It would be removed later anyway when it comes
135         // through the queue, but better to do it now).
136         queue.remove(result.qkey);
137         dictionary.remove(key);
138       }
139     }
140     return rtn;
141   }
142 
143   /**
144          * Put a key value pair into the cache.
145          *
146          * @param key The key
147          * @param item The value
148          */
149   public void put(Object key, Object item) {
150     CacheItem cacheItem = new CacheItem(key, item);
151     cacheItem.setQueueKey(queue.put(cacheItem));
152     dictionary.put(key, cacheItem);
153     if (cacheMaxObj < queue.size()) {
154       // Don't let the cache grow beyond our limit.
155       CacheItem obj = (CacheItem) queue.get();
156       dictionary.remove(obj.key);
157     }
158   }
159 
160   /**
161          * Expire the item in the cache with the given key.
162          *
163          * @param key The key of the object to expire from the cache.
164          */
165   public void expire(Object key) {
166     CacheItem result = (CacheItem) dictionary.get(key);
167     if (result != null) {
168       queue.remove(result.qkey);
169       dictionary.remove(key);
170     }
171   }
172         
173         public void clear() {
174             queue.clear();
175             dictionary = new Hashtable(dictionary.size());
176         }
177 
178   /**
179    *  This is the class we store in our internal data structures.
180    *
181    * @author     Chris
182    * @created    December 13, 2001
183    */
184   class CacheItem {
185     /**
186      *  The time this object was last accessed.
187      */
188     Date time;
189 
190     /**
191      *  The key
192      */
193     Object key;
194 
195     /**
196      *  The value
197      */
198     Object item;
199                 /** The queue to use to check when to remove an object from the cache.
200                  */                
201     JQueue.QueueKey qkey;
202 
203                 /** Adds an item to the cache.
204                  * @param theKey The key of the object.
205                  * @param theItem The item to add.
206                  */                
207     public CacheItem(Object theKey, Object theItem) {
208       key = theKey;
209       item = theItem;
210       time = new Date();
211       // now
212     }
213 
214                 /** Checks if an object equals this one.
215                  * @param other The object to compare.
216                  * @return <CODE>true</CODE>: they are equal;
217                  * <CODE>false</CODE>: they are not equal.
218                  */                
219     public boolean equals(Object other) {
220       return key.equals(((CacheItem) other).key);
221     }
222 
223                 /** Returns a hash code for this object.
224                  * @return The hash code.
225                  */                
226     public int hashCode() {
227       return key.hashCode();
228     }
229 
230                 /** Sets the queue key for this object.
231                  * @param q The key.
232                  */                
233     void setQueueKey(JQueue.QueueKey q) {
234       qkey = q;
235     }
236   }
237 }