1 5 package com.opensymphony.oscache.plugins.diskpersistence; 6 7 import com.opensymphony.oscache.base.Config; 8 import com.opensymphony.oscache.base.persistence.CachePersistenceException; 9 import com.opensymphony.oscache.base.persistence.PersistenceListener; 10 import com.opensymphony.oscache.web.ServletCacheAdministrator; 11 12 import org.apache.commons.logging.Log; 13 import org.apache.commons.logging.LogFactory; 14 15 import java.io.*; 16 17 import java.util.Set ; 18 19 import javax.servlet.jsp.PageContext ; 20 21 32 public abstract class AbstractDiskPersistenceListener implements PersistenceListener, Serializable { 33 public final static String CACHE_PATH_KEY = "cache.path"; 34 35 38 protected final static String CACHE_EXTENSION = "cache"; 39 40 43 protected final static String GROUP_DIRECTORY = "__groups__"; 44 45 48 protected final static String APPLICATION_CACHE_SUBPATH = "application"; 49 50 53 protected final static String SESSION_CACHE_SUBPATH = "session"; 54 55 58 protected static final String CONTEXT_TMPDIR = "javax.servlet.context.tempdir"; 59 private static transient final Log log = LogFactory.getLog(AbstractDiskPersistenceListener.class); 60 61 64 private File cachePath = null; 65 private File contextTmpDir; 66 67 70 private String root = null; 71 72 77 public File getCachePath() { 78 return cachePath; 79 } 80 81 87 public String getRoot() { 88 return root; 89 } 90 91 96 public File getContextTmpDir() { 97 return contextTmpDir; 98 } 99 100 107 public boolean isGroupStored(String group) throws CachePersistenceException { 108 try { 109 File file = getCacheGroupFile(group); 110 111 return file.exists(); 112 } catch (Exception e) { 113 throw new CachePersistenceException("Unable verify group '" + group + "' exists in the cache: " + e); 114 } 115 } 116 117 124 public boolean isStored(String key) throws CachePersistenceException { 125 try { 126 File file = getCacheFile(key); 127 128 return file.exists(); 129 } catch (Exception e) { 130 throw new CachePersistenceException("Unable verify id '" + key + "' is stored in the cache: " + e); 131 } 132 } 133 134 139 public void clear() throws CachePersistenceException { 140 clear(root); 141 } 142 143 149 public PersistenceListener configure(Config config) { 150 String sessionId = null; 151 int scope = 0; 152 initFileCaching(config.getProperty(CACHE_PATH_KEY)); 153 154 if (config.getProperty(ServletCacheAdministrator.HASH_KEY_SESSION_ID) != null) { 155 sessionId = config.getProperty(ServletCacheAdministrator.HASH_KEY_SESSION_ID); 156 } 157 158 if (config.getProperty(ServletCacheAdministrator.HASH_KEY_SCOPE) != null) { 159 scope = Integer.parseInt(config.getProperty(ServletCacheAdministrator.HASH_KEY_SCOPE)); 160 } 161 162 StringBuffer root = new StringBuffer (getCachePath().getPath()); 163 root.append("/"); 164 root.append(getPathPart(scope)); 165 166 if ((sessionId != null) && (sessionId.length() > 0)) { 167 root.append("/"); 168 root.append(sessionId); 169 } 170 171 this.root = root.toString(); 172 this.contextTmpDir = (File) config.get(ServletCacheAdministrator.HASH_KEY_CONTEXT_TMPDIR); 173 174 return this; 175 } 176 177 183 public void remove(String key) throws CachePersistenceException { 184 File file = getCacheFile(key); 185 remove(file); 186 } 187 188 194 public void removeGroup(String groupName) throws CachePersistenceException { 195 File file = getCacheGroupFile(groupName); 196 remove(file); 197 } 198 199 206 public Object retrieve(String key) throws CachePersistenceException { 207 return retrieve(getCacheFile(key)); 208 } 209 210 219 public Set retrieveGroup(String groupName) throws CachePersistenceException { 220 File groupFile = getCacheGroupFile(groupName); 221 222 try { 223 return (Set ) retrieve(groupFile); 224 } catch (ClassCastException e) { 225 throw new CachePersistenceException("Group file " + groupFile + " was not persisted as a Set: " + e); 226 } 227 } 228 229 236 public void store(String key, Object obj) throws CachePersistenceException { 237 File file = getCacheFile(key); 238 store(file, obj); 239 } 240 241 245 public void storeGroup(String groupName, Set group) throws CachePersistenceException { 246 File groupFile = getCacheGroupFile(groupName); 247 store(groupFile, group); 248 } 249 250 257 protected String adjustFileCachePath(String cachePathStr) { 258 if (cachePathStr.compareToIgnoreCase(CONTEXT_TMPDIR) == 0) { 259 cachePathStr = contextTmpDir.getAbsolutePath(); 260 } 261 262 return cachePathStr; 263 } 264 265 270 protected void initFileCaching(String cachePathStr) { 271 if (cachePathStr != null) { 272 cachePath = new File(cachePathStr); 273 274 try { 275 if (!cachePath.exists()) { 276 if (log.isInfoEnabled()) { 277 log.info("cache.path '" + cachePathStr + "' does not exist, creating"); 278 } 279 280 cachePath.mkdirs(); 281 } 282 283 if (!cachePath.isDirectory()) { 284 log.error("cache.path '" + cachePathStr + "' is not a directory"); 285 cachePath = null; 286 } else if (!cachePath.canWrite()) { 287 log.error("cache.path '" + cachePathStr + "' is not a writable location"); 288 cachePath = null; 289 } 290 } catch (Exception e) { 291 log.error("cache.path '" + cachePathStr + "' could not be used", e); 292 cachePath = null; 293 } 294 } else { 295 } 297 } 298 299 private static final long DELETE_THREAD_SLEEP = 500; 301 private static final int DELETE_COUNT = 60; 302 303 protected void remove(File file) throws CachePersistenceException { 304 int count = DELETE_COUNT; 305 try { 306 while (file.exists() && !file.delete() && count != 0) { 311 count--; 312 try { 313 Thread.sleep(DELETE_THREAD_SLEEP); 314 } catch (InterruptedException ignore) { 315 } 316 } 317 } catch (Exception e) { 318 throw new CachePersistenceException("Unable to remove '" + file + "' from the cache: " + e); 319 } 320 if (file.exists() && count == 0) { 321 throw new CachePersistenceException("Unable to delete '" + file + "' from the cache. "+DELETE_COUNT+" attempts at "+DELETE_THREAD_SLEEP+" milliseconds intervals."); 322 } 323 } 324 325 332 protected void store(File file, Object obj) throws CachePersistenceException { 333 if (!file.exists()) { 335 File filepath = new File(file.getParent()); 337 338 try { 339 if (!filepath.exists()) { 340 filepath.mkdirs(); 341 } 342 } catch (Exception e) { 343 throw new CachePersistenceException("Unable to create the directory " + filepath); 344 } 345 } 346 347 try { 349 FileOutputStream fout = new FileOutputStream(file); 350 try { 351 ObjectOutputStream oout = new ObjectOutputStream(new BufferedOutputStream(fout)); 352 try { 353 oout.writeObject(obj); 354 oout.flush(); 355 } finally { 356 try { 357 oout.close(); 358 } catch (Exception e) { 359 } 360 } 361 } finally { 362 try { 363 fout.close(); 364 } catch (Exception e) { 365 } 366 } 367 } catch (Exception e) { 368 int count = DELETE_COUNT; 369 while (file.exists() && !file.delete() && count != 0) { 370 count--; 371 try { 372 Thread.sleep(DELETE_THREAD_SLEEP); 373 } catch (InterruptedException ignore) { 374 } 375 } 376 throw new CachePersistenceException("Unable to write '" + file + "' in the cache. Exception: " + e.getClass().getName() + ", Message: " + e.getMessage()); 377 } 378 } 379 380 386 protected File getCacheFile(String key) { 387 char[] fileChars = getCacheFileName(key); 388 389 File file = new File(root, new String (fileChars) + "." + CACHE_EXTENSION); 390 391 return file; 392 } 393 394 400 protected abstract char[] getCacheFileName(String key); 401 402 408 private File getCacheGroupFile(String group) { 409 int AVERAGE_PATH_LENGTH = 30; 410 411 if ((group == null) || (group.length() == 0)) { 412 throw new IllegalArgumentException ("Invalid group '" + group + "' specified to getCacheGroupFile."); 413 } 414 415 StringBuffer path = new StringBuffer (AVERAGE_PATH_LENGTH); 416 417 path.append(GROUP_DIRECTORY).append('/'); 419 path.append(group).append('.').append(CACHE_EXTENSION); 420 421 return new File(root, path.toString()); 422 } 423 424 431 private String getPathPart(int scope) { 432 if (scope == PageContext.SESSION_SCOPE) { 433 return SESSION_CACHE_SUBPATH; 434 } else { 435 return APPLICATION_CACHE_SUBPATH; 436 } 437 } 438 439 446 private void clear(String baseDirName) throws CachePersistenceException { 447 File baseDir = new File(baseDirName); 448 File[] fileList = baseDir.listFiles(); 449 450 try { 451 if (fileList != null) { 452 for (int count = 0; count < fileList.length; count++) { 454 if (fileList[count].isFile()) { 455 fileList[count].delete(); 456 } else { 457 clear(fileList[count].toString()); 459 fileList[count].delete(); 460 } 461 } 462 } 463 464 baseDir.delete(); 466 } catch (Exception e) { 467 throw new CachePersistenceException("Unable to clear the cache directory"); 468 } 469 } 470 471 479 private Object retrieve(File file) throws CachePersistenceException { 480 Object readContent = null; 481 boolean fileExist; 482 483 try { 484 fileExist = file.exists(); 485 } catch (Exception e) { 486 throw new CachePersistenceException("Unable to verify if " + file + " exists: " + e); 487 } 488 489 if (fileExist) { 491 ObjectInputStream oin = null; 492 493 try { 494 BufferedInputStream in = new BufferedInputStream(new FileInputStream(file)); 495 oin = new ObjectInputStream(in); 496 readContent = oin.readObject(); 497 } catch (Exception e) { 498 throw new CachePersistenceException("Unable to read '" + file.getAbsolutePath() + "' from the cache: " + e); 503 } finally { 504 try { 506 oin.close(); 507 } catch (Exception ex) { 508 } 509 } 510 } 511 512 return readContent; 513 } 514 } 515 | Popular Tags |