View Javadoc

1   package org.apache.maven.index;
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 java.io.File;
23  import java.io.IOException;
24  import java.util.Collection;
25  import java.util.Collections;
26  import java.util.List;
27  import java.util.Map;
28  import java.util.concurrent.ConcurrentHashMap;
29  
30  import org.apache.lucene.queryParser.ParseException;
31  import org.apache.lucene.search.Query;
32  import org.apache.lucene.store.Directory;
33  import org.apache.lucene.store.FSDirectory;
34  import org.apache.maven.index.context.ContextMemberProvider;
35  import org.apache.maven.index.context.DefaultIndexingContext;
36  import org.apache.maven.index.context.ExistingLuceneIndexMismatchException;
37  import org.apache.maven.index.context.IndexCreator;
38  import org.apache.maven.index.context.IndexUtils;
39  import org.apache.maven.index.context.IndexingContext;
40  import org.apache.maven.index.context.MergedIndexingContext;
41  import org.apache.maven.index.context.StaticContextMemberProvider;
42  import org.apache.maven.index.context.UnsupportedExistingLuceneIndexException;
43  import org.apache.maven.index.expr.SearchExpression;
44  import org.apache.maven.index.util.IndexCreatorSorter;
45  import org.codehaus.plexus.component.annotations.Component;
46  import org.codehaus.plexus.component.annotations.Requirement;
47  import org.codehaus.plexus.logging.AbstractLogEnabled;
48  import org.codehaus.plexus.util.FileUtils;
49  
50  /**
51   * A default {@link NexusIndexer} implementation.
52   *
53   * @author Tamas Cservenak
54   * @author Eugene Kuleshov
55   * @deprecated Use {@link Indexer} instead. Discouraged from further use, as it suffers from multiple synchronization
56   *             and other problems. As it tries to serve as "context registry" too, but it does not synchronize the
57   *             access to it, but also, introduces some extras (like "targeted" vs "non targeted" search), that makes
58   *             it's behavior less intuitive.
59   */
60  @Deprecated
61  @Component( role = NexusIndexer.class )
62  public class DefaultNexusIndexer
63      extends AbstractLogEnabled
64      implements NexusIndexer
65  {
66  
67      @Requirement
68      private Indexer indexer;
69  
70      @Requirement
71      private Scanner scanner;
72  
73      @Requirement
74      private IndexerEngine indexerEngine;
75  
76      @Requirement
77      private QueryCreator queryCreator;
78  
79      private final Map<String, IndexingContext> indexingContexts = new ConcurrentHashMap<String, IndexingContext>();
80  
81      // ----------------------------------------------------------------------------
82      // Contexts
83      // ----------------------------------------------------------------------------
84  
85      public void addIndexingContext( IndexingContext context )
86      {
87          indexingContexts.put( context.getId(), context );
88      }
89  
90      public IndexingContext addIndexingContext( String id, String repositoryId, File repository, File indexDirectory,
91          String repositoryUrl, String indexUpdateUrl,
92          List<? extends IndexCreator> indexers )
93          throws IOException, UnsupportedExistingLuceneIndexException
94      {
95          try
96          {
97              IndexingContext context =
98                  indexer.createIndexingContext( id, repositoryId, repository, indexDirectory, repositoryUrl,
99                                                 indexUpdateUrl, true, false, indexers );
100             indexingContexts.put( context.getId(), context );
101             return context;
102         }
103         catch ( ExistingLuceneIndexMismatchException e )
104         {
105             throw new UnsupportedExistingLuceneIndexException( e.getMessage(), e );
106         }
107     }
108 
109     public IndexingContext addIndexingContextForced( String id, String repositoryId, File repository,
110         File indexDirectory, String repositoryUrl, String indexUpdateUrl,
111         List<? extends IndexCreator> indexers )
112         throws IOException
113     {
114         IndexingContext context =
115             indexer.createIndexingContext( id, repositoryId, repository, indexDirectory, repositoryUrl, indexUpdateUrl,
116                                            true, true, indexers );
117         indexingContexts.put( context.getId(), context );
118         return context;
119     }
120 
121     public IndexingContext addIndexingContext( String id, String repositoryId, File repository, Directory directory,
122         String repositoryUrl, String indexUpdateUrl,
123         List<? extends IndexCreator> indexers )
124         throws IOException, UnsupportedExistingLuceneIndexException
125     {
126         try
127         {
128             IndexingContext context =
129                 new DefaultIndexingContext( id, repositoryId, repository, directory, repositoryUrl, indexUpdateUrl,
130                                             IndexCreatorSorter.sort( indexers ), false );
131             indexingContexts.put( context.getId(), context );
132             return context;
133         }
134         catch ( ExistingLuceneIndexMismatchException e )
135         {
136             throw new UnsupportedExistingLuceneIndexException( e.getMessage(), e );
137         }
138     }
139 
140     public IndexingContext addIndexingContextForced( String id, String repositoryId, File repository,
141         Directory directory, String repositoryUrl, String indexUpdateUrl,
142         List<? extends IndexCreator> indexers )
143         throws IOException
144     {
145         IndexingContext context =
146             new DefaultIndexingContext( id, repositoryId, repository, directory, repositoryUrl, indexUpdateUrl,
147                                         IndexCreatorSorter.sort( indexers ), true );
148         indexingContexts.put( context.getId(), context );
149         return context;
150     }
151 
152     public IndexingContext addMergedIndexingContext( String id, String repositoryId, File repository,
153         File indexDirectory, boolean searchable,
154         Collection<IndexingContext> contexts )
155         throws IOException
156     {
157         return addMergedIndexingContext( id, repositoryId, repository, indexDirectory, searchable,
158                                          new StaticContextMemberProvider( contexts ) );
159     }
160 
161     public IndexingContext addMergedIndexingContext( String id, String repositoryId, File repository,
162         File indexDirectory, boolean searchable,
163         ContextMemberProvider membersProvider )
164         throws IOException
165     {
166         IndexingContext context =
167             indexer.createMergedIndexingContext( id, repositoryId, repository, indexDirectory, searchable,
168                                                  membersProvider );
169         indexingContexts.put( context.getId(), context );
170         return context;
171     }
172 
173     public IndexingContext addMergedIndexingContext( String id, String repositoryId, File repository,
174         Directory indexDirectory, boolean searchable,
175         Collection<IndexingContext> contexts )
176         throws IOException
177     {
178         IndexingContext context =
179             new MergedIndexingContext( id, repositoryId, repository, indexDirectory, searchable,
180                                        new StaticContextMemberProvider( contexts ) );
181         indexingContexts.put( context.getId(), context );
182         return context;
183     }
184 
185     public IndexingContext addMergedIndexingContext( String id, String repositoryId, File repository,
186         Directory indexDirectory, boolean searchable,
187         ContextMemberProvider membersProvider )
188         throws IOException
189     {
190         IndexingContext context =
191             new MergedIndexingContext( id, repositoryId, repository, indexDirectory, searchable, membersProvider );
192         indexingContexts.put( context.getId(), context );
193         return context;
194     }
195 
196     public void removeIndexingContext( IndexingContext context, boolean deleteFiles )
197         throws IOException
198     {
199         if ( indexingContexts.containsKey( context.getId() ) )
200         {
201             indexingContexts.remove( context.getId() );
202             indexer.closeIndexingContext( context, deleteFiles );
203         }
204     }
205 
206     public Map<String, IndexingContext> getIndexingContexts()
207     {
208         return Collections.unmodifiableMap( indexingContexts );
209     }
210 
211     // ----------------------------------------------------------------------------
212     // Scanning
213     // ----------------------------------------------------------------------------
214 
215     public void scan( final IndexingContext context )
216         throws IOException
217     {
218         scan( context, null );
219     }
220 
221     public void scan( final IndexingContext context, boolean update )
222         throws IOException
223     {
224         scan( context, null, update );
225     }
226 
227     public void scan( final IndexingContext context, final ArtifactScanningListener listener )
228         throws IOException
229     {
230         scan( context, listener, false );
231     }
232 
233     public void scan( final IndexingContext context, final ArtifactScanningListener listener, final boolean update )
234         throws IOException
235     {
236         scan( context, null, listener, update );
237     }
238 
239     /**
240      * Uses {@link Scanner} to scan repository content. A {@link ArtifactScanningListener} is used to process found
241      * artifacts and to add them to the index using
242      * {@link NexusIndexer#artifactDiscovered(ArtifactContext, IndexingContext)}.
243      *
244      * @see DefaultScannerListener
245      * @see #artifactDiscovered(ArtifactContext, IndexingContext)
246      */
247     public void scan( final IndexingContext context, final String fromPath, final ArtifactScanningListener listener,
248         final boolean update )
249         throws IOException
250     {
251         final File repositoryDirectory = context.getRepository();
252         if ( repositoryDirectory == null )
253         {
254             // nothing to scan
255             return;
256         }
257 
258         if ( !repositoryDirectory.exists() )
259         {
260             throw new IOException( "Repository directory " + repositoryDirectory + " does not exist" );
261         }
262 
263         // always use temporary context when reindexing
264         final File tmpFile = File.createTempFile( context.getId() + "-tmp", "" );
265         final File tmpDir = new File( tmpFile.getParentFile(), tmpFile.getName() + ".dir" );
266         if ( !tmpDir.mkdirs() )
267         {
268             throw new IOException( "Cannot create temporary directory: " + tmpDir );
269         }
270 
271         IndexingContext tmpContext = null;
272         try
273         {
274             final FSDirectory directory = FSDirectory.open( tmpDir );
275             if ( update )
276             {
277                 IndexUtils.copyDirectory( context.getIndexDirectory(), directory );
278             }
279             tmpContext = new DefaultIndexingContext( context.getId() + "-tmp", //
280                                                      context.getRepositoryId(), //
281                                                      context.getRepository(), //
282                                                      directory, //
283                                                      context.getRepositoryUrl(), //
284                                                      context.getIndexUpdateUrl(), //
285                                                      context.getIndexCreators(), //
286                                                      true );
287 
288             scanner.scan( new ScanningRequest( tmpContext, //
289                                                new DefaultScannerListener( tmpContext, indexerEngine,
290                                                                            update, listener ), fromPath ) );
291 
292             tmpContext.updateTimestamp( true );
293             context.replace( tmpContext.getIndexDirectory() );
294         }
295         catch ( Exception ex )
296         {
297             throw (IOException) new IOException( "Error scanning context " + context.getId() + ": " + ex ).initCause(
298                 ex );
299         }
300         finally
301         {
302             if ( tmpContext != null )
303             {
304                 tmpContext.close( true );
305             }
306 
307             if ( tmpFile.exists() )
308             {
309                 tmpFile.delete();
310             }
311 
312             FileUtils.deleteDirectory( tmpDir );
313         }
314     }
315 
316     /**
317      * Delegates to the {@link IndexerEngine} to add a new artifact to the index
318      */
319     public void artifactDiscovered( ArtifactContext ac, IndexingContext context )
320         throws IOException
321     {
322         if ( ac != null )
323         {
324             indexerEngine.index( context, ac );
325         }
326     }
327 
328     // ----------------------------------------------------------------------------
329     // Modifying
330     // ----------------------------------------------------------------------------
331 
332     /**
333      * Delegates to the {@link IndexerEngine} to update artifact to the index
334      */
335     public void addArtifactToIndex( ArtifactContext ac, IndexingContext context )
336         throws IOException
337     {
338         indexer.addArtifactsToIndex( Collections.singleton( ac ), context );
339     }
340 
341     public void addArtifactsToIndex( Collection<ArtifactContext> acs, IndexingContext context )
342         throws IOException
343     {
344         indexer.addArtifactsToIndex( acs, context );
345     }
346 
347     /**
348      * Delegates to the {@link IndexerEngine} to remove artifact from the index
349      */
350     public void deleteArtifactFromIndex( ArtifactContext ac, IndexingContext context )
351         throws IOException
352     {
353         indexer.deleteArtifactsFromIndex( Collections.singleton( ac ), context );
354     }
355 
356     public void deleteArtifactsFromIndex( Collection<ArtifactContext> acs, IndexingContext context )
357         throws IOException
358     {
359         indexer.deleteArtifactsFromIndex( acs, context );
360     }
361 
362     // ----------------------------------------------------------------------------
363     // Searching
364     // ----------------------------------------------------------------------------
365 
366     public FlatSearchResponse searchFlat( FlatSearchRequest request )
367         throws IOException
368     {
369         if ( request.getContexts().isEmpty() )
370         {
371             request.getContexts().addAll( getIndexingContexts().values() );
372         }
373         return indexer.searchFlat( request );
374     }
375 
376     public IteratorSearchResponse searchIterator( IteratorSearchRequest request )
377         throws IOException
378     {
379         if ( request.getContexts().isEmpty() )
380         {
381             request.getContexts().addAll( getIndexingContexts().values() );
382         }
383         return indexer.searchIterator( request );
384     }
385 
386     public GroupedSearchResponse searchGrouped( GroupedSearchRequest request )
387         throws IOException
388     {
389         if ( request.getContexts().isEmpty() )
390         {
391             request.getContexts().addAll( getIndexingContexts().values() );
392         }
393         return indexer.searchGrouped( request );
394     }
395 
396     // ----------------------------------------------------------------------------
397     // Query construction
398     // ----------------------------------------------------------------------------
399 
400     @Deprecated
401     public Query constructQuery( Field field, String query, SearchType type )
402         throws IllegalArgumentException
403     {
404         try
405         {
406             return queryCreator.constructQuery( field, query, type );
407         }
408         catch ( ParseException e )
409         {
410             throw new IllegalArgumentException( e );
411         }
412     }
413 
414     public Query constructQuery( Field field, SearchExpression expression )
415         throws IllegalArgumentException
416     {
417         return indexer.constructQuery( field, expression );
418     }
419 
420     // ----------------------------------------------------------------------------
421     // Identification
422     // ----------------------------------------------------------------------------
423 
424     public Collection<ArtifactInfo> identify( Field field, String query )
425         throws IllegalArgumentException, IOException
426     {
427         return identify( constructQuery( field, query, SearchType.EXACT ) );
428     }
429 
430     public Collection<ArtifactInfo> identify( File artifact )
431         throws IOException
432     {
433         return identify( artifact, indexingContexts.values() );
434     }
435 
436     public Collection<ArtifactInfo> identify( File artifact, Collection<IndexingContext> contexts )
437         throws IOException
438     {
439         return indexer.identify( artifact, contexts );
440     }
441 
442     public Collection<ArtifactInfo> identify( Query query )
443         throws IOException
444     {
445         return identify( query, indexingContexts.values() );
446     }
447 
448     public Collection<ArtifactInfo> identify( Query query, Collection<IndexingContext> contexts )
449         throws IOException
450     {
451         return indexer.identify( query, contexts );
452     }
453 }