📄 cachingprovider.java
字号:
/* JSPWiki - a JSP-based WikiWiki clone. Copyright (C) 2001-2004 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.File;import java.io.StringReader;import java.util.*;import org.apache.log4j.Logger;import org.apache.lucene.index.IndexWriter;import org.apache.lucene.index.Term;import org.apache.lucene.index.IndexReader;import org.apache.lucene.analysis.standard.StandardAnalyzer;import org.apache.lucene.document.Document;import org.apache.lucene.document.Field;import org.apache.lucene.search.*;import com.opensymphony.module.oscache.base.Cache;import com.opensymphony.module.oscache.base.NeedsRefreshException;import com.ecyrd.jspwiki.*;import com.ecyrd.jspwiki.util.ClassUtil;/** * 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. * <p> * Since 2.1.100 uses the Apache Lucene library to help in searching. * * @author Janne Jalkanen * @since 1.6.4 * @see RepositoryModifiedException */// FIXME: Keeps a list of all WikiPages in memory - should cache them too.// 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; private HashMap m_cache = new HashMap(); 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_milliSecondsBetweenChecks = 30000; // FIXME: This MUST be cached somehow. private boolean m_gotall = false; // Lucene data, if used. private boolean m_useLucene = false; private String m_luceneDirectory = null; private int m_updateCount = 0; private Thread m_luceneUpdateThread = null; private Vector m_updates = null; // Vector because multi-threaded. /** * Defines, in seconds, the amount of time a text will live in the cache * at most before requiring a refresh. */ // FIXME: This can be long, since we check it on our own. private int m_refreshPeriod = 24*60*60; // Default is one day. 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.module.oscache.base.algorithm.LRUCache"; // Lucene properties. public static final String PROP_USE_LUCENE = "jspwiki.useLucene"; private static final String LUCENE_DIR = "lucene"; // Number of page updates before we optimize the index. public static final int LUCENE_OPTIMIZE_COUNT = 10; private static final String LUCENE_ID = "id"; private static final String LUCENE_PAGE_CONTENTS = "contents"; public void initialize( WikiEngine engine, Properties properties ) throws NoRequiredPropertyException, IOException { log.debug("Initing CachingProvider"); // // Cache consistency checks // m_milliSecondsBetweenChecks = TextUtil.getIntegerProperty( properties, PROP_CACHECHECKINTERVAL, m_milliSecondsBetweenChecks ); log.debug("Cache consistency checks every "+m_milliSecondsBetweenChecks+" ms"); // // Text cache capacity // int capacity = TextUtil.getIntegerProperty( properties, PROP_CACHECAPACITY, DEFAULT_CACHECAPACITY ); log.debug("Cache capacity "+capacity+" pages."); m_textCache = new Cache( true, false, OSCACHE_ALGORITHM, capacity ); m_historyCache = new Cache( true, false, OSCACHE_ALGORITHM, capacity ); // // Find and initialize real provider. // String classname = WikiEngine.getRequiredProperty( properties, PageManager.PROP_PAGEPROVIDER ); 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"); } // // See if we're using Lucene, and if so, ensure that its // index directory is up to date. // m_useLucene = TextUtil.getBooleanProperty(properties, PROP_USE_LUCENE, true ); if( m_useLucene ) { m_luceneDirectory = engine.getWorkDir()+File.separator+LUCENE_DIR; // FIXME: Just to be simple for now, we will do full reindex // only if no files are in lucene directory. File dir = new File(m_luceneDirectory); log.info("Lucene enabled, cache will be in: "+dir.getAbsolutePath()); try { if( !dir.exists() ) { dir.mkdirs(); } if( dir.list().length == 0 ) { // // No files? Reindex! // Date start = new Date(); IndexWriter writer = null; log.info("Starting Lucene reindexing, this can take a couple minutes..."); try { // FIXME: Should smartly use a different analyzer // in case the language is something else // than English. writer = new IndexWriter( m_luceneDirectory, new StandardAnalyzer(), true ); Collection allPages = getAllPages(); for( Iterator iterator = allPages.iterator(); iterator.hasNext(); ) { WikiPage page = (WikiPage) iterator.next(); String text = getPageText( page.getName(), WikiProvider.LATEST_VERSION ); luceneIndexPage( page, text, writer ); } writer.optimize(); } finally { try { if( writer != null ) writer.close(); } catch( IOException e ) {} } Date end = new Date(); log.info("Full Lucene index finished in " + (end.getTime() - start.getTime()) + " milliseconds."); } else { log.info("Files found in Lucene directory, not reindexing."); } } catch( NoClassDefFoundError e ) { log.info("Lucene libraries do not exist - not using Lucene"); m_useLucene = false; } catch ( IOException e ) { log.error("Problem while creating Lucene index.", e); m_useLucene = false; } catch ( ProviderException e ) { log.error("Problem reading pages while creating Lucene index.", e); throw new IllegalArgumentException("unable to create Lucene index"); } startLuceneUpdateThread(); } } /* public void finalize() { if( m_luceneUpdateThread != null ) { m_luceneUpdateThread. } } */ private void startLuceneUpdateThread() { m_updates = new Vector(); m_luceneUpdateThread = new Thread(new Runnable() { public void run() { while( true ) { while( m_updates.size() > 0 ) { Object[] pair = ( Object[] ) m_updates.remove(0); WikiPage page = ( WikiPage ) pair[0]; String text = ( String ) pair[1]; updateLuceneIndex(page, text); } try { Thread.sleep(500); } catch ( InterruptedException e ) {} } } }); m_luceneUpdateThread.start(); } private void luceneIndexPage( WikiPage page, String text, IndexWriter writer ) throws IOException { // make a new, empty document Document doc = new Document(); // Raw name is the keyword we'll use to refer to this document for updates. doc.add(Field.Keyword(LUCENE_ID, page.getName())); // Body text is indexed, but not stored in doc. We add in the // title text as well to make sure it gets considered.
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -