LuceneIndexer.java
Upload User: gdxydsw
Upload Date: 2019-01-29
Package Size: 16721k
Code Size: 7k
Category:

Java Develop

Development Platform:

Java

  1. /*
  2.  * Copyright (c) JForum Team
  3.  * All rights reserved.
  4.  * 
  5.  * Redistribution and use in source and binary forms, 
  6.  * with or without modification, are permitted provided 
  7.  * that the following conditions are met:
  8.  * 
  9.  * 1) Redistributions of source code must retain the above 
  10.  * copyright notice, this list of conditions and the 
  11.  * following  disclaimer.
  12.  * 2)  Redistributions in binary form must reproduce the 
  13.  * above copyright notice, this list of conditions and 
  14.  * the following disclaimer in the documentation and/or 
  15.  * other materials provided with the distribution.
  16.  * 3) Neither the name of "Rafael Steil" nor 
  17.  * the names of its contributors may be used to endorse 
  18.  * or promote products derived from this software without 
  19.  * specific prior written permission.
  20.  * 
  21.  * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT 
  22.  * HOLDERS AND CONTRIBUTORS "AS IS" AND ANY 
  23.  * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, 
  24.  * BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF 
  25.  * MERCHANTABILITY AND FITNESS FOR A PARTICULAR 
  26.  * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL 
  27.  * THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE 
  28.  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, 
  29.  * EXEMPLARY, OR CONSEQUENTIAL DAMAGES 
  30.  * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF 
  31.  * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, 
  32.  * OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER 
  33.  * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER 
  34.  * IN CONTRACT, STRICT LIABILITY, OR TORT 
  35.  * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN 
  36.  * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF 
  37.  * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE
  38.  * 
  39.  * Created on 18/07/2007 17:18:41
  40.  * 
  41.  * The JForum Project
  42.  * http://www.jforum.net
  43.  */
  44. package net.jforum.search;
  45. import java.io.IOException;
  46. import java.util.ArrayList;
  47. import java.util.Iterator;
  48. import java.util.List;
  49. import net.jforum.entities.Post;
  50. import net.jforum.exceptions.SearchException;
  51. import net.jforum.util.preferences.ConfigKeys;
  52. import net.jforum.util.preferences.SystemGlobals;
  53. import org.apache.log4j.Logger;
  54. import org.apache.lucene.document.Document;
  55. import org.apache.lucene.document.Field;
  56. import org.apache.lucene.document.Field.Index;
  57. import org.apache.lucene.document.Field.Store;
  58. import org.apache.lucene.index.IndexReader;
  59. import org.apache.lucene.index.IndexWriter;
  60. import org.apache.lucene.index.Term;
  61. import org.apache.lucene.store.Directory;
  62. import org.apache.lucene.store.RAMDirectory;
  63. /**
  64.  * @author Rafael Steil
  65.  * @version $Id: LuceneIndexer.java,v 1.11 2007/09/01 05:46:53 rafaelsteil Exp $
  66.  */
  67. public class LuceneIndexer
  68. {
  69. private static final Logger logger = Logger.getLogger(LuceneIndexer.class);
  70. private static final Object MUTEX = new Object();
  71. private LuceneSettings settings;
  72. private Directory ramDirectory;
  73. private IndexWriter ramWriter;
  74. private int ramNumDocs;
  75. private List newDocumentAddedList = new ArrayList();
  76. public LuceneIndexer(LuceneSettings settings)
  77. {
  78. this.settings = settings;
  79. this.createRAMWriter();
  80. }
  81. public void watchNewDocuDocumentAdded(NewDocumentAdded newDoc)
  82. {
  83. this.newDocumentAddedList.add(newDoc);
  84. }
  85. public void batchCreate(Post post)
  86. {
  87. synchronized (MUTEX) {
  88. try {
  89. Document document = this.createDocument(post);
  90. this.ramWriter.addDocument(document);
  91. this.flushRAMDirectoryIfNecessary();
  92. }
  93. catch (IOException e) {
  94. throw new SearchException(e);
  95. }
  96. }
  97. }
  98. private void createRAMWriter()
  99. {
  100. try {
  101. if (this.ramWriter != null) {
  102. this.ramWriter.close();
  103. }
  104. this.ramDirectory = new RAMDirectory();
  105. this.ramWriter = new IndexWriter(this.ramDirectory, this.settings.analyzer(), true);
  106. this.ramNumDocs = SystemGlobals.getIntValue(ConfigKeys.LUCENE_INDEXER_RAM_NUMDOCS);
  107. }
  108. catch (IOException e) {
  109. throw new SearchException(e);
  110. }
  111. }
  112. private void flushRAMDirectoryIfNecessary()
  113. {
  114. if (this.ramWriter.docCount() >= this.ramNumDocs) {
  115. this.flushRAMDirectory();
  116. }
  117. }
  118. public void flushRAMDirectory()
  119. {
  120. synchronized (MUTEX) {
  121. IndexWriter writer = null;
  122. try {
  123. writer = new IndexWriter(this.settings.directory(), this.settings.analyzer());
  124. writer.addIndexes(new Directory[] { this.ramDirectory });
  125. writer.optimize();
  126. this.createRAMWriter();
  127. }
  128. catch (IOException e) {
  129. throw new SearchException(e);
  130. }
  131. finally {
  132. if (writer != null) {
  133. try { 
  134. writer.flush(); 
  135. writer.close();
  136. this.notifyNewDocumentAdded();
  137. }
  138. catch (Exception e) {}
  139. }
  140. }
  141. }
  142. }
  143. public void create(Post post)
  144. {
  145. synchronized (MUTEX) {
  146. IndexWriter writer = null;
  147. try {
  148. writer = new IndexWriter(this.settings.directory(), this.settings.analyzer());
  149. Document document = this.createDocument(post);
  150. writer.addDocument(document);
  151. this.optimize(writer);
  152. if (logger.isDebugEnabled()) {
  153. logger.debug("Indexed " + document);
  154. }
  155. }
  156. catch (Exception e) {
  157. logger.error(e.toString(), e);
  158. }
  159. finally {
  160. if (writer != null) {
  161. try {
  162. writer.flush();
  163. writer.close();
  164. this.notifyNewDocumentAdded();
  165. }
  166. catch (Exception e) {}
  167. }
  168. }
  169. }
  170. }
  171. public void update(Post post)
  172. {
  173. if (this.performDelete(post)) {
  174. this.create(post);
  175. }
  176. }
  177. private void optimize(IndexWriter writer) throws Exception
  178. {
  179. if (writer.docCount() % 100 == 0) {
  180. if (logger.isInfoEnabled()) {
  181. logger.info("Optimizing indexes. Current number of documents is " + writer.docCount());
  182. }
  183. writer.optimize();
  184. if (logger.isDebugEnabled()) {
  185. logger.debug("Indexes optimized");
  186. }
  187. }
  188. }
  189. private Document createDocument(Post p)
  190. {
  191. Document d = new Document();
  192. d.add(new Field(SearchFields.Keyword.POST_ID, String.valueOf(p.getId()), Store.YES, Index.UN_TOKENIZED));
  193. d.add(new Field(SearchFields.Keyword.FORUM_ID, String.valueOf(p.getForumId()), Store.YES, Index.UN_TOKENIZED));
  194. d.add(new Field(SearchFields.Keyword.TOPIC_ID, String.valueOf(p.getTopicId()), Store.YES, Index.UN_TOKENIZED));
  195. d.add(new Field(SearchFields.Keyword.USER_ID, String.valueOf(p.getUserId()), Store.YES, Index.UN_TOKENIZED));
  196. d.add(new Field(SearchFields.Keyword.DATE, this.settings.formatDateTime(p.getTime()), Store.YES, Index.UN_TOKENIZED));
  197. // We add the subject and message text together because, when searching, we only care about the 
  198. // matches, not where it was performed. The real subject and contents will be fetched from the database
  199. d.add(new Field(SearchFields.Indexed.CONTENTS, p.getSubject() + " " + p.getText(), Store.NO, Index.TOKENIZED));
  200. return d;
  201. }
  202. private void notifyNewDocumentAdded()
  203. {
  204. for (Iterator iter = this.newDocumentAddedList.iterator(); iter.hasNext(); ) {
  205. ((NewDocumentAdded)iter.next()).newDocumentAdded();
  206. }
  207. }
  208. public void delete(Post p)
  209. {
  210. this.performDelete(p);
  211. }
  212. private boolean performDelete(Post p)
  213. {
  214. synchronized (MUTEX) {
  215. IndexReader reader = null;
  216. boolean status = false;
  217. try {
  218. reader = IndexReader.open(this.settings.directory());
  219. reader.deleteDocuments(new Term(SearchFields.Keyword.POST_ID, String.valueOf(p.getId())));
  220. status = true;
  221. }
  222. catch (IOException e) {
  223. logger.error(e.toString(), e);
  224. }
  225. finally {
  226. if (reader != null) {
  227. try {
  228. reader.close();
  229. }
  230. catch (Exception e) {}
  231. }
  232. }
  233. return status;
  234. }
  235. }
  236. }