]> source.dussan.org Git - archiva.git/blob
8793682faa7a58bc4d93c5a0e61a2cb941f08de4
[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         IndexModifier indexModifier = null;
88         try
89         {
90             indexModifier = new IndexModifier( indexLocation, indexHandlers.getAnalyzer(), !exists() );
91             indexModifier.setMaxFieldLength( MAX_FIELD_LENGTH );
92
93             for ( Iterator i = records.iterator(); i.hasNext(); )
94             {
95                 LuceneRepositoryContentRecord record = (LuceneRepositoryContentRecord) i.next();
96
97                 if ( record != null )
98                 {
99                     Term term = new Term( LuceneDocumentMaker.PRIMARY_KEY, record.getPrimaryKey() );
100
101                     indexModifier.deleteDocuments( term );
102
103                     Document document = indexHandlers.getConverter().convert( record );
104
105                     indexModifier.addDocument( document );
106                 }
107             }
108             indexModifier.optimize();
109         }
110         catch ( IOException e )
111         {
112             throw new RepositoryIndexException( "Error updating index: " + e.getMessage(), e );
113         }
114         finally
115         {
116             closeQuietly( indexModifier );
117         }
118     }
119
120     public void modifyRecord( LuceneRepositoryContentRecord record )
121         throws RepositoryIndexException
122     {
123         IndexModifier indexModifier = null;
124         try
125         {
126             indexModifier = new IndexModifier( indexLocation, indexHandlers.getAnalyzer(), !exists() );
127             indexModifier.setMaxFieldLength( MAX_FIELD_LENGTH );
128
129             if ( record != null )
130             {
131                 Term term = new Term( LuceneDocumentMaker.PRIMARY_KEY, record.getPrimaryKey() );
132
133                 indexModifier.deleteDocuments( term );
134
135                 Document document = indexHandlers.getConverter().convert( record );
136
137                 indexModifier.addDocument( document );
138             }
139             indexModifier.optimize();
140         }
141         catch ( IOException e )
142         {
143             throw new RepositoryIndexException( "Error updating index: " + e.getMessage(), e );
144         }
145         finally
146         {
147             closeQuietly( indexModifier );
148         }
149     }
150
151     private void addRecords( Collection records )
152         throws RepositoryIndexException
153     {
154         IndexWriter indexWriter;
155         try
156         {
157             indexWriter = new IndexWriter( indexLocation, indexHandlers.getAnalyzer(), !exists() );
158             indexWriter.setMaxFieldLength( MAX_FIELD_LENGTH );
159         }
160         catch ( IOException e )
161         {
162             throw new RepositoryIndexException( "Unable to open index", e );
163         }
164
165         try
166         {
167             for ( Iterator i = records.iterator(); i.hasNext(); )
168             {
169                 LuceneRepositoryContentRecord record = (LuceneRepositoryContentRecord) i.next();
170
171                 if ( record != null )
172                 {
173                     Document document = indexHandlers.getConverter().convert( record );
174
175                     indexWriter.addDocument( document );
176                 }
177             }
178
179             indexWriter.optimize();
180         }
181         catch ( IOException e )
182         {
183             throw new RepositoryIndexException( "Failed to add an index document", e );
184         }
185         finally
186         {
187             closeQuietly( indexWriter );
188         }
189     }
190
191     public void deleteRecords( Collection records )
192         throws RepositoryIndexException
193     {
194         if ( exists() )
195         {
196             IndexReader indexReader = null;
197             try
198             {
199                 indexReader = IndexReader.open( indexLocation );
200
201                 for ( Iterator i = records.iterator(); i.hasNext(); )
202                 {
203                     LuceneRepositoryContentRecord record = (LuceneRepositoryContentRecord) i.next();
204
205                     if ( record != null )
206                     {
207                         Term term = new Term( LuceneDocumentMaker.PRIMARY_KEY, record.getPrimaryKey() );
208
209                         indexReader.deleteDocuments( term );
210                     }
211                 }
212             }
213             catch ( IOException e )
214             {
215                 throw new RepositoryIndexException( "Error deleting document: " + e.getMessage(), e );
216             }
217             finally
218             {
219                 closeQuietly( indexReader );
220             }
221         }
222     }
223
224     public Collection getAllRecordKeys()
225         throws RepositoryIndexException
226     {
227         return getAllFieldValues( LuceneDocumentMaker.PRIMARY_KEY );
228     }
229
230     private List getAllFieldValues( String fieldName )
231         throws RepositoryIndexException
232     {
233         List keys = new ArrayList();
234
235         if ( exists() )
236         {
237             IndexReader indexReader = null;
238             TermEnum terms = null;
239             try
240             {
241                 indexReader = IndexReader.open( indexLocation );
242
243                 terms = indexReader.terms( new Term( fieldName, "" ) );
244                 while ( fieldName.equals( terms.term().field() ) )
245                 {
246                     keys.add( terms.term().text() );
247
248                     if ( !terms.next() )
249                     {
250                         break;
251                     }
252                 }
253             }
254             catch ( IOException e )
255             {
256                 throw new RepositoryIndexException( "Error deleting document: " + e.getMessage(), e );
257             }
258             finally
259             {
260                 closeQuietly( indexReader );
261                 closeQuietly( terms );
262             }
263         }
264         return keys;
265     }
266     
267     public Searchable getSearchable()
268         throws RepositoryIndexSearchException
269     {
270         try
271         {
272             IndexSearcher searcher = new IndexSearcher( indexLocation.getAbsolutePath() );
273             return searcher;
274         }
275         catch ( IOException e )
276         {
277             throw new RepositoryIndexSearchException( "Unable to open index: " + e.getMessage(), e );
278         }
279     }
280
281     public boolean exists()
282         throws RepositoryIndexException
283     {
284         if ( IndexReader.indexExists( indexLocation ) )
285         {
286             return true;
287         }
288         else if ( !indexLocation.exists() )
289         {
290             return false;
291         }
292         else if ( indexLocation.isDirectory() )
293         {
294             if ( indexLocation.listFiles().length > 1 )
295             {
296                 throw new RepositoryIndexException( indexLocation + " is not a valid index directory." );
297             }
298             else
299             {
300                 return false;
301             }
302         }
303         else
304         {
305             throw new RepositoryIndexException( indexLocation + " is not a directory." );
306         }
307     }
308
309     public QueryParser getQueryParser()
310     {
311         return this.indexHandlers.getQueryParser();
312     }
313
314     public static void closeSearchable( Searchable searchable )
315     {
316         if( searchable != null )
317         {
318             try
319             {
320                 searchable.close();
321             }
322             catch ( IOException e )
323             {
324                 // Ignore
325             }
326         }
327     }
328     
329     private static void closeQuietly( TermEnum terms )
330         throws RepositoryIndexException
331     {
332         if ( terms != null )
333         {
334             try
335             {
336                 terms.close();
337             }
338             catch ( IOException e )
339             {
340                 // ignore
341             }
342         }
343     }
344
345     private static void closeQuietly( IndexWriter indexWriter )
346         throws RepositoryIndexException
347     {
348         try
349         {
350             if ( indexWriter != null )
351             {
352                 indexWriter.close();
353             }
354         }
355         catch ( IOException e )
356         {
357             // write should compain if it can't be closed, data probably not persisted
358             throw new RepositoryIndexException( e.getMessage(), e );
359         }
360     }
361
362     private static void closeQuietly( IndexModifier indexModifier )
363     {
364         if ( indexModifier != null )
365         {
366             try
367             {
368                 indexModifier.close();
369             }
370             catch ( IOException e )
371             {
372                 // ignore
373             }
374         }
375     }
376
377     private static void closeQuietly( IndexReader reader )
378     {
379         try
380         {
381             if ( reader != null )
382             {
383                 reader.close();
384             }
385         }
386         catch ( IOException e )
387         {
388             // ignore
389         }
390     }
391
392     public File getIndexDirectory()
393     {
394         return this.indexLocation;
395     }
396
397     public String getId()
398     {
399         return this.indexHandlers.getId();
400     }
401
402     public ManagedRepositoryConfiguration getRepository()
403     {
404         return repository;
405     }
406     
407     public Analyzer getAnalyzer()
408     {
409         return this.indexHandlers.getAnalyzer();
410     }
411     
412     public LuceneEntryConverter getEntryConverter()
413     {
414         return this.indexHandlers.getConverter();
415     }
416 }