1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22 import java.io.BufferedReader;
23 import java.io.ByteArrayInputStream;
24 import java.io.ByteArrayOutputStream;
25 import java.io.File;
26 import java.io.FileReader;
27 import java.io.IOException;
28 import java.io.PrintWriter;
29 import java.io.StringWriter;
30 import java.nio.file.Files;
31 import java.util.ArrayList;
32 import java.util.Collection;
33 import java.util.Collections;
34 import java.util.List;
35 import java.util.Map;
36 import java.util.Set;
37
38 import org.apache.lucene.index.Term;
39 import org.apache.lucene.search.BooleanClause.Occur;
40 import org.apache.lucene.search.BooleanQuery;
41 import org.apache.lucene.search.IndexSearcher;
42 import org.apache.lucene.search.Query;
43 import org.apache.lucene.search.TermQuery;
44 import org.apache.lucene.search.WildcardQuery;
45 import org.apache.lucene.store.RAMDirectory;
46 import org.apache.maven.index.context.IndexCreator;
47 import org.apache.maven.index.context.IndexingContext;
48 import org.apache.maven.index.context.MergedIndexingContext;
49 import org.apache.maven.index.context.StaticContextMemberProvider;
50 import org.apache.maven.index.context.UnsupportedExistingLuceneIndexException;
51 import org.apache.maven.index.creator.MinimalArtifactInfoIndexCreator;
52 import org.apache.maven.index.packer.DefaultIndexPacker;
53 import org.apache.maven.index.packer.IndexPacker;
54 import org.apache.maven.index.packer.IndexPackingRequest;
55 import org.apache.maven.index.search.grouping.GAGrouping;
56 import org.apache.maven.index.updater.DefaultIndexUpdater;
57 import org.apache.maven.index.updater.IndexUpdateRequest;
58 import org.apache.maven.index.updater.IndexUpdater;
59 import org.codehaus.plexus.util.StringUtils;
60
61 import static org.hamcrest.CoreMatchers.is;
62 import static org.junit.Assert.assertThat;
63
64
65 public class NexusIndexerTest
66 extends AbstractIndexCreatorHelper
67 {
68 private IndexingContext context;
69
70 public void testSingleQuery() throws Exception
71 {
72 NexusIndexer indexer = lookup(NexusIndexer.class);
73
74 File indexDir = super.getDirectory( "index/test" );
75 super.deleteDirectory( indexDir );
76
77 File repo = new File( getBasedir(), "src/test/repo" );
78
79 context = indexer.addIndexingContext( "test", "test", repo, indexDir, null, null, DEFAULT_CREATORS );
80 indexer.scan( context );
81
82 Query q = null;
83
84
85 q = indexer.constructQuery( MAVEN.NAME, "Some artifact name from Pom", SearchType.SCORED );
86 assertThat(q.toString(), is("(+n:some +n:artifact +n:name +n:from +n:pom*) n:\"some artifact name from pom\""));
87 }
88
89 public void testQueryCreatorNG()
90 throws Exception
91 {
92 NexusIndexer indexer = prepare();
93
94 Query q = null;
95
96
97 q = indexer.constructQuery( MAVEN.GROUP_ID, "commons-loggin*", SearchType.EXACT );
98
99
100 assertEquals( MinimalArtifactInfoIndexCreator.FLD_GROUP_ID_KW.getKey() + ":commons-loggin*", q.toString() );
101
102
103 q = indexer.constructQuery( MAVEN.GROUP_ID, "commons-loggin*", SearchType.SCORED );
104
105
106 assertEquals( "g:commons-loggin* ((+groupId:commons +groupId:loggin*) groupId:\"commons loggin\")",
107 q.toString() );
108
109
110 q = indexer.constructQuery( MAVEN.GROUP_ID, "commons-logging", SearchType.EXACT );
111
112 assertEquals( MinimalArtifactInfoIndexCreator.FLD_GROUP_ID_KW.getKey() + ":commons-logging", q.toString() );
113
114
115 q = indexer.constructQuery( MAVEN.PACKAGING, "maven-archetype", SearchType.EXACT );
116
117 assertEquals( MinimalArtifactInfoIndexCreator.FLD_PACKAGING.getKey() + ":maven-archetype", q.toString() );
118
119
120 q = indexer.constructQuery( MAVEN.PACKAGING, "maven-archetype", SearchType.SCORED );
121
122 assertEquals( "p:maven-archetype p:maven-archetype*", q.toString() );
123
124
125 q = indexer.constructQuery( MAVEN.ARTIFACT_ID, "commons-logging", SearchType.SCORED );
126
127 assertEquals(
128 "(a:commons-logging a:commons-logging*) ((+artifactId:commons +artifactId:logging*) artifactId:\"commons logging\")",
129 q.toString() );
130
131
132 q = indexer.constructQuery( MAVEN.NAME, "Some artifact name from Pom", SearchType.SCORED );
133
134 assertEquals( "(+n:some +n:artifact +n:name +n:from +n:pom*) n:\"some artifact name from pom\"", q.toString() );
135
136
137 q = indexer.constructQuery( MAVEN.NAME, "some artifact name from Pom", SearchType.EXACT );
138
139 assertNull( q );
140 }
141
142 public void performQueryCreatorNGSearch( NexusIndexer indexer, IndexingContext context )
143 throws Exception
144 {
145 String qstr = null;
146 Query q = null;
147
148 IteratorSearchRequest req = null;
149
150 IteratorSearchResponse res = null;
151
152
153
154
155 qstr = "commons-logg";
156 q = indexer.constructQuery( MAVEN.GROUP_ID, qstr, SearchType.SCORED );
157
158 req = new IteratorSearchRequest( q, context );
159
160 res = indexer.searchIterator( req );
161
162 checkResults( MAVEN.GROUP_ID, qstr, q, res,
163 getTestFile( "src/test/resources/testQueryCreatorNGSearch/case01.txt" ) );
164
165
166
167
168 qstr = "commons logg";
169 q = indexer.constructQuery( MAVEN.GROUP_ID, qstr, SearchType.SCORED );
170
171 req = new IteratorSearchRequest( q, context );
172
173 res = indexer.searchIterator( req );
174
175 checkResults( MAVEN.GROUP_ID, qstr, q, res,
176 getTestFile( "src/test/resources/testQueryCreatorNGSearch/case02.txt" ) );
177
178
179
180 qstr = "commons";
181 q = indexer.constructQuery( MAVEN.GROUP_ID, qstr, SearchType.SCORED );
182
183 req = new IteratorSearchRequest( q, context );
184
185 res = indexer.searchIterator( req );
186
187 checkResults( MAVEN.GROUP_ID, qstr, q, res,
188 getTestFile( "src/test/resources/testQueryCreatorNGSearch/case03.txt" ) );
189
190
191
192 qstr = "log";
193 q = indexer.constructQuery( MAVEN.GROUP_ID, qstr, SearchType.SCORED );
194
195 req = new IteratorSearchRequest( q, context );
196
197 res = indexer.searchIterator( req );
198
199 checkResults( MAVEN.GROUP_ID, qstr, q, res,
200 getTestFile( "src/test/resources/testQueryCreatorNGSearch/case04.txt" ) );
201
202
203
204
205 qstr = "1.0";
206 q = indexer.constructQuery( MAVEN.VERSION, "1.0", SearchType.SCORED );
207
208 req = new IteratorSearchRequest( q, context );
209
210 res = indexer.searchIterator( req );
211
212 checkResults( MAVEN.VERSION, qstr, q, res,
213 getTestFile( "src/test/resources/testQueryCreatorNGSearch/case05.txt" ) );
214
215
216
217 qstr = "1.0";
218 q = indexer.constructQuery( MAVEN.VERSION, qstr, SearchType.EXACT );
219
220 req = new IteratorSearchRequest( q, context );
221
222 res = indexer.searchIterator( req );
223
224 checkResults( MAVEN.VERSION, qstr, q, res,
225 getTestFile( "src/test/resources/testQueryCreatorNGSearch/case06.txt" ) );
226
227
228
229
230 BooleanQuery bq = new BooleanQuery();
231
232 Query g = indexer.constructQuery( MAVEN.GROUP_ID, "commons-logging", SearchType.EXACT );
233 Query a = indexer.constructQuery( MAVEN.ARTIFACT_ID, "commons-logging", SearchType.EXACT );
234 Query v = indexer.constructQuery( MAVEN.VERSION, "1.0.4", SearchType.EXACT );
235 Query p = indexer.constructQuery( MAVEN.PACKAGING, "jar", SearchType.EXACT );
236 Query c = indexer.constructQuery( MAVEN.CLASSIFIER, Field.NOT_PRESENT, SearchType.EXACT );
237
238
239 bq.add( g, Occur.MUST );
240 bq.add( a, Occur.MUST );
241 bq.add( v, Occur.MUST );
242 bq.add( p, Occur.MUST );
243 bq.add( c, Occur.MUST_NOT );
244
245
246 Collection<ArtifactInfo> ais = indexer.identify( bq, Collections.singletonList( context ) );
247
248 assertEquals( 1, ais.size() );
249
250 ArtifactInfo ai = ais.iterator().next();
251
252
253 assertTrue( ai != null );
254
255
256 assertEquals( "commons-logging:commons-logging:1.0.4:null:jar", ai.getGroupId() + ":" + ai.getArtifactId() + ":" + ai.getVersion() + ":" + ai.getClassifier() + ":" + ai.getPackaging() );
257 }
258
259 public void testQueryCreatorNGSearch()
260 throws Exception
261 {
262 NexusIndexer indexer = prepare();
263
264 performQueryCreatorNGSearch( indexer, context );
265 }
266
267 public void testQueryCreatorNGSearchOnMergedContext()
268 throws Exception
269 {
270 NexusIndexer indexer = prepare();
271
272 File indexMergedDir = super.getDirectory( "index/testMerged" );
273
274 IndexingContext mergedContext =
275 new MergedIndexingContext( "test", "merged", context.getRepository(), indexMergedDir, true,
276 new StaticContextMemberProvider( Collections.singletonList( context ) ) );
277
278 performQueryCreatorNGSearch( indexer, mergedContext );
279 }
280
281
282
283
284 public void checkResults( Field field, String query, Query q, IteratorSearchResponse res, File expectedResults )
285 throws IOException
286 {
287
288
289 boolean print = true;
290
291 StringWriter sw = new StringWriter();
292
293 PrintWriter pw = new PrintWriter( sw );
294
295 String line = null;
296
297 line =
298 "### Searched for field " + field.toString() + " using query \"" + query + "\" (QC create LQL \""
299 + q.toString() + "\")";
300
301 if ( print )
302 {
303 System.out.println( line );
304 }
305
306 pw.println( line );
307
308 int totalHits = 0;
309
310 for ( ArtifactInfo ai : res )
311 {
312 line = ai.getContext() + " :: " + ai.getGroupId() + ":" + ai.getArtifactId() + ":" + ai.getVersion() + ":" + ai.getClassifier() + ":" + ai.getPackaging();
313
314 if ( print )
315 {
316 System.out.println( line );
317 }
318
319 pw.println( line );
320
321 totalHits++;
322 }
323
324 line = "### TOTAL:" + totalHits + " (response said " + res.getTotalHits() + ")";
325
326 if ( print )
327 {
328 System.out.println( line );
329 }
330
331 pw.println( line );
332
333
334
335 StringWriter ressw = new StringWriter();
336 PrintWriter respw = new PrintWriter( ressw );
337
338 BufferedReader reader = new BufferedReader( new FileReader( expectedResults ) );
339 String currentline = null;
340
341 while ( ( currentline = reader.readLine() ) != null )
342 {
343 respw.println( currentline );
344 }
345
346 String shouldBe = ressw.toString();
347 String whatWeHave = sw.toString();
348
349
350 assertEquals( "Search results inconsistent!", shouldBe, whatWeHave );
351 }
352
353 public void testSearchIterator()
354 throws Exception
355 {
356 NexusIndexer indexer = prepare();
357
358 Query q = indexer.constructQuery( MAVEN.GROUP_ID, "qdox", SearchType.SCORED );
359
360 IteratorSearchRequest request = new IteratorSearchRequest( q );
361
362 IteratorSearchResponse response = indexer.searchIterator( request );
363
364 assertEquals( 2, response.getTotalHits() );
365
366 for ( ArtifactInfo ai : response.getResults() )
367 {
368 assertEquals( "GroupId must match \"qdox\"!", "qdox", ai.getGroupId() );
369 }
370 }
371
372 public void testSearchIteratorWithFilter()
373 throws Exception
374 {
375 NexusIndexer indexer = prepare();
376
377 Query q = indexer.constructQuery( MAVEN.GROUP_ID, "qdox", SearchType.SCORED );
378
379 IteratorSearchRequest request = new IteratorSearchRequest( q, new ArtifactInfoFilter()
380 {
381 public boolean accepts( IndexingContext ctx, ArtifactInfo ai )
382 {
383
384 return !StringUtils.equals( ai.getVersion(), "1.5" );
385 }
386 } );
387
388 IteratorSearchResponse response = indexer.searchIterator( request );
389
390 assertEquals( 2, response.getTotalHits() );
391
392 assertTrue( "Iterator has to have next (2 found, 1 filtered out)", response.getResults().hasNext() );
393
394 ArtifactInfo ai = response.getResults().next();
395
396 assertEquals( "1.5 is filtered out, so 1.6.1 must appear here!", "1.6.1", ai.getVersion() );
397 }
398
399 public void testSearchGrouped()
400 throws Exception
401 {
402 NexusIndexer indexer = prepare();
403
404 {
405 Query q = indexer.constructQuery( MAVEN.GROUP_ID, "qdox", SearchType.SCORED );
406 GroupedSearchRequest request = new GroupedSearchRequest( q, new GAGrouping() );
407 GroupedSearchResponse response = indexer.searchGrouped( request );
408 Map<String, ArtifactInfoGroup> r = response.getResults();
409 assertEquals( 1, r.size() );
410
411 ArtifactInfoGroup gi0 = r.values().iterator().next();
412 assertEquals( "qdox : qdox", gi0.getGroupKey() );
413 List<ArtifactInfo> list = new ArrayList<>( gi0.getArtifactInfos() );
414 ArtifactInfo ai0 = list.get( 0 );
415 assertEquals( "1.6.1", ai0.getVersion() );
416 ArtifactInfo ai1 = list.get( 1 );
417 assertEquals( "1.5", ai1.getVersion() );
418 assertEquals( "test", ai1.getRepository() );
419 }
420 {
421 WildcardQuery q = new WildcardQuery( new Term( ArtifactInfo.UINFO, "commons-log*" ) );
422 GroupedSearchRequest request =
423 new GroupedSearchRequest( q, new GAGrouping(), String.CASE_INSENSITIVE_ORDER );
424 GroupedSearchResponse response = indexer.searchGrouped( request );
425 Map<String, ArtifactInfoGroup> r = response.getResults();
426 assertEquals( 1, r.size() );
427
428 ArtifactInfoGroup gi1 = r.values().iterator().next();
429 assertEquals( "commons-logging : commons-logging", gi1.getGroupKey() );
430 }
431 }
432
433 public void testSearchFlat()
434 throws Exception
435 {
436 NexusIndexer indexer = prepare();
437
438 {
439 WildcardQuery q = new WildcardQuery( new Term( ArtifactInfo.UINFO, "*testng*" ) );
440 FlatSearchResponse response = indexer.searchFlat( new FlatSearchRequest( q ) );
441 Set<ArtifactInfo> r = response.getResults();
442 assertEquals( r.toString(), 4, r.size() );
443 }
444
445 {
446 BooleanQuery bq = new BooleanQuery( true );
447 bq.add( new WildcardQuery( new Term( ArtifactInfo.GROUP_ID, "testng*" ) ), Occur.SHOULD );
448 bq.add( new WildcardQuery( new Term( ArtifactInfo.ARTIFACT_ID, "testng*" ) ), Occur.SHOULD );
449 bq.setMinimumNumberShouldMatch( 1 );
450
451 FlatSearchResponse response = indexer.searchFlat( new FlatSearchRequest( bq ) );
452 Set<ArtifactInfo> r = response.getResults();
453
454 assertEquals( r.toString(), 4, r.size() );
455 }
456 }
457
458 public void testSearchPackaging()
459 throws Exception
460 {
461 NexusIndexer indexer = prepare();
462
463 WildcardQuery q = new WildcardQuery( new Term( ArtifactInfo.PACKAGING, "maven-plugin" ) );
464 FlatSearchResponse response = indexer.searchFlat( new FlatSearchRequest( q ) );
465 Set<ArtifactInfo> r = response.getResults();
466 assertEquals( r.toString(), 2, r.size() );
467 }
468
469 public void testIdentity()
470 throws Exception
471 {
472 NexusIndexer nexus = prepare();
473
474
475
476 Collection<ArtifactInfo> ais = nexus.identify( MAVEN.SHA1, "4d2db265eddf1576cb9d896abc90c7ba46b48d87" );
477
478 assertEquals( 1, ais.size() );
479
480 ArtifactInfo ai = ais.iterator().next();
481
482 assertNotNull( ai );
483
484 assertEquals( "qdox", ai.getGroupId() );
485
486 assertEquals( "qdox", ai.getArtifactId() );
487
488 assertEquals( "1.5", ai.getVersion() );
489
490 assertEquals( "test", ai.getRepository() );
491
492
493
494 File artifact = new File( getBasedir(), "src/test/repo/qdox/qdox/1.5/qdox-1.5.jar" );
495
496 ais = nexus.identify( artifact );
497
498 assertEquals( 1, ais.size() );
499
500 ai = ais.iterator().next();
501
502 assertNotNull( ai );
503
504 assertEquals( "qdox", ai.getGroupId() );
505
506 assertEquals( "qdox", ai.getArtifactId() );
507
508 assertEquals( "1.5", ai.getVersion() );
509
510 assertEquals( "test", ai.getRepository() );
511 }
512
513 public void testUpdateArtifact()
514 throws Exception
515 {
516 NexusIndexer indexer = prepare();
517
518 Query q =
519 new TermQuery( new Term( ArtifactInfo.UINFO, "org.apache.maven.plugins|maven-core-it-plugin|1.0|NA|jar" ) );
520
521 FlatSearchRequest request = new FlatSearchRequest( q );
522
523 FlatSearchResponse response1 = indexer.searchFlat( request );
524 Collection<ArtifactInfo> res1 = response1.getResults();
525 assertEquals( 1, res1.size() );
526
527 ArtifactInfo ai = res1.iterator().next();
528
529 assertEquals( "Maven Core Integration Test Plugin", ai.getName() );
530
531 long oldSize = ai.getSize();
532
533 ai.setName( "bla bla bla" );
534
535 ai.setSize( ai.getSize() + 100 );
536
537 IndexingContext indexingContext = indexer.getIndexingContexts().get( "test" );
538
539
540
541
542
543
544
545
546 indexer.addArtifactToIndex( new ArtifactContext( null, null, null, ai, null ), indexingContext );
547
548 FlatSearchResponse response2 = indexer.searchFlat( request );
549 Collection<ArtifactInfo> res2 = response2.getResults();
550 assertEquals( 1, res2.size() );
551
552 ArtifactInfo ai2 = res2.iterator().next();
553
554 assertEquals( oldSize + 100, ai2.getSize() );
555
556 assertEquals( "bla bla bla", ai2.getName() );
557 }
558
559 public void testUnpack()
560 throws Exception
561 {
562 NexusIndexer indexer = prepare();
563
564 String indexId = context.getId();
565 String repositoryId = context.getRepositoryId();
566 File repository = context.getRepository();
567 String repositoryUrl = context.getRepositoryUrl();
568 List<IndexCreator> indexCreators = context.getIndexCreators();
569
570
571 final File targetDir = Files.createTempDirectory("testIndexTimestamp" ).toFile();
572 targetDir.deleteOnExit();
573
574 final IndexPacker indexPacker = lookup( IndexPacker.class );
575 final IndexSearcher indexSearcher = context.acquireIndexSearcher();
576 try
577 {
578 final IndexPackingRequest request =
579 new IndexPackingRequest( context, indexSearcher.getIndexReader(), targetDir );
580 indexPacker.packIndex( request );
581 }
582 finally
583 {
584 context.releaseIndexSearcher( indexSearcher );
585 }
586
587 indexer.removeIndexingContext( context, false );
588
589 RAMDirectory newDirectory = new RAMDirectory();
590
591 IndexingContext newContext = indexer.addIndexingContext( indexId,
592 repositoryId, repository, newDirectory, repositoryUrl, null, indexCreators );
593
594 final IndexUpdater indexUpdater = lookup( IndexUpdater.class );
595 indexUpdater.fetchAndUpdateIndex( new IndexUpdateRequest( newContext, new DefaultIndexUpdater.FileFetcher( targetDir ) ) );
596
597 WildcardQuery q = new WildcardQuery( new Term( ArtifactInfo.PACKAGING, "maven-plugin" ) );
598 FlatSearchResponse response = indexer.searchFlat( new FlatSearchRequest( q ) );
599 Collection<ArtifactInfo> infos = response.getResults();
600
601 assertEquals( infos.toString(), 2, infos.size() );
602 }
603
604 private NexusIndexer prepare()
605 throws Exception, IOException, UnsupportedExistingLuceneIndexException
606 {
607 NexusIndexer indexer = lookup( NexusIndexer.class );
608
609
610 File indexDir = super.getDirectory( "index/test" );
611 super.deleteDirectory( indexDir );
612
613 File repo = new File( getBasedir(), "src/test/repo" );
614
615 context = indexer.addIndexingContext( "test", "test", repo, indexDir, null, null, DEFAULT_CREATORS );
616 indexer.scan( context );
617
618
619
620
621
622
623
624
625
626 return indexer;
627 }
628
629
630
631
632
633
634
635
636
637
638
639 }