package org.okip.service.filing.impl.rfs; import org.okip.service.filing.api.*; public class RfsEntryCache implements java.io.Serializable { static final byte IS_CABINET = 1; static final byte IS_BYTESTORE = 2; static final byte CAN_READ = 4; static final byte CAN_WRITE = 8; private static final byte TESTING_EXIST = 64; /* * Here are the non-transients that are sent over the wire * whenever any information is requested. */ long length; long lastModified; byte bits; String name; transient long lastRefresh = 0; transient RfsEntry rfsEntry; transient int maxCacheAge = 0; transient boolean isStale = false; protected RfsEntryCache(RfsEntry rfsEntry) throws FilingException { setEntry(rfsEntry); } protected RfsEntryCache(java.io.File file) { initFromFile(file); } protected void setEntry(RfsEntry entry) throws FilingException { this.rfsEntry = entry; this.maxCacheAge = rfsEntry.factory.getMaxCacheAge(); this.name = rfsEntry.getName(); if (entry.isByteStore()) this.bits |= IS_BYTESTORE; else if (entry.isCabinet()) this.bits |= IS_CABINET; } protected void setLastRefresh(long time) { this.lastRefresh = time; } boolean isByteStore() { return (this.bits & IS_BYTESTORE) != 0; } boolean isCabinet() { return (this.bits & IS_CABINET) != 0; } /* * Data Acccess methods */ String getName() { return this.name; } long length() throws FilingException { ensureCache(); return this.length; } long getLastModifiedTime() throws FilingException { ensureCache(); return this.lastModified; } boolean canRead() throws FilingException { ensureCache(); return (this.bits & CAN_READ) != 0; } boolean canWrite() throws FilingException { ensureCache(); return (this.bits & CAN_WRITE) != 0; } boolean exists() throws FilingException { // don't use ensureCache here, because we don't // want to throw an exception if it doesn't exist -- // we simply want to report that fact. if (isCurrent()) return !this.isStale; else { bits |= TESTING_EXIST; refreshCache(); bits &= ~TESTING_EXIST; } return !this.isStale; } /* * Cache-function methdos */ private final boolean isCurrent() { return (System.currentTimeMillis() - this.lastRefresh) < maxCacheAge; } protected void invalidate() { this.lastRefresh = 0; } private void empty() { this.length = 0; this.lastModified = 0; this.bits = 0; } protected void markStale(long t) { setLastRefresh(t == 0 ? System.currentTimeMillis() : t); markStale(); } protected void markStale() { empty(); this.isStale = true; } void ensureCache() throws FilingException { if (isStale) throw new FilingException("'" + name + "' - stale RFS entry (no longer exists): " + rfsEntry.getPath()); if (!isCurrent()) refreshCache(); } protected boolean isReadableSet() { return (this.bits & CAN_READ) != 0; } protected void copyUpdate(RfsEntryCache rc) { this.lastRefresh = System.currentTimeMillis(); this.lastModified = rc.lastModified; this.length = rc.length; this.bits = rc.bits; } protected void copy(RfsEntryCache rc) { this.lastRefresh = rc.lastRefresh; this.lastModified = rc.lastModified; this.length = rc.length; this.bits = rc.bits; } protected void refreshCache() throws FilingException { if (!rfsEntry.hasClient) throw new FilingException("attempted update of RfsEntryCache without a client"); RfsEntryCache c; try { c = (RfsEntryCache) rfsEntry.factory.invoke (this, "refreshCacheRemotely", String.class, rfsEntry.idStr); if (c == null) { this.markStale(); } else { this.copyUpdate(c); this.isStale = false; } } catch (FilingException e) { this.markStale(); throw e; } } public RfsEntryCache refreshCacheRemotely(String path) throws FilingException { java.io.File file; try { file = RfsEntry.getEntryFile(path, isCabinet()); } catch (NotFoundException e) { if ((bits & TESTING_EXIST) != 0) return null; else throw e; } this.bits = 0; initFromFile(file); return this; } private void initFromFile(java.io.File file) { this.length = file.length(); this.lastModified = file.lastModified(); this.name = file.getName(); try { if (file.canRead()) this.bits |= CAN_READ; } catch (java.security.AccessControlException e) {} try { if (file.canWrite()) this.bits |= CAN_WRITE; } catch (java.security.AccessControlException e) {} try { if (file.isDirectory()) this.bits |= IS_CABINET; } catch (java.security.AccessControlException e) {} try { if (file.isFile()) this.bits |= IS_BYTESTORE; } catch (java.security.AccessControlException e) {} } public String toString() { String s = "Rec" + Integer.toHexString(hashCode()) + "["+name; if (lastRefresh > 0) s += " age=" + (System.currentTimeMillis() - lastRefresh); if (isStale) s += " STALE"; s += "]"; return s; } }