1 package org.apache.maven.index.examples;
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.document.Document;
23 import org.apache.lucene.index.IndexReader;
24 import org.apache.lucene.index.MultiBits;
25 import org.apache.lucene.search.BooleanClause.Occur;
26 import org.apache.lucene.search.BooleanQuery;
27 import org.apache.lucene.search.IndexSearcher;
28 import org.apache.lucene.search.Query;
29 import org.apache.lucene.util.Bits;
30 import org.apache.maven.index.ArtifactInfo;
31 import org.apache.maven.index.ArtifactInfoFilter;
32 import org.apache.maven.index.ArtifactInfoGroup;
33 import org.apache.maven.index.Field;
34 import org.apache.maven.index.FlatSearchRequest;
35 import org.apache.maven.index.FlatSearchResponse;
36 import org.apache.maven.index.GroupedSearchRequest;
37 import org.apache.maven.index.GroupedSearchResponse;
38 import org.apache.maven.index.Grouping;
39 import org.apache.maven.index.Indexer;
40 import org.apache.maven.index.IteratorSearchRequest;
41 import org.apache.maven.index.IteratorSearchResponse;
42 import org.apache.maven.index.MAVEN;
43 import org.apache.maven.index.context.IndexCreator;
44 import org.apache.maven.index.context.IndexUtils;
45 import org.apache.maven.index.context.IndexingContext;
46 import org.apache.maven.index.expr.SourcedSearchExpression;
47 import org.apache.maven.index.expr.UserInputSearchExpression;
48 import org.apache.maven.index.search.grouping.GAGrouping;
49 import org.apache.maven.index.updater.IndexUpdateRequest;
50 import org.apache.maven.index.updater.IndexUpdateResult;
51 import org.apache.maven.index.updater.IndexUpdater;
52 import org.apache.maven.index.updater.ResourceFetcher;
53 import org.apache.maven.index.updater.WagonHelper;
54 import org.apache.maven.wagon.Wagon;
55 import org.apache.maven.wagon.events.TransferEvent;
56 import org.apache.maven.wagon.events.TransferListener;
57 import org.apache.maven.wagon.observers.AbstractTransferListener;
58 import org.codehaus.plexus.DefaultContainerConfiguration;
59 import org.codehaus.plexus.DefaultPlexusContainer;
60 import org.codehaus.plexus.PlexusConstants;
61 import org.codehaus.plexus.PlexusContainer;
62 import org.codehaus.plexus.PlexusContainerException;
63 import org.codehaus.plexus.component.repository.exception.ComponentLookupException;
64 import org.codehaus.plexus.util.StringUtils;
65 import org.eclipse.aether.util.version.GenericVersionScheme;
66 import org.eclipse.aether.version.InvalidVersionSpecificationException;
67 import org.eclipse.aether.version.Version;
68
69 import java.io.File;
70 import java.io.IOException;
71 import java.time.Duration;
72 import java.time.Instant;
73 import java.util.ArrayList;
74 import java.util.Collections;
75 import java.util.Date;
76 import java.util.List;
77 import java.util.Map;
78
79
80
81
82 public class BasicUsageExample
83 {
84 public static void main( String[] args )
85 throws Exception
86 {
87 new BasicUsageExample().perform();
88 }
89
90
91
92 private final PlexusContainer plexusContainer;
93
94 private final Indexer indexer;
95
96 private final IndexUpdater indexUpdater;
97
98 private final Wagon httpWagon;
99
100 private IndexingContext centralContext;
101
102 public BasicUsageExample()
103 throws PlexusContainerException, ComponentLookupException
104 {
105
106
107
108
109
110 final DefaultContainerConfiguration config = new DefaultContainerConfiguration();
111 config.setClassPathScanning( PlexusConstants.SCANNING_INDEX );
112 this.plexusContainer = new DefaultPlexusContainer( config );
113
114
115 this.indexer = plexusContainer.lookup( Indexer.class );
116 this.indexUpdater = plexusContainer.lookup( IndexUpdater.class );
117
118 this.httpWagon = plexusContainer.lookup( Wagon.class, "http" );
119
120 }
121
122 public void perform()
123 throws IOException, ComponentLookupException, InvalidVersionSpecificationException
124 {
125
126 File centralLocalCache = new File( "target/central-cache" );
127 File centralIndexDir = new File( "target/central-index" );
128
129
130 List<IndexCreator> indexers = new ArrayList<>();
131 indexers.add( plexusContainer.lookup( IndexCreator.class, "min" ) );
132 indexers.add( plexusContainer.lookup( IndexCreator.class, "jarContent" ) );
133 indexers.add( plexusContainer.lookup( IndexCreator.class, "maven-plugin" ) );
134
135
136 centralContext =
137 indexer.createIndexingContext( "central-context", "central", centralLocalCache, centralIndexDir,
138 "https://repo1.maven.org/maven2", null, true, true, indexers );
139
140
141
142
143
144
145 if ( true )
146 {
147 Instant updateStart = Instant.now();
148 System.out.println( "Updating Index..." );
149 System.out.println( "This might take a while on first run, so please be patient!" );
150
151
152 TransferListener listener = new AbstractTransferListener()
153 {
154 Instant start;
155 public void transferStarted( TransferEvent transferEvent )
156 {
157 start = Instant.now();
158 System.out.print( " Downloading " + transferEvent.getResource().getName() );
159 }
160
161 public void transferProgress( TransferEvent transferEvent, byte[] buffer, int length )
162 {
163 }
164
165 public void transferCompleted( TransferEvent transferEvent )
166 {
167 System.out.println( " - Done in "
168 + Duration.between( start, Instant.now() ).getSeconds() + " sec" );
169 }
170 };
171 ResourceFetcher resourceFetcher = new WagonHelper.WagonFetcher( httpWagon, listener, null, null );
172
173 Date centralContextCurrentTimestamp = centralContext.getTimestamp();
174 IndexUpdateRequest updateRequest = new IndexUpdateRequest( centralContext, resourceFetcher );
175 IndexUpdateResult updateResult = indexUpdater.fetchAndUpdateIndex( updateRequest );
176 if ( updateResult.isFullUpdate() )
177 {
178 System.out.println( "Full update happened!" );
179 }
180 else if ( updateResult.getTimestamp().equals( centralContextCurrentTimestamp ) )
181 {
182 System.out.println( "No update needed, index is up to date!" );
183 }
184 else
185 {
186 System.out.println(
187 "Incremental update happened, change covered " + centralContextCurrentTimestamp + " - "
188 + updateResult.getTimestamp() + " period." );
189 }
190
191 System.out.println( "Finished in " + Duration.between( updateStart, Instant.now() ).getSeconds() + " sec" );
192 System.out.println();
193 }
194
195 System.out.println();
196 System.out.println( "Using index" );
197 System.out.println( "===========" );
198 System.out.println();
199
200
201
202
203
204
205 if ( false )
206 {
207 final IndexSearcher searcher = centralContext.acquireIndexSearcher();
208 try
209 {
210 final IndexReader ir = searcher.getIndexReader();
211 Bits liveDocs = MultiBits.getLiveDocs( ir );
212 for ( int i = 0; i < ir.maxDoc(); i++ )
213 {
214 if ( liveDocs == null || liveDocs.get( i ) )
215 {
216 final Document doc = ir.document( i );
217 final ArtifactInfo ai = IndexUtils.constructArtifactInfo( doc, centralContext );
218 System.out.println( ai.getGroupId() + ":" + ai.getArtifactId() + ":" + ai.getVersion() + ":"
219 + ai.getClassifier() + " (sha1=" + ai.getSha1() + ")" );
220 }
221 }
222 }
223 finally
224 {
225 centralContext.releaseIndexSearcher( searcher );
226 }
227 }
228
229
230
231
232
233 final GenericVersionScheme versionScheme = new GenericVersionScheme();
234 final String versionString = "3.1.0";
235 final Version version = versionScheme.parseVersion( versionString );
236
237
238 final Query groupIdQ =
239 indexer.constructQuery( MAVEN.GROUP_ID, new SourcedSearchExpression( "org.apache.maven" ) );
240 final Query artifactIdQ =
241 indexer.constructQuery( MAVEN.ARTIFACT_ID, new SourcedSearchExpression( "maven-plugin-api" ) );
242
243 final BooleanQuery query = new BooleanQuery.Builder()
244 .add( groupIdQ, Occur.MUST )
245 .add( artifactIdQ, Occur.MUST )
246
247 .add( indexer.constructQuery( MAVEN.PACKAGING, new SourcedSearchExpression( "jar" ) ), Occur.MUST )
248
249
250 .add( indexer.constructQuery( MAVEN.CLASSIFIER,
251 new SourcedSearchExpression( Field.NOT_PRESENT ) ), Occur.MUST_NOT )
252 .build();
253
254
255 final ArtifactInfoFilter versionFilter = ( ctx, ai ) ->
256 {
257 try
258 {
259 final Version aiV = versionScheme.parseVersion( ai.getVersion() );
260
261 return aiV.compareTo( version ) > 0;
262 }
263 catch ( InvalidVersionSpecificationException e )
264 {
265
266 return true;
267 }
268 };
269
270 System.out.println(
271 "Searching for all GAVs with org.apache.maven:maven-plugin-api having V greater than 3.1.0" );
272 final IteratorSearchRequest request =
273 new IteratorSearchRequest( query, Collections.singletonList( centralContext ), versionFilter );
274 final IteratorSearchResponse response = indexer.searchIterator( request );
275 for ( ArtifactInfo ai : response )
276 {
277 System.out.println( ai.toString() );
278 }
279
280
281
282
283 Query gidQ =
284 indexer.constructQuery( MAVEN.GROUP_ID, new SourcedSearchExpression( "org.apache.maven.indexer" ) );
285 Query aidQ = indexer.constructQuery( MAVEN.ARTIFACT_ID, new SourcedSearchExpression( "indexer-core" ) );
286
287 BooleanQuery bq = new BooleanQuery.Builder()
288 .add( gidQ, Occur.MUST )
289 .add( aidQ, Occur.MUST )
290 .build();
291
292 searchAndDump( indexer, "all artifacts under GA org.apache.maven.indexer:indexer-core", bq );
293
294
295 bq = new BooleanQuery.Builder()
296 .add( gidQ, Occur.MUST )
297 .add( aidQ, Occur.MUST )
298 .add( indexer.constructQuery( MAVEN.CLASSIFIER, new SourcedSearchExpression( "*" ) ), Occur.MUST_NOT )
299 .build();
300
301 searchAndDump( indexer, "main artifacts under GA org.apache.maven.indexer:indexer-core", bq );
302
303
304 searchAndDump( indexer, "SHA1 7ab67e6b20e5332a7fb4fdf2f019aec4275846c2",
305 indexer.constructQuery( MAVEN.SHA1,
306 new SourcedSearchExpression( "7ab67e6b20e5332a7fb4fdf2f019aec4275846c2" )
307 )
308 );
309
310 searchAndDump( indexer, "SHA1 7ab67e6b20 (partial hash)",
311 indexer.constructQuery( MAVEN.SHA1, new UserInputSearchExpression( "7ab67e6b20" ) ) );
312
313
314 searchAndDump( indexer, "classname DefaultNexusIndexer (note: Central does not publish classes in the index)",
315 indexer.constructQuery( MAVEN.CLASSNAMES,
316 new UserInputSearchExpression( "DefaultNexusIndexer" ) ) );
317
318
319 bq = new BooleanQuery.Builder()
320 .add( indexer.constructQuery( MAVEN.PACKAGING, new SourcedSearchExpression( "maven-plugin" ) ), Occur.MUST )
321 .add( indexer.constructQuery( MAVEN.GROUP_ID,
322 new SourcedSearchExpression( "org.apache.maven.plugins" ) ), Occur.MUST )
323 .build();
324
325 searchGroupedAndDumpFlat( indexer, "all \"canonical\" maven plugins", bq, new GAGrouping() );
326
327
328 searchGroupedAndDump( indexer, "all maven archetypes (latest versions)",
329 indexer.constructQuery( MAVEN.PACKAGING,
330 new SourcedSearchExpression( "maven-archetype" ) ),
331 new GAGrouping() );
332
333
334 indexer.closeIndexingContext( centralContext, false );
335 }
336
337 public void searchAndDump( Indexer nexusIndexer, String descr, Query q )
338 throws IOException
339 {
340 System.out.println( "Searching for " + descr );
341
342 FlatSearchResponse response = nexusIndexer.searchFlat( new FlatSearchRequest( q, centralContext ) );
343
344 for ( ArtifactInfo ai : response.getResults() )
345 {
346 System.out.println( ai.toString() );
347 }
348
349 System.out.println( "------" );
350 System.out.println( "Total: " + response.getTotalHitsCount() );
351 System.out.println();
352 }
353
354 private static final int MAX_WIDTH = 60;
355
356 public void searchGroupedAndDumpFlat( Indexer nexusIndexer, String descr, Query q, Grouping g )
357 throws IOException
358 {
359 System.out.println( "Searching for " + descr );
360
361 GroupedSearchResponse response = nexusIndexer.searchGrouped( new GroupedSearchRequest( q, g, centralContext ) );
362
363 for ( Map.Entry<String, ArtifactInfoGroup> entry : response.getResults().entrySet() )
364 {
365 ArtifactInfo ai = entry.getValue().getArtifactInfos().iterator().next();
366 System.out.println( "* " + ai.getGroupId() + ":" + ai.getArtifactId() + ":" + ai.getVersion() );
367 }
368
369 System.out.println( "------" );
370 System.out.println( "Total record hits: " + response.getTotalHitsCount() );
371 System.out.println();
372 }
373
374 public void searchGroupedAndDump( Indexer nexusIndexer, String descr, Query q, Grouping g )
375 throws IOException
376 {
377 System.out.println( "Searching for " + descr );
378
379 GroupedSearchResponse response = nexusIndexer.searchGrouped( new GroupedSearchRequest( q, g, centralContext ) );
380
381 for ( Map.Entry<String, ArtifactInfoGroup> entry : response.getResults().entrySet() )
382 {
383 ArtifactInfo ai = entry.getValue().getArtifactInfos().iterator().next();
384 System.out.println( "* Entry " + ai );
385 System.out.println( " Latest version: " + ai.getVersion() );
386 System.out.println( StringUtils.isBlank( ai.getDescription() )
387 ? "No description in plugin's POM."
388 : StringUtils.abbreviate( ai.getDescription(), MAX_WIDTH ) );
389 System.out.println();
390 }
391
392 System.out.println( "------" );
393 System.out.println( "Total record hits: " + response.getTotalHitsCount() );
394 System.out.println();
395 }
396 }