1 16 17 package org.apache.jetspeed.cache; 18 19 import java.util.Collections ; 20 import java.util.Date ; 21 import java.util.Map ; 22 import java.util.HashMap ; 23 import java.util.List ; 24 import java.util.LinkedList ; 25 import java.util.Iterator ; 26 import java.io.File ; 27 28 import org.apache.jetspeed.services.logging.JetspeedLogFactoryService; 30 import org.apache.jetspeed.services.logging.JetspeedLogger; 31 32 41 42 public class FileCache implements java.util.Comparator 43 { 44 protected long scanRate = 300; protected int maxSize = 100; protected List listeners = new LinkedList (); 47 48 private FileCacheScanner scanner = null; 49 private Map cache = null; 50 51 54 private static final JetspeedLogger logger = JetspeedLogFactoryService.getLogger(FileCache.class.getName()); 55 56 60 public FileCache() 61 { 62 cache = new HashMap (); 63 this.scanner = new FileCacheScanner(); 64 this.scanner.setDaemon(true); 65 } 66 67 73 public FileCache(long scanRate, 74 int maxSize) 75 { 76 cache = new HashMap (); 77 78 this.scanRate = scanRate; 79 this.maxSize = maxSize; 80 this.scanner = new FileCacheScanner(); 81 this.scanner.setDaemon(true); 82 } 83 84 92 public FileCache(int initialCapacity, 93 int loadFactor, 94 long scanRate, 95 int maxSize) 96 { 97 cache = new HashMap (initialCapacity, loadFactor); 98 99 this.scanRate = scanRate; 100 this.maxSize = maxSize; 101 this.scanner = new FileCacheScanner(); 102 this.scanner.setDaemon(true); 103 } 104 105 110 public void setScanRate(long scanRate) 111 { 112 this.scanRate= scanRate; 113 } 114 115 120 public long getScanRate() 121 { 122 return scanRate; 123 } 124 125 130 public void setMaxSize(int maxSize) 131 { 132 this.maxSize = maxSize; 133 } 134 135 140 public int getMaxSize() 141 { 142 return maxSize; 143 } 144 145 151 public FileCacheEntry get(String key) 152 { 153 return (FileCacheEntry) cache.get(key); 154 } 155 156 162 public Object getDocument(String 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 178 public void put(File file, Object document) 179 throws java.io.IOException 180 { 181 FileCacheEntry entry = new FileCacheEntry(file, document); 182 cache.put(file.getCanonicalPath(), entry); 183 } 184 185 191 public void put(String key, Object document) 192 throws java.io.IOException 193 { 194 File file = new File (key); 195 FileCacheEntry entry = new FileCacheEntry(file, document); 196 cache.put(file.getCanonicalPath(), entry); 197 } 198 199 205 public Object remove(String key) 206 { 207 return cache.remove(key); 208 } 209 210 211 216 public void addListener(FileCacheEventListener listener) 217 { 218 listeners.add(listener); 219 } 220 221 225 public void startFileScanner() 226 { 227 try 228 { 229 230 this.scanner.start(); 231 } 232 catch (java.lang.IllegalThreadStateException e) 233 { 234 logger.error("Exception starting scanner", e); 235 } 236 } 237 238 242 public void stopFileScanner() 243 { 244 this.scanner.setStopping(true); 245 } 246 247 251 protected void evict() 252 { 253 synchronized (cache) 254 { 255 if (this.getMaxSize() >= cache.size()) 256 { 257 return; 258 } 259 260 List list = new LinkedList (cache.values()); 261 Collections.sort(list, this); 262 263 int count = 0; 264 int limit = cache.size() - this.getMaxSize(); 265 266 for (Iterator it = list.iterator(); it.hasNext(); ) 267 { 268 if (count >= limit) 269 { 270 break; 271 } 272 273 FileCacheEntry entry = (FileCacheEntry) it.next(); 274 String key = null; 275 try 276 { 277 key = entry.getFile().getCanonicalPath(); 278 } 279 catch (java.io.IOException e) 280 { 281 logger.error("Exception getting file path: ", e); 282 } 283 for (Iterator 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 301 public int compare(Object o1, Object 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 320 protected class FileCacheScanner extends Thread 321 { 322 private boolean stopping = false; 323 324 public void setStopping(boolean flag) 325 { 326 this.stopping = flag; 327 } 328 329 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 it = FileCache.this.cache.values().iterator(); it.hasNext(); ) 347 { 348 FileCacheEntry entry = (FileCacheEntry) it.next(); 349 Date modified = new Date (entry.getFile().lastModified()); 350 351 if (modified.after(entry.getLastModified())) 352 { 353 for (Iterator 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 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 e) 384 { 385 logger.error("FileCacheScanner: recieved interruption, exiting.", e); 386 } 387 } 388 } 390 391 396 public Iterator getIterator() 397 { 398 return cache.values().iterator(); 399 } 400 401 406 public int getSize() 407 { 408 return cache.size(); 409 } 410 } 411 412 | Popular Tags |