KickJava   Java API By Example, From Geeks To Geeks.

Java > Open Source Codes > org > apache > roller > business > IndexManagerImpl


1 /*
2  * Licensed to the Apache Software Foundation (ASF) under one or more
3  * contributor license agreements. The ASF licenses this file to You
4  * under the Apache License, Version 2.0 (the "License"); you may not
5  * use this file except in compliance with the License.
6  * You may obtain a copy of the License at
7  *
8  * http://www.apache.org/licenses/LICENSE-2.0
9  *
10  * Unless required by applicable law or agreed to in writing, software
11  * distributed under the License is distributed on an "AS IS" BASIS,
12  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13  * See the License for the specific language governing permissions and
14  * limitations under the License. For additional information regarding
15  * copyright in this work, please see the NOTICE file in the top level
16  * directory of this distribution.
17  */

18 /* Created on Jul 18, 2003 */
19 package org.apache.roller.business;
20
21 import java.io.File JavaDoc;
22 import java.io.IOException JavaDoc;
23
24 import org.apache.commons.logging.Log;
25 import org.apache.commons.logging.LogFactory;
26 import org.apache.lucene.analysis.Analyzer;
27 import org.apache.lucene.analysis.standard.StandardAnalyzer;
28 import org.apache.lucene.index.IndexReader;
29 import org.apache.lucene.index.IndexWriter;
30 import org.apache.lucene.store.Directory;
31 import org.apache.lucene.store.FSDirectory;
32 import org.apache.lucene.store.RAMDirectory;
33 import org.apache.roller.RollerException;
34 import org.apache.roller.business.search.operations.AddEntryOperation;
35 import org.apache.roller.business.search.operations.IndexOperation;
36 import org.apache.roller.business.search.operations.ReIndexEntryOperation;
37 import org.apache.roller.business.search.operations.RebuildWebsiteIndexOperation;
38 import org.apache.roller.business.search.operations.RemoveEntryOperation;
39 import org.apache.roller.business.search.operations.RemoveWebsiteIndexOperation;
40 import org.apache.roller.business.search.operations.WriteToIndexOperation;
41 import org.apache.roller.model.IndexManager;
42 import org.apache.roller.pojos.WeblogEntryData;
43 import org.apache.roller.pojos.WebsiteData;
44
45 import EDU.oswego.cs.dl.util.concurrent.ReadWriteLock;
46 import EDU.oswego.cs.dl.util.concurrent.WriterPreferenceReadWriteLock;
47 import org.apache.roller.config.RollerConfig;
48 import org.apache.roller.model.RollerFactory;
49 import org.apache.commons.lang.StringUtils;
50
51 /**
52  * Lucene implementation of IndexManager. This is the central entry point
53  * into the Lucene searching API.
54  * @author Mindaugas Idzelis (min@idzelis.com)
55  * @author mraible (formatting and making indexDir configurable)
56  */

57 public class IndexManagerImpl implements IndexManager {
58     //~ Static fields/initializers
59
// =============================================
60

61     private IndexReader reader;
62     
63     static Log mLogger = LogFactory.getFactory().getInstance(
64             IndexManagerImpl.class);
65     
66     //~ Instance fields
67
// ========================================================
68

69     private boolean searchEnabled = true;
70     
71     File JavaDoc indexConsistencyMarker;
72     
73     private boolean useRAMIndex = false;
74     
75     private RAMDirectory fRAMindex;
76     
77     private String JavaDoc indexDir = null;
78     
79     private boolean inconsistentAtStartup = false;
80     
81     private ReadWriteLock rwl = new WriterPreferenceReadWriteLock();
82     
83     //~ Constructors
84
// ===========================================================
85

86     /**
87      * Creates a new lucene index manager. This should only be created once.
88      * Creating the index manager more than once will definately result in
89      * errors. The preferred way of getting an index is through the
90      * RollerContext.
91      *
92      * @param indexDir -
93      * the path to the index directory
94      */

95     public IndexManagerImpl() {
96         // check config to see if the internal search is enabled
97
String JavaDoc enabled = RollerConfig.getProperty("search.enabled");
98         if("false".equalsIgnoreCase(enabled))
99             this.searchEnabled = false;
100         
101         // we also need to know what our index directory is
102
// Note: system property expansion is now handled by RollerConfig
103
String JavaDoc searchIndexDir = RollerConfig.getProperty("search.index.dir");
104         
105         this.indexDir = searchIndexDir.replace('/', File.separatorChar);
106         
107         // a little debugging
108
mLogger.info("search enabled: " + this.searchEnabled);
109         mLogger.info("index dir: " + this.indexDir);
110         
111         String JavaDoc test = indexDir + File.separator + ".index-inconsistent";
112         indexConsistencyMarker = new File JavaDoc(test);
113         
114         // only setup the index if search is enabled
115
if (this.searchEnabled) {
116             
117             // 1. If inconsistency marker exists.
118
// Delete index
119
// 2. if we're using RAM index
120
// load ram index wrapper around index
121
//
122
if (indexConsistencyMarker.exists()) {
123                 getFSDirectory(true);
124                 inconsistentAtStartup = true;
125             } else {
126                 try {
127                     File JavaDoc makeIndexDir = new File JavaDoc(indexDir);
128                     if (!makeIndexDir.exists()) {
129                         makeIndexDir.mkdirs();
130                         inconsistentAtStartup = true;
131                     }
132                     indexConsistencyMarker.createNewFile();
133                 } catch (IOException JavaDoc e) {
134                     mLogger.error(e);
135                 }
136             }
137             
138             if (indexExists()) {
139                 if (useRAMIndex) {
140                     Directory filesystem = getFSDirectory(false);
141                     
142                     try {
143                         fRAMindex = new RAMDirectory(filesystem);
144                     } catch (IOException JavaDoc e) {
145                         mLogger.error("Error creating in-memory index", e);
146                     }
147                 }
148             } else {
149                 if (useRAMIndex) {
150                     fRAMindex = new RAMDirectory();
151                     createIndex(fRAMindex);
152                 } else {
153                     createIndex(getFSDirectory(true));
154                 }
155             }
156             
157             if (isInconsistentAtStartup()) {
158                 mLogger.info(
159                         "Index was inconsistent. Rebuilding index in the background...");
160                 try {
161                     rebuildWebsiteIndex();
162                 } catch (RollerException e) {
163                     mLogger.error("ERROR: scheduling re-index operation");
164                 }
165             }
166         }
167     }
168     
169     //~ Methods
170
// ================================================================
171

172     public void rebuildWebsiteIndex() throws RollerException {
173         scheduleIndexOperation(
174                 new RebuildWebsiteIndexOperation(this, null));
175     }
176     
177     public void rebuildWebsiteIndex(WebsiteData website) throws RollerException {
178         scheduleIndexOperation(
179                 new RebuildWebsiteIndexOperation(this, website));
180     }
181     
182     public void removeWebsiteIndex(WebsiteData website) throws RollerException {
183         scheduleIndexOperation(
184                 new RemoveWebsiteIndexOperation(this, website));
185     }
186     
187     public void addEntryIndexOperation(WeblogEntryData entry) throws RollerException {
188         AddEntryOperation addEntry = new AddEntryOperation(this, entry);
189         scheduleIndexOperation(addEntry);
190     }
191     
192     public void addEntryReIndexOperation(WeblogEntryData entry) throws RollerException {
193         ReIndexEntryOperation reindex = new ReIndexEntryOperation(this, entry);
194         scheduleIndexOperation(reindex);
195     }
196     
197     public void removeEntryIndexOperation(WeblogEntryData entry) throws RollerException {
198         RemoveEntryOperation removeOp = new RemoveEntryOperation(this, entry);
199         executeIndexOperationNow(removeOp);
200     }
201     
202     public ReadWriteLock getReadWriteLock() {
203         return rwl;
204     }
205     
206     public boolean isInconsistentAtStartup() {
207         return inconsistentAtStartup;
208     }
209     
210     /**
211      * This is the analyzer that will be used to tokenize comment text.
212      *
213      * @return Analyzer to be used in manipulating the database.
214      */

215     public static final Analyzer getAnalyzer() {
216         return new StandardAnalyzer();
217     }
218     
219     private void scheduleIndexOperation(final IndexOperation op) {
220         try {
221             // only if search is enabled
222
if(this.searchEnabled) {
223                 mLogger.debug("Starting scheduled index operation: "+op.getClass().getName());
224                 RollerFactory.getRoller().getThreadManager().executeInBackground(op);
225             }
226         } catch (RollerException re) {
227             mLogger.error("Error getting thread manager", re);
228         } catch (InterruptedException JavaDoc e) {
229             mLogger.error("Error executing operation", e);
230         }
231     }
232     
233     /**
234      * @param search
235      */

236     public void executeIndexOperationNow(final IndexOperation op) {
237         try {
238             // only if search is enabled
239
if(this.searchEnabled) {
240                 mLogger.debug("Executing index operation now: "+op.getClass().getName());
241                 RollerFactory.getRoller().getThreadManager().executeInForeground(op);
242             }
243         } catch (RollerException re) {
244             mLogger.error("Error getting thread manager", re);
245         } catch (InterruptedException JavaDoc e) {
246             mLogger.error("Error executing operation", e);
247         }
248     }
249     
250     public synchronized void resetSharedReader() {
251         reader = null;
252     }
253     public synchronized IndexReader getSharedIndexReader() {
254         if (reader == null) {
255             try {
256                 reader = IndexReader.open(getIndexDirectory());
257             } catch (IOException JavaDoc e) {
258             }
259         }
260         return reader;
261     }
262     
263     /**
264      * Get the directory that is used by the lucene index. This method will
265      * return null if there is no index at the directory location. If we are
266      * using a RAM index, the directory will be a ram directory.
267      *
268      * @return Directory The directory containing the index, or null if error.
269      */

270     public Directory getIndexDirectory() {
271         if (useRAMIndex) {
272             return fRAMindex;
273         } else {
274             return getFSDirectory(false);
275         }
276     }
277     
278     private boolean indexExists() {
279         return IndexReader.indexExists(indexDir);
280     }
281     
282     Directory getFSDirectory(boolean delete) {
283         Directory directory = null;
284         
285         try {
286             directory = FSDirectory.getDirectory(indexDir, delete);
287         } catch (IOException JavaDoc e) {
288             mLogger.error("Problem accessing index directory", e);
289         }
290         
291         return directory;
292     }
293     
294     private void createIndex(Directory dir) {
295         IndexWriter writer = null;
296         
297         try {
298             writer = new IndexWriter(dir, IndexManagerImpl.getAnalyzer(), true);
299         } catch (IOException JavaDoc e) {
300             mLogger.error("Error creating index", e);
301         } finally {
302             try {
303                 if (writer != null) {
304                     writer.close();
305                 }
306             } catch (IOException JavaDoc e) {
307             }
308         }
309     }
310     
311     private IndexOperation getSaveIndexOperation() {
312         return new WriteToIndexOperation(this) {
313             public void doRun() {
314                 Directory dir = getIndexDirectory();
315                 Directory fsdir = getFSDirectory(true);
316                 
317                 IndexWriter writer = null;
318                 
319                 try {
320                     writer = new IndexWriter(fsdir, IndexManagerImpl
321                             .getAnalyzer(), true);
322                     
323                     writer.addIndexes(new Directory[] { dir });
324                     indexConsistencyMarker.delete();
325                 } catch (IOException JavaDoc e) {
326                     mLogger.error("Problem saving index to disk", e);
327                     
328                     // Delete the directory, since there was a problem saving
329
// the RAM contents
330
getFSDirectory(true);
331                 } finally {
332                     try {
333                         if (writer != null)
334                             writer.close();
335                     } catch (IOException JavaDoc e1) {
336                         mLogger.warn("Unable to close IndexWriter.");
337                     }
338                 }
339                 
340             }
341         };
342     }
343     
344     public void release() {
345         // no-op
346
}
347     
348     public void shutdown() {
349         if (useRAMIndex) {
350             scheduleIndexOperation(getSaveIndexOperation());
351         } else {
352             indexConsistencyMarker.delete();
353         }
354         
355         try {
356             if (reader != null)
357                 reader.close();
358         } catch (IOException JavaDoc e) {
359             // won't happen, since it was
360
}
361     }
362 }
Popular Tags