Commits

Anonymous committed 7edb993

Doesn't all compile yet but my get/put test case passed, so I thought I'd mark this momentous occasion with a commit.

  • Participants
  • Parent commits 4f1abd3
  • Branches amarch_sandbox

Comments (0)

Files changed (7)

File src/core/java/com/opensymphony/oscache/base/AbstractCacheAdministrator.java

      */
     private boolean unlimitedDiskCache;
 
+	/**
+	 * Application cache
+	 */
+	protected Cache applicationCache = null;
+
     /**
      * Create the AbstractCacheAdministrator.
      * This will initialize all values and load the properties from oscache.properties.
             log.debug("Constructed AbstractCacheAdministrator()");
         }
     }
+    
+    protected Object get(Object key) {
+    		CacheEntry entry = getCache().get(key);
+    		return entry.getContent();
+    }
+    
+    protected void put(Object key, Object value) {
+    		CacheEntry entry = new CacheEntry(key, value);
+		synchronized (entry) {
+			CacheEntry oldEntry = getCache().put(key, entry);
+			// Signal to any threads waiting on this update that it's now ready for
+			// them
+			// in the cache!
+			completeUpdate(entry);
+			entry.notifyAll();
+		}
+    }
+    
+    /**
+	 * Removes the update state for the specified key and notifies any other
+	 * threads that are waiting on this object. This is called automatically by
+	 * the {@link #putInCache} method. This method must be called only when the entry is 
+	 * locked.
+	 * 
+	 * @param key
+	 *            The cache key that is no longer being updated.
+	 */
+	protected void completeUpdate(CacheEntry cacheEntry) {
+
+		if (cacheEntry != null) {
+			if (!cacheEntry.isUpdating()) {
+				cacheEntry.startUpdate();
+			}
+
+			cacheEntry.completeUpdate();
+		}
+	}
 
     /**
      * Sets the algorithm to use for the cache.
             Class clazz = Class.forName(persistenceClassname);
             PersistenceListener persistenceListener = (PersistenceListener) clazz.newInstance();
 
-            cache.setPersistenceListener(persistenceListener.configure(config));
+//            cache.setPersistenceListener(persistenceListener.configure(config));
         } catch (ClassNotFoundException e) {
             log.error("PersistenceListener class '" + persistenceClassname + "' not found. Check your configuration.", e);
         } catch (Exception e) {
                 }
 
                 if (listeners[i] instanceof CacheEntryEventListener) {
-                    cache.addCacheEventListener(listeners[i], CacheEntryEventListener.class);
+//                    cache.addCacheEventListener(listeners[i], CacheEntryEventListener.class);
                 }
 
                 if (listeners[i] instanceof CacheMapAccessEventListener) {
-                    cache.addCacheEventListener(listeners[i], CacheMapAccessEventListener.class);
+//                    cache.addCacheEventListener(listeners[i], CacheMapAccessEventListener.class);
                 }
             }
         }
             return;
         }
 
-        Object[] listeners = cache.getListenerList().getListenerList();
-
-        for (int i = listeners.length - 2; i >= 0; i -= 2) {
-            if (listeners[i + 1] instanceof LifecycleAware) {
-                try {
-                    ((LifecycleAware) listeners[i + 1]).finialize();
-                } catch (FinalizationException e) {
-                    log.error("Listener could not be finalized", e);
-                }
-            }
-        }
+//        Object[] listeners = cache.getListenerList().getListenerList();
+//
+//        for (int i = listeners.length - 2; i >= 0; i -= 2) {
+//            if (listeners[i + 1] instanceof LifecycleAware) {
+//                try {
+//                    ((LifecycleAware) listeners[i + 1]).finialize();
+//                } catch (FinalizationException e) {
+//                    log.error("Listener could not be finalized", e);
+//                }
+//            }
+//        }
     }
 
     /**
     private void loadProps(Properties p) {
         config = new Config(p);
     }
+
+	/**
+	 * Grabs a cache
+	 *
+	 * @return The cache
+	 */
+	public Cache getCache() {
+	    return applicationCache;
+	}
+
+	/**
+	 * @return Returns the applicationCache.
+	 */
+	public Cache getApplicationCache() {
+		return applicationCache;
+	}
+
+	/**
+	 * @param applicationCache The applicationCache to set.
+	 */
+	public void setApplicationCache(Cache applicationCache) {
+		this.applicationCache = applicationCache;
+	}
 }

File src/core/java/com/opensymphony/oscache/base/Cache.java

 
 /**
  * DOCUMENT ME!
- *
+ * 
  * @author $author$
  * @version $Revision$
  */
 public interface Cache {
-    /**
-     * An event that origininated from within another event.
-     */
-    public static final String NESTED_EVENT = "NESTED";
+	/**
+	 * An event that origininated from within another event.
+	 */
+	public static final String NESTED_EVENT = "NESTED";
 
-    /**
-     * Allows the capacity of the cache to be altered dynamically. Note that
-     * some cache implementations may choose to ignore this setting (eg the
-     * {@link UnlimitedCache} ignores this call).
-     *
-     * @param capacity the maximum number of items to hold in the cache.
-     */
-    public abstract void setCapacity(int capacity);
+	/**
+	 * Allows the capacity of the cache to be altered dynamically. Note that
+	 * some cache implementations may choose to ignore this setting (eg the
+	 * {@link UnlimitedCache} ignores this call).
+	 * 
+	 * @param capacity
+	 *            the maximum number of items to hold in the cache.
+	 */
+	public abstract void setCapacity(int capacity);
 
-    /**
-     * Checks if the cache was flushed more recently than the CacheEntry provided.
-     * Used to determine whether to refresh the particular CacheEntry.
-     *
-     * @param cacheEntry The cache entry which we're seeing whether to refresh
-     * @return Whether or not the cache has been flushed more recently than this cache entry was updated.
-     */
-    public abstract boolean isFlushed(CacheEntry cacheEntry);
+	/**
+	 * Checks if the cache was flushed more recently than the CacheEntry
+	 * provided. Used to determine whether to refresh the particular CacheEntry.
+	 * 
+	 * @param cacheEntry
+	 *            The cache entry which we're seeing whether to refresh
+	 * @return Whether or not the cache has been flushed more recently than this
+	 *         cache entry was updated.
+	 */
+	public abstract boolean isFlushed(CacheEntry cacheEntry);
 
-    /**
-     * Retrieve an object from the cache specifying its key.
-     *
-     * @param key             Key of the object in the cache.
-     *
-     * @return The object from cache
-     *
-     */
-    public abstract Object get(Object key) ;
+	/**
+	 * Retrieve an object from the cache specifying its key.
+	 * 
+	 * @param key
+	 *            Key of the object in the cache.
+	 * 
+	 * @return The object from cache
+	 * 
+	 */
+	public abstract CacheEntry get(Object key);
 
-    /**
-     * Retrieve an object from the cache specifying its key.
-     *
-     * @param key             Key of the object in the cache.
-     * @param refreshPeriod   How long before the object needs refresh. To
-     * allow the object to stay in the cache indefinitely, supply a value
-     * of {@link CacheEntry#INDEFINITE_EXPIRY}.
-     *
-     * @return The object from cache
-     *
-     */
-    public abstract Object get(Object key, int refreshPeriod);
+	/**
+	 * Retrieve an object from the cache specifying its key.
+	 * 
+	 * @param key
+	 *            Key of the object in the cache.
+	 * @param refreshPeriod
+	 *            How long before the object needs refresh. To allow the object
+	 *            to stay in the cache indefinitely, supply a value of
+	 *            {@link CacheEntry#INDEFINITE_EXPIRY}.
+	 * 
+	 * @return The object from cache
+	 * 
+	 */
+	public abstract CacheEntry get(Object key, int refreshPeriod);
 
-    /**
-     * Retrieve an object from the cache specifying its key.
-     *
-     * @param key             Key of the object in the cache.
-     * @param refreshPeriod   How long before the object needs refresh. To
-     * allow the object to stay in the cache indefinitely, supply a value
-     * of {@link CacheEntry#INDEFINITE_EXPIRY}.
-     * @param cronExpiry      A cron expression that specifies fixed date(s)
-     *                        and/or time(s) that this cache entry should
-     *                        expire on.
-     *
-     * @return The object from cache
-     *
-     */
-    public abstract Object get(Object key, int refreshPeriod, String cronExpiry);
+	/**
+	 * Retrieve an object from the cache specifying its key.
+	 * 
+	 * @param key
+	 *            Key of the object in the cache.
+	 * @param refreshPeriod
+	 *            How long before the object needs refresh. To allow the object
+	 *            to stay in the cache indefinitely, supply a value of
+	 *            {@link CacheEntry#INDEFINITE_EXPIRY}.
+	 * @param cronExpiry
+	 *            A cron expression that specifies fixed date(s) and/or time(s)
+	 *            that this cache entry should expire on.
+	 * 
+	 * @return The object from cache
+	 * 
+	 */
+	public abstract CacheEntry get(Object key, int refreshPeriod, String cronExpiry);
 
-    /**
-     * Set the listener to use for data persistence. Only one
-     * <code>PersistenceListener</code> can be configured per cache.
-     *
-     * @param listener The implementation of a persistance listener
-     */
-    public abstract void setPersistenceListener(PersistenceListener listener);
+	/**
+	 * Cancels any pending update for this cache entry. This should
+	 * <em>only</em> be called by the thread that is responsible for
+	 * performing the update ie the thread that received the original
+	 * {@link NeedsRefreshException}.<p/> If a cache entry is not updated (via
+	 * {@link #putInCache} and this method is not called to let OSCache know the
+	 * update will not be forthcoming, subsequent requests for this cache entry
+	 * will either block indefinitely (if this is a new cache entry or
+	 * cache.blocking=true), or forever get served stale content. Note however
+	 * that there is no harm in cancelling an update on a key that either does
+	 * not exist or is not currently being updated.
+	 * 
+	 * @param key
+	 *            The key for the cache entry in question.
+	 */
+	public abstract void cancelUpdate(String key);
 
-    /**
-     * Retrieves the currently configured <code>PersistenceListener</code>.
-     *
-     * @return the cache's <code>PersistenceListener</code>, or <code>null</code>
-     * if no listener is configured.
-     */
-    public abstract PersistenceListener getPersistenceListener();
+	/**
+	 * Flush all entries in the cache on the given date/time.
+	 * 
+	 * @param date
+	 *            The date at which all cache entries will be flushed.
+	 */
+	public abstract void flushAll(Date date);
 
-    /**
-     * Register a listener for Cache events. The listener must implement
-     * one of the child interfaces of the {@link CacheEventListener} interface.
-     *
-     * @param listener  The object that listens to events.
-     */
-    public abstract void addCacheEventListener(CacheEventListener listener, Class clazz);
+	/**
+	 * Flush all entries in the cache on the given date/time.
+	 * 
+	 * @param date
+	 *            The date at which all cache entries will be flushed.
+	 * @param origin
+	 *            The origin of this flush request (optional)
+	 */
+	public abstract void flushAll(Date date, String origin);
 
-    /**
-     * Cancels any pending update for this cache entry. This should <em>only</em>
-     * be called by the thread that is responsible for performing the update ie
-     * the thread that received the original {@link NeedsRefreshException}.<p/>
-     * If a cache entry is not updated (via {@link #putInCache} and this method is
-     * not called to let OSCache know the update will not be forthcoming, subsequent
-     * requests for this cache entry will either block indefinitely (if this is a new
-     * cache entry or cache.blocking=true), or forever get served stale content. Note
-     * however that there is no harm in cancelling an update on a key that either
-     * does not exist or is not currently being updated.
-     *
-     * @param key The key for the cache entry in question.
-     */
-    public abstract void cancelUpdate(String key);
+	/**
+	 * Flush the cache entry (if any) that corresponds to the cache key
+	 * supplied. This call will flush the entry from the cache and remove the
+	 * references to it from any cache groups that it is a member of. On
+	 * completion of the flush, a <tt>CacheEntryEventType.ENTRY_FLUSHED</tt>
+	 * event is fired.
+	 * 
+	 * @param key
+	 *            The key of the entry to flush
+	 */
+	public abstract void flushEntry(String key);
 
-    /**
-     * Flush all entries in the cache on the given date/time.
-     *
-     * @param date The date at which all cache entries will be flushed.
-     */
-    public abstract void flushAll(Date date);
+	/**
+	 * Flush the cache entry (if any) that corresponds to the cache key
+	 * supplied. This call will mark the cache entry as flushed so that the next
+	 * access to it will cause a {@link NeedsRefreshException}. On completion
+	 * of the flush, a <tt>CacheEntryEventType.ENTRY_FLUSHED</tt> event is
+	 * fired.
+	 * 
+	 * @param key
+	 *            The key of the entry to flush
+	 * @param origin
+	 *            The origin of this flush request (optional)
+	 */
+	public abstract void flushEntry(String key, String origin);
 
-    /**
-     * Flush all entries in the cache on the given date/time.
-     *
-     * @param date The date at which all cache entries will be flushed.
-     * @param origin The origin of this flush request (optional)
-     */
-    public abstract void flushAll(Date date, String origin);
+	/**
+	 * Put an object in the cache specifying the key to use.
+	 * 
+	 * @param key
+	 *            Key of the object in the cache.
+	 * @param content
+	 *            The CacheEntry to cache.
+	 */
+	public abstract CacheEntry put(Object key, CacheEntry content);
 
-    /**
-     * Flush the cache entry (if any) that corresponds to the cache key supplied.
-     * This call will flush the entry from the cache and remove the references to
-     * it from any cache groups that it is a member of. On completion of the flush,
-     * a <tt>CacheEntryEventType.ENTRY_FLUSHED</tt> event is fired.
-     *
-     * @param key The key of the entry to flush
-     */
-    public abstract void flushEntry(String key);
+	/**
+	 * Put an object in the cache specifying the key and refresh policy to use.
+	 * 
+	 * @param key
+	 *            Key of the object in the cache.
+	 * @param content
+	 *            The CacheEntry to cache.
+	 * @param policy
+	 *            Object that implements refresh policy logic
+	 */
+	public abstract CacheEntry put(Object key, CacheEntry content,
+			EntryRefreshPolicy policy);
 
-    /**
-     * Flush the cache entry (if any) that corresponds to the cache key supplied.
-     * This call will mark the cache entry as flushed so that the next access
-     * to it will cause a {@link NeedsRefreshException}. On completion of the
-     * flush, a <tt>CacheEntryEventType.ENTRY_FLUSHED</tt> event is fired.
-     *
-     * @param key The key of the entry to flush
-     * @param origin The origin of this flush request (optional)
-     */
-    public abstract void flushEntry(String key, String origin);
+	/**
+	 * Put an object into the cache specifying both the key to use and the cache
+	 * groups the object belongs to.
+	 * 
+	 * @param key
+	 *            Key of the object in the cache
+	 * @param content
+	 *            The CacheEntry to cache
+	 * @param policy
+	 *            Object that implements the refresh policy logic
+	 */
+	public abstract CacheEntry put(Object key, CacheEntry content,
+			EntryRefreshPolicy policy, String origin);
 
-   
-    /**
-     * Put an object in the cache specifying the key to use.
-     *
-     * @param key       Key of the object in the cache.
-     * @param content   The object to cache.
-     */
-    public abstract void put(Object key, Object content);
+	/**
+	 * Completely clears the cache.
+	 */
+	public abstract void clear();
 
-    /**
-     * Put an object in the cache specifying the key and refresh policy to use.
-     *
-     * @param key       Key of the object in the cache.
-     * @param content   The object to cache.
-     * @param policy   Object that implements refresh policy logic
-     */
-    public abstract void put(Object key, Object content, EntryRefreshPolicy policy);
+	/**
+	 * Completely removes a cache entry from the cache and its associated cache
+	 * groups.
+	 * 
+	 * @param key
+	 *            The key of the entry to remove.
+	 */
+	public abstract CacheEntry removeEntry(String key);
 
-    /**
-     * Put an object into the cache specifying both the key to use and the
-     * cache groups the object belongs to.
-     *
-     * @param key       Key of the object in the cache
-     * @param content   The object to cache
-     * @param policy    Object that implements the refresh policy logic
-     */
-    public abstract void put(Object key, Object content, EntryRefreshPolicy policy, String origin);
-
-    /**
-     * Unregister a listener for Cache events.
-     *
-     * @param listener  The object that currently listens to events.
-     */
-    public abstract void removeCacheEventListener(CacheEventListener listener, Class clazz);
-
-    /**
-    * Completely clears the cache.
-    */
-    public abstract void clear();
-
-    /**
-     * Completely removes a cache entry from the cache and its associated cache
-     * groups.
-     *
-     * @param key The key of the entry to remove.
-     */
-    public abstract void removeEntry(String key);
-
-    public abstract EventListenerList getListenerList();
 }

File src/core/java/com/opensymphony/oscache/base/CacheEntry.java

  */
 package com.opensymphony.oscache.base;
 
-import com.opensymphony.oscache.web.filter.ResponseContent;
-
+import java.io.ByteArrayOutputStream;
+import java.io.IOException;
+import java.io.ObjectOutputStream;
 import java.io.Serializable;
 
-import java.util.Collection;
-import java.util.HashSet;
-import java.util.Set;
-
 /**
  * A CacheEntry instance represents one entry in the cache. It holds the object that
  * is being cached, along with a host of information about that entry such as the
  * cache key, the time it was cached, whether the entry has been flushed or not and
  * the groups it belongs to.
  *
- * @version        $Revision$
  * @author        <a href="mailto:mike@atlassian.com">Mike Cannon-Brookes</a>
  * @author        <a href="mailto:tgochenour@peregrine.com">Todd Gochenour</a>
  * @author <a href="mailto:fbeauregard@pyxis-tech.com">Francois Beauregard</a>
+ * @author <a href="mailto:oscache@andresmarch.com">Andres March</a>
  */
 public class CacheEntry implements Serializable {
     /**
+	 * 
+	 */
+	private static final long serialVersionUID = -3776911995865680219L;
+
+	/**
  * Default initialization value for the creation time and the last
  * update time. This is a placeholder that indicates the value has
  * not been set yet.
  */
     public static final int INDEFINITE_EXPIRY = -1;
 
+	
+
     /**
  * The entry refresh policy object to use for this cache entry. This is optional.
  */
     private EntryRefreshPolicy policy = null;
-    private final EntryUpdateState updateState;
+    
+    
+    
+    private int state;
+    
+    public static final int STATE_VALID = 0;
+    public static final int STATE_STALE = -1;
+    public static final int STATE_UPDATING = 1;
 
     /**
  * The actual content that is being cached. Wherever possible this object
         this(key, null);
     }
 
-    /**
- * Construct a CacheEntry.
- *
- * @param key      The unique key for this <code>CacheEntry</code>.
- * @param policy   Object that implements refresh policy logic. This parameter
- * is optional.
- */
-    public CacheEntry(Object key, EntryRefreshPolicy policy) {
-        this(key, policy, null);
-    }
 
     /**
  * Construct a CacheEntry.
  * @param key     The unique key for this <code>CacheEntry</code>.
  * @param policy  The object that implements the refresh policy logic. This
  * parameter is optional.
- * @param groups  The groups that this <code>CacheEntry</code> belongs to. This
- * parameter is optional.
  */
-    public CacheEntry(Object key, EntryRefreshPolicy policy, String[] groups) {
+    public CacheEntry(Object key, EntryRefreshPolicy policy) {
         this.key = key;
 
         this.policy = policy;
         this.created = System.currentTimeMillis();
-        this.updateState = new EntryUpdateState();
+        this.state = STATE_VALID;
     }
 
-    /**
+    public CacheEntry(Object key, Object value) {
+    		this(key, null);
+    		setContent(value);
+	}
+
+
+	/**
  * Sets the actual content that is being cached. Wherever possible this
  * object should be <code>Serializable</code>, however it is not an
  * absolute requirement when using a memory-only cache. Being <code>Serializable</code>
     /**
  * Get the size of the cache entry in bytes (roughly).<p>
  *
- * Currently this method only handles 
- * {@link ResponseContent} objects.
  *
  * @return The approximate size of the entry in bytes, or -1 if the
  * size could not be estimated.
  */
     public int getSize() {
-        int size = 0;
-
-        if (content.getClass() == String.class) {
-            size += ((content.toString().length() * 2) + 4);
-        } else if (content instanceof ResponseContent) {
-            size += ((ResponseContent) content).getSize();
-        } else {
-            return -1;
-        }
-
-        //add created, lastUpdate, and wasFlushed field sizes (1, 8, and 8)
-        return size + 17;
+    		ByteArrayOutputStream bout = new ByteArrayOutputStream();
+        ObjectOutputStream out;
+		try {
+			out = new ObjectOutputStream(bout);
+			out.writeObject(this);			
+		} catch (IOException e) {
+			// TODO Auto-generated catch block
+			e.printStackTrace();
+			return -1;
+		}
+		byte[] bytes = bout.toByteArray();
+		return bytes.length;
+        
     }
 
     /**
         return needsRefresh;
     }
 
-    public EntryUpdateState getUpdateState() {
-        return updateState;
+    public int getState() {
+        return state;
+    }
+
+
+	public boolean isUpdating() {
+		return state == STATE_UPDATING;
+	}
+
+
+	public void startUpdate() {
+		
+		state = STATE_UPDATING;
+	}
+	
+	/**
+     * Updates the state to <code>UPDATE_CANCELLED</code>. This should <em>only<em>
+     * be called by the thread that managed to get the update lock.
+     */
+    public void cancelUpdate() {
+        if (state != STATE_UPDATING) {
+            throw new IllegalStateException("Cannot cancel cache update - current state (" + state + ") is not UPDATE_IN_PROGRESS");
+        }
+
+        state = STATE_VALID;
+    }
+    
+    /**
+     * Updates the state to <code>UPDATE_COMPLETE</code>. This should <em>only</em>
+     * be called by the thread that managed to get the update lock.
+     */
+    public void completeUpdate() {
+        if (state != STATE_UPDATING) {
+            throw new IllegalStateException("Cannot complete cache update - current state (" + state + ") is not UPDATE_IN_PROGRESS");
+        }
+
+        state = STATE_VALID;
     }
 }

File src/core/java/com/opensymphony/oscache/base/EntryUpdateState.java

         return state == UPDATE_IN_PROGRESS;
     }
 
-    /**
-     * Updates the state to <code>UPDATE_CANCELLED</code>. This should <em>only<em>
-     * be called by the thread that managed to get the update lock.
-     */
-    public void cancelUpdate() {
-        if (state != UPDATE_IN_PROGRESS) {
-            throw new IllegalStateException("Cannot cancel cache update - current state (" + state + ") is not UPDATE_IN_PROGRESS");
-        }
-
-        state = UPDATE_CANCELLED;
-    }
-
-    /**
-     * Updates the state to <code>UPDATE_COMPLETE</code>. This should <em>only</em>
-     * be called by the thread that managed to get the update lock.
-     */
-    public void completeUpdate() {
-        if (state != UPDATE_IN_PROGRESS) {
-            throw new IllegalStateException("Cannot complete cache update - current state (" + state + ") is not UPDATE_IN_PROGRESS");
-        }
-
-        state = UPDATE_COMPLETE;
-    }
 
     /**
      * Attempt to change the state to <code>UPDATE_IN_PROGRESS</code>. Calls

File src/core/java/com/opensymphony/oscache/base/MemoryCache.java

 import java.util.Date;
 import java.util.Map;
 
-import javax.swing.event.EventListenerList;
-
 import org.apache.commons.logging.Log;
 import org.apache.commons.logging.LogFactory;
 
-import com.opensymphony.oscache.base.events.CacheEntryEvent;
-import com.opensymphony.oscache.base.events.CacheEntryEventListener;
-import com.opensymphony.oscache.base.events.CacheEntryEventType;
-import com.opensymphony.oscache.base.events.CacheEventListener;
-import com.opensymphony.oscache.base.events.CacheGroupEvent;
-import com.opensymphony.oscache.base.events.CacheMapAccessEvent;
-import com.opensymphony.oscache.base.events.CacheMapAccessEventListener;
 import com.opensymphony.oscache.base.events.CacheMapAccessEventType;
-import com.opensymphony.oscache.base.events.CachePatternEvent;
-import com.opensymphony.oscache.base.events.CachewideEvent;
-import com.opensymphony.oscache.base.events.CachewideEventType;
-import com.opensymphony.oscache.base.persistence.PersistenceListener;
 import com.opensymphony.oscache.util.FastCronParser;
 
 import edu.emory.mathcs.backport.java.util.concurrent.ConcurrentHashMap;
  * will create a cache that behaves according to its construction parameters.
  * The public API provides methods to manage objects in the cache and configure
  * any cache event listeners.
- *
- * @version        $Revision$
+ * 
+ * @version $Revision$
  * @author <a href="mailto:mike@atlassian.com">Mike Cannon-Brookes</a>
  * @author <a href="mailto:tgochenour@peregrine.com">Todd Gochenour</a>
  * @author <a href="mailto:fbeauregard@pyxis-tech.com">Francois Beauregard</a>
- * @author <a href="&#109;a&#105;&#108;&#116;&#111;:chris&#64;swebtec.&#99;&#111;&#109;">Chris Miller</a>
+ * @author <a
+ *         href="&#109;a&#105;&#108;&#116;&#111;:chris&#64;swebtec.&#99;&#111;&#109;">Chris
+ *         Miller</a>
  */
 public class MemoryCache implements Serializable, Cache {
-    private static transient final Log log = LogFactory.getLog(Cache.class);
+	private static transient final Log log = LogFactory
+			.getLog(MemoryCache.class);
 
-    /**
-     * A list of all registered event listeners for this cache.
-     */
-    protected EventListenerList listenerList = new EventListenerList();
+	/**
+	 * Date of last complete cache flush.
+	 */
+	private Date flushDateTime = null;
 
-    /**
-     * Date of last complete cache flush.
-     */
-    private Date flushDateTime = null;
-
-    /**
-     * The actual cache map. This is where the cached objects are held.
-     */
-    private Map cacheMap = new ConcurrentHashMap();
-
-    private PersistenceListener persistenceListener;
-
-    /**
-     * Indicates whether the cache blocks requests until new content has
-     * been generated or just serves stale content instead.
-     */
-    private boolean blocking = false;
-    private boolean overflowPersistence;
-    private boolean unlimitedDiskCache;
-    private boolean useMemoryCaching;
-    private int capacity;
+	/**
+	 * The actual cache map. This is where the cached objects are held.
+	 */
+	private Map cacheMap = new ConcurrentHashMap();
+	
+	private int capacity; 
 
 	/**
 	 * 
 
 		// TODO Auto-generated constructor stub
 	}
-    /**
-     * Create a new Cache
-     *
-     * @param useMemoryCaching Specify if the memory caching is going to be used
-     * @param unlimitedDiskCache Specify if the disk caching is unlimited
-     * @param overflowPersistence Specify if the persistent cache is used in overflow only mode
-     */
-    public MemoryCache(boolean useMemoryCaching, boolean unlimitedDiskCache, boolean overflowPersistence) {
-        this(useMemoryCaching, unlimitedDiskCache, overflowPersistence, false, 0);
-    }
-
-    /**
-     * Create a new Cache.
-     *
-     * If a valid algorithm class is specified, it will be used for this cache.
-     * Otherwise if a capacity is specified, it will use LRUCache.
-     * If no algorithm or capacity is specified UnlimitedCache is used.
-     *
-     * @see com.opensymphony.oscache.base.algorithm.LRUCache
-     * @see com.opensymphony.oscache.base.algorithm.UnlimitedCache
-     * @param useMemoryCaching Specify if the memory caching is going to be used
-     * @param unlimitedDiskCache Specify if the disk caching is unlimited
-     * @param overflowPersistence Specify if the persistent cache is used in overflow only mode
-     * @param blocking This parameter takes effect when a cache entry has
-     * just expired and several simultaneous requests try to retrieve it. While
-     * one request is rebuilding the content, the other requests will either
-     * block and wait for the new content (<code>blocking == true</code>) or
-     * instead receive a copy of the stale content so they don't have to wait
-     * (<code>blocking == false</code>). the default is <code>false</code>,
-     * which provides better performance but at the expense of slightly stale
-     * data being served.
-     * @param capacity The capacity
-     */
-    public MemoryCache(boolean useMemoryCaching, boolean unlimitedDiskCache, boolean overflowPersistence, boolean blocking, int capacity) {
-        try {
-            cacheMap = new ConcurrentHashMap();
-        } catch (Exception e) {
-            log.error("Invalid class name for cache algorithm class. " + e.toString());
-        }
-
-        this.unlimitedDiskCache = unlimitedDiskCache;
-        this.overflowPersistence = overflowPersistence;
-        this.useMemoryCaching = useMemoryCaching;
-
-        this.blocking = blocking;
-    }
-
-    /**
-	 * @param capacity2
+	
+	/**
+	 * 
 	 */
 	public MemoryCache(int capacity) {
+
 		this.capacity = capacity;
 	}
+
+
+	/*
+	 * (non-Javadoc)
+	 * 
+	 * @see com.opensymphony.oscache.base.Cache#isFlushed(com.opensymphony.oscache.base.CacheEntry)
+	 */
+	public boolean isFlushed(CacheEntry cacheEntry) {
+		if (flushDateTime != null) {
+			long lastUpdate = cacheEntry.getLastUpdate();
+
+			return (flushDateTime.getTime() >= lastUpdate);
+		} else {
+			return false;
+		}
+	}
+
+	/*
+	 * (non-Javadoc)
+	 * 
+	 * @see com.opensymphony.oscache.base.CacheAPI#getFromCache(java.lang.String)
+	 */
+	public CacheEntry get(Object key) {
+		return get(key, CacheEntry.INDEFINITE_EXPIRY, null);
+	}
+
+	/*
+	 * (non-Javadoc)
+	 * 
+	 * @see com.opensymphony.oscache.base.CacheAPI#getFromCache(java.lang.String,
+	 *      int)
+	 */
+	public CacheEntry get(Object key, int refreshPeriod) {
+		return get(key, refreshPeriod, null);
+	}
+
+	/*
+	 * (non-Javadoc)
+	 * 
+	 * @see com.opensymphony.oscache.base.CacheAPI#getFromCache(java.lang.String,
+	 *      int, java.lang.String)
+	 */
+	public CacheEntry get(Object key, int refreshPeriod, String cronExpiry) {
+		CacheEntry cacheEntry = getCacheEntry(key, null, null);
+
+		Object content = cacheEntry.getContent();
+		CacheMapAccessEventType accessEventType = CacheMapAccessEventType.HIT;
+
+		boolean reload = false;
+
+		// Check if this entry has expired or has not yet been added to the
+		// cache. If
+		// so, we need to decide whether to block or serve stale content
+		if (this.isStale(cacheEntry, refreshPeriod, cronExpiry)) {
+
+			synchronized (cacheEntry) {
+				if (!cacheEntry.isUpdating()) {
+					// No one else is currently updating this entry - grab
+					// ownership
+					cacheEntry.startUpdate();
+
+					if (cacheEntry.isNew()) {
+						accessEventType = CacheMapAccessEventType.MISS;
+					} else {
+						accessEventType = CacheMapAccessEventType.STALE_HIT;
+					}
+				} else {
+					// Another thread is already updating the cache. We block if
+					// this
+					// is a new entry, or blocking mode is enabled. Either
+					// putInCache()
+					// or cancelUpdate() can cause this thread to resume.
+					if (cacheEntry.isNew()) {
+						do {
+							try {
+								cacheEntry.wait();
+							} catch (InterruptedException e) {
+							}
+						} while (cacheEntry.isUpdating());
+						
+							// The updating thread cancelled the update, let
+							// this one have a go.
+						cacheEntry.startUpdate();
+
+						if (cacheEntry.isNew()) {
+							accessEventType = CacheMapAccessEventType.MISS;
+						} else {
+							accessEventType = CacheMapAccessEventType.STALE_HIT;
+						}						
+						
+					}
+					reload = true;
+				} 
+			}
+		}
+
+		// If reload is true then another thread must have successfully rebuilt
+		// the cache entry
+		if (reload) {
+			cacheEntry = (CacheEntry) cacheMap.get(key);
+
+			if (cacheEntry != null) {
+				content = cacheEntry.getContent();
+			} else {
+				log
+						.error("Could not reload cache entry after waiting for it to be rebuilt");
+			}
+		}
+
+
+		// If we didn't end up getting a hit then we need to throw a NRE
+		if (accessEventType != CacheMapAccessEventType.HIT) {
+			
+		}
+
+		return cacheEntry;
+	}
+
+	/*
+	 * (non-Javadoc)
+	 * 
+	 * @see com.opensymphony.oscache.base.CacheAPI#cancelUpdate(java.lang.String)
+	 */
+	public void cancelUpdate(String key) {
+
+		if (key != null) {
+			CacheEntry cacheEntry = (CacheEntry) cacheMap.get(key);
+
+			if (cacheEntry != null) {
+				synchronized (cacheEntry) {
+					cacheEntry.cancelUpdate();
+					cacheEntry.notify();
+				}
+			}
+		}
+	}
+
+	/*
+	 * (non-Javadoc)
+	 * 
+	 * @see com.opensymphony.oscache.base.CacheAPI#flushAll(java.util.Date)
+	 */
+	public void flushAll(Date date) {
+		flushAll(date, null);
+	}
+
+	/*
+	 * (non-Javadoc)
+	 * 
+	 * @see com.opensymphony.oscache.base.CacheAPI#flushAll(java.util.Date,
+	 *      java.lang.String)
+	 */
+	public void flushAll(Date date, String origin) {
+		flushDateTime = date;
+	}
+
+	/*
+	 * (non-Javadoc)
+	 * 
+	 * @see com.opensymphony.oscache.base.CacheAPI#flushEntry(java.lang.String)
+	 */
+	public void flushEntry(String key) {
+		flushEntry(key, null);
+	}
+
+	/*
+	 * (non-Javadoc)
+	 * 
+	 * @see com.opensymphony.oscache.base.CacheAPI#flushEntry(java.lang.String,
+	 *      java.lang.String)
+	 */
+	public void flushEntry(String key, String origin) {
+		flushEntry(getCacheEntry(key, null, origin), origin);
+	}
+
+	/*
+	 * (non-Javadoc)
+	 * 
+	 * @see com.opensymphony.oscache.base.CacheAPI#putInCache(java.lang.String,
+	 *      java.lang.Object)
+	 */
+	public CacheEntry put(Object key, CacheEntry cacheEntry) {
+		return put(key, cacheEntry, null);
+	}
+
+	/*
+	 * (non-Javadoc)
+	 * 
+	 * @see com.opensymphony.oscache.base.CacheAPI#putInCache(java.lang.String,
+	 *      java.lang.Object, com.opensymphony.oscache.base.EntryRefreshPolicy)
+	 */
+	public CacheEntry put(Object key, CacheEntry cacheEntry, EntryRefreshPolicy policy) {
+		return put(key, cacheEntry, null, null);
+	}
+
+	/*
+	 * (non-Javadoc)
+	 * 
+	 * @see com.opensymphony.oscache.base.CacheAPI#putInCache(java.lang.String,
+	 *      java.lang.Object, java.lang.String[],
+	 *      com.opensymphony.oscache.base.EntryRefreshPolicy, java.lang.String)
+	 */
+	public CacheEntry put(Object key, CacheEntry cacheEntry, EntryRefreshPolicy policy,
+			String origin) {
+		
+			return (CacheEntry) cacheMap.put(key, cacheEntry);
+	}
+
+	/**
+	 * Get an entry from this cache or create one if it doesn't exist.
+	 * 
+	 * @param key
+	 *            The key of the cache entry
+	 * @param policy
+	 *            Object that implements refresh policy logic
+	 * @param origin
+	 *            The origin of request (optional)
+	 * @return CacheEntry for the specified key.
+	 */
+	protected CacheEntry getCacheEntry(Object key, EntryRefreshPolicy policy,
+			String origin) {
+		CacheEntry cacheEntry = null;
+
+		// Verify that the key is valid
+		if (key == null) {
+			throw new IllegalArgumentException(
+					"getCacheEntry called with an empty or null key");
+		}
+
+		cacheEntry = (CacheEntry) cacheMap.get(key);
+
+		// if the cache entry does not exist, create a new one
+		if (cacheEntry == null) {
+			if (log.isDebugEnabled()) {
+				log.debug("No cache entry exists for key='" + key
+						+ "', creating");
+			}
+
+			cacheEntry = new CacheEntry(key, policy);
+			cacheMap.put(key, cacheEntry);
+		}
+
+		return cacheEntry;
+	}
+
+	/**
+	 * Indicates whether or not the cache entry is stale.
+	 * 
+	 * @param cacheEntry
+	 *            The cache entry to test the freshness of.
+	 * @param refreshPeriod
+	 *            The maximum allowable age of the entry, in seconds.
+	 * @param cronExpiry
+	 *            A cron expression specifying absolute date(s) and/or time(s)
+	 *            that the cache entry should expire at. If the cache entry was
+	 *            refreshed prior to the most recent match for the cron
+	 *            expression, the entry will be considered stale.
+	 * 
+	 * @return <code>true</code> if the entry is stale, <code>false</code>
+	 *         otherwise.
+	 */
+	protected boolean isStale(CacheEntry cacheEntry, int refreshPeriod,
+			String cronExpiry) {
+		boolean result = cacheEntry.needsRefresh(refreshPeriod)
+				|| isFlushed(cacheEntry);
+
+		if ((cronExpiry != null) && (cronExpiry.length() > 0)) {
+			try {
+				FastCronParser parser = new FastCronParser(cronExpiry);
+				result = result
+						|| parser
+								.hasMoreRecentMatch(cacheEntry.getLastUpdate());
+			} catch (ParseException e) {
+				log.warn(e);
+			}
+		}
+
+		return result;
+	}
+
+	/**
+	 * Completely clears the cache.
+	 */
+	public void clear() {
+		cacheMap.clear();
+	}
+
 	
-	/* (non-Javadoc)
-         * @see com.opensymphony.oscache.base.CacheAPI#setCapacity(int)
-         */
-    public void setCapacity(int capacity) {
-        this.capacity = capacity;
-    }
 
-    /* (non-Javadoc)
-         * @see com.opensymphony.oscache.base.CacheAPI#isFlushed(com.opensymphony.oscache.base.CacheEntry)
-         */
-    public boolean isFlushed(CacheEntry cacheEntry) {
-        if (flushDateTime != null) {
-            long lastUpdate = cacheEntry.getLastUpdate();
+	/*
+	 * (non-Javadoc)
+	 * 
+	 * @see com.opensymphony.oscache.base.CacheAPI#removeEntry(java.lang.String)
+	 */
+	public CacheEntry removeEntry(String key) {
+		return removeEntry(key, null);
+	}
 
-            return (flushDateTime.getTime() >= lastUpdate);
-        } else {
-            return false;
-        }
-    }
+	/**
+	 * Completely removes a cache entry from the cache and its associated cache
+	 * groups.
+	 * 
+	 * @param key
+	 *            The key of the entry to remove.
+	 * @param origin
+	 *            The origin of this remove request.
+	 */
+	protected CacheEntry removeEntry(String key, String origin) {
+		CacheEntry cacheEntry = (CacheEntry) cacheMap.get(key);
+		return (CacheEntry) cacheMap.remove(key);
+	}
 
-    /* (non-Javadoc)
-         * @see com.opensymphony.oscache.base.CacheAPI#getFromCache(java.lang.String)
-         */
-    public Object get(Object key){
-        return get(key, CacheEntry.INDEFINITE_EXPIRY, null);
-    }
+	/**
+	 * Flush a cache entry. On completion of the flush, a
+	 * <tt>CacheEntryEventType.ENTRY_FLUSHED</tt> event is fired.
+	 * 
+	 * @param entry
+	 *            The entry to flush
+	 * @param origin
+	 *            The origin of this flush event (optional)
+	 */
+	private void flushEntry(CacheEntry entry, String origin) {
+		Object key = entry.getKey();
 
-    /* (non-Javadoc)
-         * @see com.opensymphony.oscache.base.CacheAPI#getFromCache(java.lang.String, int)
-         */
-    public Object get(Object key, int refreshPeriod){
-        return get(key, refreshPeriod, null);
-    }
+		// Flush the object itself
+		entry.flush();
 
-    /* (non-Javadoc)
-         * @see com.opensymphony.oscache.base.CacheAPI#getFromCache(java.lang.String, int, java.lang.String)
-         */
-    public Object get(Object key, int refreshPeriod, String cronExpiry){
-        CacheEntry cacheEntry = getCacheEntry(key, null, null);
+		if (!entry.isNew()) {
+			// Update the entry's state in the map
+			cacheMap.put(key, entry);
+		}
 
-        Object content = cacheEntry.getContent();
-        CacheMapAccessEventType accessEventType = CacheMapAccessEventType.HIT;
+	}
 
-        boolean reload = false;
+	/**
+	 * @return Returns the capacity.
+	 */
+	public int getCapacity() {
+		return capacity;
+	}
 
-        // Check if this entry has expired or has not yet been added to the cache. If
-        // so, we need to decide whether to block, serve stale content or throw a
-        // NeedsRefreshException
-        if (this.isStale(cacheEntry, refreshPeriod, cronExpiry)) {
-			
-			
-            EntryUpdateState updateState = cacheEntry.getUpdateState();
-            synchronized (updateState) {
-                if (updateState.isAwaitingUpdate() || updateState.isCancelled() || updateState.isComplete()) {
-                    // No one else is currently updating this entry - grab ownership
-                    updateState.startUpdate();
+	/**
+	 * @param capacity The capacity to set.
+	 */
+	public void setCapacity(int capacity) {
+		this.capacity = capacity;
+	}
 
-                    if (cacheEntry.isNew()) {
-                        accessEventType = CacheMapAccessEventType.MISS;
-                    } else {
-                        accessEventType = CacheMapAccessEventType.STALE_HIT;
-                    }
-                } else if (updateState.isUpdating()) {
-                    // Another thread is already updating the cache. We block if this
-                    // is a new entry, or blocking mode is enabled. Either putInCache()
-                    // or cancelUpdate() can cause this thread to resume.
-                    if (cacheEntry.isNew() || blocking) {
-                        do {
-                            try {
-                                updateState.wait();
-                            } catch (InterruptedException e) {
-                            }
-                        } while (updateState.isUpdating());
 
-                        if (updateState.isCancelled()) {
-                            // The updating thread cancelled the update, let this one have a go.
-                            updateState.startUpdate();
-
-                            if (cacheEntry.isNew()) {
-                                accessEventType = CacheMapAccessEventType.MISS;
-                            } else {
-                                accessEventType = CacheMapAccessEventType.STALE_HIT;
-                            }
-                        } else if (updateState.isComplete()) {
-                            reload = true;
-                        } else {
-                            log.error("Invalid update state for cache entry " + key);
-                        }
-                    }
-                } else {
-                    reload = true;
-                }
-            }
-        }
-
-        // If reload is true then another thread must have successfully rebuilt the cache entry
-        if (reload) {
-            cacheEntry = (CacheEntry) cacheMap.get(key);
-
-            if (cacheEntry != null) {
-                content = cacheEntry.getContent();
-            } else {
-                log.error("Could not reload cache entry after waiting for it to be rebuilt");
-            }
-        }
-
-        dispatchCacheMapAccessEvent(accessEventType, cacheEntry, null);
-
-        // If we didn't end up getting a hit then we need to throw a NRE
-        if (accessEventType != CacheMapAccessEventType.HIT) {
-//            throw new NeedsRefreshException(content);
-        }
-
-        return content;
-    }
-
-    /* (non-Javadoc)
-         * @see com.opensymphony.oscache.base.CacheAPI#setPersistenceListener(com.opensymphony.oscache.base.persistence.PersistenceListener)
-         */
-    public void setPersistenceListener(PersistenceListener listener) {
-        this.persistenceListener = listener;
-    }
-
-    /* (non-Javadoc)
-         * @see com.opensymphony.oscache.base.CacheAPI#getPersistenceListener()
-         */
-    public PersistenceListener getPersistenceListener() {
-        return this.persistenceListener;
-    }
-
-    /* (non-Javadoc)
-         * @see com.opensymphony.oscache.base.CacheAPI#addCacheEventListener(com.opensymphony.oscache.base.events.CacheEventListener, java.lang.Class)
-         */
-    public void addCacheEventListener(CacheEventListener listener, Class clazz) {
-        if (CacheEventListener.class.isAssignableFrom(clazz)) {
-            listenerList.add(clazz, listener);
-        } else {
-            log.error("The class '" + clazz.getName() + "' is not a CacheEventListener. Ignoring this listener.");
-        }
-    }
-
-    /* (non-Javadoc)
-         * @see com.opensymphony.oscache.base.CacheAPI#cancelUpdate(java.lang.String)
-         */
-    public void cancelUpdate(String key) {
-        EntryUpdateState state;
-
-        if (key != null) {
-            CacheEntry cacheEntry = (CacheEntry) cacheMap.get(key);
-            state = (EntryUpdateState) cacheEntry.getUpdateState();
-
-            if (state != null) {
-                synchronized (state) {
-                    state.cancelUpdate();
-                    state.notify();
-                }
-            }
-        }
-    }
-
-    /* (non-Javadoc)
-         * @see com.opensymphony.oscache.base.CacheAPI#flushAll(java.util.Date)
-         */
-    public void flushAll(Date date) {
-        flushAll(date, null);
-    }
-
-    /* (non-Javadoc)
-         * @see com.opensymphony.oscache.base.CacheAPI#flushAll(java.util.Date, java.lang.String)
-         */
-    public void flushAll(Date date, String origin) {
-        flushDateTime = date;
-
-        if (listenerList.getListenerCount() > 0) {
-            dispatchCachewideEvent(CachewideEventType.CACHE_FLUSHED, date, origin);
-        }
-    }
-
-    /* (non-Javadoc)
-         * @see com.opensymphony.oscache.base.CacheAPI#flushEntry(java.lang.String)
-         */
-    public void flushEntry(String key) {
-        flushEntry(key, null);
-    }
-
-    /* (non-Javadoc)
-         * @see com.opensymphony.oscache.base.CacheAPI#flushEntry(java.lang.String, java.lang.String)
-         */
-    public void flushEntry(String key, String origin) {
-        flushEntry(getCacheEntry(key, null, origin), origin);
-    }
-
-    /* (non-Javadoc)
-         * @see com.opensymphony.oscache.base.CacheAPI#putInCache(java.lang.String, java.lang.Object)
-         */
-    public void put(Object key, Object content) {
-        put(key, content, null);
-    }
-
-    /* (non-Javadoc)
-         * @see com.opensymphony.oscache.base.CacheAPI#putInCache(java.lang.String, java.lang.Object, com.opensymphony.oscache.base.EntryRefreshPolicy)
-         */
-    public void put(Object key, Object content, EntryRefreshPolicy policy) {
-        put(key, content, null, null);
-    }
-
-    /* (non-Javadoc)
-         * @see com.opensymphony.oscache.base.CacheAPI#putInCache(java.lang.String, java.lang.Object, java.lang.String[], com.opensymphony.oscache.base.EntryRefreshPolicy, java.lang.String)
-         */
-    public void put(Object key, Object content, EntryRefreshPolicy policy, String origin) {
-        CacheEntry cacheEntry = getCacheEntry(key, policy, origin);
-        boolean isNewEntry = cacheEntry.isNew();
-
-        synchronized (cacheEntry) {
-            cacheEntry.setContent(content);
-            cacheMap.put(key, cacheEntry);
-           
-        }
-
-        // Signal to any threads waiting on this update that it's now ready for them
-        // in the cache!
-        completeUpdate(cacheEntry);
-
-        if (listenerList.getListenerCount() > 0) {
-            CacheEntryEvent event = new CacheEntryEvent(this, cacheEntry, origin);
-
-            if (isNewEntry) {
-                dispatchCacheEntryEvent(CacheEntryEventType.ENTRY_ADDED, event);
-            } else {
-                dispatchCacheEntryEvent(CacheEntryEventType.ENTRY_UPDATED, event);
-            }
-        }
-    }
-
-
-    /* (non-Javadoc)
-         * @see com.opensymphony.oscache.base.CacheAPI#removeCacheEventListener(com.opensymphony.oscache.base.events.CacheEventListener, java.lang.Class)
-         */
-    public void removeCacheEventListener(CacheEventListener listener, Class clazz) {
-        listenerList.remove(clazz, listener);
-    }
-
-    /**
-     * Get an entry from this cache or create one if it doesn't exist.
-     *
-     * @param key    The key of the cache entry
-     * @param policy Object that implements refresh policy logic
-     * @param origin The origin of request (optional)
-     * @return CacheEntry for the specified key.
-     */
-    protected CacheEntry getCacheEntry(Object key, EntryRefreshPolicy policy, String origin) {
-        CacheEntry cacheEntry = null;
-
-        // Verify that the key is valid
-        if (key == null) {
-            throw new IllegalArgumentException("getCacheEntry called with an empty or null key");
-        }
-
-        cacheEntry = (CacheEntry) cacheMap.get(key);
-
-        // if the cache entry does not exist, create a new one
-        if (cacheEntry == null) {
-            if (log.isDebugEnabled()) {
-                log.debug("No cache entry exists for key='" + key + "', creating");
-            }
-
-            cacheEntry = new CacheEntry(key, policy);
-            cacheMap.put(key, cacheEntry);
-        }
-
-        return cacheEntry;
-    }
-
-    /**
-     * Indicates whether or not the cache entry is stale.
-     *
-     * @param cacheEntry     The cache entry to test the freshness of.
-     * @param refreshPeriod  The maximum allowable age of the entry, in seconds.
-     * @param cronExpiry     A cron expression specifying absolute date(s) and/or time(s)
-     * that the cache entry should expire at. If the cache entry was refreshed prior to
-     * the most recent match for the cron expression, the entry will be considered stale.
-     *
-     * @return <code>true</code> if the entry is stale, <code>false</code> otherwise.
-     */
-    protected boolean isStale(CacheEntry cacheEntry, int refreshPeriod, String cronExpiry) {
-        boolean result = cacheEntry.needsRefresh(refreshPeriod) || isFlushed(cacheEntry);
-
-        if ((cronExpiry != null) && (cronExpiry.length() > 0)) {
-            try {
-                FastCronParser parser = new FastCronParser(cronExpiry);
-                result = result || parser.hasMoreRecentMatch(cacheEntry.getLastUpdate());
-            } catch (ParseException e) {
-                log.warn(e);
-            }
-        }
-
-        return result;
-    }
-
-    /**
-     * Completely clears the cache.
-     */
-    public void clear() {
-        cacheMap.clear();
-    }
-
-    /**
-     * Removes the update state for the specified key and notifies any other
-     * threads that are waiting on this object. This is called automatically
-     * by the {@link #putInCache} method.
-     *
-     * @param key The cache key that is no longer being updated.
-     */
-    protected void completeUpdate(CacheEntry cacheEntry) {
-        EntryUpdateState state;
-
-        state = (EntryUpdateState) cacheEntry.getUpdateState();
-
-        if (state != null) {
-            synchronized (state) {
-                if (!state.isUpdating()) {
-                    state.startUpdate();
-                }
-
-                state.completeUpdate();
-                state.notifyAll();
-            }
-        }
-    }
-
-    /* (non-Javadoc)
-         * @see com.opensymphony.oscache.base.CacheAPI#removeEntry(java.lang.String)
-         */
-    public void removeEntry(String key) {
-        removeEntry(key, null);
-    }
-
-    /**
-     * Completely removes a cache entry from the cache and its associated cache
-     * groups.
-     *
-     * @param key    The key of the entry to remove.
-     * @param origin The origin of this remove request.
-     */
-    protected void removeEntry(String key, String origin) {
-        CacheEntry cacheEntry = (CacheEntry) cacheMap.get(key);
-        cacheMap.remove(key);
-
-        if (listenerList.getListenerCount() > 0) {
-            CacheEntryEvent event = new CacheEntryEvent(this, cacheEntry, origin);
-            dispatchCacheEntryEvent(CacheEntryEventType.ENTRY_REMOVED, event);
-        }
-    }
-
-    /**
-     * Dispatch a cache entry event to all registered listeners.
-     *
-     * @param eventType   The type of event (used to branch on the proper method)
-     * @param event       The event that was fired
-     */
-    private void dispatchCacheEntryEvent(CacheEntryEventType eventType, CacheEntryEvent event) {
-        // Guaranteed to return a non-null array
-        Object[] listeners = listenerList.getListenerList();
-
-        // Process the listeners last to first, notifying
-        // those that are interested in this event
-        for (int i = listeners.length - 2; i >= 0; i -= 2) {
-            if (listeners[i] == CacheEntryEventListener.class) {
-                if (eventType.equals(CacheEntryEventType.ENTRY_ADDED)) {
-                    ((CacheEntryEventListener) listeners[i + 1]).cacheEntryAdded(event);
-                } else if (eventType.equals(CacheEntryEventType.ENTRY_UPDATED)) {
-                    ((CacheEntryEventListener) listeners[i + 1]).cacheEntryUpdated(event);
-                } else if (eventType.equals(CacheEntryEventType.ENTRY_FLUSHED)) {
-                    ((CacheEntryEventListener) listeners[i + 1]).cacheEntryFlushed(event);
-                } else if (eventType.equals(CacheEntryEventType.ENTRY_REMOVED)) {
-                    ((CacheEntryEventListener) listeners[i + 1]).cacheEntryRemoved(event);
-                }
-            }
-        }
-    }
-
-    /**
-     * Dispatch a cache group event to all registered listeners.
-     *
-     * @param eventType The type of event (this is used to branch to the correct method handler)
-     * @param group     The cache group that the event applies to
-     * @param origin      The origin of this event (optional)
-     */
-    private void dispatchCacheGroupEvent(CacheEntryEventType eventType, String group, String origin) {
-        CacheGroupEvent event = new CacheGroupEvent(this, group, origin);
-
-        // Guaranteed to return a non-null array
-        Object[] listeners = listenerList.getListenerList();
-
-        // Process the listeners last to first, notifying
-        // those that are interested in this event
-        for (int i = listeners.length - 2; i >= 0; i -= 2) {
-            if (listeners[i] == CacheEntryEventListener.class) {
-                if (eventType.equals(CacheEntryEventType.GROUP_FLUSHED)) {
-                    ((CacheEntryEventListener) listeners[i + 1]).cacheGroupFlushed(event);
-                }
-            }
-        }
-    }
-
-    /**
-     * Dispatch a cache map access event to all registered listeners.
-     *
-     * @param eventType     The type of event
-     * @param entry         The entry that was affected.
-     * @param origin        The origin of this event (optional)
-     */
-    private void dispatchCacheMapAccessEvent(CacheMapAccessEventType eventType, CacheEntry entry, String origin) {
-        CacheMapAccessEvent event = new CacheMapAccessEvent(eventType, entry, origin);
-
-        // Guaranteed to return a non-null array
-        Object[] listeners = listenerList.getListenerList();
-
-        // Process the listeners last to first, notifying
-        // those that are interested in this event
-        for (int i = listeners.length - 2; i >= 0; i -= 2) {
-            if (listeners[i] == CacheMapAccessEventListener.class) {
-                ((CacheMapAccessEventListener) listeners[i + 1]).accessed(event);
-            }
-        }
-    }
-
-    /**
-     * Dispatch a cache pattern event to all registered listeners.
-     *
-     * @param eventType The type of event (this is used to branch to the correct method handler)
-     * @param pattern     The cache pattern that the event applies to
-     * @param origin      The origin of this event (optional)
-     */
-    private void dispatchCachePatternEvent(CacheEntryEventType eventType, String pattern, String origin) {
-        CachePatternEvent event = new CachePatternEvent(this, pattern, origin);
-
-        // Guaranteed to return a non-null array
-        Object[] listeners = listenerList.getListenerList();
-
-        // Process the listeners last to first, notifying
-        // those that are interested in this event
-        for (int i = listeners.length - 2; i >= 0; i -= 2) {
-            if (listeners[i] == CacheEntryEventListener.class) {
-                if (eventType.equals(CacheEntryEventType.PATTERN_FLUSHED)) {
-                    ((CacheEntryEventListener) listeners[i + 1]).cachePatternFlushed(event);
-                }
-            }
-        }
-    }
-
-    /**
-     * Dispatches a cache-wide event to all registered listeners.
-     *
-     * @param eventType The type of event (this is used to branch to the correct method handler)
-     * @param origin The origin of this event (optional)
-     */
-    private void dispatchCachewideEvent(CachewideEventType eventType, Date date, String origin) {
-        CachewideEvent event = new CachewideEvent(this, date, origin);
-
-        // Guaranteed to return a non-null array
-        Object[] listeners = listenerList.getListenerList();
-
-        // Process the listeners last to first, notifying
-        // those that are interested in this event
-        for (int i = listeners.length - 2; i >= 0; i -= 2) {
-            if (listeners[i] == CacheEntryEventListener.class) {
-                if (eventType.equals(CachewideEventType.CACHE_FLUSHED)) {
-                    ((CacheEntryEventListener) listeners[i + 1]).cacheFlushed(event);
-                }
-            }
-        }
-    }
-
-    /**
-     * Flush a cache entry. On completion of the flush, a
-     * <tt>CacheEntryEventType.ENTRY_FLUSHED</tt> event is fired.
-     *
-     * @param entry The entry to flush
-     * @param origin The origin of this flush event (optional)
-     */
-    private void flushEntry(CacheEntry entry, String origin) {
-    	Object key = entry.getKey();
-
-        // Flush the object itself
-        entry.flush();
-
-        if (!entry.isNew()) {
-            // Update the entry's state in the map
-            cacheMap.put(key, entry);
-        }
-
-        // Trigger an ENTRY_FLUSHED event. [CACHE-107] Do this for all flushes.
-        if (listenerList.getListenerCount() > 0) {
-            CacheEntryEvent event = new CacheEntryEvent(this, entry, origin);
-            dispatchCacheEntryEvent(CacheEntryEventType.ENTRY_FLUSHED, event);
-        }
-    }
-
-    public EventListenerList getListenerList() {
-        return listenerList;
-    }
 }

File src/core/java/com/opensymphony/oscache/general/GeneralCacheAdministrator.java

     private static transient final Log log = LogFactory.getLog(GeneralCacheAdministrator.class);
 
     /**
-     * Application cache
-     */
-    private Cache applicationCache = null;
-
-    /**
      * Create the cache administrator.
      */
     public GeneralCacheAdministrator() {
     }
 
     /**
-     * Grabs a cache
-     *
-     * @return The cache
-     */
-    public Cache getCache() {
-        return applicationCache;
-    }
-
-    /**
      * Remove an object from the cache
      *
      * @param key             The key entered by the user.
     }
 
     /**
-     * Put an object in a cache
-     *
-     * @param key       The key entered by the user
-     * @param content   The object to store
-     * @param policy    Object that implements refresh policy logic
-     */
-    public void putInCache(String key, Object content, EntryRefreshPolicy policy) {
-        Cache cache = getCache();
-        cache.put(key, content, policy);
-    }
-
-    /**
-     * Put an object in a cache
-     *
-     * @param key       The key entered by the user
-     * @param content   The object to store
-     */
-    public void putInCache(String key, Object content) {
-        putInCache(key, content, (EntryRefreshPolicy) null);
-    }
-
-    /**
      * Sets the cache capacity (number of items). If the cache contains
      * more than <code>capacity</code> items then items will be removed
      * to bring the cache back down to the new size.
     private void createCache() {
         log.info("Creating new cache");
 
-        applicationCache = new MemoryCache(isMemoryCaching(), isUnlimitedDiskCache(), isOverflowPersistence(), isBlocking(), cacheCapacity);
+        applicationCache = new MemoryCache(cacheCapacity);
 
         configureStandardListeners(applicationCache);
     }

File src/core/test/com/opensymphony/oscache/base/TestAbstractCacheAdministrator.java

  * @version        $Revision$
  * @author <a href="mailto:abergevin@pyxis-tech.com">Alain Bergevin</a>
  */
-public abstract class TestAbstractCacheAdministrator extends TestCase {
+public class TestAbstractCacheAdministrator extends TestCase {
     // Constants used in the tests
     private final String CACHE_PATH_PROP = "cache.path";
     private final String CONTENT = "Content for the abstract cache admin test";
     private final String INVALID_PROP_NAME = "INVALID_PROP_NAME";
     private final String TEST_LOG = "test log";
 
-    /**
-     * Constructor for the this test class.
-     * <p>
-     * @param str Test name (required by JUnit)
-     */
-    protected TestAbstractCacheAdministrator(String str) {
-        super(str);
+   
+
+    public void testGetAndPut() {
+    		AbstractCacheAdministrator admin = getAdmin();
+    		admin.setApplicationCache(new MemoryCache());
+    		Object value = admin.get(ENTRY_KEY);
+    		assertNull(value);
+    		admin.put(ENTRY_KEY, CONTENT);
+    		value = admin.get(ENTRY_KEY);
+    		assertEquals(value, CONTENT);    		
     }
-
+    
     /**
      * Cannot be tested since CacheContents is an interface
      */
     }
 
     // Abstract method that returns an instance of an admin
-    protected abstract AbstractCacheAdministrator getAdmin();
+    protected AbstractCacheAdministrator getAdmin() {
+    		return new AbstractCacheAdministrator() {
+    		};
+    }
 }