1 package org.apache.maven.archiva.indexer.lucene;
4 * Copyright 2005-2006 The Apache Software Foundation.
6 * Licensed under the Apache License, Version 2.0 (the "License");
7 * you may not use this file except in compliance with the License.
8 * You may obtain a copy of the License at
10 * http://www.apache.org/licenses/LICENSE-2.0
12 * Unless required by applicable law or agreed to in writing, software
13 * distributed under the License is distributed on an "AS IS" BASIS,
14 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
15 * See the License for the specific language governing permissions and
16 * limitations under the License.
19 import org.apache.lucene.analysis.Analyzer;
20 import org.apache.lucene.analysis.standard.StandardAnalyzer;
21 import org.apache.lucene.document.Document;
22 import org.apache.lucene.document.Field;
23 import org.apache.lucene.index.IndexReader;
24 import org.apache.lucene.index.IndexWriter;
25 import org.apache.lucene.index.Term;
26 import org.apache.lucene.search.Hits;
27 import org.apache.lucene.search.IndexSearcher;
28 import org.apache.maven.archiva.indexer.RepositoryArtifactIndex;
29 import org.apache.maven.archiva.indexer.RepositoryIndexException;
30 import org.apache.maven.archiva.indexer.RepositoryIndexSearchException;
31 import org.apache.maven.archiva.indexer.query.Query;
32 import org.apache.maven.archiva.indexer.record.RepositoryIndexRecord;
35 import java.io.IOException;
36 import java.text.ParseException;
37 import java.util.ArrayList;
38 import java.util.Collection;
39 import java.util.Iterator;
40 import java.util.List;
43 * Lucene implementation of a repository index.
45 * @author <a href="mailto:brett@apache.org">Brett Porter</a>
47 public class LuceneRepositoryArtifactIndex
48 implements RepositoryArtifactIndex
51 * The location of the index on the file system.
53 private File indexLocation;
56 * Convert repository records to Lucene documents.
58 private LuceneIndexRecordConverter converter;
60 private static final String FLD_PK = "pk";
62 public LuceneRepositoryArtifactIndex( File indexPath, LuceneIndexRecordConverter converter )
64 this.indexLocation = indexPath;
65 this.converter = converter;
68 public void indexRecords( Collection records )
69 throws RepositoryIndexException
71 deleteRecords( records );
73 addRecords( records );
76 private void addRecords( Collection records )
77 throws RepositoryIndexException
79 IndexWriter indexWriter;
82 indexWriter = new IndexWriter( indexLocation, getAnalyzer(), !exists() );
84 catch ( IOException e )
86 throw new RepositoryIndexException( "Unable to open index", e );
91 for ( Iterator i = records.iterator(); i.hasNext(); )
93 RepositoryIndexRecord record = (RepositoryIndexRecord) i.next();
97 Document document = converter.convert( record );
99 new Field( FLD_PK, record.getPrimaryKey(), Field.Store.NO, Field.Index.UN_TOKENIZED ) );
101 indexWriter.addDocument( document );
105 indexWriter.optimize();
107 catch ( IOException e )
109 throw new RepositoryIndexException( "Failed to add an index document", e );
113 close( indexWriter );
117 private void close( IndexWriter indexWriter )
118 throws RepositoryIndexException
122 if ( indexWriter != null )
127 catch ( IOException e )
129 throw new RepositoryIndexException( e.getMessage(), e );
133 private Analyzer getAnalyzer()
135 // TODO: investigate why changed in original! Probably for MD5 and number querying.
136 return new StandardAnalyzer();
139 public void deleteRecords( Collection records )
140 throws RepositoryIndexException
144 IndexReader indexReader = null;
147 indexReader = IndexReader.open( indexLocation );
149 for ( Iterator artifacts = records.iterator(); artifacts.hasNext(); )
151 RepositoryIndexRecord record = (RepositoryIndexRecord) artifacts.next();
153 if ( record != null )
155 Term term = new Term( FLD_PK, record.getPrimaryKey() );
157 indexReader.deleteDocuments( term );
161 catch ( IOException e )
163 throw new RepositoryIndexException( "Error deleting document: " + e.getMessage(), e );
167 if ( indexReader != null )
169 closeQuietly( indexReader );
175 public boolean exists()
176 throws RepositoryIndexException
178 if ( IndexReader.indexExists( indexLocation ) )
182 else if ( !indexLocation.exists() )
186 else if ( indexLocation.isDirectory() )
188 if ( indexLocation.listFiles().length > 1 )
190 throw new RepositoryIndexException( indexLocation + " is not a valid index directory." );
199 throw new RepositoryIndexException( indexLocation + " is not a directory." );
203 public List search( Query query )
204 throws RepositoryIndexSearchException
206 LuceneQuery lQuery = (LuceneQuery) query;
208 org.apache.lucene.search.Query luceneQuery = lQuery.getLuceneQuery();
210 IndexSearcher searcher;
213 searcher = new IndexSearcher( indexLocation.getAbsolutePath() );
215 catch ( IOException e )
217 throw new RepositoryIndexSearchException( "Unable to open index: " + e.getMessage(), e );
220 List records = new ArrayList();
223 Hits hits = searcher.search( luceneQuery );
224 for ( int i = 0; i < hits.length(); i++ )
226 Document doc = hits.doc( i );
228 records.add( converter.convert( doc ) );
231 catch ( IOException e )
233 throw new RepositoryIndexSearchException( "Unable to search index: " + e.getMessage(), e );
235 catch ( ParseException e )
237 throw new RepositoryIndexSearchException( "Unable to search index: " + e.getMessage(), e );
241 closeQuietly( searcher );
247 private static void closeQuietly( IndexSearcher searcher )
251 if ( searcher != null )
256 catch ( IOException e )
262 private static void closeQuietly( IndexReader reader )
266 if ( reader != null )
271 catch ( IOException e )