servletcacheadministrator.java

来自「一个不错的cache」· Java 代码 · 共 744 行 · 第 1/2 页

JAVA
744
字号
/* * Copyright (c) 2002-2003 by OpenSymphony * All rights reserved. */package com.opensymphony.oscache.web;import com.opensymphony.oscache.base.*;import com.opensymphony.oscache.base.events.CacheEventListener;import com.opensymphony.oscache.base.events.ScopeEvent;import com.opensymphony.oscache.base.events.ScopeEventListener;import com.opensymphony.oscache.base.events.ScopeEventType;import org.apache.commons.logging.Log;import org.apache.commons.logging.LogFactory;import java.io.Serializable;import java.util.*;import javax.servlet.ServletContext;import javax.servlet.http.HttpServletRequest;import javax.servlet.http.HttpSession;import javax.servlet.jsp.PageContext;/** * A ServletCacheAdministrator creates, flushes and administers the cache. * <p> * This is a "servlet Singleton". This means it's not a Singleton in the traditional sense, * that is stored in a static instance. It's a Singleton _per web app context_. * <p> * Once created it manages the cache path on disk through the oscache.properties * file, and also keeps track of the flush times. * * @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: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> * @version        $Revision: 1.11 $ */public class ServletCacheAdministrator extends AbstractCacheAdministrator implements Serializable {    private static final transient Log log = LogFactory.getLog(ServletCacheAdministrator.class);    /**    * Constants for properties read/written from/to file    */    private final static String CACHE_USE_HOST_DOMAIN_KEY = "cache.use.host.domain.in.key";    private final static String CACHE_KEY_KEY = "cache.key";    /**    * The default cache key that is used to store the cache in context.    */    private final static String DEFAULT_CACHE_KEY = "__oscache_cache";    /**    * Constants for scope's name    */    public final static String SESSION_SCOPE_NAME = "session";    public final static String APPLICATION_SCOPE_NAME = "application";    /**    * The key under which the CacheAdministrator will be stored in the ServletContext    */    private final static String CACHE_ADMINISTRATOR_KEY = "__oscache_admin";    /**    * Key used to store the current scope in the configuration. This is a hack    * to let the scope information get passed through to the DiskPersistenceListener,    * and will be removed in a future release.    */    public final static String HASH_KEY_SCOPE = "scope";    /**    * Key used to store the current session ID in the configuration. This is a hack    * to let the scope information get passed through to the DiskPersistenceListener,    * and will be removed in a future release.    */    public final static String HASH_KEY_SESSION_ID = "sessionId";    /**    * Key used to store the servlet container temporary directory in the configuration.    * This is a hack to let the scope information get passed through to the    * DiskPersistenceListener, and will be removed in a future release.    */    public final static String HASH_KEY_CONTEXT_TMPDIR = "context.tempdir";    /**    * The string to use as a file separator.    */    private final static String FILE_SEPARATOR = "/";    /**    * The character to use as a file separator.    */    private final static char FILE_SEPARATOR_CHAR = FILE_SEPARATOR.charAt(0);    /**    * Constant for Key generation.    */    private final static short AVERAGE_KEY_LENGTH = 30;    /**    * Usable caracters for key generation    */    private static final String m_strBase64Chars = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/";    /**    * Map containing the flush times of different scopes    */    private Map flushTimes;    //private transient ServletContext context;    /**    * Key to use for storing and retrieving Object in contexts (Servlet, session).    */    private String cacheKey;    /**    *  Set property cache.use.host.domain.in.key=true to add domain information to key    *  generation for hosting multiple sites.    */    private boolean useHostDomainInKey = false;    /**    *        Create the cache administrator.    *    *        This will reset all the flush times and load the properties file.    */    private ServletCacheAdministrator(ServletContext context, Properties p) {        super(p);        config.set(HASH_KEY_CONTEXT_TMPDIR, context.getAttribute("javax.servlet.context.tempdir"));        //this.context = context;        flushTimes = new HashMap();        initHostDomainInKey();    }    /**    * Obtain an instance of the CacheAdministrator    *    * @param context The ServletContext that this CacheAdministrator is a Singleton under    * @return Returns the CacheAdministrator instance for this context    */    public static ServletCacheAdministrator getInstance(ServletContext context) {        return getInstance(context, null);    }    /**    * Obtain an instance of the CacheAdministrator    *    * @param context The ServletContext that this CacheAdministrator is a Singleton under    * @param p the properties to use for the cache if the cache administrator has not been    * created yet. Once the administrator has been created, the properties parameter is    * ignored for all future invocations. If a null value is passed in, then the properties    * are loaded from the oscache.properties file in the classpath.    * @return Returns the CacheAdministrator instance for this context    */    public static ServletCacheAdministrator getInstance(ServletContext context, Properties p) {        ServletCacheAdministrator admin;        admin = (ServletCacheAdministrator) context.getAttribute(CACHE_ADMINISTRATOR_KEY);        // First time we need to create the administrator and store it in the        // servlet context        if (admin == null) {            admin = new ServletCacheAdministrator(context, p);            context.setAttribute(CACHE_ADMINISTRATOR_KEY, admin);            if (log.isInfoEnabled()) {                log.info("Created new instance of ServletCacheAdministrator");            }            admin.getAppScopeCache(context);        }        return admin;    }    /**    * Shuts down the cache administrator. This should usually only be called    * when the controlling application shuts down.    */    public static void destroyInstance(ServletContext context) {        ServletCacheAdministrator admin;        admin = (ServletCacheAdministrator) context.getAttribute(CACHE_ADMINISTRATOR_KEY);        if (admin != null) {            // Finalize the application scope cache            Cache cache = (Cache) context.getAttribute(admin.getCacheKey());            if (cache != null) {                admin.finalizeListeners(cache);                context.removeAttribute(admin.getCacheKey());                context.removeAttribute(CACHE_ADMINISTRATOR_KEY);                cache = null;                if (log.isInfoEnabled()) {                    log.info("Shut down the ServletCacheAdministrator");                }            }            admin = null;        }    }    /**    * Grabs the cache for the specified scope    *    * @param request The current request    * @param scope The scope of this cache (<code>PageContext.APPLICATION_SCOPE</code>    * or <code>PageContext.SESSION_SCOPE</code>)    * @return The cache    */    public Cache getCache(HttpServletRequest request, int scope) {        if (scope == PageContext.APPLICATION_SCOPE) {            return getAppScopeCache(request.getSession(true).getServletContext());        }        if (scope == PageContext.SESSION_SCOPE) {            return getSessionScopeCache(request.getSession(true));        }        throw new RuntimeException("The supplied scope value of " + scope + " is invalid. Acceptable values are PageContext.APPLICATION_SCOPE and PageContext.SESSION_SCOPE");    }    /**    * A convenience method to retrieve the application scope cache    * @param context the current <code>ServletContext</code>    * @return the application scope cache. If none is present, one will    * be created.    */    public Cache getAppScopeCache(ServletContext context) {        Cache cache;        Object obj = context.getAttribute(getCacheKey());        if ((obj == null) || !(obj instanceof Cache)) {            if (log.isInfoEnabled()) {                log.info("Created new application-scoped cache at key: " + getCacheKey());            }            cache = createCache(PageContext.APPLICATION_SCOPE, null);            context.setAttribute(getCacheKey(), cache);        } else {            cache = (Cache) obj;        }        return cache;    }    /**    * A convenience method to retrieve the session scope cache    *    * @param session the current <code>HttpSession</code>    * @return the session scope cache for this session. If none is present,    * one will be created.    */    public Cache getSessionScopeCache(HttpSession session) {        Cache cache;        Object obj = session.getAttribute(getCacheKey());        if ((obj == null) || !(obj instanceof Cache)) {            if (log.isInfoEnabled()) {                log.info("Created new session-scoped cache in session " + session.getId() + " at key: " + getCacheKey());            }            cache = createCache(PageContext.SESSION_SCOPE, session.getId());            session.setAttribute(getCacheKey(), cache);        } else {            cache = (Cache) obj;        }        return cache;    }    /**    * Get the cache key from the properties. Set it to a default value if it    * is not present in the properties    *    * @return The cache.key property or the DEFAULT_CACHE_KEY    */    public String getCacheKey() {        if (cacheKey == null) {            cacheKey = getProperty(CACHE_KEY_KEY);            if (cacheKey == null) {                cacheKey = DEFAULT_CACHE_KEY;            }        }        return cacheKey;    }    /**    * Set the flush time for a specific scope to a specific time    *    * @param date  The time to flush the scope    * @param scope The scope to be flushed    */    public void setFlushTime(Date date, int scope) {        if (log.isInfoEnabled()) {            log.info("Flushing scope " + scope + " at " + date);        }        synchronized (flushTimes) {            if (date != null) {                // Trigger a SCOPE_FLUSHED event                dispatchScopeEvent(ScopeEventType.SCOPE_FLUSHED, scope, date, null);                flushTimes.put(new Integer(scope), date);            } else {                logError("setFlushTime called with a null date.");                throw new IllegalArgumentException("setFlushTime called with a null date.");            }        }    }    /**    * Set the flush time for a specific scope to the current time.    *    * @param scope The scope to be flushed    */    public void setFlushTime(int scope) {        setFlushTime(new Date(), scope);    }    /**    *        Get the flush time for a particular scope.    *    *        @param        scope        The scope to get the flush time for.    *        @return A date representing the time this scope was last flushed.    *        Returns null if it has never been flushed.    */    public Date getFlushTime(int scope) {        synchronized (flushTimes) {            return (Date) flushTimes.get(new Integer(scope));        }    }    /**    * Retrieve an item from the cache    *    * @param scope The cache scope    * @param request The servlet request    * @param key The key of the object to retrieve    * @param refreshPeriod The time interval specifying if an entry needs refresh    * @return The requested object    * @throws NeedsRefreshException    */    public Object getFromCache(int scope, HttpServletRequest request, String key, int refreshPeriod) throws NeedsRefreshException {        Cache cache = getCache(request, scope);        key = this.generateEntryKey(key, request, scope);        return cache.getFromCache(key, refreshPeriod);    }    /**    * Checks if the given scope 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    * @param scope The scope we're checking    *    * @return Whether or not the scope has been flushed more recently than this cache entry was updated.    */    public boolean isScopeFlushed(CacheEntry cacheEntry, int scope) {        Date flushDateTime = getFlushTime(scope);        if (flushDateTime != null) {            long lastUpdate = cacheEntry.getLastUpdate();            return (flushDateTime.getTime() >= lastUpdate);        } else {            return false;        }

⌨️ 快捷键说明

复制代码Ctrl + C
搜索代码Ctrl + F
全屏模式F11
增大字号Ctrl + =
减小字号Ctrl + -
显示快捷键?