]> source.dussan.org Git - archiva.git/blob
369d67535f3dade6165327df0965aacea665f938
[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 Collection getAllRecordKeys()
238         throws RepositoryIndexException
239     {
240         return getAllFieldValues( LuceneDocumentMaker.PRIMARY_KEY );
241     }
242
243     private List getAllFieldValues( String fieldName )
244         throws RepositoryIndexException
245     {
246         synchronized( repository )
247         {
248             List keys = new ArrayList();
249     
250             if ( exists() )
251             {
252                 IndexReader indexReader = null;
253                 TermEnum terms = null;
254                 try
255                 {
256                     indexReader = IndexReader.open( indexLocation );
257     
258                     terms = indexReader.terms( new Term( fieldName, "" ) );
259                     while ( fieldName.equals( terms.term().field() ) )
260                     {
261                         keys.add( terms.term().text() );
262     
263                         if ( !terms.next() )
264                         {
265                             break;
266                         }
267                     }
268                 }
269                 catch ( IOException e )
270                 {
271                     throw new RepositoryIndexException( "Error deleting document: " + e.getMessage(), e );
272                 }
273                 finally
274                 {
275                     closeQuietly( indexReader );
276                     closeQuietly( terms );
277                 }
278             }
279             return keys;
280         }
281     }
282     
283     public Searchable getSearchable()
284         throws RepositoryIndexSearchException
285     {
286         try
287         {
288             IndexSearcher searcher = new IndexSearcher( indexLocation.getAbsolutePath() );
289             return searcher;
290         }
291         catch ( IOException e )
292         {
293             throw new RepositoryIndexSearchException( "Unable to open index: " + e.getMessage(), e );
294         }
295     }
296
297     public boolean exists()
298         throws RepositoryIndexException
299     {
300         if ( IndexReader.indexExists( indexLocation ) )
301         {
302             return true;
303         }
304         else if ( !indexLocation.exists() )
305         {
306             return false;
307         }
308         else if ( indexLocation.isDirectory() )
309         {
310             if ( indexLocation.listFiles().length > 1 )
311             {
312                 throw new RepositoryIndexException( indexLocation + " is not a valid index directory." );
313             }
314             else
315             {
316                 return false;
317             }
318         }
319         else
320         {
321             throw new RepositoryIndexException( indexLocation + " is not a directory." );
322         }
323     }
324
325     public QueryParser getQueryParser()
326     {
327         return this.indexHandlers.getQueryParser();
328     }
329
330     public static void closeSearchable( Searchable searchable )
331     {
332         if( searchable != null )
333         {
334             try
335             {
336                 searchable.close();
337             }
338             catch ( IOException e )
339             {
340                 // Ignore
341             }
342         }
343     }
344     
345     private static void closeQuietly( TermEnum terms )
346         throws RepositoryIndexException
347     {
348         if ( terms != null )
349         {
350             try
351             {
352                 terms.close();
353             }
354             catch ( IOException e )
355             {
356                 // ignore
357             }
358         }
359     }
360
361     private static void closeQuietly( IndexWriter indexWriter )
362         throws RepositoryIndexException
363     {
364         try
365         {
366             if ( indexWriter != null )
367             {
368                 indexWriter.close();
369             }
370         }
371         catch ( IOException e )
372         {
373             // write should compain if it can't be closed, data probably not persisted
374             throw new RepositoryIndexException( e.getMessage(), e );
375         }
376     }
377
378     private static void closeQuietly( IndexModifier indexModifier )
379     {
380         if ( indexModifier != null )
381         {
382             try
383             {
384                 indexModifier.close();
385             }
386             catch ( IOException e )
387             {
388                 // ignore
389             }
390         }
391     }
392
393     private static void closeQuietly( IndexReader reader )
394     {
395         try
396         {
397             if ( reader != null )
398             {
399                 reader.close();
400             }
401         }
402         catch ( IOException e )
403         {
404             // ignore
405         }
406     }
407
408     public File getIndexDirectory()
409     {
410         return this.indexLocation;
411     }
412
413     public String getId()
414     {
415         return this.indexHandlers.getId();
416     }
417
418     public ManagedRepositoryConfiguration getRepository()
419     {
420         return repository;
421     }
422     
423     public Analyzer getAnalyzer()
424     {
425         return this.indexHandlers.getAnalyzer();
426     }
427     
428     public LuceneEntryConverter getEntryConverter()
429     {
430         return this.indexHandlers.getConverter();
431     }
432 }