1 package org.apache.maven.index.treeview;
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22 import javax.inject.Inject;
23 import javax.inject.Named;
24 import javax.inject.Singleton;
25 import java.io.IOException;
26 import java.util.HashMap;
27 import java.util.HashSet;
28 import java.util.Map;
29 import java.util.Set;
30
31 import org.apache.lucene.search.BooleanClause;
32 import org.apache.lucene.search.BooleanQuery;
33 import org.apache.lucene.search.Query;
34 import org.apache.maven.index.ArtifactInfo;
35 import org.apache.maven.index.Field;
36 import org.apache.maven.index.Indexer;
37 import org.apache.maven.index.IteratorSearchRequest;
38 import org.apache.maven.index.IteratorSearchResponse;
39 import org.apache.maven.index.MAVEN;
40 import org.apache.maven.index.expr.SourcedSearchExpression;
41 import org.apache.maven.index.treeview.TreeNode.Type;
42 import org.codehaus.plexus.util.StringUtils;
43
44 @Singleton
45 @Named
46 public class DefaultIndexTreeView
47 implements IndexTreeView
48 {
49
50 private final Indexer indexer;
51
52
53 @Inject
54 public DefaultIndexTreeView( Indexer indexer )
55 {
56 this.indexer = indexer;
57 }
58
59 protected Indexer getIndexer()
60 {
61 return indexer;
62 }
63
64 public TreeNode listNodes( TreeViewRequest request )
65 throws IOException
66 {
67
68 String name = null;
69
70 if ( !"/".equals( request.getPath() ) )
71 {
72
73 if ( request.getPath().endsWith( "/" ) )
74 {
75 name = request.getPath().substring( 0, request.getPath().length() - 1 );
76 }
77 else
78 {
79 name = request.getPath();
80 }
81
82 name = name.substring( name.lastIndexOf( '/' ) + 1, name.length() );
83
84
85 if ( !name.equals( "/" ) && name.endsWith( "/" ) )
86 {
87 name = name.substring( 0, name.length() - 1 );
88 }
89
90 }
91 else
92 {
93 name = "/";
94 }
95
96
97 TreeNode result = request.getFactory().createGNode( this, request, request.getPath(), name );
98
99 if ( request.hasFieldHints() )
100 {
101 listChildren( result, request, null );
102 }
103 else
104 {
105
106 if ( "/".equals( request.getPath() ) )
107 {
108
109 Set<String> rootGroups = request.getIndexingContext().getRootGroups();
110
111 for ( String group : rootGroups )
112 {
113 if ( group.length() > 0 )
114 {
115 result.getChildren().add(
116 request.getFactory().createGNode( this, request, request.getPath() + group + "/", group ) );
117 }
118 }
119 }
120 else
121 {
122 Set<String> allGroups = request.getIndexingContext().getAllGroups();
123
124 listChildren( result, request, allGroups );
125 }
126 }
127
128 return result;
129 }
130
131
132
133
134
135
136
137 protected void listChildren( TreeNode root, TreeViewRequest request, Set<String> allGroups )
138 throws IOException
139 {
140 String path = root.getPath();
141
142 Map<String, TreeNode> folders = new HashMap<String, TreeNode>();
143
144 String rootPartialGroupId = StringUtils.strip( root.getPath().replaceAll( "/", "." ), "." );
145
146 folders.put( Type.G + ":" + rootPartialGroupId, root );
147
148 IteratorSearchResponse artifacts = getArtifacts( root, request );
149
150 try
151 {
152 for ( ArtifactInfo ai : artifacts )
153 {
154 String versionKey = Type.V + ":" + ai.getArtifactId() + ":" + ai.getVersion();
155
156 TreeNode versionResource = folders.get( versionKey );
157
158 if ( versionResource == null )
159 {
160 String artifactKey = Type.A + ":" + ai.getArtifactId();
161
162 TreeNode artifactResource = folders.get( artifactKey );
163
164 if ( artifactResource == null )
165 {
166 TreeNode groupParentResource = root;
167
168 TreeNode groupResource = root;
169
170
171 String partialGroupId = null;
172
173 String[] groupIdElems = ai.getGroupId().split( "\\." );
174
175 for ( String groupIdElem : groupIdElems )
176 {
177 if ( partialGroupId == null )
178 {
179 partialGroupId = groupIdElem;
180 }
181 else
182 {
183 partialGroupId = partialGroupId + "." + groupIdElem;
184 }
185
186 String groupKey = Type.G + ":" + partialGroupId;
187
188 groupResource = folders.get( groupKey );
189
190
191 if ( groupResource == null
192 && groupParentResource.getPath().length() < getPathForAi( ai,
193 MAVEN.GROUP_ID ).length() )
194 {
195 String gNodeName =
196 partialGroupId.lastIndexOf( '.' ) > -1 ? partialGroupId.substring(
197 partialGroupId.lastIndexOf( '.' ) + 1, partialGroupId.length() )
198 : partialGroupId;
199
200 groupResource =
201 request.getFactory().createGNode( this, request,
202 "/" + partialGroupId.replaceAll( "\\.", "/" ) + "/", gNodeName );
203
204 groupParentResource.getChildren().add( groupResource );
205
206 folders.put( groupKey, groupResource );
207
208 groupParentResource = groupResource;
209 }
210 else if ( groupResource != null )
211 {
212
213 if ( groupResource.getPath().equals( getPathForAi( ai, MAVEN.GROUP_ID ) ) )
214 {
215 break;
216 }
217
218 groupParentResource = groupResource;
219 }
220 }
221
222 artifactResource = request.getFactory().createANode( this, request, ai,
223 getPathForAi( ai, MAVEN.ARTIFACT_ID ) );
224
225 groupParentResource.getChildren().add( artifactResource );
226
227 folders.put( artifactKey, artifactResource );
228 }
229
230 versionResource =
231 request.getFactory().createVNode( this, request, ai, getPathForAi( ai, MAVEN.VERSION ) );
232
233 artifactResource.getChildren().add( versionResource );
234
235 folders.put( versionKey, versionResource );
236 }
237
238 String nodePath = getPathForAi( ai, null );
239
240 versionResource.getChildren().add(
241 request.getFactory().createArtifactNode( this, request, ai, nodePath ) );
242 }
243 }
244 finally
245 {
246 artifacts.close();
247 }
248
249 if ( !request.hasFieldHints() )
250 {
251 Set<String> groups = getGroups( path, allGroups );
252
253 for ( String group : groups )
254 {
255 TreeNode groupResource = root.findChildByPath( path + group + "/", Type.G );
256
257 if ( groupResource == null )
258 {
259 groupResource = request.getFactory().createGNode( this, request, path + group + "/", group );
260
261 root.getChildren().add( groupResource );
262 }
263 else
264 {
265
266
267 listChildren( groupResource, request, allGroups );
268 }
269 }
270 }
271 }
272
273
274
275
276
277
278
279
280
281
282 protected String getPathForAi( ArtifactInfo ai, Field field )
283 {
284 StringBuilder sb = new StringBuilder( "/" );
285
286 sb.append( ai.getGroupId().replaceAll( "\\.", "/" ) );
287
288 if ( MAVEN.GROUP_ID.equals( field ) )
289 {
290
291 return sb.append( "/" ).toString();
292 }
293
294 sb.append( "/" ).append( ai.getArtifactId() );
295
296 if ( MAVEN.ARTIFACT_ID.equals( field ) )
297 {
298
299 return sb.append( "/" ).toString();
300 }
301
302 sb.append( "/" ).append( ai.getVersion() );
303
304 if ( MAVEN.VERSION.equals( field ) )
305 {
306
307 return sb.append( "/" ).toString();
308 }
309
310 sb.append( "/" ).append( ai.getArtifactId() ).append( "-" ).append( ai.getVersion() );
311
312 if ( ai.getClassifier() != null )
313 {
314 sb.append( "-" ).append( ai.getClassifier() );
315 }
316
317 sb.append( "." ).append( ai.getFileExtension() == null ? "jar" : ai.getFileExtension() );
318
319 return sb.toString();
320 }
321
322 protected Set<String> getGroups( String path, Set<String> allGroups )
323 {
324 path = path.substring( 1 ).replace( '/', '.' );
325
326 int n = path.length();
327
328 Set<String> result = new HashSet<String>();
329
330 for ( String group : allGroups )
331 {
332 if ( group.startsWith( path ) )
333 {
334 group = group.substring( n );
335
336 int nextDot = group.indexOf( '.' );
337
338 if ( nextDot > -1 )
339 {
340 group = group.substring( 0, nextDot );
341 }
342
343 if ( group.length() > 0 && !result.contains( group ) )
344 {
345 result.add( group );
346 }
347 }
348 }
349
350 return result;
351 }
352
353 protected IteratorSearchResponse getArtifacts( TreeNode root, TreeViewRequest request )
354 throws IOException
355 {
356 if ( request.hasFieldHints() )
357 {
358 return getHintedArtifacts( root, request );
359 }
360
361 String path = root.getPath();
362
363 IteratorSearchResponse result = null;
364
365 String g = null;
366
367 String a = null;
368
369 String v = null;
370
371
372 String wp = null;
373
374
375 if ( path.endsWith( "/" ) )
376 {
377 path = path.substring( 0, path.length() - 1 );
378 }
379
380
381
382
383 wp = path;
384
385 g = wp.substring( 1 ).replace( '/', '.' );
386
387 result = getArtifactsByG( g, request );
388
389 if ( result.getTotalHitsCount() > 0 )
390 {
391 return result;
392 }
393 else
394 {
395 result.close();
396 }
397
398
399
400 if ( path.lastIndexOf( '/' ) > 0 )
401 {
402
403 wp = path;
404
405 a = wp.substring( wp.lastIndexOf( '/' ) + 1, wp.length() );
406
407 g = wp.substring( 1, wp.lastIndexOf( '/' ) ).replace( '/', '.' );
408
409 result = getArtifactsByGA( g, a, request );
410
411 if ( result.getTotalHitsCount() > 0 )
412 {
413 return result;
414 }
415 else
416 {
417 result.close();
418 }
419
420
421
422 try
423 {
424
425 wp = path;
426
427 v = wp.substring( wp.lastIndexOf( '/' ) + 1, wp.length() );
428
429 wp = wp.substring( 0, wp.lastIndexOf( '/' ) );
430
431 a = wp.substring( wp.lastIndexOf( '/' ) + 1, wp.length() );
432
433 g = wp.substring( 1, wp.lastIndexOf( '/' ) ).replace( '/', '.' );
434
435 result = getArtifactsByGAV( g, a, v, request );
436
437 if ( result.getTotalHitsCount() > 0 )
438 {
439 return result;
440 }
441 else
442 {
443 result.close();
444 }
445 }
446 catch ( StringIndexOutOfBoundsException e )
447 {
448
449 }
450 }
451
452
453 return IteratorSearchResponse.empty( result.getQuery() );
454 }
455
456 protected IteratorSearchResponse getHintedArtifacts( TreeNode root, TreeViewRequest request )
457 throws IOException
458 {
459
460 if ( request.hasFieldHint( MAVEN.GROUP_ID, MAVEN.ARTIFACT_ID, MAVEN.VERSION ) )
461 {
462 return getArtifactsByGAV( request.getFieldHint( MAVEN.GROUP_ID ),
463 request.getFieldHint( MAVEN.ARTIFACT_ID ), request.getFieldHint( MAVEN.VERSION ), request );
464 }
465 else if ( request.hasFieldHint( MAVEN.GROUP_ID, MAVEN.ARTIFACT_ID ) )
466 {
467 return getArtifactsByGA( request.getFieldHint( MAVEN.GROUP_ID ), request.getFieldHint( MAVEN.ARTIFACT_ID ),
468 request );
469 }
470 else if ( request.hasFieldHint( MAVEN.GROUP_ID ) )
471 {
472 return getArtifactsByG( request.getFieldHint( MAVEN.GROUP_ID ), request );
473 }
474 else
475 {
476
477 return IteratorSearchResponse.empty( null );
478 }
479 }
480
481 protected IteratorSearchResponse getArtifactsByG( String g, TreeViewRequest request )
482 throws IOException
483 {
484 return getArtifactsByGAVField( g, null, null, request );
485 }
486
487 protected IteratorSearchResponse getArtifactsByGA( String g, String a, TreeViewRequest request )
488 throws IOException
489 {
490 return getArtifactsByGAVField( g, a, null, request );
491 }
492
493 protected IteratorSearchResponse getArtifactsByGAV( String g, String a, String v, TreeViewRequest request )
494 throws IOException
495 {
496 return getArtifactsByGAVField( g, a, v, request );
497 }
498
499 protected IteratorSearchResponse getArtifactsByGAVField( String g, String a, String v, TreeViewRequest request )
500 throws IOException
501 {
502 assert g != null;
503
504 Query groupIdQ = null;
505 Query artifactIdQ = null;
506 Query versionQ = null;
507
508
509 groupIdQ = getIndexer().constructQuery( MAVEN.GROUP_ID, new SourcedSearchExpression( g ) );
510
511 if ( StringUtils.isNotBlank( a ) )
512 {
513 artifactIdQ = getIndexer().constructQuery( MAVEN.ARTIFACT_ID, new SourcedSearchExpression( a ) );
514 }
515
516 if ( StringUtils.isNotBlank( v ) )
517 {
518 versionQ = getIndexer().constructQuery( MAVEN.VERSION, new SourcedSearchExpression( v ) );
519 }
520
521 BooleanQuery q = new BooleanQuery();
522
523 q.add( new BooleanClause( groupIdQ, BooleanClause.Occur.MUST ) );
524
525 if ( artifactIdQ != null )
526 {
527 q.add( new BooleanClause( artifactIdQ, BooleanClause.Occur.MUST ) );
528 }
529
530 if ( versionQ != null )
531 {
532 q.add( new BooleanClause( versionQ, BooleanClause.Occur.MUST ) );
533 }
534
535 IteratorSearchRequest searchRequest = new IteratorSearchRequest( q, request.getArtifactInfoFilter() );
536
537 searchRequest.getContexts().add( request.getIndexingContext() );
538
539 IteratorSearchResponse result = getIndexer().searchIterator( searchRequest );
540
541 return result;
542 }
543 }