]> source.dussan.org Git - archiva.git/blob
469418cdfb3d72b727debc00a3ce7ee4d414f818
[archiva.git] /
1 package org.apache.maven.archiva.indexer.lucene;
2
3 /*
4  * Licensed to the Apache Software Foundation (ASF) under one
5  * or more contributor license agreements.  See the NOTICE file
6  * distributed with this work for additional information
7  * regarding copyright ownership.  The ASF licenses this file
8  * to you under the Apache License, Version 2.0 (the
9  * "License"); you may not use this file except in compliance
10  * with the License.  You may obtain a copy of the License at
11  *
12  *   http://www.apache.org/licenses/LICENSE-2.0
13  *
14  * Unless required by applicable law or agreed to in writing,
15  * software distributed under the License is distributed on an
16  * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
17  * KIND, either express or implied.  See the License for the
18  * specific language governing permissions and limitations
19  * under the License.
20  */
21
22 import org.apache.lucene.analysis.Analyzer;
23 import org.apache.lucene.document.Document;
24 import org.apache.lucene.index.IndexModifier;
25 import org.apache.lucene.index.IndexReader;
26 import org.apache.lucene.index.IndexWriter;
27 import org.apache.lucene.index.Term;
28 import org.apache.lucene.index.TermEnum;
29 import org.apache.lucene.queryParser.QueryParser;
30 import org.apache.lucene.search.IndexSearcher;
31 import org.apache.lucene.search.Searchable;
32 import org.apache.maven.archiva.configuration.ManagedRepositoryConfiguration;
33 import org.apache.maven.archiva.indexer.RepositoryContentIndex;
34 import org.apache.maven.archiva.indexer.RepositoryIndexException;
35 import org.apache.maven.archiva.indexer.RepositoryIndexSearchException;
36
37 import java.io.File;
38 import java.io.IOException;
39 import java.util.ArrayList;
40 import java.util.Collection;
41 import java.util.Iterator;
42 import java.util.List;
43
44 /**
45  * Lucene implementation of a repository index.
46  *
47  * @author <a href="mailto:brett@apache.org">Brett Porter</a>
48  */
49 public class LuceneRepositoryContentIndex
50     implements RepositoryContentIndex
51 {
52     /**
53      * The max field length for a field in a document.
54      */
55     private static final int MAX_FIELD_LENGTH = 40000;
56
57     /**
58      * The location of the index on the file system.
59      */
60     private File indexLocation;
61
62     /**
63      * The Lucene Index Handlers
64      */
65     private LuceneIndexHandlers indexHandlers;
66     
67     private ManagedRepositoryConfiguration repository;
68
69     public LuceneRepositoryContentIndex( ManagedRepositoryConfiguration repository, File indexDir, LuceneIndexHandlers handlers )
70     {
71         this.repository = repository;
72         this.indexLocation = indexDir;
73         this.indexHandlers = handlers;
74     }
75
76     public void indexRecords( Collection records )
77         throws RepositoryIndexException
78     {
79         deleteRecords( records );
80
81         addRecords( records );
82     }
83
84     public void modifyRecords( Collection records )
85         throws RepositoryIndexException
86     {
87         synchronized( repository )
88         {
89             IndexModifier indexModifier = null;
90             try
91             {
92                 indexModifier = new IndexModifier( indexLocation, indexHandlers.getAnalyzer(), !exists() );
93                 indexModifier.setMaxFieldLength( MAX_FIELD_LENGTH );
94     
95                 for ( Iterator i = records.iterator(); i.hasNext(); )
96                 {
97                     LuceneRepositoryContentRecord record = (LuceneRepositoryContentRecord) i.next();
98     
99                     if ( record != null )
100                     {
101                         Term term = new Term( LuceneDocumentMaker.PRIMARY_KEY, record.getPrimaryKey() );
102     
103                         indexModifier.deleteDocuments( term );
104     
105                         Document document = indexHandlers.getConverter().convert( record );
106     
107                         indexModifier.addDocument( document );
108                     }
109                 }
110                 indexModifier.optimize();
111             }
112             catch ( IOException e )
113             {
114                 throw new RepositoryIndexException( "Error updating index: " + e.getMessage(), e );
115             }
116             finally
117             {
118                 closeQuietly( indexModifier );
119             }
120         }
121     }
122
123     public void modifyRecord( LuceneRepositoryContentRecord record )
124         throws RepositoryIndexException
125     {
126         synchronized( repository )
127         {
128             IndexModifier indexModifier = null;
129             try
130             {
131                 indexModifier = new IndexModifier( indexLocation, indexHandlers.getAnalyzer(), !exists() );
132                 indexModifier.setMaxFieldLength( MAX_FIELD_LENGTH );
133     
134                 if ( record != null )
135                 {
136                     Term term = new Term( LuceneDocumentMaker.PRIMARY_KEY, record.getPrimaryKey() );
137     
138                     indexModifier.deleteDocuments( term );
139     
140                     Document document = indexHandlers.getConverter().convert( record );
141     
142                     indexModifier.addDocument( document );
143                 }
144                 indexModifier.optimize();
145             }
146             catch ( IOException e )
147             {
148                 throw new RepositoryIndexException( "Error updating index: " + e.getMessage(), e );
149             }
150             finally
151             {
152                 closeQuietly( indexModifier );
153             }
154         }
155     }
156         
157
158     private void addRecords( Collection records )
159         throws RepositoryIndexException
160     {
161         synchronized( repository )
162         {
163             IndexWriter indexWriter;
164             try
165             {
166                 indexWriter = new IndexWriter( indexLocation, indexHandlers.getAnalyzer(), !exists() );
167                 indexWriter.setMaxFieldLength( MAX_FIELD_LENGTH );
168             }
169             catch ( IOException e )
170             {
171                 throw new RepositoryIndexException( "Unable to open index", e );
172             }
173     
174             try
175             {
176                 for ( Iterator i = records.iterator(); i.hasNext(); )
177                 {
178                     LuceneRepositoryContentRecord record = (LuceneRepositoryContentRecord) i.next();
179     
180                     if ( record != null )
181                     {
182                         Document document = indexHandlers.getConverter().convert( record );
183     
184                         indexWriter.addDocument( document );
185                     }
186                 }
187     
188                 indexWriter.optimize();
189             }
190             catch ( IOException e )
191             {
192                 throw new RepositoryIndexException( "Failed to add an index document", e );
193             }
194             finally
195             {
196                 closeQuietly( indexWriter );
197             }
198         }
199     }
200
201     public void deleteRecords( Collection records )
202         throws RepositoryIndexException
203     {
204         synchronized( repository )
205         {
206             if ( exists() )
207             {
208                 IndexReader indexReader = null;
209                 try
210                 {
211                     indexReader = IndexReader.open( indexLocation );
212     
213                     for ( Iterator i = records.iterator(); i.hasNext(); )
214                     {
215                         LuceneRepositoryContentRecord record = (LuceneRepositoryContentRecord) i.next();
216     
217                         if ( record != null )
218                         {
219                             Term term = new Term( LuceneDocumentMaker.PRIMARY_KEY, record.getPrimaryKey() );
220                             
221                             indexReader.deleteDocuments( term );                            
222                         }
223                     }
224                 }
225                 catch ( IOException e )
226                 {
227                     throw new RepositoryIndexException( "Error deleting document: " + e.getMessage(), e );
228                 }
229                 finally
230                 {
231                     closeQuietly( indexReader );
232                 }
233             }
234         }
235     }
236     
237     public void deleteRecord( LuceneRepositoryContentRecord record )
238         throws RepositoryIndexException
239     {
240         synchronized( repository )
241         {
242             if ( exists() )
243             {
244                 IndexReader indexReader = null;
245                 try
246                 {
247                     indexReader = IndexReader.open( indexLocation );    
248                     
249                     if ( record != null )
250                     {
251                         Term term = new Term( LuceneDocumentMaker.PRIMARY_KEY, record.getPrimaryKey() );
252                         
253                         indexReader.deleteDocuments( term );                            
254                     }                    
255                 }
256                 catch ( IOException e )
257                 {
258                     throw new RepositoryIndexException( "Error deleting document: " + e.getMessage(), e );
259                 }
260                 finally
261                 {
262                     closeQuietly( indexReader );
263                 }
264             }
265         }
266     }
267     
268     
269     public Collection getAllRecordKeys()
270         throws RepositoryIndexException
271     {
272         return getAllFieldValues( LuceneDocumentMaker.PRIMARY_KEY );
273     }
274
275     private List getAllFieldValues( String fieldName )
276         throws RepositoryIndexException
277     {
278         synchronized( repository )
279         {
280             List keys = new ArrayList();
281     
282             if ( exists() )
283             {
284                 IndexReader indexReader = null;
285                 TermEnum terms = null;
286                 try
287                 {
288                     indexReader = IndexReader.open( indexLocation );
289     
290                     terms = indexReader.terms( new Term( fieldName, "" ) );
291                     while ( fieldName.equals( terms.term().field() ) )
292                     {
293                         keys.add( terms.term().text() );
294     
295                         if ( !terms.next() )
296                         {
297                             break;
298                         }
299                     }
300                 }
301                 catch ( IOException e )
302                 {
303                     throw new RepositoryIndexException( "Error deleting document: " + e.getMessage(), e );
304                 }
305                 finally
306                 {
307                     closeQuietly( indexReader );
308                     closeQuietly( terms );
309                 }
310             }
311             return keys;
312         }
313     }
314     
315     public Searchable getSearchable()
316         throws RepositoryIndexSearchException
317     {
318         try
319         {
320             IndexSearcher searcher = new IndexSearcher( indexLocation.getAbsolutePath() );
321             return searcher;
322         }
323         catch ( IOException e )
324         {
325             throw new RepositoryIndexSearchException( "Unable to open index: " + e.getMessage(), e );
326         }
327     }
328
329     public boolean exists()
330         throws RepositoryIndexException
331     {
332         if ( IndexReader.indexExists( indexLocation ) )
333         {
334             return true;
335         }
336         else if ( !indexLocation.exists() )
337         {
338             return false;
339         }
340         else if ( indexLocation.isDirectory() )
341         {
342             if ( indexLocation.listFiles().length > 1 )
343             {
344                 throw new RepositoryIndexException( indexLocation + " is not a valid index directory." );
345             }
346             else
347             {
348                 return false;
349             }
350         }
351         else
352         {
353             throw new RepositoryIndexException( indexLocation + " is not a directory." );
354         }
355     }
356
357     public QueryParser getQueryParser()
358     {
359         return this.indexHandlers.getQueryParser();
360     }
361
362     public static void closeSearchable( Searchable searchable )
363     {
364         if( searchable != null )
365         {
366             try
367             {
368                 searchable.close();
369             }
370             catch ( IOException e )
371             {
372                 // Ignore
373             }
374         }
375     }
376     
377     private static void closeQuietly( TermEnum terms )
378         throws RepositoryIndexException
379     {
380         if ( terms != null )
381         {
382             try
383             {
384                 terms.close();
385             }
386             catch ( IOException e )
387             {
388                 // ignore
389             }
390         }
391     }
392
393     private static void closeQuietly( IndexWriter indexWriter )
394         throws RepositoryIndexException
395     {
396         try
397         {
398             if ( indexWriter != null )
399             {
400                 indexWriter.close();
401             }
402         }
403         catch ( IOException e )
404         {
405             // write should compain if it can't be closed, data probably not persisted
406             throw new RepositoryIndexException( e.getMessage(), e );
407         }
408     }
409
410     private static void closeQuietly( IndexModifier indexModifier )
411     {
412         if ( indexModifier != null )
413         {
414             try
415             {
416                 indexModifier.close();
417             }
418             catch ( IOException e )
419             {
420                 // ignore
421             }
422         }
423     }
424
425     private static void closeQuietly( IndexReader reader )
426     {
427         try
428         {
429             if ( reader != null )
430             {
431                 reader.close();
432             }
433         }
434         catch ( IOException e )
435         {
436             // ignore
437         }
438     }
439
440     public File getIndexDirectory()
441     {
442         return this.indexLocation;
443     }
444
445     public String getId()
446     {
447         return this.indexHandlers.getId();
448     }
449
450     public ManagedRepositoryConfiguration getRepository()
451     {
452         return repository;
453     }
454     
455     public Analyzer getAnalyzer()
456     {
457         return this.indexHandlers.getAnalyzer();
458     }
459     
460     public LuceneEntryConverter getEntryConverter()
461     {
462         return this.indexHandlers.getConverter();
463     }
464 }