KickJava   Java API By Example, From Geeks To Geeks.

Java > Open Source Codes > org > apache > jetspeed > cache > FileCache


1 /*
2  * Copyright 2000-2001,2004 The Apache Software Foundation.
3  *
4  * Licensed under the Apache License, Version 2.0 (the "License");
5  * you may not use this file except in compliance with the License.
6  * You may obtain a copy of the License at
7  *
8  * http://www.apache.org/licenses/LICENSE-2.0
9  *
10  * Unless required by applicable law or agreed to in writing, software
11  * distributed under the License is distributed on an "AS IS" BASIS,
12  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13  * See the License for the specific language governing permissions and
14  * limitations under the License.
15  */

16
17 package org.apache.jetspeed.cache;
18
19 import java.util.Collections JavaDoc;
20 import java.util.Date JavaDoc;
21 import java.util.Map JavaDoc;
22 import java.util.HashMap JavaDoc;
23 import java.util.List JavaDoc;
24 import java.util.LinkedList JavaDoc;
25 import java.util.Iterator JavaDoc;
26 import java.io.File JavaDoc;
27
28 // Jetspeed logging classes
29
import org.apache.jetspeed.services.logging.JetspeedLogFactoryService;
30 import org.apache.jetspeed.services.logging.JetspeedLogger;
31
32 /**
33  * FileCache keeps a cache of files up-to-date with a most simple eviction policy.
34  * The eviction policy will keep n items in the cache, and then start evicting
35  * the items ordered-by least used first. The cache runs a thread to check for
36  * both evictions and refreshes.
37  *
38  * @author David S. Taylor <a HREF="mailto:taylor@apache.org">David Sean Taylor</a>
39  * @version $Id: FileCache.java,v 1.5 2004/03/25 16:27:41 jford Exp $
40  */

41
42 public class FileCache implements java.util.Comparator JavaDoc
43 {
44     protected long scanRate = 300; // every 5 minutes
45
protected int maxSize = 100; // maximum of 100 items
46
protected List JavaDoc listeners = new LinkedList JavaDoc();
47
48     private FileCacheScanner scanner = null;
49     private Map JavaDoc cache = null;
50     
51     /**
52      * Static initialization of the logger for this class
53      */

54     private static final JetspeedLogger logger = JetspeedLogFactoryService.getLogger(FileCache.class.getName());
55
56     /**
57      * Default constructor. Use default values for scanReate and maxSize
58      *
59      */

60     public FileCache()
61     {
62         cache = new HashMap JavaDoc();
63         this.scanner = new FileCacheScanner();
64         this.scanner.setDaemon(true);
65     }
66
67     /**
68      * Set scanRate and maxSize
69      *
70      * @param scanRate how often in seconds to refresh and evict from the cache
71      * @param maxSize the maximum allowed size of the cache before eviction starts
72      */

73     public FileCache(long scanRate,
74                      int maxSize)
75     {
76         cache = new HashMap JavaDoc();
77
78         this.scanRate = scanRate;
79         this.maxSize = maxSize;
80         this.scanner = new FileCacheScanner();
81         this.scanner.setDaemon(true);
82     }
83
84     /**
85      * Set all parameters on the cache
86      *
87      * @param initialCapacity the initial size of the cache as passed to HashMap
88      * @param loadFactor how full the hash table is allowed to get before increasing
89      * @param scanRate how often in seconds to refresh and evict from the cache
90      * @param maxSize the maximum allowed size of the cache before eviction starts
91      */

92     public FileCache(int initialCapacity,
93                      int loadFactor,
94                      long scanRate,
95                      int maxSize)
96     {
97         cache = new HashMap JavaDoc(initialCapacity, loadFactor);
98
99         this.scanRate = scanRate;
100         this.maxSize = maxSize;
101         this.scanner = new FileCacheScanner();
102         this.scanner.setDaemon(true);
103     }
104
105     /**
106      * Set the new refresh scan rate on managed files.
107      *
108      * @param scanRate the new scan rate in seconds
109      */

110     public void setScanRate(long scanRate)
111     {
112         this.scanRate= scanRate;
113     }
114
115     /**
116      * Get the refresh scan rate
117      *
118      * @return the current refresh scan rate in seconds
119      */

120     public long getScanRate()
121     {
122         return scanRate;
123     }
124
125     /**
126      * Set the new maximum size of the cache
127      *
128      * @param maxSize the maximum size of the cache
129      */

130     public void setMaxSize(int maxSize)
131     {
132         this.maxSize = maxSize;
133     }
134
135     /**
136      * Get the maximum size of the cache
137      *
138      * @return the current maximum size of the cache
139      */

140     public int getMaxSize()
141     {
142         return maxSize;
143     }
144
145     /**
146      * Gets an entry from the cache given a key
147      *
148      * @param key the key to look up the entry by
149      * @return the entry
150      */

151     public FileCacheEntry get(String JavaDoc key)
152     {
153         return (FileCacheEntry) cache.get(key);
154     }
155
156     /**
157      * Gets an entry from the cache given a key
158      *
159      * @param key the key to look up the entry by
160      * @return the entry
161      */

162     public Object JavaDoc getDocument(String JavaDoc key)
163     {
164         FileCacheEntry entry = (FileCacheEntry) cache.get(key);
165         if (entry != null)
166         {
167             return entry.getDocument();
168         }
169         return null;
170     }
171
172     /**
173      * Puts a file entry in the file cache
174      *
175      * @param file The file to be put in the cache
176      * @param document the cached document
177      */

178     public void put(File JavaDoc file, Object JavaDoc document)
179         throws java.io.IOException JavaDoc
180     {
181         FileCacheEntry entry = new FileCacheEntry(file, document);
182         cache.put(file.getCanonicalPath(), entry);
183     }
184
185     /**
186      * Puts a file entry in the file cache
187      *
188      * @param path the full path name of the file
189      * @param document the cached document
190      */

191     public void put(String JavaDoc key, Object JavaDoc document)
192         throws java.io.IOException JavaDoc
193     {
194         File JavaDoc file = new File JavaDoc(key);
195         FileCacheEntry entry = new FileCacheEntry(file, document);
196         cache.put(file.getCanonicalPath(), entry);
197     }
198
199     /**
200      * Removes a file entry from the file cache
201      *
202      * @param key the full path name of the file
203      * @return the entry removed
204      */

205     public Object JavaDoc remove(String JavaDoc key)
206     {
207         return cache.remove(key);
208     }
209
210
211     /**
212      * Add a File Cache Event Listener
213      *
214      * @param listener the event listener
215      */

216     public void addListener(FileCacheEventListener listener)
217     {
218         listeners.add(listener);
219     }
220
221     /**
222      * Start the file Scanner running at the current scan rate.
223      *
224      */

225     public void startFileScanner()
226     {
227         try
228         {
229
230             this.scanner.start();
231         }
232         catch (java.lang.IllegalThreadStateException JavaDoc e)
233         {
234             logger.error("Exception starting scanner", e);
235         }
236     }
237
238     /**
239      * Stop the file Scanner
240      *
241      */

242     public void stopFileScanner()
243     {
244         this.scanner.setStopping(true);
245     }
246
247     /**
248      * Evicts entries based on last accessed time stamp
249      *
250      */

251     protected void evict()
252     {
253         synchronized (cache)
254         {
255             if (this.getMaxSize() >= cache.size())
256             {
257                 return;
258             }
259     
260             List JavaDoc list = new LinkedList JavaDoc(cache.values());
261             Collections.sort(list, this);
262     
263             int count = 0;
264             int limit = cache.size() - this.getMaxSize();
265     
266             for (Iterator JavaDoc it = list.iterator(); it.hasNext(); )
267             {
268                 if (count >= limit)
269                 {
270                     break;
271                 }
272     
273                 FileCacheEntry entry = (FileCacheEntry) it.next();
274                 String JavaDoc key = null;
275                 try
276                 {
277                     key = entry.getFile().getCanonicalPath();
278                 }
279                 catch (java.io.IOException JavaDoc e)
280                 {
281                     logger.error("Exception getting file path: ", e);
282                 }
283                 // notify that eviction will soon take place
284
for (Iterator JavaDoc lit = this.listeners.iterator(); lit.hasNext(); )
285                 {
286                     FileCacheEventListener listener =
287                         (FileCacheEventListener) lit.next();
288                     listener.evict(entry);
289                 }
290                 cache.remove(key);
291     
292                 count++;
293             }
294         }
295     }
296
297     /**
298      * Comparator function for sorting by last accessed during eviction
299      *
300      */

301     public int compare(Object JavaDoc o1, Object JavaDoc o2)
302     {
303         FileCacheEntry e1 = (FileCacheEntry)o1;
304         FileCacheEntry e2 = (FileCacheEntry)o2;
305         if (e1.getLastAccessed() < e2.getLastAccessed())
306         {
307             return -1;
308         }
309         else if (e1.getLastAccessed() == e2.getLastAccessed())
310         {
311             return 0;
312         }
313         return 1;
314     }
315
316     /**
317      * inner class that runs as a thread to scan the cache for updates or evictions
318      *
319      */

320     protected class FileCacheScanner extends Thread JavaDoc
321     {
322         private boolean stopping = false;
323
324         public void setStopping(boolean flag)
325         {
326             this.stopping = flag;
327         }
328
329         /**
330          * Run the file scanner thread
331          *
332          */

333         public void run()
334         {
335             boolean done = false;
336     
337             try
338             {
339                 while(!done)
340                 {
341                     try
342                     {
343                         int count = 0;
344                         synchronized(FileCache.this)
345                         {
346                             for (Iterator JavaDoc it = FileCache.this.cache.values().iterator(); it.hasNext(); )
347                             {
348                                 FileCacheEntry entry = (FileCacheEntry) it.next();
349                                 Date JavaDoc modified = new Date JavaDoc(entry.getFile().lastModified());
350         
351                                 if (modified.after(entry.getLastModified()))
352                                 {
353                                     for (Iterator JavaDoc lit = FileCache.this.listeners.iterator(); lit.hasNext(); )
354                                     {
355                                         FileCacheEventListener listener =
356                                             (FileCacheEventListener) lit.next();
357                                         listener.refresh(entry);
358                                         entry.setLastModified(modified);
359                                     }
360                                 }
361                                 count++;
362                             }
363                         }
364                         if (count > FileCache.this.getMaxSize())
365                         {
366                             FileCache.this.evict();
367                         }
368                     }
369                     catch (Exception JavaDoc e)
370                     {
371                         logger.error("FileCache Scanner: Error in iteration...", e);
372                     }
373     
374                     sleep(FileCache.this.getScanRate() * 1000);
375
376                     if (this.stopping)
377                     {
378                         this.stopping = false;
379                         done = true;
380                     }
381                 }
382             }
383             catch (InterruptedException JavaDoc e)
384             {
385                 logger.error("FileCacheScanner: recieved interruption, exiting.", e);
386             }
387         }
388     } // end inner class: FileCacheScanner
389

390
391     /**
392      * get an iterator over the cache values
393      *
394      * @return iterator over the cache values
395      */

396     public Iterator JavaDoc getIterator()
397     {
398         return cache.values().iterator();
399     }
400
401     /**
402       * get the size of the cache
403       *
404       * @return the size of the cache
405       */

406     public int getSize()
407     {
408         return cache.size();
409     }
410 }
411
412
Popular Tags