]> source.dussan.org Git - archiva.git/blob
c97b468cbde78e8bc9f57d38598976754492847e
[archiva.git] /
1 package org.apache.maven.archiva.indexer.lucene;
2
3 /*
4  * Copyright 2005-2006 The Apache Software Foundation.
5  *
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
9  *
10  *      http://www.apache.org/licenses/LICENSE-2.0
11  *
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.
17  */
18
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;
33
34 import java.io.File;
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;
41
42 /**
43  * Lucene implementation of a repository index.
44  *
45  * @author <a href="mailto:brett@apache.org">Brett Porter</a>
46  */
47 public class LuceneRepositoryArtifactIndex
48     implements RepositoryArtifactIndex
49 {
50     /**
51      * The location of the index on the file system.
52      */
53     private File indexLocation;
54
55     /**
56      * Convert repository records to Lucene documents.
57      */
58     private LuceneIndexRecordConverter converter;
59
60     private static final String FLD_PK = "pk";
61
62     public LuceneRepositoryArtifactIndex( File indexPath, LuceneIndexRecordConverter converter )
63     {
64         this.indexLocation = indexPath;
65         this.converter = converter;
66     }
67
68     public void indexRecords( Collection records )
69         throws RepositoryIndexException
70     {
71         deleteRecords( records );
72
73         addRecords( records );
74     }
75
76     private void addRecords( Collection records )
77         throws RepositoryIndexException
78     {
79         IndexWriter indexWriter;
80         try
81         {
82             indexWriter = new IndexWriter( indexLocation, getAnalyzer(), !exists() );
83         }
84         catch ( IOException e )
85         {
86             throw new RepositoryIndexException( "Unable to open index", e );
87         }
88
89         try
90         {
91             for ( Iterator i = records.iterator(); i.hasNext(); )
92             {
93                 RepositoryIndexRecord record = (RepositoryIndexRecord) i.next();
94
95                 if ( record != null )
96                 {
97                     Document document = converter.convert( record );
98                     document.add(
99                         new Field( FLD_PK, record.getPrimaryKey(), Field.Store.NO, Field.Index.UN_TOKENIZED ) );
100
101                     indexWriter.addDocument( document );
102                 }
103             }
104
105             indexWriter.optimize();
106         }
107         catch ( IOException e )
108         {
109             throw new RepositoryIndexException( "Failed to add an index document", e );
110         }
111         finally
112         {
113             close( indexWriter );
114         }
115     }
116
117     private void close( IndexWriter indexWriter )
118         throws RepositoryIndexException
119     {
120         try
121         {
122             if ( indexWriter != null )
123             {
124                 indexWriter.close();
125             }
126         }
127         catch ( IOException e )
128         {
129             throw new RepositoryIndexException( e.getMessage(), e );
130         }
131     }
132
133     private Analyzer getAnalyzer()
134     {
135         // TODO: investigate why changed in original! Probably for MD5 and number querying.
136         return new StandardAnalyzer();
137     }
138
139     public void deleteRecords( Collection records )
140         throws RepositoryIndexException
141     {
142         if ( exists() )
143         {
144             IndexReader indexReader = null;
145             try
146             {
147                 indexReader = IndexReader.open( indexLocation );
148
149                 for ( Iterator artifacts = records.iterator(); artifacts.hasNext(); )
150                 {
151                     RepositoryIndexRecord record = (RepositoryIndexRecord) artifacts.next();
152
153                     if ( record != null )
154                     {
155                         Term term = new Term( FLD_PK, record.getPrimaryKey() );
156
157                         indexReader.deleteDocuments( term );
158                     }
159                 }
160             }
161             catch ( IOException e )
162             {
163                 throw new RepositoryIndexException( "Error deleting document: " + e.getMessage(), e );
164             }
165             finally
166             {
167                 if ( indexReader != null )
168                 {
169                     closeQuietly( indexReader );
170                 }
171             }
172         }
173     }
174
175     public boolean exists()
176         throws RepositoryIndexException
177     {
178         if ( IndexReader.indexExists( indexLocation ) )
179         {
180             return true;
181         }
182         else if ( !indexLocation.exists() )
183         {
184             return false;
185         }
186         else if ( indexLocation.isDirectory() )
187         {
188             if ( indexLocation.listFiles().length > 1 )
189             {
190                 throw new RepositoryIndexException( indexLocation + " is not a valid index directory." );
191             }
192             else
193             {
194                 return false;
195             }
196         }
197         else
198         {
199             throw new RepositoryIndexException( indexLocation + " is not a directory." );
200         }
201     }
202
203     public List search( Query query )
204         throws RepositoryIndexSearchException
205     {
206         LuceneQuery lQuery = (LuceneQuery) query;
207
208         org.apache.lucene.search.Query luceneQuery = lQuery.getLuceneQuery();
209
210         IndexSearcher searcher;
211         try
212         {
213             searcher = new IndexSearcher( indexLocation.getAbsolutePath() );
214         }
215         catch ( IOException e )
216         {
217             throw new RepositoryIndexSearchException( "Unable to open index: " + e.getMessage(), e );
218         }
219
220         List records = new ArrayList();
221         try
222         {
223             Hits hits = searcher.search( luceneQuery );
224             for ( int i = 0; i < hits.length(); i++ )
225             {
226                 Document doc = hits.doc( i );
227
228                 records.add( converter.convert( doc ) );
229             }
230         }
231         catch ( IOException e )
232         {
233             throw new RepositoryIndexSearchException( "Unable to search index: " + e.getMessage(), e );
234         }
235         catch ( ParseException e )
236         {
237             throw new RepositoryIndexSearchException( "Unable to search index: " + e.getMessage(), e );
238         }
239         finally
240         {
241             closeQuietly( searcher );
242         }
243
244         return records;
245     }
246
247     private static void closeQuietly( IndexSearcher searcher )
248     {
249         try
250         {
251             if ( searcher != null )
252             {
253                 searcher.close();
254             }
255         }
256         catch ( IOException e )
257         {
258             // ignore
259         }
260     }
261
262     private static void closeQuietly( IndexReader reader )
263     {
264         try
265         {
266             if ( reader != null )
267             {
268                 reader.close();
269             }
270         }
271         catch ( IOException e )
272         {
273             // ignore
274         }
275     }
276 }