knguyen 2005/04/22 15:11:05 CEST
Modified files:
core/src/java/org/jahia/services/search SearchIndexer.java
SearchManager.java
Added files:
core/src/java/org/jahia/services/search/lucene
AbstractLuceneSearchHandler.java
AbstractLuceneSearchIndexer.java
core/src/java/org/jahia/services/search/lucene/fs
LuceneSearchHandlerImpl.java
LuceneSearchIndexer.java
core/src/java/org/jahia/services/search/lucene/jdbc
JDBCDirectoryManagerWrapper.java
LuceneJDBCSearchHandlerImpl.java
LuceneJDBCSearchIndexer.java
Removed files:
core/src/java/org/jahia/services/search/lucene
LuceneSearchHandlerImpl.java
LuceneSearchIndexer.java
Log:
- rprovide for testing a jdbc implementation version of lucene indexer
Revision Changes Path
1.2 +4 -2
jahia/core/src/java/org/jahia/services/search/SearchIndexer.java
http://jahia.mine.nu:8080/cgi-bin/cvsweb.cgi/jahia/core/src/java/org/jahia/services/search/SearchIndexer.java.diff?r1=1.1&r2=1.2&f=h
1.2 +1 -1
jahia/core/src/java/org/jahia/services/search/SearchManager.java
http://jahia.mine.nu:8080/cgi-bin/cvsweb.cgi/jahia/core/src/java/org/jahia/services/search/SearchManager.java.diff?r1=1.1&r2=1.2&f=h
1.1 +179 -0
jahia/core/src/java/org/jahia/services/search/lucene/AbstractLuceneSearchHandler.java
(new)
http://jahia.mine.nu:8080/cgi-bin/cvsweb.cgi/jahia/core/src/java/org/jahia/services/search/lucene/AbstractLuceneSearchHandler.java?rev=1.1&content-type=text/plain
1.1 +551 -0
jahia/core/src/java/org/jahia/services/search/lucene/AbstractLuceneSearchIndexer.java
(new)
http://jahia.mine.nu:8080/cgi-bin/cvsweb.cgi/jahia/core/src/java/org/jahia/services/search/lucene/AbstractLuceneSearchIndexer.java?rev=1.1&content-type=text/plain
1.2 +0 -197
jahia/core/src/java/org/jahia/services/search/lucene/LuceneSearchHandlerImpl.java
(dead)
http://jahia.mine.nu:8080/cgi-bin/cvsweb.cgi/jahia/core/src/java/org/jahia/services/search/lucene/LuceneSearchHandlerImpl.java?rev=1.1&content-type=text/plain
1.4 +0 -543
jahia/core/src/java/org/jahia/services/search/lucene/LuceneSearchIndexer.java
(dead)
http://jahia.mine.nu:8080/cgi-bin/cvsweb.cgi/jahia/core/src/java/org/jahia/services/search/lucene/LuceneSearchIndexer.java?rev=1.3&content-type=text/plain
1.1 +104 -0
jahia/core/src/java/org/jahia/services/search/lucene/fs/LuceneSearchHandlerImpl.java
(new)
http://jahia.mine.nu:8080/cgi-bin/cvsweb.cgi/jahia/core/src/java/org/jahia/services/search/lucene/fs/LuceneSearchHandlerImpl.java?rev=1.1&content-type=text/plain
1.1 +110 -0
jahia/core/src/java/org/jahia/services/search/lucene/fs/LuceneSearchIndexer.java
(new)
http://jahia.mine.nu:8080/cgi-bin/cvsweb.cgi/jahia/core/src/java/org/jahia/services/search/lucene/fs/LuceneSearchIndexer.java?rev=1.1&content-type=text/plain
1.1 +46 -0
jahia/core/src/java/org/jahia/services/search/lucene/jdbc/JDBCDirectoryManagerWrapper.java
(new)
http://jahia.mine.nu:8080/cgi-bin/cvsweb.cgi/jahia/core/src/java/org/jahia/services/search/lucene/jdbc/JDBCDirectoryManagerWrapper.java?rev=1.1&content-type=text/plain
1.1 +88 -0
jahia/core/src/java/org/jahia/services/search/lucene/jdbc/LuceneJDBCSearchHandlerImpl.java
(new)
http://jahia.mine.nu:8080/cgi-bin/cvsweb.cgi/jahia/core/src/java/org/jahia/services/search/lucene/jdbc/LuceneJDBCSearchHandlerImpl.java?rev=1.1&content-type=text/plain
1.1 +118 -0
jahia/core/src/java/org/jahia/services/search/lucene/jdbc/LuceneJDBCSearchIndexer.java
(new)
http://jahia.mine.nu:8080/cgi-bin/cvsweb.cgi/jahia/core/src/java/org/jahia/services/search/lucene/jdbc/LuceneJDBCSearchIndexer.java?rev=1.1&content-type=text/plain
Index: SearchIndexer.java
===================================================================
RCS file:
/home/cvs/repository/jahia/core/src/java/org/jahia/services/search/SearchIndexer.java,v
retrieving revision 1.1
retrieving revision 1.2
diff -u -r1.1 -r1.2
--- SearchIndexer.java 28 Feb 2005 16:10:19 -0000 1.1
+++ SearchIndexer.java 22 Apr 2005 13:11:03 -0000 1.2
@@ -16,8 +16,10 @@
public abstract void removeDocument(RemovableDocument document);
- public abstract void setSearchHandler(SearchHandlerImpl
searchHandlerImpl);
+ public abstract void setSearchHandler(SearchHandler searchHandler);
- public abstract SearchHandlerImpl getSearchHandler();
+ public abstract SearchHandler getSearchHandler();
+
+ public abstract void start() throws Exception;
}
Index: SearchManager.java
===================================================================
RCS file:
/home/cvs/repository/jahia/core/src/java/org/jahia/services/search/SearchManager.java,v
retrieving revision 1.1
retrieving revision 1.2
diff -u -r1.1 -r1.2
--- SearchManager.java 28 Feb 2005 16:10:19 -0000 1.1
+++ SearchManager.java 22 Apr 2005 13:11:03 -0000 1.2
@@ -21,7 +21,7 @@
static public String DEFAULT_SEARCH_HANDLER_NAME = "default";
static public String DEFAULT_SEARCH_HANDLER_CLASS
- = "org.jahia.services.search.lucene.LuceneSearchHandlerImpl";
+ = "org.jahia.services.search.lucene.fs.LuceneSearchHandlerImpl";
private static SearchManager searchManager;
Index: AbstractLuceneSearchHandler.java
====================================================================
package org.jahia.services.search.lucene;
import org.jahia.services.search.*;
import org.jahia.services.search.analyzer.StandardAnalyzer;
import org.apache.lucene.search.*;
import org.apache.lucene.analysis.Analyzer;
import org.apache.lucene.index.IndexReader;
import org.apache.lucene.queryParser.QueryParser;
import org.apache.lucene.document.Document;
import org.apache.lucene.document.Field;
import java.util.*;
import java.io.File;
import java.io.IOException;
/**
* Created by IntelliJ IDEA.
* User: hollis
* Date: 15 f�vr. 2005
* Time: 18:47:47
* To change this template use File | Settings | File Templates.
*/
public abstract class AbstractLuceneSearchHandler extends SearchHandlerImpl {
private static org.apache.log4j.Logger logger =
org.apache.log4j.Logger.getLogger
(AbstractLuceneSearchHandler.class);
private SearchIndexer indexer = null;
/** The Lucene analyzer * */
private Analyzer analyzer;
private Properties config = new Properties();
public AbstractLuceneSearchHandler(){
super();
}
public AbstractLuceneSearchHandler(Properties config){
super(config);
}
public AbstractLuceneSearchHandler(SearchManager searchManager,
Properties config){
super(searchManager, config);
}
/**
* This method should be called, once the config and searchManager are
set to allow
* internal initialisation.
*
* @throws Exception
*/
public void init() throws Exception{
if ( this.getAnalyzer() == null ){
String[] stopWorld = {};
this.setAnalyzer(new StandardAnalyzer (stopWorld));
}
}
public Analyzer getAnalyzer() {
return analyzer;
}
public void setAnalyzer(Analyzer analyzer) {
this.analyzer = analyzer;
}
public Properties getConfig() {
return config;
}
public void setConfig(Properties config) {
this.config = config;
}
public SearchResult search(String query){
SearchResult result = new SearchResultImpl();
search(query, result);
return result;
}
public void search(String query, SearchResult collector){
SearchResult result = null;
IndexReader reader = null;
try {
reader = this.getIndexReader();
IndexSearcher searcher = new IndexSearcher(reader);
Query q = QueryParser.parse(query,
IndexableDocument.DEFAULT_FULLTEXT_SEARCH_FIELD,
this.analyzer);
Hits hits = searcher.search (q);
result = getSearchResult(hits);
collector.results().addAll(result.results());
} catch ( Throwable t ){
logger.debug("Exception occured when performing search search",
t);
} finally {
this.closeIndexReader(reader);
}
}
public SearchIndexer getIndexer(){
return this.indexer;
}
public void setIndexer(SearchIndexer indexer){
this.indexer = indexer;
}
public Searchable getSearchable(){
IndexSearcher searcher = null;
IndexReader reader = null;
try {
reader = this.getIndexReader();
searcher = new IndexSearcher(reader);
return searcher;
} catch ( Throwable t ){
logger.debug("Exception occured when creating searchable", t);
} finally {
}
return null;
}
//--------------------------------------------------------------------------
/**
*
* @return
* @throws Exception
*/
protected abstract IndexReader getIndexReader () throws Exception;
//--------------------------------------------------------------------------
/**
* Close a IndexReader
*
* @param reader the index reader
*/
protected abstract void closeIndexReader (IndexReader reader);
/**
*
* @param hits
* @return
* @throws Exception
*/
private SearchResult getSearchResult(Hits hits) throws Exception {
SearchResultImpl searchResult = new SearchResultImpl();
if ( hits == null || hits.length()==0 ){
return searchResult;
}
int size = hits.length();
for ( int i=0; i<size; i++ ){
Document doc = hits.doc(i);
SearchHitImpl searchHit = new SearchHitImpl(doc);
searchHit.setScore(hits.score(i));
Enumeration fields = doc.fields();
Field field = null;
String name = null;
List list = null;
Hashtable fieldsMap = new Hashtable();
while ( fields.hasMoreElements() ){
list = new ArrayList();
field = (Field)fields.nextElement();
name = field.name();
String[] values = doc.getValues(name);
String val = null;
for ( int j=0; j<values.length; j++ ){
val = values[j];
list.add(new FieldValue(val));
}
fieldsMap.put(name,list);
}
searchHit.setFields(fieldsMap);
searchResult.add(searchHit);
}
return searchResult;
}
}
Index: AbstractLuceneSearchIndexer.java
====================================================================
package org.jahia.services.search.lucene;
import org.jahia.services.search.*;
import org.jahia.services.search.analyzer.StandardAnalyzer;
import org.apache.lucene.analysis.Analyzer;
import org.apache.lucene.index.IndexWriter;
import org.apache.lucene.index.IndexReader;
import org.apache.lucene.index.Term;
import org.apache.lucene.document.Document;
import org.apache.lucene.document.Field;
import org.apache.lucene.store.RAMDirectory;
import org.apache.lucene.store.Directory;
import org.apache.log4j.Logger;
import org.apache.commons.lang.StringUtils;
import java.util.*;
import java.io.File;
import java.io.IOException;
/**
* Created by IntelliJ IDEA.
* User: hollis
* Date: 15 f�vr. 2005
* Time: 13:05:57
* To change this template use File | Settings | File Templates.
*/
public abstract class AbstractLuceneSearchIndexer implements SearchIndexer ,
Runnable {
private static Logger logger =
Logger.getLogger (AbstractLuceneSearchIndexer.class);
/** The Lucene analyzer * */
private Analyzer analyzer;
private byte[] lock = new byte[0];
private Properties config = new Properties();
// list of all removed/added fields to add/remove from the index in
background
private Vector indexOrders = new Vector(); // les ordres de add/remove
private Thread backgroundIndexingThread;
private boolean indexingThreadActivated = true;
private boolean localIndexing = true;
private SearchHandler searchHandler;
protected Directory indexDirectory;
/** For write **/
private IndexReader cachedIndexReaderForWrite;
/** For write **/
private IndexWriter cachedWriter;
public AbstractLuceneSearchIndexer(){
}
public AbstractLuceneSearchIndexer( boolean localIndexing,
Analyzer analyzer,
Properties config){
this.localIndexing = localIndexing;
this.analyzer = analyzer;
if ( analyzer == null ){
String[] stopWorld = {};
this.analyzer = new StandardAnalyzer (stopWorld);
}
this.setConfig(config);
}
public void start() throws Exception {
if ( !IndexReader.indexExists(this.getIndexDirectory()) ){
getIndexWriter (this.analyzer, true);
}
// now let's remove any stale lock files if there were some.
removeStaleLockFiles ();
backgroundIndexingThread = new Thread(this,"LuceneSearchIndexer
Background Thread");
int priority = Thread.NORM_PRIORITY;
String prop =
this.getConfig().getProperty("org.apache.lucene.backgroundIndexing.priority");
if ( prop != null){
try {
priority = Integer.parseInt(prop);
} catch ( Throwable t ){
}
}
backgroundIndexingThread.setPriority(priority);
backgroundIndexingThread.setDaemon(true);
backgroundIndexingThread.start(); // start background thread
}
public boolean isLocalIndexing() {
return localIndexing;
}
public void setLocalIndexing(boolean localIndexing) {
this.localIndexing = localIndexing;
}
public Directory getIndexDirectory() {
return indexDirectory;
}
public void setIndexDirectory(Directory indexDirectory) {
this.indexDirectory = indexDirectory;
}
public Analyzer getAnalyzer() {
return analyzer;
}
public void setAnalyzer(Analyzer analyzer) {
this.analyzer = analyzer;
}
public Properties getConfig() {
return config;
}
public void setConfig(Properties config) {
this.config = config;
if ( this.config == null ){
this.config = new Properties();
}
}
public void addDocument(IndexableDocument document){
if ( document == null ){
return;
}
if ( this.localIndexing ){
addToIndexOrder(document);
}
synchronized(lock){
lock.notifyAll();
}
SearchEvent ev = new SearchEvent(this,document);
this.getSearchHandler().notify(ev,"addDocument");
}
public void removeDocument(RemovableDocument document){
if ( document == null ){
return;
}
if ( this.localIndexing ){
addToIndexOrder(document);
}
synchronized(lock){
lock.notifyAll();
}
SearchEvent ev = new SearchEvent(this,document);
this.getSearchHandler().notify(ev,"removeDocument");
}
public void setSearchHandler(SearchHandler searchHandler){
this.searchHandler = searchHandler;
}
public SearchHandler getSearchHandler(){
return this.searchHandler;
}
/**
* Background task that handles the remove/add fields to search engine
from
* the queue
*/
public void run () {
RAMDirectory ramDir = null;
Integer siteId = null;
try {
while (indexingThreadActivated) {
Vector v = new Vector();
HashMap toBeAdded = new HashMap();
HashMap toBeRemoved = new HashMap();
IndexableDocument doc = null;
synchronized (this.indexOrders) {
// 1. separate docs that are going to be added or removed
for ( int i=0; i<indexOrders.size(); i++ ){
doc = (IndexableDocument)indexOrders.get(i);
if ( doc instanceof RemovableDocument ){
toBeRemoved.put(doc.getKeyFieldName() + "_" +
doc.getKey(),new Integer(i));
} else {
toBeAdded.put(doc.getKeyFieldName() + "_" +
doc.getKey(),new Integer(i));
}
v.add(indexOrders.get(i));
}
// 2. remove "to added" docs, if they are going to be
removed
Iterator iterator = toBeRemoved.keySet().iterator();
String key = null;
Integer addOrder = null;
Integer removeOrder = null;
while ( iterator.hasNext() ){
key = (String)iterator.next();
addOrder = (Integer)toBeAdded.get(key);
if ( addOrder != null ){
removeOrder = (Integer)toBeRemoved.get(key);
if ( removeOrder.intValue() > addOrder.intValue()
){
// it would be great to use weight with
objects to be removed or added
// ( removing a staging entry of a field is
not as weight as removing the whole field )
v.setElementAt(null,addOrder.intValue());
}
}
}
// 3. batch removing Term before adding again
int size = v.size();
for (int i=0; i<size; i++){
IndexableDocument nextObject =
(IndexableDocument)v.get(i);
if ( !(nextObject instanceof RemovableDocument) ){
removeDoc(new
Term(nextObject.getKeyFieldName(),NumberPadding.pad(nextObject.getKey())));
}
}
indexOrders = new Vector();
}
long indexingStartTime = System.currentTimeMillis();
int indexOrderCount = v.size ();
boolean removing = false;
while (v.size() > 0) {
IndexableDocument nextObject = null;
if (v.size() != 0) {
nextObject = (IndexableDocument)
v.elementAt(0);
v.remove(0);
}
// okay now we have the next added/removed field, we
process it!
if (nextObject != null) {
if (nextObject instanceof RemovableDocument) {
backgroundRemoveObjectFromSearchEngine(nextObject);
} else {
backgroundAddObjectToSearchEngine(nextObject);
}
}
}
long indexingElapsedTime = System.currentTimeMillis() -
indexingStartTime;
if (logger.isInfoEnabled()) {
logger.info(
"Finished processing " + indexOrderCount +
" indexing orders in " + indexingElapsedTime + "ms.");
}
int size = 0;
synchronized (this) {
size = indexOrders.size();
}
if (size == 0) {
this.closeIndexReaderForWrite();
this.closeIndexWriter();
org.jahia.services.database.ConnectionDispenser.
terminateConnection();
synchronized (lock) {
try {
lock.wait(); // wait for next notify
}
catch (InterruptedException ie) {
}
}
}
}
} catch ( Throwable t) {
logger.debug("Exception search indexing in background",t);
} finally {
}
}
private void addToIndexOrder(IndexableDocument indObj){
if ( indObj == null ){
return;
}
synchronized(this.indexOrders){
IndexableDocument doc = null;
int size = this.indexOrders.size();
Vector result = new Vector();
for ( int i=0; i<size; i++ ){
doc = (IndexableDocument)this.indexOrders.get(i);
if ( indObj.getKeyFieldName().equals(doc.getKeyFieldName())
&& indObj.getKey().equals(doc.getKey()) ){
if ( !(indObj instanceof RemovableDocument)
&& !(doc instanceof RemovableDocument) ){
// same doc, ignore old doc
} else if ( (indObj instanceof RemovableDocument)
&& (doc instanceof RemovableDocument) ){
// same doc, ignore old doc
} else {
result.add(doc);
}
} else {
result.add(doc);
}
}
result.add(indObj);
this.indexOrders = result;
}
}
/**
* index an IndexableDocument
*
* @param indObj
*/
private void index (IndexableDocument indObj) {
if (indObj == null)
return;
long startTime = System.currentTimeMillis();
Document doc = new Document ();
Map fields = indObj.getFields ();
if (fields != null) {
Iterator iterator = fields.keySet().iterator();
DocumentField docField = null;
int count = 0;
List vals;
while (iterator.hasNext()) {
docField = (DocumentField) fields.get(iterator.next());
vals = docField.getValues();
Iterator valsIterator = vals.iterator();
while ( valsIterator.hasNext() ){
FieldValue val = (FieldValue) valsIterator.next();
String name = docField.getName();
// FIXME : should we call val.getValueAsString(Locale)
String strVal = val.getValueAsString();
// @todo : number padding, we should be done somewhere
else and customizable
strVal = NumberPadding.pad(strVal);
if ( strVal != null ){
strVal = strVal.toLowerCase();
}
if (docField.isKeyword() ) {
doc.add (Field.Keyword(name.toLowerCase(), strVal));
} else if ( docField.isText() ) {
doc.add (Field.Text(name.toLowerCase(), strVal));
} else if ( docField.isUnindexed() ){
doc.add (Field.UnIndexed(name.toLowerCase(), strVal));
} else if ( docField.isUnstoredText() ){
doc.add (Field.UnStored(name.toLowerCase(), strVal));
}
}
}
}
doc.add (Field.Keyword(indObj.getKeyFieldName ().toLowerCase(),
NumberPadding.pad(indObj.getKey ())));
// Fixme : For performance issue, should be done in batch before
adding again.
// first remove previous entry
//Term term = new Term (indObj.getKeyFieldName (), indObj.getKey ());
//removeDoc (term, reader);
try {
startTime = System.currentTimeMillis();
// Try to get the site's index if any.
this.getIndexWriter(this.analyzer,false);
if (this.cachedWriter == null) {
logger.warn ("The index writer is null, abort indexing the
object");
return;
}
this.cachedWriter.addDocument(doc);
} catch (Throwable t) {
logger.error ("Error while indexing object " + indObj.getKey () +
":", t);
} finally {
}
if (logger.isInfoEnabled()) {
logger.debug(
"Indexing document : " + indObj.getKey() + " in "
+ (System.currentTimeMillis() - startTime) + " ms.");
}
}
//--------------------------------------------------------------------------
/**
* Add an object into the search engine index in background
*
* @param indObj
*/
private void backgroundAddObjectToSearchEngine (IndexableDocument indObj)
{
if (indObj == null)
return;
index (indObj);
}
//--------------------------------------------------------------------------
/**
* Remove an object from search engine in background
*
* @param indObj
*/
private void backgroundRemoveObjectFromSearchEngine (IndexableDocument
indObj) {
// Create a term with the object key unique identifier.
Term term = new Term (indObj.getKeyFieldName (),
String.valueOf (indObj.getKey ()));
removeDoc (term);
}
//--------------------------------------------------------------------------
/**
* Remove all docs containing a given term
*
* @param term
*/
private void removeDoc (Term term) {
if ( term == null ){
return;
}
try {
// Try to get the site's index if any.
getIndexReaderForWrite();
if ( this.cachedIndexReaderForWrite == null ){
logger.debug("IndexReader is null!! Abort removing Term " +
term.field() + "=" + term.text());
return;
}
// Remove all documents containing the term.
int nbDeleted = this.cachedIndexReaderForWrite.delete (term);
} catch (Throwable t) {
logger.error ("Error while removing doc for term " + term.field()
+ "=" + term.text(), t);
} finally {
}
}
/**
* Returns the IndexWriter for a given site.
* Don't forget to close the returned index writer to flush change to the
index file !
*
* @param analyzer the analyzer to use.
* @param create if true, create a new index and replace existing one.
*
* @return IndexWriter writer, the IndexWriter, null on error.
*/
protected IndexWriter getIndexWriter (Analyzer analyzer,
boolean create) {
closeIndexReaderForWrite();
if ( create ) {
closeIndexWriter();
}
if ( this.cachedWriter == null || create ){
try {
if ( create ) {
this.cachedWriter = createIndexWriter(analyzer);
} else {
this.cachedWriter = new
IndexWriter(this.getIndexDirectory(),
analyzer, false);
}
} catch (Throwable t) {
logger.error (
"An IO Exception occured when opening the
IndexWriter :",
t);
}
}
return cachedWriter;
}
/**
* Create a new Index writer, overriding the old index
*
* @param analyzer
* @return
* @throws Exception
*/
protected abstract IndexWriter createIndexWriter(Analyzer analyzer)
throws Exception;
/**
* Returns the IndexReader for write .
* Don't forget to close the returned index reader to flush change to the
index file !
*
* @return reader, the IndexReader, null if not found.
*/
protected IndexReader getIndexReaderForWrite() throws IOException {
this.closeIndexWriter();
if ( this.cachedIndexReaderForWrite == null ){
this.cachedIndexReaderForWrite =
IndexReader.open(this.getIndexDirectory());
}
return this.cachedIndexReaderForWrite;
}
/**
* Returns the IndexReader for read only ( search ) .
*
* @return reader, the IndexReader, null if not found.
*/
public abstract IndexReader getIndexReaderForRead() throws Exception;
/**
* Close a IndexWriter
*
*/
protected void closeIndexWriter () {
if (cachedWriter != null) {
try {
cachedWriter.close();
doCloseIndexWriter();
} catch (Throwable t) {
logger.error ("Error while closing index writer:", t);
} finally {
cachedWriter = null;
}
}
}
/**
* Close the IndexReader used for write
*
*/
protected void closeIndexReaderForWrite () {
if (cachedIndexReaderForWrite != null) {
try {
cachedIndexReaderForWrite.close ();
doCloseIndexReaderForWrite();
} catch (Throwable t) {
logger.error ("Error while closing index reader:", t);
} finally {
cachedIndexReaderForWrite = null;
}
}
}
protected abstract void doCloseIndexWriter();
protected abstract void doCloseIndexReaderForWrite();
/**
* Removes all *.lock files in the specified directory, going down
* recursively. Make sure you call this ONLY on lucene managed
directories.
*
*/
protected void removeStaleLockFiles (){
try {
if ( IndexReader.isLocked(this.getIndexDirectory()) ){
IndexReader.unlock(this.getIndexDirectory());
}
} catch ( Throwable t ){
logger.debug("Exception removing locks",t);
}
}
}
Index: LuceneSearchHandlerImpl.java
====================================================================
package org.jahia.services.search.lucene.fs;
import org.jahia.services.search.*;
import org.jahia.services.search.lucene.fs.LuceneSearchIndexer;
import org.jahia.services.search.lucene.AbstractLuceneSearchHandler;
import org.jahia.services.search.analyzer.StandardAnalyzer;
import org.apache.lucene.search.*;
import org.apache.lucene.analysis.Analyzer;
import org.apache.lucene.index.IndexReader;
import org.apache.lucene.queryParser.QueryParser;
import org.apache.lucene.document.Document;
import org.apache.lucene.document.Field;
import java.util.*;
import java.io.File;
import java.io.IOException;
/**
* Created by IntelliJ IDEA.
* User: hollis
* Date: 15 f�vr. 2005
* Time: 18:47:47
* To change this template use File | Settings | File Templates.
*/
public class LuceneSearchHandlerImpl extends AbstractLuceneSearchHandler {
private static org.apache.log4j.Logger logger =
org.apache.log4j.Logger.getLogger (LuceneSearchHandlerImpl.class);
public static final String DEFAULT_INDEX_DIRECTORY =
System.getProperty("java.io.tmpdir");
private String indexDirectory = "";
public LuceneSearchHandlerImpl(){
super();
}
public LuceneSearchHandlerImpl(Properties config){
super(config);
}
public LuceneSearchHandlerImpl(SearchManager searchManager, Properties
config){
super(searchManager, config);
}
/**
* This method should be called, once the config and searchManager are
set to allow
* internal initialisation.
*
* @throws Exception
*/
public void init() throws Exception {
super.init();
indexDirectory = this.getConfig().getProperty("indexDirectory");
if ( indexDirectory == null ){
indexDirectory = DEFAULT_INDEX_DIRECTORY;
}
File f = new File(indexDirectory + File.separator + this.getName());
this.setIndexer(new LuceneSearchIndexer(f,true,this.getAnalyzer(),new
Properties()));
this.getIndexer().setSearchHandler(this);
this.getIndexer().start();
}
//--------------------------------------------------------------------------
/**
*
* @return
* @throws java.io.IOException
*/
protected IndexReader getIndexReader () throws Exception {
IndexReader reader = null;
File indexDirFile = new File (this.indexDirectory + File.separator +
this.getName());
if (indexDirFile.exists ()) {
reader = IndexReader.open (this.indexDirectory + File.separator +
this.getName());
} else {
logger.warn (
"Cannot read index because directory "
+ this.indexDirectory
+ " does not exist, will be created upon first full site
indexing...");
return null;
}
return reader;
}
//--------------------------------------------------------------------------
/**
* Close a IndexReader
*
* @param reader the index reader
*/
protected void closeIndexReader (IndexReader reader) {
if (reader == null)
return;
try {
reader.close ();
} catch (Throwable t) {
logger.error ("Error while closing index reader:", t);
}
}
}
Index: LuceneSearchIndexer.java
====================================================================
package org.jahia.services.search.lucene.fs;
import org.apache.lucene.analysis.Analyzer;
import org.apache.lucene.store.FSDirectory;
import org.apache.lucene.store.Directory;
import org.apache.lucene.index.IndexReader;
import org.apache.lucene.index.IndexWriter;
import org.jahia.services.search.lucene.AbstractLuceneSearchIndexer;
import java.util.*;
import java.io.File;
import java.io.IOException;
/**
* Created by IntelliJ IDEA.
* User: hollis
* Date: 15 f�vr. 2005
* Time: 13:05:57
* To change this template use File | Settings | File Templates.
*/
public class LuceneSearchIndexer extends AbstractLuceneSearchIndexer {
private static org.apache.log4j.Logger logger =
org.apache.log4j.Logger.getLogger (LuceneSearchIndexer.class);
private String indexPath = "";
public LuceneSearchIndexer(){
super();
}
public LuceneSearchIndexer(File indexDirectory,
boolean localIndexing,
Analyzer analyzer,
Properties config){
super(localIndexing,analyzer,config);
if ( indexDirectory != null ) {
this.indexPath = indexDirectory.getAbsolutePath();
FSDirectory fsDirectory = null;
try {
fsDirectory = FSDirectory.getDirectory(indexDirectory,false);
/*
if ( !IndexReader.indexExists(indexDirectory) ){
fsDirectory =
FSDirectory.getDirectory(indexDirectory,true);
} else {
fsDirectory =
FSDirectory.getDirectory(indexDirectory,false);
}*/
this.setIndexDirectory(fsDirectory);
} catch ( IOException ioe ) {
logger.debug("Error opening FSDirectory", ioe);
}
}
}
protected void doCloseIndexWriter(){
// nothing here
}
protected void doCloseIndexReaderForWrite(){
// nothing here
}
/**
* Create a new IndexWriter
*
* @param analyzer
* @return
*/
protected IndexWriter createIndexWriter(Analyzer analyzer) throws
Exception {
return new IndexWriter(this.indexPath,analyzer,true);
}
/**
* Returns the IndexReader for read only ( search ) .
*
* @return reader, the IndexReader, null if not found.
*/
public IndexReader getIndexReaderForRead() throws Exception {
return IndexReader.open(this.getIndexDirectory());
}
/**
* Removes all *.lock files in the specified directory, going down
* recursively. Make sure you call this ONLY on lucene managed
directories.
*
*/
protected synchronized void removeStaleLockFiles () {
// With lucene > 1.3,
// the locks are created in "java.io.tmpdir", not in the search index
folder
String tmpDir = System.getProperty("java.io.tmpdir");
File f = new File (tmpDir);
if (!f.isDirectory ()) {
return;
}
File[] files = f.listFiles();
for (int i = 0; i < files.length; i++) {
File curFile = files[i];
if (curFile.isFile() &&
curFile.getName().toLowerCase().startsWith("lucene")
&& curFile.getName().toLowerCase().endsWith (".lock")) {
logger.debug ("Removing stale lock file : [" +
curFile.toString () + "]");
curFile.delete ();
}
}
}
}
Index: JDBCDirectoryManagerWrapper.java
====================================================================
/*
* $Id: JDBCDirectoryManagerWrapper.java,v 1.1 2005/04/22 13:11:04 knguyen
Exp $
*/
package org.jahia.services.search.lucene.jdbc;
import ppi.jdbc.util.JDBCFile;
import ppi.jdbc.util.JDBCDirectoryManager;
import java.io.IOException;
import java.sql.*;
import java.util.Hashtable;
import java.util.Iterator;
import java.util.TreeMap;
import java.util.WeakHashMap;
import org.jahia.services.database.ConnectionDispenser;
/**
* @author vito
* Date: Jun 24, 2003
* @version $Revision: 1.1 $
*/
public class JDBCDirectoryManagerWrapper extends JDBCDirectoryManager {
private JDBCDirectoryManager manager;
/**
* Manages information in the database in the form of blocks. Each block
is identified with a directoryID
* and a fileName. This class will work, but not preform very well, if
the connection used does not support
* pooling prepared statements.
*
* @param directoryID
* @param tableName
* @throws SQLException
*/
public JDBCDirectoryManagerWrapper(String directoryID,
String tableName) throws SQLException {
super(ConnectionDispenser.getConnection(),directoryID,tableName);
}
public Connection getConn() {
return ConnectionDispenser.getConnection();
}
}
Index: LuceneJDBCSearchHandlerImpl.java
====================================================================
package org.jahia.services.search.lucene.jdbc;
import org.jahia.services.search.*;
import org.jahia.services.search.lucene.AbstractLuceneSearchHandler;
import org.jahia.services.search.analyzer.StandardAnalyzer;
import org.jahia.services.database.ConnectionDispenser;
import org.jahia.registries.ServicesRegistry;
import org.apache.lucene.search.*;
import org.apache.lucene.analysis.Analyzer;
import org.apache.lucene.index.IndexReader;
import org.apache.lucene.queryParser.QueryParser;
import org.apache.lucene.document.Document;
import org.apache.lucene.document.Field;
import org.apache.lucene.store.Directory;
import java.util.*;
import java.io.File;
import java.io.IOException;
import java.sql.Connection;
import ppi.jdbc.util.JDBCDirectory;
/**
* Created by IntelliJ IDEA.
* User: hollis
* Date: 15 f�vr. 2005
* Time: 18:47:47
* To change this template use File | Settings | File Templates.
*/
public class LuceneJDBCSearchHandlerImpl extends AbstractLuceneSearchHandler {
private static org.apache.log4j.Logger logger =
org.apache.log4j.Logger.getLogger
(LuceneJDBCSearchHandlerImpl.class);
public LuceneJDBCSearchHandlerImpl(){
super();
}
public LuceneJDBCSearchHandlerImpl(Properties config){
super(config);
}
public LuceneJDBCSearchHandlerImpl(SearchManager searchManager,
Properties config){
super(searchManager, config);
}
/**
* This method should be called, once the config and searchManager are
set to allow
* internal initialisation.
*
* @throws Exception
*/
public void init() throws Exception {
super.init();
this.setIndexer(new LuceneJDBCSearchIndexer("lucene_index_"
+this.getName(),true,this.getAnalyzer(),new Properties()));
this.getIndexer().setSearchHandler(this);
this.getIndexer().start();
}
//--------------------------------------------------------------------------
/**
*
* @return
* @throws java.io.IOException
*/
protected IndexReader getIndexReader () throws Exception {
return
((LuceneJDBCSearchIndexer)this.getIndexer()).getIndexReaderForRead();
}
//--------------------------------------------------------------------------
/**
* Close a IndexReader
*
* @param reader the index reader
*/
protected void closeIndexReader (IndexReader reader) {
if (reader == null)
return;
try {
reader.close ();
} catch (Throwable t) {
logger.error ("Error while closing index reader:", t);
}
}
}
Index: LuceneJDBCSearchIndexer.java
====================================================================
package org.jahia.services.search.lucene.jdbc;
import org.jahia.services.search.*;
import org.jahia.services.search.lucene.jdbc.JDBCDirectoryManagerWrapper;
import org.jahia.services.search.lucene.AbstractLuceneSearchIndexer;
import org.jahia.services.search.analyzer.StandardAnalyzer;
import org.jahia.services.database.ConnectionDispenser;
import org.apache.lucene.analysis.Analyzer;
import org.apache.lucene.index.IndexWriter;
import org.apache.lucene.index.IndexReader;
import org.apache.lucene.index.Term;
import org.apache.lucene.document.Document;
import org.apache.lucene.document.Field;
import org.apache.lucene.store.RAMDirectory;
import org.apache.lucene.store.Directory;
import org.apache.log4j.Logger;
import org.apache.commons.lang.StringUtils;
import java.util.*;
import java.io.File;
import java.io.IOException;
import java.sql.Connection;
import ppi.jdbc.util.JDBCDirectory;
/**
* Created by IntelliJ IDEA.
* User: hollis
* Date: 15 f�vr. 2005
* Time: 13:05:57
* To change this template use File | Settings | File Templates.
*/
public class LuceneJDBCSearchIndexer extends AbstractLuceneSearchIndexer {
private static org.apache.log4j.Logger logger =
org.apache.log4j.Logger.getLogger (LuceneJDBCSearchIndexer.class);
private String directoryId;
public LuceneJDBCSearchIndexer(){
super();
}
public LuceneJDBCSearchIndexer( String directoryId,
boolean localIndexing,
Analyzer analyzer,
Properties config){
super(localIndexing,analyzer,config);
this.directoryId = directoryId;
}
public void start() throws Exception {
JDBCDirectoryManagerWrapper manager =
new JDBCDirectoryManagerWrapper(directoryId,
JDBCDirectory.INDEX_TABLE_NAME);
JDBCDirectory directory = new JDBCDirectory(manager,directoryId);
this.setIndexDirectory(directory);
super.start();
}
/**
* Create a new Index writer, overriding the old index
*
* @param analyzer
* @return
* @throws Exception
*/
protected IndexWriter createIndexWriter(Analyzer analyzer) throws
Exception{
return new IndexWriter(this.getIndexDirectory(),analyzer,true);
}
protected synchronized void removeStaleLockFiles () {
//
}
/**
* Returns the IndexReader for read only ( search ) .
*
* @return reader, the IndexReader, null if not found.
*/
public IndexReader getIndexReaderForRead() throws Exception {
JDBCDirectoryManagerWrapper manager =
new JDBCDirectoryManagerWrapper(directoryId,
JDBCDirectory.INDEX_TABLE_NAME);
JDBCDirectory directory = new JDBCDirectory(manager,directoryId);
return IndexReader.open(directory);
}
protected void doCloseIndexWriter(){
try {
this.getIndexDirectory().close();
// reopen
JDBCDirectoryManagerWrapper manager =
new JDBCDirectoryManagerWrapper(directoryId,
JDBCDirectory.INDEX_TABLE_NAME);
JDBCDirectory directory = new JDBCDirectory(manager,directoryId);
this.setIndexDirectory(directory);
} catch ( Throwable t ) {
logger.debug("Error closing index Writer",t);
}
}
protected void doCloseIndexReaderForWrite(){
try {
this.getIndexDirectory().close();
// reopen
JDBCDirectoryManagerWrapper manager =
new JDBCDirectoryManagerWrapper(directoryId,
JDBCDirectory.INDEX_TABLE_NAME);
JDBCDirectory directory = new JDBCDirectory(manager,directoryId);
this.setIndexDirectory(directory);
} catch ( Throwable t ) {
logger.debug("Error closing index Reader",t);
}
}
}