⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 cachingprovider.java

📁 wiki建站资源 java编写的 很好用
💻 JAVA
📖 第 1 页 / 共 2 页
字号:
/*    JSPWiki - a JSP-based WikiWiki clone.    Copyright (C) 2001-2005 Janne Jalkanen (Janne.Jalkanen@iki.fi)    This program is free software; you can redistribute it and/or modify    it under the terms of the GNU Lesser General Public License as published by    the Free Software Foundation; either version 2.1 of the License, or    (at your option) any later version.    This program is distributed in the hope that it will be useful,    but WITHOUT ANY WARRANTY; without even the implied warranty of    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the    GNU Lesser General Public License for more details.    You should have received a copy of the GNU Lesser General Public License    along with this program; if not, write to the Free Software    Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA */package com.ecyrd.jspwiki.providers;import java.io.IOException;import java.io.StringReader;import java.io.StringWriter;import java.util.*;import org.apache.log4j.Logger;import com.ecyrd.jspwiki.*;import com.ecyrd.jspwiki.util.ClassUtil;import com.opensymphony.oscache.base.Cache;import com.opensymphony.oscache.base.NeedsRefreshException;import com.opensymphony.oscache.base.events.*;/** *  Provides a caching page provider.  This class rests on top of a *  real provider class and provides a cache to speed things up.  Only *  if the cache copy of the page text has expired, we fetch it from *  the provider. *  <p> *  This class also detects if someone has modified the page *  externally, not through JSPWiki routines, and throws the proper *  RepositoryModifiedException. *  <p> *  Heavily based on ideas by Chris Brooking. *  <p> *  Since 2.1.52 uses the OSCache library from OpenSymphony. * *  @author Janne Jalkanen *  @since 1.6.4 *  @see RepositoryModifiedException */// FIXME: Synchronization is a bit inconsistent in places.// FIXME: A part of the stuff is now redundant, since we could easily use the text cache//        for a lot of things.  RefactorMe.public class CachingProvider    implements WikiPageProvider{    private static final Logger log = Logger.getLogger(CachingProvider.class);    private WikiPageProvider m_provider;    // FIXME: Find another way to the search engine to use instead of from WikiEngine?    private WikiEngine       m_engine;    private Cache            m_cache;    private Cache            m_negCache; // Cache for holding non-existing pages        private Cache            m_textCache;    private Cache            m_historyCache;    private long             m_cacheMisses = 0;    private long             m_cacheHits   = 0;    private long             m_historyCacheMisses = 0;    private long             m_historyCacheHits   = 0;    private int              m_expiryPeriod = 30;        /**     *  This can be very long, as normally all modifications are noticed in an earlier     *  stage.     */    private int              m_pageContentExpiryPeriod = 24*60*60;        // FIXME: This MUST be cached somehow.    private boolean          m_gotall = false;    private CacheItemCollector m_allCollector = new CacheItemCollector();        /**     *  Defines, in seconds, the amount of time a text will live in the cache     *  at most before requiring a refresh.     */        public static final String PROP_CACHECHECKINTERVAL = "jspwiki.cachingProvider.cacheCheckInterval";    public static final String PROP_CACHECAPACITY      = "jspwiki.cachingProvider.capacity";    private static final int   DEFAULT_CACHECAPACITY   = 1000; // Good most wikis    private static final String OSCACHE_ALGORITHM      = "com.opensymphony.oscache.base.algorithm.LRUCache";        public void initialize( WikiEngine engine, Properties properties )        throws NoRequiredPropertyException,               IOException    {        log.debug("Initing CachingProvider");        //        //  Cache consistency checks        //        m_expiryPeriod = TextUtil.getIntegerProperty( properties,                                                      PROP_CACHECHECKINTERVAL,                                                      m_expiryPeriod );        log.debug("Cache expiry period is "+m_expiryPeriod+" s");        //        //  Text cache capacity        //        int capacity = TextUtil.getIntegerProperty( properties,                                                    PROP_CACHECAPACITY,                                                    DEFAULT_CACHECAPACITY );        log.debug("Cache capacity "+capacity+" pages.");        m_cache = new Cache( true, false, true );                //        //  OSCache documentation sucks big time.  The clazz-parameter is completely        //  undefined; I had to read the source code to figure out that you need        //  to declare what type of a listener you are adding by sending the type        //  of the interface.        //        m_cache.addCacheEventListener( m_allCollector, CacheEntryEventListener.class );                m_negCache = new Cache( true, false, true );                m_textCache = new Cache( true, false, true,                                 false,                                 OSCACHE_ALGORITHM,                                 capacity );        m_historyCache = new Cache( true, false, true, false,                                    OSCACHE_ALGORITHM,                                    capacity );                                            //        //  Find and initialize real provider.        //        String classname = WikiEngine.getRequiredProperty( properties,                                                            PageManager.PROP_PAGEPROVIDER );        // engine is used for getting the search engine        m_engine = engine;        try        {                        Class providerclass = ClassUtil.findClass( "com.ecyrd.jspwiki.providers",                                                       classname );            m_provider = (WikiPageProvider)providerclass.newInstance();            log.debug("Initializing real provider class "+m_provider);            m_provider.initialize( engine, properties );        }        catch( ClassNotFoundException e )        {            log.error("Unable to locate provider class "+classname,e);            throw new IllegalArgumentException("no provider class");        }        catch( InstantiationException e )        {            log.error("Unable to create provider class "+classname,e);            throw new IllegalArgumentException("faulty provider class");        }        catch( IllegalAccessException e )        {            log.error("Illegal access to provider class "+classname,e);            throw new IllegalArgumentException("illegal provider class");        }    }    private WikiPage getPageInfoFromCache( String name )        throws ProviderException,               RepositoryModifiedException    {        // Sanity check; seems to occur sometimes        if( name == null ) return null;                try        {            WikiPage item = (WikiPage)m_cache.getFromCache( name, m_expiryPeriod );                        if( item != null )                return item;                        return null;        }        catch( NeedsRefreshException e )        {            WikiPage cached = (WikiPage)e.getCacheContent();                        // int version = (cached != null) ? cached.getVersion() : WikiPageProvider.LATEST_VERSION;                        WikiPage refreshed = m_provider.getPageInfo( name, WikiPageProvider.LATEST_VERSION );              if( refreshed == null && cached != null )            {                //  Page has been removed evilly by a goon from outer space                log.debug("Page "+name+" has been removed externally.");                                m_cache.putInCache( name, null );                m_textCache.putInCache( name, null );                m_historyCache.putInCache( name, null );                // We cache a page miss                m_negCache.putInCache( name, name );                                throw new RepositoryModifiedException( "Removed: "+name, name );            }            else if( cached == null )            {                // The page did not exist in the first place                                if( refreshed != null )                {                    // We must now add it                    m_cache.putInCache( name, refreshed );                    // Requests for this page are now no longer denied                    m_negCache.putInCache( name, null );                                        throw new RepositoryModifiedException( "Added: "+name, name );                    // return refreshed;                }                else                {                    // Cache page miss                    m_negCache.putInCache( name, name );                    m_cache.cancelUpdate( name );                }            }            else if( cached.getVersion() != refreshed.getVersion() )            {                //  The newest version has been deleted, but older versions still remain                log.debug("Page "+cached.getName()+" newest version deleted, reloading...");                                m_cache.putInCache( name, refreshed );                // Requests for this page are now no longer denied                m_negCache.putInCache( name, null );                m_textCache.flushEntry( name );                m_historyCache.flushEntry( name );                                return refreshed;            }            else if( Math.abs(refreshed.getLastModified().getTime()-cached.getLastModified().getTime()) > 1000L )            {                //  Yes, the page has been modified externally and nobody told us                         log.info("Page "+cached.getName()+" changed, reloading...");                m_cache.putInCache( name, refreshed );                // Requests for this page are now no longer denied                m_negCache.putInCache( name, null );                m_textCache.flushEntry( name );                m_historyCache.flushEntry( name );                throw new RepositoryModifiedException( "Modified: "+name, name );            }            else            {                // Refresh the cache by putting the same object back                m_cache.putInCache( name, cached );                // Requests for this page are now no longer denied                m_negCache.putInCache( name, null );            }            return cached;        }    }    public boolean pageExists( String pageName )    {        if( pageName == null ) return false;                //        //  First, check the negative cache if we've seen it before        //        try        {                    String isNonExistant = (String) m_negCache.getFromCache( pageName, m_expiryPeriod );                        if( isNonExistant != null ) return false; // No such page        }        catch( NeedsRefreshException e )        {            m_negCache.cancelUpdate(pageName);        }        WikiPage p = null;                try        {            p = getPageInfoFromCache( pageName );        }        catch( RepositoryModifiedException e )         {            // The repository was modified, we need to check now if the page was removed or            // added.            // TODO: This information would be available in the exception, but we would            //       need to subclass.                        try            {                p = getPageInfoFromCache( pageName );            }            catch( Exception ex ) { return false; } // This should not happen        }        catch( ProviderException e )         {            log.info("Provider failed while trying to check if page exists: "+pageName);            return false;        }                //        //  A null item means that the page either does not        //  exist, or has not yet been cached; a non-null        //  means that the page does exist.        //        if( p != null )        {            return true;        }        //        //  If we have a list of all pages in memory, then any page        //  not in the cache must be non-existent.        //        //  FIXME: There's a problem here; if someone modifies the        //         repository by adding a page outside JSPWiki,         //         we won't notice it.        if( m_gotall )        {            return false;        }        //        //  We could add the page to the cache here as well,        //  but in order to understand whether that is a        //  good thing or not we would need to analyze        //  the JSPWiki calling patterns extensively.  Presumably        //  it would be a good thing if pageExists() is called        //  many times before the first getPageText() is called,        //  and the whole page is cached.        //        return m_provider.pageExists( pageName );    }    /**     *  @throws RepositoryModifiedException If the page has been externally modified.     */    public String getPageText( String pageName, int version )        throws ProviderException,               RepositoryModifiedException    {        String result = null;        if( pageName == null ) return null;                if( version == WikiPageProvider.LATEST_VERSION )        {            result = getTextFromCache( pageName );        }        else        {            WikiPage p = getPageInfoFromCache( pageName );            //            //  Or is this the latest version fetched by version number?            //            if( p != null && p.getVersion() == version )            {                result = getTextFromCache( pageName );            }            else            {                result = m_provider.getPageText( pageName, version );            }        }        return result;

⌨️ 快捷键说明

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