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 + -
显示快捷键?