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