dbsearchmanager.java

来自「Jive是基于JSP/JAVA技术构架的一个大型BBS论坛系统,这是Jive论坛」· Java 代码 · 共 1,026 行 · 第 1/3 页

JAVA
1,026
字号
/** * $RCSfile: DbSearchManager.java,v $ * $Revision: 1.16 $ * $Date: 2002/07/09 15:34:04 $ * * Copyright (C) 1999-2001 CoolServlets, Inc. All rights reserved. * * This software is the proprietary information of CoolServlets, Inc. * Use is subject to license terms. */package com.jivesoftware.forum.database;import java.sql.*;import java.util.*;import java.util.TimerTask;import java.util.Date;import java.io.*;import org.apache.lucene.document.*;import org.apache.lucene.analysis.*;import org.apache.lucene.analysis.standard.*;import org.apache.lucene.index.*;import org.apache.lucene.store.*;import org.apache.lucene.search.Searcher;import org.apache.lucene.search.IndexSearcher;import com.jivesoftware.forum.*;import com.jivesoftware.forum.util.*;import com.jivesoftware.util.*;/** * Database implementation of SearchManager using the Lucene search package. * Search indexes are stored in the "search" subdirectory of <tt>jiveHome</tt>. * * @author Matt Tucker */public class DbSearchManager implements SearchManager, Runnable {    /** DATABASE QUERIES **/    private static final String MESSAGES_BEFORE_DATE =        "SELECT jiveMessage.messageID, jiveMessage.userID, jiveMessage.threadID, " +                "jiveMessage.forumID, subject, body, jiveMessage.creationDate " +          "FROM jiveMessage, jiveForum " +         "WHERE jiveForum.forumID=jiveMessage.forumID " +           "AND messageID >= ? AND messageID < ? " +           "AND jiveMessage.modifiedDate < ? " +           "AND jiveMessage.modValue >= jiveForum.modMinThreadVal";    private static final String MESSAGES_BEFORE_DATE_COUNT =        "SELECT count(1) " +          "FROM jiveMessage, jiveForum " +         "WHERE jiveForum.forumID=jiveMessage.forumID " +           "AND jiveMessage.modValue >= jiveForum.modMinThreadVal " +           "AND jiveMessage.modifiedDate < ?";    private static final String MESSAGES_SINCE_DATE =        "SELECT jiveMessage.messageID, jiveMessage.userID, jiveMessage.threadID, " +                "jiveMessage.forumID, subject, body, jiveMessage.creationDate " +          "FROM jiveMessage, jiveForum " +         "WHERE jiveForum.forumID=jiveMessage.forumID " +           "AND jiveMessage.modValue >= jiveForum.modMinThreadVal " +           "AND jiveMessage.modifiedDate > ? AND jiveMessage.modifiedDate < ?";    private static final String MESSAGES_SINCE_DATE_COUNT =        "SELECT count(1) " +          "FROM jiveMessage, jiveForum " +         "WHERE jiveForum.forumID=jiveMessage.forumID " +           "AND jiveMessage.modValue >= jiveForum.modMinThreadVal " +           "AND jiveMessage.modifiedDate > ? AND jiveMessage.modifiedDate < ?";    private static final String MESSAGE_IDS_SINCE_DATE =        "SELECT jiveMessage.messageID " +          "FROM jiveMessage, jiveForum " +         "WHERE jiveForum.forumID=jiveMessage.forumID " +           "AND jiveMessage.modValue >= jiveForum.modMinThreadVal " +           "AND jiveMessage.modifiedDate > ? AND jiveMessage.modifiedDate < ?";    private static final String HIGHEST_MESSAGE_ID =            "SELECT MAX(messageID) FROM jiveMessage";    /**     * The number of messages to retrieve at once during index rebuilds.     */    private static final int BLOCK_SIZE = 500;    /**     * The analyzer governs how words are tokenized. We make the analyzer protected so     * that the DbQuery class can also reference it (indexing and searching should use the same     * analyzer).     */    protected static Analyzer analyzer = null;    /**     * The standard analyzer provides good indexing for Western languages. This is the default     * analyzer is another is not specified.     */    public static final String STANDARD_ANALYZER =            "org.apache.lucene.analysis.standard.StandardAnalyzer";    /**     * The german analyzer provides improved indexing when most content is in German.     */    public static final String GERMAN_ANALYZER =            "org.apache.lucene.analysis.de.GermanAnalyzer";    /**     * The double-byte analyzer support for double-byte languages such as Chinese, Japanese, etc.     */    public static final String DOUBLE_BYTE_ANALYZER =            "org.apache.lucene.analysis.cn.ChineseAnalyzer";    static {        loadAnalyzer();    }    /**     * Load the search analyzer. A custom analyzer class will be used if it is defined.     */    private static void loadAnalyzer() {        String analyzerClass = JiveGlobals.getJiveProperty("search.analyzer.className");        if (analyzerClass != null) {            try {                // Load the class.                Class c = Class.forName(analyzerClass);                // Create an instance of the custom analyzer.                analyzer = (Analyzer)c.newInstance();            }            catch (Exception e) {                System.err.println("Error loading custom search analyzer: " + analyzerClass);                e.printStackTrace();            }        }        // If the anazlyer is still null, use the standard analyzer.        if (analyzer == null) {            analyzer = new StandardAnalyzer();        }    }    /**     * Returns the Lucene analyzer class that is be used for indexing. The following constant     * values are common values, but any valid analyzer may be used:<ul>     *     *  <li> STANDARD_ANALYZER (default)     *  <li> GERMAN_ANALYZER     *  <li> DOUBLE_BYTE_ANALYZER</ul>     *     * The analyzer class name is stored as the Jive Property <tt>search.analyzer.className</tt>.     *     * @return the name of the analyzer class that is used for indexing.     */    public static String getAnalyzer() {        String analyzerClass = JiveGlobals.getJiveProperty("search.analyzer.className");        if (analyzerClass == null) {            return STANDARD_ANALYZER;        }        else {            return analyzerClass;        }    }    /**     * Sets the Lucene analyzer class that is used for indexing. The following constant     * values are common values, but any valid analyzer may be used:<ul>     *     *  <li> STANDARD_ANALYZER (default)     *  <li> GERMAN_ANALYZER     *  <li> DOUBLE_BYTE_ANALYZER</ul>     *     * Anytime the analyzer class is changed, the search index must be rebuilt for searching     * to work reliably. The analyzer class name is stored as the Jive Property     * <tt>search.analyzer.className</tt>.     *     * @param className the name of the analyzer class will be used for indexing.     */    public static void setAnalyzer(String className) {        if (className == null) {            throw new NullPointerException("Argument is null.");        }        // If the setting hasn't changed, do nothing.        if (className.equals(getAnalyzer())) {            return;        }        // If the standard analyzer has been selected, we don't need to        if (className.equals(STANDARD_ANALYZER)) {            JiveGlobals.deleteJiveProperty("search.analyzer.className");        }        else {            JiveGlobals.setJiveProperty("search.analyzer.className", className);        }        loadAnalyzer();    }    private static Directory searchDirectory = null;    private static Searcher searcher = null;    private static IndexReader searcherReader = null;    private static Semaphore indexLock = new Semaphore(1);    private static Semaphore newIndexLock = new Semaphore(1);    static ReadWriteLock searcherLock = new ReadWriteLock();    /**     * Indicates whether search is on or off at a global level. If off, index     * add and delete operations will be ignored, and auto-indexing will be     * disabled.     */    private boolean searchEnabled = true;    /**     * Indicates whether auto-indexing should be on or off. When on, an update     * will be run at the "updateInterval".     */    private boolean autoIndexEnabled = true;    /**     * Maintains the amount of time in minutes should elapse before the next     * index auto-update.     */    private int autoIndexInterval;    /**     * Maintains the time that the last index took place.     */    private Date lastIndexed;    // Values used to calculate the current percent complete.    int currentCount = 0;    int totalCount = -1;    /**     * The scheduled task for auto-indexing.     */    private TimerTask timerTask = null;    /**     * Creates a new DbSearchIndexer. It attempts to load properties for     * the update interval and when the last index occured from the Jive     * properties then starts the indexing thread.     */    public DbSearchManager() {        // Default to performing updates ever 10 minutes.        autoIndexInterval = 10;        // If the update interval property exists, use that        String interval = JiveGlobals.getJiveProperty("search.autoIndexInterval");        try {            autoIndexInterval = Integer.parseInt(interval);        }        catch (Exception e) { /* ignore */ }        // Determine if search should be turned on.        String enabled = JiveGlobals.getJiveProperty("search.enabled");        try {            searchEnabled = Boolean.valueOf(enabled).booleanValue();        }        catch (Exception e) { }        // Determine if auto-indexing should be turned on.        String index = JiveGlobals.getJiveProperty("search.autoIndexEnabled");        try {            autoIndexEnabled = Boolean.valueOf(index).booleanValue();        }        catch (Exception e) { }        // Attempt to get the last updated time from the Jive properties        String lastInd = JiveGlobals.getJiveProperty("search.lastIndexed");        try {            lastIndexed = new Date(Long.parseLong(lastInd));        }        catch (Exception e) {            // Something went wrong. Therefore, set lastIndexed far into the            // past so that we'll do a full re-index. If you've time travelled            // backwards too far with this code, this could be a problem.            lastIndexed = new Date(0);        }        // If autoIndexing is turned on, schedule indexing task.        if (autoIndexEnabled) {            timerTask = TaskEngine.scheduleTask(                    this,autoIndexInterval*JiveGlobals.MINUTE,                    autoIndexInterval*JiveGlobals.MINUTE);        }        // Initialize the search directory. Get path of where search index is.        String jiveHome = JiveGlobals.getJiveHome();        if (jiveHome == null) {            System.err.println("ERROR: the jiveHome property is not set.");        }        File mainDir = new File(jiveHome + File.separator + "search");        // If the search directory doesn't exist, create it.        if (!mainDir.exists()) {            mainDir.mkdir();        }        // The actual directory that the index is stored in lives underneath        // the main search dir. Every time we rebuild the index, a new directory        // is created. The current search directory is stored as a Jive prop.        String subDir = JiveGlobals.getJiveProperty("search.directory");        // If the search directory isn't defined, then delete all contents        // of the search directory and rebuild a new index. This will happen        // if jive_config.xml gets corrupted or the user is upgrading from        // an older Jive release.        if (subDir == null) {            // Delete all contents of mainDir.            File [] files = mainDir.listFiles();            try {                for (int i=0; i<files.length; i++) {                    File file = files[i];                    if (file.isDirectory()) {                        File [] subfiles = file.listFiles();                        for (int j=0; j<subfiles.length; j++) {                            subfiles[j].delete();                        }                        file.delete();                    }                    else {                        files[i].delete();                    }                }            }            catch (Exception e) {                e.printStackTrace();            }            // Rebuild index.            rebuildIndex();        }        // Otherwise, the search directory is defined so use it.        else {            File searchDir = new File(mainDir, subDir);            // Delete all contents of mainDir.            File [] files = mainDir.listFiles();            try {                for (int i=0; i<files.length; i++) {                    File file = files[i];                    // Delete all content from the search directory except                    // for the current search directory. This is necessary                    // since old index directories don't get deleted after                    // new ones are created. Trying to delete the old index                    // directories immediately has the possibility of failing                    // since some threads may still be doing search operations                    // on them.                    if (file.isDirectory() && !file.equals(searchDir)) {                        File [] subfiles = file.listFiles();                        for (int j=0; j<subfiles.length; j++) {                            subfiles[j].delete();                        }                        file.delete();                    }                    else {

⌨️ 快捷键说明

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