Anonymous avatar Anonymous committed 6facee2

Submitter: Andres March

major refactorings to move towards 3.0. ACRC is gone, yay! basic memory cache in place.

Comments (0)

Files changed (61)

src/core/java/com/opensymphony/oscache/algorithm/LRUEvictionAlgorithm.java

+package com.opensymphony.oscache.algorithm;
+
+import java.util.Iterator;
+import java.util.LinkedHashSet;
+import java.util.Properties;
+import java.util.Set;
+
+import com.opensymphony.oscache.core.EvictionAlgorithm;
+
+/**
+ * An {@link EvictionAlgorithm} that evicts cache entries based on
+ * a least recently used (LRU) algorithm.
+ */
+public class LRUEvictionAlgorithm implements EvictionAlgorithm {
+  
+  /**
+   * A configuration parameter that specifies the maximum size of the cache before
+   * elements start getting evicted.
+   */
+  public static final String SIZE_PARAM = "maxSize";
+  private static final int DEFAULT_SIZE = 1000;
+
+  private int maxSize = DEFAULT_SIZE;
+
+  private Set elements = new LinkedHashSet();
+
+  /**
+   * Configures the LRU policy. Valid parameters are:
+   * <ul>
+   * <li>{@link #SIZE_PARAM} - the maximum number of entries to hold in the cache</li>
+   * </ul>
+   *
+   * @param params
+   */
+  public void init(Properties params) {
+    String sizeStr = (String) params.get(SIZE_PARAM);
+    if (sizeStr != null) {
+      try {
+        maxSize = Integer.parseInt(sizeStr);
+      } catch (NumberFormatException e) {
+        //log.warn("The '" + SIZE_PARAM + "' parameter for the LRU eviciton policy is not a valid integer. Defaulting to " + DEFAULT_SIZE);
+      }
+    }
+  }
+
+  /**
+   * Called when an object is put in the cache. This causes the LRU algorithm
+   * to update its internal data structure.
+   */
+  public void put(Object key, Object value) {
+    // Move the key to the back of the set
+    elements.remove(key);
+    elements.add(key);
+  }
+
+  /**
+   * Called when an object is retrieved from the cache. This causes the LRU
+   * algorithm to update its internal data structure.
+   */
+  public void get(Object key, Object value) {
+    // Move the key to the back of the set
+    elements.remove(key);
+    elements.add(key);
+  }
+
+  /**
+   * Called when an object is removed from the cache. This causes the LRU
+   * algorithm to update its internal data structure.
+   *
+   * @param key
+   * @param value
+   */
+  public void remove(Object key, Object value) {
+    elements.remove(key);
+  }
+
+  /**
+   * Evict a cache entry if the cache has grown too large. The entry to be evicted
+   * will be the one that was used least-recently.
+   *
+   * @return the object that was evicted, or <code>null</code> if the cache
+   *         has not yet reached the specified maximum size.
+   */
+  public Object evict() {
+    Object toEvict = null;
+    if (elements.size() > maxSize) {
+      // Remove the first element (this is the one that was used least-recently)
+      Iterator it = elements.iterator();
+      toEvict = it.next();
+      it.remove();
+    }
+    return toEvict;
+  }
+}

src/core/java/com/opensymphony/oscache/algorithm/package.html

+<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 3.2 Final//EN">
+<html>
+<head>
+<!--
+
+  @(#)package.html
+
+  Copyright (c) 2002-2003 by OpenSymphony
+  All rights reserved.
+
+-->
+</head>
+<body bgcolor="white">
+
+Provides the classes that implement the caching algorithms used by OSCache, all of
+which are based on a derivative of Doug Lea's <code>ConcurrentReaderHashMap</code>.
+
+
+<h2>Package Specification</h2>
+
+<h2>Related Documentation</h2>
+
+
+For overviews, tutorials, examples, guides, and tool documentation, please see:
+<ul>
+  <li><a href="http://www.opensymphony.com/oscache">The OSCache Homepage</a>
+</ul>
+
+For further information on Doug Lea's concurrency package, please see:
+<ul>
+  <li><a href="http://gee.cs.oswego.edu/dl/classes/EDU/oswego/cs/dl/util/concurrent/intro.html">http://gee.cs.oswego.edu/dl/classes/EDU/oswego/cs/dl/util/concurrent/intro.html</a>
+</ul>
+
+<!-- Put @see and @since tags down here. -->
+
+</body>
+</html>

src/core/java/com/opensymphony/oscache/base/algorithm/FIFOCache.java

-/*
- * Copyright (c) 2002-2003 by OpenSymphony
- * All rights reserved.
- */
-package com.opensymphony.oscache.base.algorithm;
-
-import java.util.Collection;
-import java.util.Iterator;
-import java.util.LinkedHashSet;
-import java.util.LinkedList;
-import java.util.List;
-
-import com.opensymphony.oscache.base.MemoryCache;
-
-/**
- * FIFO (First In First Out) based queue algorithm for the cache.
- *
- * No synchronization is required in this class since the
- * <code>AbstractConcurrentReadCache</code> already takes care of any
- * synchronization requirements.
- *
- * @version        $Revision$
- * @author        <a href="mailto:mike@atlassian.com">Mike Cannon-Brookes</a>
- * @author        <a href="mailto:abergevin@pyxis-tech.com">Alain Bergevin</a>
- * @author        <a href="&#109;a&#105;&#108;&#116;&#111;:chris&#64;swebtec.&#99;&#111;&#109;">Chris Miller</a>
- */
-public class FIFOCache extends MemoryCache {
-    /**
-     * A queue containing all cache keys
-     */
-    private Collection list;
-
-    /**
-     * A flag indicating whether we are using a List or a Set for the key collection
-     */
-    private boolean isSet = false;
-
-    /**
-     * Constructs a FIFO Cache.
-     */
-    public FIFOCache() {
-        super();
-
-        // Check if we're running under JRE 1.4+. If so we can use a LinkedHashSet
-        // instead of a LinkedList for a big performance boost when removing elements.
-        try {
-            Class.forName("java.util.LinkedHashSet");
-            list = new LinkedHashSet();
-            isSet = true;
-        } catch (ClassNotFoundException e) {
-            list = new LinkedList();
-        }
-    }
-
-    /**
-     * Constructs a FIFO Cache of the specified capacity.
-     *
-     * @param capacity The maximum cache capacity.
-     */
-    public FIFOCache(int capacity) {
-        super(capacity);
-    }
-
-    /**
-     * An object was retrieved from the cache. This implementation
-     * does noting since this event has no impact on the FIFO algorithm.
-     *
-     * @param key The cache key of the item that was retrieved.
-     */
-    protected void itemRetrieved(Object key) {
-    }
-
-    /**
-     * An object was put in the cache. This implementation just adds
-     * the key to the end of the list if it doesn't exist in the list
-     * already.
-     *
-     * @param key The cache key of the item that was put.
-     */
-    protected void itemPut(Object key) {
-        if (!list.contains(key)) {
-            list.add(key);
-        }
-    }
-
-    /**
-     * An item needs to be removed from the cache. The FIFO implementation
-     * removes the first element in the list (ie, the item that has been in
-     * the cache for the longest time).
-     *
-     * @return The key of whichever item was removed.
-     */
-    protected Object removeItem() {
-        Object toRemove;
-
-        if (isSet) {
-            Iterator it = list.iterator();
-            toRemove = it.next();
-            it.remove();
-        } else {
-            toRemove = ((List) list).remove(0);
-        }
-
-        return toRemove;
-    }
-
-    /**
-     * Remove specified key since that object has been removed from the cache.
-     *
-     * @param key The cache key of the item that was removed.
-     */
-    protected void itemRemoved(Object key) {
-        list.remove(key);
-    }
-}

src/core/java/com/opensymphony/oscache/base/algorithm/LRUCache.java

-/*
- * Copyright (c) 2002-2003 by OpenSymphony
- * All rights reserved.
- */
-package com.opensymphony.oscache.base.algorithm;
-
-import com.opensymphony.oscache.base.MemoryCache;
-import com.opensymphony.oscache.util.ClassLoaderUtil;
-
-import org.apache.commons.collections.SequencedHashMap;
-import org.apache.commons.logging.Log;
-import org.apache.commons.logging.LogFactory;
-
-import java.util.*;
-
-/**
- * <p>LRU (Least Recently Used) algorithm for the cache.</p>
- *
- * <p>This class tries to provide the best possible performance by first
- * attempting to use the JDK 1.4.x <code>LinkedHashSet</code> class,
- * followed by the Jakarta commons-collections <code>SequencedHashMap</code>
- * class, and finally resorting to the <code>LinkedList</code> class if
- * neither of the above classes are available. If this class has to revert
- * to using a <code>LinkedList</code> a warning is logged since the performance
- * penalty can be severe.</p>
- *
- * <p>No synchronization is required in this class since the
- * <code>AbstractConcurrentReadCache</code> already takes care of any
- * synchronization requirements.</p>
- *
- * @version        $Revision$
- * @author <a href="mailto:salaman@teknos.com">Victor Salaman</a>
- * @author <a href="mailto:fbeauregard@pyxis-tech.com">Francois Beauregard</a>
- * @author <a href="mailto:abergevin@pyxis-tech.com">Alain Bergevin</a>
- * @author <a href="&#109;a&#105;&#108;&#116;&#111;:chris&#64;swebtec.&#99;&#111;&#109;">Chris Miller</a>
- */
-public class LRUCache extends MemoryCache {
-    private static final Log log = LogFactory.getLog(LRUCache.class);
-
-    /**
-     * Cache queue containing all cache keys.
-     */
-    private Collection list;
-
-    /**
-     * Jakarta commons collections unfortunately doesn't provide us with an ordered
-     * hash set, so we have to use their ordered map instead.
-     */
-    private Map map;
-
-    /**
-     * A flag indicating if we are using a List for the key collection. This happens
-     * when we're running under JDK 1.3 or lower and there is no commons-collections
-     * in the classpath.
-     */
-    private boolean isList = false;
-
-    /**
-     * A flag indicating if we are using a Map for the key collection. This happens
-     * when we're running under JDK 1.3 and commons-collections is available.
-     */
-    private boolean isMap = false;
-
-    /**
-     * A flag indicating if we are using a Set for the key collection. This happens
-     * when we're running under JDK 1.4 and is the best case scenario.
-     */
-    private boolean isSet = false;
-
-    /**
-     * A flag indicating whether there is a removal operation in progress.
-     */
-    private volatile boolean removeInProgress = false;
-
-    /**
-     * Constructs an LRU Cache.
-     */
-    public LRUCache() {
-        super();
-
-        // Decide if we're running under JRE 1.4+. If so we can use a LinkedHashSet
-        // instead of a LinkedList for a big performance boost when removing elements.
-        try {
-            ClassLoaderUtil.loadClass("java.util.LinkedHashSet", this.getClass());
-            list = new LinkedHashSet();
-            isSet = true;
-        } catch (ClassNotFoundException e) {
-            // There's no LinkedHashSet available so we'll try for the jakarta-collections
-            // SequencedHashMap instead [CACHE-47]
-            try {
-                ClassLoaderUtil.loadClass("org.apache.commons.collections.SequencedHashMap", this.getClass());
-                map = new SequencedHashMap();
-                isMap = true;
-            } catch (ClassNotFoundException e1) {
-                // OK, time to get all inefficient and resort to a LinkedList. We log this
-                // as a warning since it potentially can have a big impact.
-                log.warn("When using the LRUCache under JRE 1.3.x, commons-collections.jar should be added to your classpath to increase OSCache's performance.");
-                list = new LinkedList();
-                isList = true;
-            }
-        }
-    }
-
-    /**
-     * Constructors a LRU Cache of the specified capacity.
-     *
-     * @param capacity The maximum cache capacity.
-     */
-    public LRUCache(int capacity) {
-        super(capacity);
-    }
-
-    /**
-     * An item was retrieved from the list. The LRU implementation moves
-     * the retrieved item's key to the front of the list.
-     *
-     * @param key The cache key of the item that was retrieved.
-     */
-    protected void itemRetrieved(Object key) {
-        // Prevent list operations during remove
-        while (removeInProgress) {
-            try {
-                Thread.sleep(5);
-            } catch (InterruptedException ie) {
-            }
-        }
-
-        // We need to synchronize here because AbstractConcurrentReadCache
-        // doesn't prevent multiple threads from calling this method simultaneously.
-        if (isMap) {
-            synchronized (map) {
-                map.remove(key);
-                map.put(key, Boolean.TRUE);
-            }
-        } else {
-            synchronized (list) {
-                list.remove(key);
-                list.add(key);
-            }
-        }
-    }
-
-    /**
-     * An object was put in the cache. This implementation adds/moves the
-     * key to the end of the list.
-     *
-     * @param key The cache key of the item that was put.
-     */
-    protected void itemPut(Object key) {
-        // Since this entry was just accessed, move it to the back of the list.
-        if (isMap) {
-            synchronized (map) { // A further fix for CACHE-44
-                map.remove(key);
-                map.put(key, Boolean.TRUE);
-            }
-        } else {
-            synchronized (list) { // A further fix for CACHE-44
-                list.remove(key);
-                list.add(key);
-            }
-        }
-    }
-
-    /**
-     * An item needs to be removed from the cache. The LRU implementation
-     * removes the first element in the list (ie, the item that was least-recently
-     * accessed).
-     *
-     * @return The key of whichever item was removed.
-     */
-    protected Object removeItem() {
-        removeInProgress = true;
-
-        Object toRemove;
-
-        try {
-            toRemove = removeFirst();
-        } catch (Exception e) {
-            // List is empty.
-            // this is theorically possible if we have more than the size concurrent
-            // thread in getItem. Remove completed but add not done yet.
-            // We simply wait for add to complete.
-            do {
-                try {
-                    Thread.sleep(5);
-                } catch (InterruptedException ie) {
-                }
-            } while (isMap ? (map.size() == 0) : (list.size() == 0));
-
-            toRemove = removeFirst();
-        }
-
-        removeInProgress = false;
-
-        return toRemove;
-    }
-
-    /**
-     * Remove specified key since that object has been removed from the cache.
-     *
-     * @param key The cache key of the item that was removed.
-     */
-    protected void itemRemoved(Object key) {
-        if (isMap) {
-            map.remove(key);
-        } else {
-            list.remove(key);
-        }
-    }
-
-    /**
-     * Removes the first object from the list of keys.
-     *
-     * @return the object that was removed
-     */
-    private Object removeFirst() {
-        Object toRemove;
-
-        if (isSet) {
-            Iterator it = list.iterator();
-            toRemove = it.next();
-            it.remove();
-        } else if (isMap) {
-            toRemove = ((SequencedHashMap) map).getFirstKey();
-            map.remove(toRemove);
-        } else {
-            toRemove = ((List) list).remove(0);
-        }
-
-        return toRemove;
-    }
-}

src/core/java/com/opensymphony/oscache/base/algorithm/UnlimitedCache.java

-/*
- * Copyright (c) 2002-2003 by OpenSymphony
- * All rights reserved.
- */
-package com.opensymphony.oscache.base.algorithm;
-
-import com.opensymphony.oscache.base.MemoryCache;
-
-
-/**
- * A simple unlimited cache that has no upper bound to the number of
- * cache entries it can contain.
- *
- * @version        $Revision$
- * @author <a href="mailto:fbeauregard@pyxis-tech.com">Francois Beauregard</a>
- * @author <a href="mailto:abergevin@pyxis-tech.com">Alain Bergevin</a>
- */
-public final class UnlimitedCache extends MemoryCache {
-    /**
-     * Creates an unlimited cache by calling the super class's constructor
-     * with an <code>UNLIMITED</code> maximum number of entries.
-     */
-    public UnlimitedCache() {
-        super(-1);
-    }
-
-    /**
-     * Overrides the <code>setMaxEntries</code> with an empty implementation.
-     * This property cannot be modified and is ignored for an
-     * <code>UnlimitedCache</code>.
-     */
-    public void setMaxEntries(int maxEntries) {
-    }
-
-    /**
-     * Implements <code>itemRetrieved</code> with an empty implementation.
-     * The unlimited cache doesn't care that an item was retrieved.
-     */
-    protected void itemRetrieved(Object key) {
-    }
-
-    /**
-     * Implements <code>itemPut</code> with an empty implementation.
-     * The unlimited cache doesn't care that an item was put in the cache.
-     */
-    protected void itemPut(Object key) {
-    }
-
-    /**
-     * This method just returns <code>null</code> since items should
-     * never end up being removed from an unlimited cache!
-     */
-    protected Object removeItem() {
-        return null;
-    }
-
-    /**
-     * An empty implementation. The unlimited cache doesn't care that an
-     * item was removed.
-     */
-    protected void itemRemoved(Object key) {
-    }
-}

src/core/java/com/opensymphony/oscache/base/algorithm/package.html

-<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 3.2 Final//EN">
-<html>
-<head>
-<!--
-
-  @(#)package.html
-
-  Copyright (c) 2002-2003 by OpenSymphony
-  All rights reserved.
-
--->
-</head>
-<body bgcolor="white">
-
-Provides the classes that implement the caching algorithms used by OSCache, all of
-which are based on a derivative of Doug Lea's <code>ConcurrentReaderHashMap</code>.
-
-
-<h2>Package Specification</h2>
-
-<h2>Related Documentation</h2>
-
-
-For overviews, tutorials, examples, guides, and tool documentation, please see:
-<ul>
-  <li><a href="http://www.opensymphony.com/oscache">The OSCache Homepage</a>
-</ul>
-
-For further information on Doug Lea's concurrency package, please see:
-<ul>
-  <li><a href="http://gee.cs.oswego.edu/dl/classes/EDU/oswego/cs/dl/util/concurrent/intro.html">http://gee.cs.oswego.edu/dl/classes/EDU/oswego/cs/dl/util/concurrent/intro.html</a>
-</ul>
-
-<!-- Put @see and @since tags down here. -->
-
-</body>
-</html>

src/core/java/com/opensymphony/oscache/base/persistence/CachePersistenceException.java

-/*
- * Copyright (c) 2002-2003 by OpenSymphony
- * All rights reserved.
- */
-package com.opensymphony.oscache.base.persistence;
-
-
-/**
- * Exception thrown when an error occurs in a PersistenceListener implementation.
- *
- * @version        $Revision$
- * @author <a href="mailto:fbeauregard@pyxis-tech.com">Francois Beauregard</a>
- */
-public final class CachePersistenceException extends Exception {
-    /**
-     * Creates new CachePersistenceException without detail message.
-     */
-    public CachePersistenceException() {
-    }
-
-    /**
-     * Constructs an CachePersistenceException with the specified detail message.
-     *
-     * @param msg the detail message.
-     */
-    public CachePersistenceException(String msg) {
-        super(msg);
-    }
-}

src/core/java/com/opensymphony/oscache/base/persistence/PersistenceListener.java

-/*
- * Copyright (c) 2002-2003 by OpenSymphony
- * All rights reserved.
- */
-package com.opensymphony.oscache.base.persistence;
-
-import com.opensymphony.oscache.base.Config;
-
-import java.util.Set;
-
-/**
- * Defines the methods that are required to persist cache data.
- * To provide a custom persistence mechanism you should implement this
- * interface and supply the fully-qualified classname to the cache via
- * the <code>cache.persistence.class</code> configuration property.
- *
- * @version        $Revision$
- * @author <a href="mailto:fbeauregard@pyxis-tech.com">Francois Beauregard</a>
- */
-public interface PersistenceListener {
-    /**
-     * Verify if an object is currently stored in the persistent cache.
-     *
-     * @param key The cache key of the object to check.
-     */
-    public boolean isStored(String key) throws CachePersistenceException;
-
-    /**
-     * Verify if a group is currently stored in the persistent cache.
-     *
-     * @param groupName The name of the group to check.
-     */
-    public boolean isGroupStored(String groupName) throws CachePersistenceException;
-
-    /**
-     * Clear the entire persistent cache (including the root)
-     */
-    public void clear() throws CachePersistenceException;
-
-    /**
-     * Allow the persistence code to initialize itself based on the supplied
-     * cache configuration.
-     */
-    public PersistenceListener configure(Config config);
-
-    /**
-     * Removes an object from the persistent cache
-     */
-    public void remove(String key) throws CachePersistenceException;
-
-    /**
-     * Removes a group from the persistent cache.
-     *
-     * @param groupName The name of the cache group to remove.
-     */
-    public void removeGroup(String groupName) throws CachePersistenceException;
-
-    /**
-     * Retrieves an object from the persistent cache.
-     *
-     * @param key The unique cache key that maps to the object
-     * being retrieved.
-     * @return The object, or <code>null</code> if no object was found
-     * matching the supplied key.
-     */
-    public Object retrieve(String key) throws CachePersistenceException;
-
-    /**
-     * Stores an object in the persistent cache.
-     *
-     * @param key The key to uniquely identify this object.
-     * @param obj The object to persist. Most implementations
-     * of this interface will require this object implements
-     * <code>Serializable</code>.
-     */
-    public void store(String key, Object obj) throws CachePersistenceException;
-
-    /**
-     * Stores a group in the persistent cache.
-     *
-     * @param groupName The name of the group to persist.
-     * @param group A set containing the keys of all the <code>CacheEntry</code>
-     * objects that belong to this group.
-     */
-    public void storeGroup(String groupName, Set group) throws CachePersistenceException;
-
-    /**
-     * Retrieves a group from the persistent cache.
-     *
-     * @param groupName The name of the group to retrieve.
-     * @return The returned set should contain the keys
-     * of all the <code>CacheEntry</code> objects that belong
-     * to this group.
-     */
-    Set retrieveGroup(String groupName) throws CachePersistenceException;
-}

src/core/java/com/opensymphony/oscache/base/persistence/package.html

-<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 3.2 Final//EN">
-<html>
-<head>
-<!--
-
-  @(#)package.html
-
-  Copyright (c) 2002-2003 by OpenSymphony
-  All rights reserved.
-
--->
-</head>
-<body bgcolor="white">
-
-Provides the interfaces that provide persistence storage of cached objects.
-
-
-<h2>Package Specification</h2>
-
-<h2>Related Documentation</h2>
-
-
-For overviews, tutorials, examples, guides, and tool documentation, please see:
-<ul>
-  <li><a href="http://www.opensymphony.com/oscache">The OSCache Homepage</a>
-</ul>
-
-<!-- Put @see and @since tags down here. -->
-
-</body>
-</html>

src/core/java/com/opensymphony/oscache/events/CacheEntryEvent.java

+/*
+ * Copyright (c) 2002-2003 by OpenSymphony
+ * All rights reserved.
+ */
+package com.opensymphony.oscache.events;
+
+import com.opensymphony.oscache.core.Cache;
+import com.opensymphony.oscache.core.CacheEntry;
+
+/**
+ * CacheEntryEvent is the object created when an event occurs on a
+ * cache entry (Add, update, remove, flush). It contains the entry itself and
+ * its map.
+ *
+ * @version        $Revision$
+ * @author <a href="mailto:fbeauregard@pyxis-tech.com">Francois Beauregard</a>
+ */
+public final class CacheEntryEvent extends CacheEvent {
+    /**
+     * The cache where the entry resides.
+     */
+    private Cache map = null;
+
+    /**
+     * The entry that the event applies to.
+     */
+    private CacheEntry entry = null;
+
+    /**
+     * Constructs a cache entry event object with no specified origin
+     *
+     * @param map     The cache map of the cache entry
+     * @param entry   The cache entry that the event applies to
+     */
+    public CacheEntryEvent(Cache map, CacheEntry entry) {
+        this(map, entry, null);
+    }
+
+    /**
+     * Constructs a cache entry event object
+     *
+     * @param map     The cache map of the cache entry
+     * @param entry   The cache entry that the event applies to
+     * @param origin  The origin of this event
+     */
+    public CacheEntryEvent(Cache map, CacheEntry entry, String origin) {
+        super(origin);
+        this.map = map;
+        this.entry = entry;
+    }
+
+    /**
+     * Retrieve the cache entry that the event applies to.
+     */
+    public CacheEntry getEntry() {
+        return entry;
+    }
+
+    /**
+     * Retrieve the cache map where the entry resides.
+     */
+    public Cache getMap() {
+        return map;
+    }
+
+    public String toString() {
+        return "key=" + entry.getKey();
+    }
+}

src/core/java/com/opensymphony/oscache/events/CacheEntryEventListener.java

+/*
+ * Copyright (c) 2002-2003 by OpenSymphony
+ * All rights reserved.
+ */
+package com.opensymphony.oscache.events;
+
+
+/**
+ * This is the interface to listen to cache entry events. There is a method
+ * for each event type. These methods are called via a dispatcher. If you
+ * want to be notified when an event occurs on an entry, group or across a
+ * pattern, register a listener and implement this interface.
+ *
+ * @version        $Revision$
+ * @author <a href="mailto:fbeauregard@pyxis-tech.com">Francois Beauregard</a>
+ */
+public interface CacheEntryEventListener extends CacheEventListener {
+    /**
+     * Event fired when an entry is added to the cache.
+     */
+    void cacheEntryAdded(CacheEntryEvent event);
+
+    /**
+     * Event fired when an entry is flushed from the cache.
+     */
+    void cacheEntryFlushed(CacheEntryEvent event);
+
+    /**
+     * Event fired when an entry is removed from the cache.
+     */
+    void cacheEntryRemoved(CacheEntryEvent event);
+
+    /**
+     * Event fired when an entry is updated in the cache.
+     */
+    void cacheEntryUpdated(CacheEntryEvent event);
+
+    /**
+     * Event fired when a group is flushed from the cache.
+     */
+    void cacheGroupFlushed(CacheGroupEvent event);
+
+    /**
+     * Event fired when a key pattern is flushed from the cache.
+     * Note that this event will <em>not</em> be fired if the pattern
+     * is <code>null</code> or an empty string, instead the flush
+     * request will silently be ignored.
+     */
+    void cachePatternFlushed(CachePatternEvent event);
+
+    /**
+     * An event that is fired when an entire cache gets flushed.
+     */
+    void cacheFlushed(CachewideEvent event);
+}

src/core/java/com/opensymphony/oscache/events/CacheEntryEventType.java

+/*
+ * Copyright (c) 2002-2003 by OpenSymphony
+ * All rights reserved.
+ */
+package com.opensymphony.oscache.events;
+
+
+/**
+ * This is all the possible events that may occur on a cache entry or
+ * collection of cache entries.<p>
+ * There is a corresponding interface {@link CacheEntryEventListener} for
+ * handling these events.
+ *
+ * @version        $Revision$
+ * @author <a href="mailto:fbeauregard@pyxis-tech.com">Francois Beauregard</a>
+ */
+public final class CacheEntryEventType {
+    /**
+     * Get an event type for an entry added.
+     */
+    public static CacheEntryEventType ENTRY_ADDED = new CacheEntryEventType();
+
+    /**
+     * Get an event type for an entry updated.
+     */
+    public static CacheEntryEventType ENTRY_UPDATED = new CacheEntryEventType();
+
+    /**
+     * Get an event type for an entry flushed.
+     */
+    public static CacheEntryEventType ENTRY_FLUSHED = new CacheEntryEventType();
+
+    /**
+     * Get an event type for an entry removed.
+     */
+    public static CacheEntryEventType ENTRY_REMOVED = new CacheEntryEventType();
+
+    /**
+     * Get an event type for a group flush event.
+     */
+    public static CacheEntryEventType GROUP_FLUSHED = new CacheEntryEventType();
+
+    /**
+     * Get an event type for a pattern flush event.
+     */
+    public static CacheEntryEventType PATTERN_FLUSHED = new CacheEntryEventType();
+
+    /**
+     * Private constructor to ensure that no object of that type are
+     * created externally.
+     */
+    private CacheEntryEventType() {
+    }
+}

src/core/java/com/opensymphony/oscache/events/CacheEvent.java

+/*
+ * Copyright (c) 2002-2003 by OpenSymphony
+ * All rights reserved.
+ */
+package com.opensymphony.oscache.events;
+
+
+/**
+ * The root event class for all cache events. Each subclasses of this class
+ * classifies a particular type of cache event.
+ *
+ * @author <a href="&#109;a&#105;&#108;&#116;&#111;:chris&#64;swebtec.&#99;&#111;&#109;">Chris Miller</a>
+ * Date: 20-May-2003
+ * Time: 15:25:02
+ */
+public abstract class CacheEvent {
+    /**
+     * An optional tag that can be attached to the event to specify the event's origin.
+     */
+    protected String origin = null;
+
+    /**
+     * No-argument constructor so subtypes can easily implement <code>Serializable</code>
+     */
+    public CacheEvent() {
+    }
+
+    /**
+     * Creates a cache event object that came from the specified origin.
+     *
+     * @param origin A string that indicates where this event was fired from.
+     * This value is optional; <code>null</code> can be passed in if an
+     * origin is not required.
+     */
+    public CacheEvent(String origin) {
+        this.origin = origin;
+    }
+
+    /**
+     * Retrieves the origin of this event, if one was specified. This is most
+     * useful when an event handler causes another event to fire - by checking
+     * the origin the handler is able to prevent recursive events being
+     * fired.
+     */
+    public String getOrigin() {
+        return origin;
+    }
+}

src/core/java/com/opensymphony/oscache/events/CacheEventListener.java

+/*
+ * Copyright (c) 2002-2003 by OpenSymphony
+ * All rights reserved.
+ */
+package com.opensymphony.oscache.events;
+
+import java.util.EventListener;
+
+/**
+ * This is the base interface for cache events.
+ *
+ * @version        $Revision$
+ * @author <a href="&#109;a&#105;&#108;&#116;&#111;:chris&#64;swebtec.&#99;&#111;&#109;">Chris Miller</a>
+ */
+public interface CacheEventListener extends EventListener {
+}

src/core/java/com/opensymphony/oscache/events/CacheGroupEvent.java

+/*
+ * Copyright (c) 2002-2003 by OpenSymphony
+ * All rights reserved.
+ */
+package com.opensymphony.oscache.events;
+
+import com.opensymphony.oscache.core.Cache;
+
+/**
+ * CacheGroupEvent is an event that occurs at the cache group level
+ * (Add, update, remove, flush). It contains the group name and the
+ * originating cache object.
+ *
+ * @version        $Revision$
+ * @author <a href="&#109;a&#105;&#108;&#116;&#111;:chris&#64;swebtec.&#99;&#111;&#109;">Chris Miller</a>
+ */
+public final class CacheGroupEvent extends CacheEvent {
+    /**
+     * The cache where the entry resides.
+     */
+    private Cache map = null;
+
+    /**
+     * The group that the event applies to.
+     */
+    private String group = null;
+
+    /**
+     * Constructs a cache group event with no origin
+     *
+     * @param map     The cache map of the cache entry
+     * @param group   The cache group that the event applies to.
+     */
+    public CacheGroupEvent(Cache map, String group) {
+        this(map, group, null);
+    }
+
+    /**
+     * Constructs a cache group event
+     *
+     * @param map     The cache map of the cache entry
+     * @param group   The cache group that the event applies to.
+     * @param origin  An optional tag that can be attached to the event to
+     * specify the event's origin. This is useful to prevent events from being
+     * fired recursively in some situations, such as when an event handler
+     * causes another event to be fired.
+     */
+    public CacheGroupEvent(Cache map, String group, String origin) {
+        super(origin);
+        this.map = map;
+        this.group = group;
+    }
+
+    /**
+     * Retrieve the cache group that the event applies to.
+     */
+    public String getGroup() {
+        return group;
+    }
+
+    /**
+     * Retrieve the cache map where the group resides.
+     */
+    public Cache getMap() {
+        return map;
+    }
+
+    public String toString() {
+        return "groupName=" + group;
+    }
+}

src/core/java/com/opensymphony/oscache/events/CacheMapAccessEvent.java

+/*
+ * Copyright (c) 2002-2003 by OpenSymphony
+ * All rights reserved.
+ */
+package com.opensymphony.oscache.events;
+
+import com.opensymphony.oscache.core.CacheEntry;
+
+/**
+ * Cache map access event. This is the object created when an event occurs on a
+ * cache map (cache Hit, cache miss). It contains the entry that was referenced
+ * by the event and the event type.
+ *
+ * @version        $Revision$
+ * @author <a href="mailto:fbeauregard@pyxis-tech.com">Francois Beauregard</a>
+ */
+public final class CacheMapAccessEvent extends CacheEvent {
+    /**
+     * The cache entry that the event applies to.
+     */
+    private CacheEntry entry = null;
+
+    /**
+     * Type of the event.
+     */
+    private CacheMapAccessEventType eventType = null;
+
+    /**
+     * Constructor.
+     * <p>
+     * @param eventType   Type of the event.
+     * @param entry       The cache entry that the event applies to.
+     */
+    public CacheMapAccessEvent(CacheMapAccessEventType eventType, CacheEntry entry) {
+        this(eventType, entry, null);
+    }
+
+    /**
+     * Constructor.
+     * <p>
+     * @param eventType   Type of the event.
+     * @param entry       The cache entry that the event applies to.
+     * @param origin      The origin of the event
+     */
+    public CacheMapAccessEvent(CacheMapAccessEventType eventType, CacheEntry entry, String origin) {
+        super(origin);
+        this.eventType = eventType;
+        this.entry = entry;
+    }
+
+    /**
+     * Retrieve the cache entry that the event applies to.
+     */
+    public CacheEntry getEntry() {
+        return entry;
+    }
+
+    /**
+     * Retrieve the type of the event.
+     */
+    public CacheMapAccessEventType getEventType() {
+        return eventType;
+    }
+}

src/core/java/com/opensymphony/oscache/events/CacheMapAccessEventListener.java

+/*
+ * Copyright (c) 2002-2003 by OpenSymphony
+ * All rights reserved.
+ */
+package com.opensymphony.oscache.events;
+
+
+/**
+ * This is the interface to listen to cache map access events. The events are
+ * cache hits and misses, and are dispatched through this interface
+ *
+ * @version        $Revision$
+ * @author <a href="mailto:fbeauregard@pyxis-tech.com">Francois Beauregard</a>
+ */
+public interface CacheMapAccessEventListener extends CacheEventListener {
+    /**
+     * Event fired when an entry is accessed.
+     * Use getEventType to differentiate between access events.
+     */
+    public void accessed(CacheMapAccessEvent event);
+}

src/core/java/com/opensymphony/oscache/events/CacheMapAccessEventType.java

+/*
+ * Copyright (c) 2002-2003 by OpenSymphony
+ * All rights reserved.
+ */
+package com.opensymphony.oscache.events;
+
+
+/**
+ * This is an enumeration of the cache events that represent the
+ * various outcomes of cache accesses.
+ *
+ * @version $Revision$
+ * @author <a href="mailto:fbeauregard@pyxis-tech.com">Francois Beauregard</a>
+ */
+public final class CacheMapAccessEventType {
+    /**
+     * Get an event type for a cache hit.
+     */
+    public static CacheMapAccessEventType HIT = new CacheMapAccessEventType();
+
+    /**
+     * Get an event type for a cache miss.
+     */
+    public static CacheMapAccessEventType MISS = new CacheMapAccessEventType();
+
+    /**
+     * Get an event type for when the data was found in the cache but was stale.
+     */
+    public static CacheMapAccessEventType STALE_HIT = new CacheMapAccessEventType();
+
+    /**
+     * Private constructor to ensure that no object of this type are
+     * created externally.
+     */
+    private CacheMapAccessEventType() {
+    }
+}

src/core/java/com/opensymphony/oscache/events/CachePatternEvent.java

+/*
+ * Copyright (c) 2002-2003 by OpenSymphony
+ * All rights reserved.
+ */
+package com.opensymphony.oscache.events;
+
+import com.opensymphony.oscache.core.Cache;
+
+/**
+ * A CachePatternEvent is fired when a pattern has been applied to a cache.
+ *
+ * @version        $Revision$
+ * @author <a href="&#109;a&#105;&#108;&#116;&#111;:chris&#64;swebtec.&#99;&#111;&#109;">Chris Miller</a>
+ */
+public final class CachePatternEvent extends CacheEvent {
+    /**
+     * The cache the pattern is being applied to.
+     */
+    private Cache map = null;
+
+    /**
+     * The pattern that is being applied.
+     */
+    private String pattern = null;
+
+    /**
+     * Constructs a cache pattern event with no origin
+     *
+     * @param map     The cache map that the pattern was applied to
+     * @param pattern The pattern that was applied
+     */
+    public CachePatternEvent(Cache map, String pattern) {
+        this(map, pattern, null);
+    }
+
+    /**
+     * Constructs a cache pattern event
+     *
+     * @param map     The cache map that the pattern was applied to
+     * @param pattern The cache pattern that the event applies to.
+     * @param origin  An optional tag that can be attached to the event to
+     * specify the event's origin. This is useful to prevent events from being
+     * fired recursively in some situations, such as when an event handler
+     * causes another event to be fired, or for logging purposes.
+     */
+    public CachePatternEvent(Cache map, String pattern, String origin) {
+        super(origin);
+        this.map = map;
+        this.pattern = pattern;
+    }
+
+    /**
+     * Retrieve the cache map that had the pattern applied.
+     */
+    public Cache getMap() {
+        return map;
+    }
+
+    /**
+     * Retrieve the pattern that was applied to the cache.
+     */
+    public String getPattern() {
+        return pattern;
+    }
+
+    public String toString() {
+        return "pattern=" + pattern;
+    }
+}

src/core/java/com/opensymphony/oscache/events/CachewideEvent.java

+/*
+ * Copyright (c) 2002-2003 by OpenSymphony
+ * All rights reserved.
+ */
+package com.opensymphony.oscache.events;
+
+import com.opensymphony.oscache.core.Cache;
+
+import java.util.Date;
+
+/**
+ * A <code>CachewideEvent<code> represents and event that occurs on
+ * the the entire cache, eg a cache flush or clear.
+ *
+ * @version $Revision$
+ * @author <a href="&#109;a&#105;&#108;&#116;&#111;:chris&#64;swebtec.&#99;&#111;&#109;">Chris Miller</a>
+ */
+public final class CachewideEvent extends CacheEvent {
+    /**
+     * The cache where the event occurred.
+     */
+    private Cache cache = null;
+
+    /**
+     * The date/time for when the flush is scheduled
+     */
+    private Date date = null;
+
+    /**
+     * Constructs a cachewide event with the specified origin.
+     *
+     * @param cache   The cache map that the event occurred on.
+     * @param date    The date/time that this cachewide event is scheduled for
+     * (eg, the date that the cache is to be flushed).
+     * @param origin  An optional tag that can be attached to the event to
+     * specify the event's origin. This is useful to prevent events from being
+     * fired recursively in some situations, such as when an event handler
+     * causes another event to be fired.
+     */
+    public CachewideEvent(Cache cache, Date date, String origin) {
+        super(origin);
+        this.date = date;
+        this.cache = cache;
+    }
+
+    /**
+     * Retrieve the cache map that the event occurred on.
+     */
+    public Cache getCache() {
+        return cache;
+    }
+
+    /**
+     * Retrieve the date/time that the cache flush is scheduled for.
+     */
+    public Date getDate() {
+        return date;
+    }
+}

src/core/java/com/opensymphony/oscache/events/CachewideEventType.java

+/*
+ * Copyright (c) 2002-2003 by OpenSymphony
+ * All rights reserved.
+ */
+package com.opensymphony.oscache.events;
+
+
+/**
+ * This is an enumeration holding all the events that can
+ * occur at the cache-wide level.
+ *
+ * @author <a href="&#109;a&#105;&#108;&#116;&#111;:chris&#64;swebtec.&#99;&#111;&#109;">Chris Miller</a>
+ */
+public class CachewideEventType {
+    /**
+     * Get an event type for a cache flush event.
+     */
+    public static CachewideEventType CACHE_FLUSHED = new CachewideEventType();
+
+    /**
+     * Private constructor to ensure that no object of this type are
+     * created externally.
+     */
+    private CachewideEventType() {
+    }
+}

src/core/java/com/opensymphony/oscache/events/ScopeEvent.java

+/*
+ * Copyright (c) 2002-2003 by OpenSymphony
+ * All rights reserved.
+ */
+package com.opensymphony.oscache.events;
+
+import java.util.Date;
+
+/**
+ * A <code>ScopeEvent</code> is created when an event occurs across one or all scopes.
+ * This type of event is only applicable to the <code>ServletCacheAdministrator</code>.
+ *
+ * @version        $Revision$
+ * @author <a href="mailto:fbeauregard@pyxis-tech.com">Francois Beauregard</a>
+ */
+public final class ScopeEvent extends CacheEvent {
+    /**
+     * Date that the event applies to.
+     */
+    private Date date = null;
+
+    /**
+     * Type of the event.
+     */
+    private ScopeEventType eventType = null;
+
+    /**
+     * Scope that applies to this event.
+     */
+    private int scope = 0;
+
+    /**
+     * Constructs a scope event object with no specified origin.
+     *
+     * @param eventType   Type of the event.
+     * @param scope       Scope that applies to the event.
+     * @param date        Date that the event applies to.
+     */
+    public ScopeEvent(ScopeEventType eventType, int scope, Date date) {
+        this(eventType, scope, date, null);
+    }
+
+    /**
+     * Constructs a scope event object.
+     *
+     * @param eventType   Type of the event.
+     * @param scope       Scope that applies to the event.
+     * @param date        Date that the event applies to.
+     * @param origin      The origin of this event.
+     */
+    public ScopeEvent(ScopeEventType eventType, int scope, Date date, String origin) {
+        super(origin);
+        this.eventType = eventType;
+        this.scope = scope;
+        this.date = date;
+    }
+
+    /**
+     * Retrieve the event date
+     */
+    public Date getDate() {
+        return date;
+    }
+
+    /**
+     * Retrieve the type of the event.
+     */
+    public ScopeEventType getEventType() {
+        return eventType;
+    }
+
+    /**
+     * Retrieve the scope that applies to the event.
+     */
+    public int getScope() {
+        return scope;
+    }
+}

src/core/java/com/opensymphony/oscache/events/ScopeEventListener.java

+/*
+ * Copyright (c) 2002-2003 by OpenSymphony
+ * All rights reserved.
+ */
+package com.opensymphony.oscache.events;
+
+
+/**
+ * This is the interface to listen to scope events. The events are
+ * scope flushed and all scope flushed, and are dispatched thru this interface
+ *
+ * @version        $Revision$
+ * @author <a href="mailto:fbeauregard@pyxis-tech.com">Francois Beauregard</a>
+ */
+public interface ScopeEventListener extends CacheEventListener {
+    /**
+     * Event fired when a specific or all scopes are flushed.
+     * Use getEventType to differentiate between the two.
+     */
+    public void scopeFlushed(ScopeEvent event);
+}

src/core/java/com/opensymphony/oscache/events/ScopeEventType.java

+/*
+ * Copyright (c) 2002-2003 by OpenSymphony
+ * All rights reserved.
+ */
+package com.opensymphony.oscache.events;
+
+
+/**
+ * This is an enumeration of all the possible events that may occur
+ * at the scope level. Scope-level events are only relevant to the
+ * <code>ServletCacheAdministrator</code>.
+ *
+ * @version        $Revision$
+ * @author <a href="mailto:fbeauregard@pyxis-tech.com">Francois Beauregard</a>
+ */
+public final class ScopeEventType {
+    /**
+     * Specifies an event type for the all scope flushed event.
+     */
+    public static ScopeEventType ALL_SCOPES_FLUSHED = new ScopeEventType();
+
+    /**
+     * Specifies an event type for the flushing of a  specific scope.
+     */
+    public static ScopeEventType SCOPE_FLUSHED = new ScopeEventType();
+
+    /**
+     * Private constructor to ensure that no object of that type are
+     * created externally.
+     */
+    private ScopeEventType() {
+    }
+}

src/core/java/com/opensymphony/oscache/events/package.html

+<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 3.2 Final//EN">
+<html>
+<head>
+<!--
+
+  @(#)package.html
+
+  Copyright (c) 2002-2003 by OpenSymphony
+  All rights reserved.
+
+-->
+</head>
+<body bgcolor="white">
+
+Provides the base classes and interfaces that allow pluggable event handlers to be
+incorporated into OSCache.
+
+
+<h2>Package Specification</h2>
+
+<h2>Related Documentation</h2>
+
+
+For overviews, tutorials, examples, guides, and tool documentation, please see:
+<ul>
+  <li><a href="http://www.opensymphony.com/oscache">The OSCache Homepage</a>
+</ul>
+
+<!-- Put @see and @since tags down here. -->
+
+</body>
+</html>

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

 import org.apache.commons.logging.Log;
 import org.apache.commons.logging.LogFactory;
 
-import com.opensymphony.oscache.base.AbstractCacheAdministrator;
-import com.opensymphony.oscache.base.Cache;
-import com.opensymphony.oscache.base.CacheEntry;
-import com.opensymphony.oscache.base.MemoryCache;
-import com.opensymphony.oscache.base.EntryRefreshPolicy;
+import com.opensymphony.oscache.core.AbstractCacheAdministrator;
+import com.opensymphony.oscache.core.Cache;
+import com.opensymphony.oscache.core.CacheEntry;
+import com.opensymphony.oscache.core.EntryRefreshPolicy;
+import com.opensymphony.oscache.core.MemoryCache;
 
 /**
  * A GeneralCacheAdministrator creates, flushes and administers the cache.

src/core/java/com/opensymphony/oscache/persistence/CachePersistenceException.java

+/*
+ * Copyright (c) 2002-2003 by OpenSymphony
+ * All rights reserved.
+ */
+package com.opensymphony.oscache.persistence;
+
+
+/**
+ * Exception thrown when an error occurs in a PersistenceListener implementation.
+ *
+ * @version        $Revision$
+ * @author <a href="mailto:fbeauregard@pyxis-tech.com">Francois Beauregard</a>
+ */
+public final class CachePersistenceException extends Exception {
+    /**
+     * Creates new CachePersistenceException without detail message.
+     */
+    public CachePersistenceException() {
+    }
+
+    /**
+     * Constructs an CachePersistenceException with the specified detail message.
+     *
+     * @param msg the detail message.
+     */
+    public CachePersistenceException(String msg) {
+        super(msg);
+    }
+}

src/core/java/com/opensymphony/oscache/persistence/PersistenceListener.java

+/*
+ * Copyright (c) 2002-2003 by OpenSymphony
+ * All rights reserved.
+ */
+package com.opensymphony.oscache.persistence;
+
+import com.opensymphony.oscache.core.Config;
+
+import java.util.Set;
+
+/**
+ * Defines the methods that are required to persist cache data.
+ * To provide a custom persistence mechanism you should implement this
+ * interface and supply the fully-qualified classname to the cache via
+ * the <code>cache.persistence.class</code> configuration property.
+ *
+ * @version        $Revision$
+ * @author <a href="mailto:fbeauregard@pyxis-tech.com">Francois Beauregard</a>
+ */
+public interface PersistenceListener {
+    /**
+     * Verify if an object is currently stored in the persistent cache.
+     *
+     * @param key The cache key of the object to check.
+     */
+    public boolean isStored(String key) throws CachePersistenceException;
+
+    /**
+     * Verify if a group is currently stored in the persistent cache.
+     *
+     * @param groupName The name of the group to check.
+     */
+    public boolean isGroupStored(String groupName) throws CachePersistenceException;
+
+    /**
+     * Clear the entire persistent cache (including the root)
+     */
+    public void clear() throws CachePersistenceException;
+
+    /**
+     * Allow the persistence code to initialize itself based on the supplied
+     * cache configuration.
+     */
+    public PersistenceListener configure(Config config);
+
+    /**
+     * Removes an object from the persistent cache
+     */
+    public void remove(String key) throws CachePersistenceException;
+
+    /**
+     * Removes a group from the persistent cache.
+     *
+     * @param groupName The name of the cache group to remove.
+     */
+    public void removeGroup(String groupName) throws CachePersistenceException;
+
+    /**
+     * Retrieves an object from the persistent cache.
+     *
+     * @param key The unique cache key that maps to the object
+     * being retrieved.
+     * @return The object, or <code>null</code> if no object was found
+     * matching the supplied key.
+     */
+    public Object retrieve(String key) throws CachePersistenceException;
+
+    /**
+     * Stores an object in the persistent cache.
+     *
+     * @param key The key to uniquely identify this object.
+     * @param obj The object to persist. Most implementations
+     * of this interface will require this object implements
+     * <code>Serializable</code>.
+     */
+    public void store(String key, Object obj) throws CachePersistenceException;
+
+    /**
+     * Stores a group in the persistent cache.
+     *
+     * @param groupName The name of the group to persist.
+     * @param group A set containing the keys of all the <code>CacheEntry</code>
+     * objects that belong to this group.
+     */
+    public void storeGroup(String groupName, Set group) throws CachePersistenceException;
+
+    /**
+     * Retrieves a group from the persistent cache.
+     *
+     * @param groupName The name of the group to retrieve.
+     * @return The returned set should contain the keys
+     * of all the <code>CacheEntry</code> objects that belong
+     * to this group.
+     */
+    Set retrieveGroup(String groupName) throws CachePersistenceException;
+}

src/core/java/com/opensymphony/oscache/persistence/package.html

+<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 3.2 Final//EN">
+<html>
+<head>
+<!--
+
+  @(#)package.html
+
+  Copyright (c) 2002-2003 by OpenSymphony
+  All rights reserved.
+
+-->
+</head>
+<body bgcolor="white">
+
+Provides the interfaces that provide persistence storage of cached objects.
+
+
+<h2>Package Specification</h2>
+
+<h2>Related Documentation</h2>
+
+
+For overviews, tutorials, examples, guides, and tool documentation, please see:
+<ul>
+  <li><a href="http://www.opensymphony.com/oscache">The OSCache Homepage</a>
+</ul>
+
+<!-- Put @see and @since tags down here. -->
+
+</body>
+</html>

src/core/java/com/opensymphony/oscache/web/tag/CacheTag.java

 import org.apache.commons.logging.Log;
 import org.apache.commons.logging.LogFactory;
 
-import com.opensymphony.oscache.base.Cache;
+import com.opensymphony.oscache.core.Cache;
 import com.opensymphony.oscache.util.StringUtil;
 import com.opensymphony.oscache.web.ServletCacheAdministrator;
 import com.opensymphony.oscache.web.WebEntryRefreshPolicy;

src/core/java/com/opensymphony/oscache/web/tag/FlushTag.java

  */
 package com.opensymphony.oscache.web.tag;
 
-import com.opensymphony.oscache.base.Cache;
+import com.opensymphony.oscache.core.Cache;
 import com.opensymphony.oscache.web.ServletCacheAdministrator;
 
 import javax.servlet.http.HttpServletRequest;

src/core/test/com/opensymphony/oscache/base/DummyAlwayRefreshEntryPolicy.java

  */
 package com.opensymphony.oscache.base;
 
+import com.opensymphony.oscache.core.CacheEntry;
+import com.opensymphony.oscache.core.EntryRefreshPolicy;
+
 
 /**
  * This is an dummy implementation of an EntryRefreshPolicy. It is just to

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

  */
 package com.opensymphony.oscache.base;