1 package org.apache.maven.index.examples.indexing;
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22 import org.apache.lucene.analysis.core.WhitespaceAnalyzer;
23 import org.apache.lucene.queryparser.classic.MultiFieldQueryParser;
24 import org.apache.lucene.queryparser.classic.ParseException;
25 import org.apache.lucene.search.BooleanQuery;
26 import org.apache.lucene.search.Query;
27 import org.apache.maven.index.ArtifactContext;
28 import org.apache.maven.index.ArtifactInfo;
29 import org.apache.maven.index.ArtifactScanningListener;
30 import org.apache.maven.index.FlatSearchRequest;
31 import org.apache.maven.index.FlatSearchResponse;
32 import org.apache.maven.index.Indexer;
33 import org.apache.maven.index.MAVEN;
34 import org.apache.maven.index.Scanner;
35 import org.apache.maven.index.ScanningRequest;
36 import org.apache.maven.index.ScanningResult;
37 import org.apache.maven.index.context.IndexCreator;
38 import org.apache.maven.index.context.IndexingContext;
39 import org.apache.maven.index.expr.SourcedSearchExpression;
40 import org.slf4j.Logger;
41 import org.slf4j.LoggerFactory;
42
43 import java.io.File;
44 import java.io.IOException;
45 import java.util.ArrayList;
46 import java.util.Collection;
47 import java.util.List;
48 import java.util.Set;
49
50 import static java.util.Arrays.asList;
51 import static org.apache.lucene.search.BooleanClause.Occur.MUST;
52
53
54
55
56
57
58 public class RepositoryIndexer
59 {
60
61 private static final Logger LOGGER = LoggerFactory.getLogger( RepositoryIndexer.class );
62
63 private static final String[] LUCENE_FIELDS = new String[]{"g", "a", "v", "p", "c" };
64
65 private static final WhitespaceAnalyzer LUCENE_ANALYZER = new WhitespaceAnalyzer( );
66
67 private Indexer indexer;
68
69 private Scanner scanner;
70
71 private List<IndexCreator> indexers;
72
73 private IndexingContext indexingContext;
74
75 private String repositoryId;
76
77 private File repositoryBasedir;
78
79 private File indexDir;
80
81
82 public RepositoryIndexer()
83 {
84
85 }
86
87 public void close()
88 throws IOException
89 {
90 indexer.closeIndexingContext( indexingContext, false );
91 }
92
93 public void close( boolean deleteFiles )
94 throws IOException
95 {
96 indexingContext.close( deleteFiles );
97 }
98
99 public void delete( final Collection<ArtifactInfo> artifacts )
100 throws IOException
101 {
102 final List<ArtifactContext> delete = new ArrayList<>();
103 for ( final ArtifactInfo artifact : artifacts )
104 {
105 LOGGER.debug( "Deleting artifact: {}; ctx id: {}; idx dir: {}",
106 artifact, indexingContext.getId(), indexingContext.getIndexDirectory() );
107
108 delete.add( new ArtifactContext( null, null, null, artifact, null ) );
109 }
110
111 getIndexer().deleteArtifactsFromIndex( delete, indexingContext );
112 }
113
114 public Set<ArtifactInfo> search( final String groupId, final String artifactId, final String version,
115 final String packaging, final String classifier )
116 throws IOException
117 {
118 final BooleanQuery.Builder queryBuilder = new BooleanQuery.Builder();
119
120 if ( groupId != null )
121 {
122 queryBuilder.add( getIndexer().constructQuery( MAVEN.GROUP_ID,
123 new SourcedSearchExpression( groupId ) ), MUST );
124 }
125
126 if ( artifactId != null )
127 {
128 queryBuilder.add( getIndexer().constructQuery( MAVEN.ARTIFACT_ID,
129 new SourcedSearchExpression( artifactId ) ), MUST );
130 }
131
132 if ( version != null )
133 {
134 queryBuilder.add( getIndexer().constructQuery( MAVEN.VERSION,
135 new SourcedSearchExpression( version ) ), MUST );
136 }
137
138 if ( packaging != null )
139 {
140 queryBuilder.add( getIndexer().constructQuery( MAVEN.PACKAGING,
141 new SourcedSearchExpression( packaging ) ), MUST );
142 }
143 else
144 {
145
146 queryBuilder.add( getIndexer().constructQuery( MAVEN.PACKAGING,
147 new SourcedSearchExpression( "jar" ) ), MUST );
148 }
149
150 if ( classifier != null )
151 {
152 queryBuilder.add( getIndexer().constructQuery( MAVEN.CLASSIFIER,
153 new SourcedSearchExpression( classifier ) ),
154 MUST );
155 }
156
157 Query query = queryBuilder.build();
158
159 LOGGER.debug( "Executing search query: {}; ctx id: {}; idx dir: {}",
160 query, indexingContext.getId(), indexingContext.getIndexDirectory() );
161
162 final FlatSearchResponse response = getIndexer().searchFlat( new FlatSearchRequest( query, indexingContext ) );
163
164 LOGGER.info( "Hit count: {}", response.getReturnedHitsCount() );
165
166 final Set<ArtifactInfo> results = response.getResults();
167 if ( LOGGER.isDebugEnabled() )
168 {
169 for ( final ArtifactInfo result : results )
170 {
171 LOGGER.debug( "Found artifact: {}", result.toString() );
172 }
173 }
174
175 return results;
176 }
177
178 public Set<ArtifactInfo> search( final String queryText )
179 throws ParseException, IOException
180 {
181 final Query query = new MultiFieldQueryParser( LUCENE_FIELDS, LUCENE_ANALYZER ).parse( queryText );
182
183 LOGGER.debug( "Executing search query: {}; ctx id: {}; idx dir: {}",
184 query, indexingContext.getId(), indexingContext.getIndexDirectory() );
185
186 final FlatSearchResponse response = getIndexer().searchFlat( new FlatSearchRequest( query, indexingContext ) );
187
188 final Set<ArtifactInfo> results = response.getResults();
189 if ( LOGGER.isDebugEnabled() )
190 {
191 LOGGER.debug( "Hit count: {}", response.getReturnedHitsCount() );
192
193 for ( final ArtifactInfo result : results )
194 {
195 LOGGER.debug( "Found artifact: {}; uinfo: {}", result.toString(), result.getUinfo() );
196 }
197 }
198
199 return results;
200 }
201
202 public Set<ArtifactInfo> searchBySHA1( final String checksum )
203 throws IOException
204 {
205 final BooleanQuery query = new BooleanQuery.Builder()
206 .add( getIndexer().constructQuery( MAVEN.SHA1, new SourcedSearchExpression( checksum ) ), MUST )
207 .build();
208
209 LOGGER.debug( "Executing search query: {}; ctx id: {}; idx dir: {}",
210 query, indexingContext.getId(), indexingContext.getIndexDirectory() );
211
212 final FlatSearchResponse response = getIndexer().searchFlat( new FlatSearchRequest( query, indexingContext ) );
213
214 LOGGER.info( "Hit count: {}", response.getReturnedHitsCount() );
215
216 final Set<ArtifactInfo> results = response.getResults();
217 if ( LOGGER.isDebugEnabled() )
218 {
219 for ( final ArtifactInfo result : results )
220 {
221 LOGGER.debug( "Found artifact: {}", result.toString() );
222 }
223 }
224
225 return results;
226 }
227
228 public int index( final File startingPath )
229 {
230 final ScanningResult scan = getScanner().scan(
231 new ScanningRequest( indexingContext, new ReindexArtifactScanningListener(),
232 startingPath == null ? "." : startingPath.getPath() ) );
233 return scan.getTotalFiles();
234 }
235
236 public void addArtifactToIndex( final File artifactFile, final ArtifactInfo artifactInfo )
237 throws IOException
238 {
239 getIndexer().addArtifactsToIndex(
240 asList( new ArtifactContext( null, artifactFile, null, artifactInfo, null ) ),
241 indexingContext );
242 }
243
244 public void addArtifactToIndex( String repository, File artifactFile, String groupId, String artifactId,
245 String version, String extension, String classifier )
246 throws IOException
247 {
248 ArtifactInfo artifactInfo = new ArtifactInfo( repository, groupId, artifactId, version, classifier, extension );
249 if ( extension != null )
250 {
251 artifactInfo.setFieldValue( MAVEN.EXTENSION, extension );
252 }
253
254 LOGGER.debug( "Adding artifact: {}; repo: {}; type: {}", artifactInfo.getUinfo(), repository, extension );
255
256 getIndexer().addArtifactsToIndex(
257 asList( new ArtifactContext( null, artifactFile, null, artifactInfo, artifactInfo.calculateGav() ) ),
258 indexingContext );
259 }
260
261 private class ReindexArtifactScanningListener
262 implements ArtifactScanningListener
263 {
264
265 int totalFiles = 0;
266
267 private IndexingContext context;
268
269 @Override
270 public void scanningStarted( final IndexingContext context )
271 {
272 this.context = context;
273 }
274
275 @Override
276 public void scanningFinished( final IndexingContext context, final ScanningResult result )
277 {
278 result.setTotalFiles( totalFiles );
279 LOGGER.debug( "Scanning finished; total files: {}; has exception: {}", result.getTotalFiles(),
280 result.hasExceptions() );
281 }
282
283 @Override
284 public void artifactError( final ArtifactContext ac, final Exception ex )
285 {
286 LOGGER.error( "Artifact error!", ex );
287 }
288
289 @Override
290 public void artifactDiscovered( final ArtifactContext ac )
291 {
292 try
293 {
294 LOGGER.debug( "Adding artifact gav: {}; ctx id: {}; idx dir: {}",
295 ac.getGav(), context.getId(), context.getIndexDirectory() );
296
297 getIndexer().addArtifactsToIndex( asList( ac ), context );
298 totalFiles++;
299 }
300 catch ( IOException ex )
301 {
302 LOGGER.error( "Artifact index error", ex );
303 }
304 }
305 }
306
307 public Indexer getIndexer()
308 {
309 return indexer;
310 }
311
312 public void setIndexer( Indexer indexer )
313 {
314 this.indexer = indexer;
315 }
316
317 public Scanner getScanner()
318 {
319 return scanner;
320 }
321
322 public void setScanner( Scanner scanner )
323 {
324 this.scanner = scanner;
325 }
326
327 public List<IndexCreator> getIndexers()
328 {
329 return indexers;
330 }
331
332 public void setIndexers( List<IndexCreator> indexers )
333 {
334 this.indexers = indexers;
335 }
336
337 public IndexingContext getIndexingContext()
338 {
339 return indexingContext;
340 }
341
342 public void setIndexingContext( IndexingContext indexingContext )
343 {
344 this.indexingContext = indexingContext;
345 }
346
347 public String getRepositoryId()
348 {
349 return repositoryId;
350 }
351
352 public void setRepositoryId( String repositoryId )
353 {
354 this.repositoryId = repositoryId;
355 }
356
357 public File getRepositoryBasedir()
358 {
359 return repositoryBasedir;
360 }
361
362 public void setRepositoryBasedir( File repositoryBasedir )
363 {
364 this.repositoryBasedir = repositoryBasedir;
365 }
366
367 public File getIndexDir()
368 {
369 return indexDir;
370 }
371
372 public void setIndexDir( File indexDir )
373 {
374 this.indexDir = indexDir;
375 }
376
377 }