Coverage Report - org.apache.maven.index.treeview.DefaultIndexTreeView
 
Classes in this File Line Coverage Branch Coverage Complexity
DefaultIndexTreeView
88 %
152/171
75 %
69/92
6
 
 1  
 package org.apache.maven.index.treeview;
 2  
 
 3  
 /*
 4  
  * Licensed to the Apache Software Foundation (ASF) under one
 5  
  * or more contributor license agreements.  See the NOTICE file
 6  
  * distributed with this work for additional information
 7  
  * regarding copyright ownership.  The ASF licenses this file
 8  
  * to you under the Apache License, Version 2.0 (the
 9  
  * "License"); you may not use this file except in compliance
 10  
  * with the License.  You may obtain a copy of the License at
 11  
  *
 12  
  *   http://www.apache.org/licenses/LICENSE-2.0    
 13  
  *
 14  
  * Unless required by applicable law or agreed to in writing,
 15  
  * software distributed under the License is distributed on an
 16  
  * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
 17  
  * KIND, either express or implied.  See the License for the
 18  
  * specific language governing permissions and limitations
 19  
  * under the License.
 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.IteratorSearchRequest;
 34  
 import org.apache.maven.index.IteratorSearchResponse;
 35  
 import org.apache.maven.index.MAVEN;
 36  
 import org.apache.maven.index.NexusIndexer;
 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  1
 @Component( role = IndexTreeView.class )
 45  6
 public class DefaultIndexTreeView
 46  
     extends AbstractLogEnabled
 47  
     implements IndexTreeView
 48  
 {
 49  
     @Requirement
 50  
     private NexusIndexer nexusIndexer;
 51  
 
 52  
     protected NexusIndexer getNexusIndexer()
 53  
     {
 54  176
         return nexusIndexer;
 55  
     }
 56  
 
 57  
     public TreeNode listNodes( TreeViewRequest request )
 58  
         throws IOException
 59  
     {
 60  
         // get the last path elem
 61  47
         String name = null;
 62  
 
 63  47
         if ( !"/".equals( request.getPath() ) )
 64  
         {
 65  
 
 66  46
             if ( request.getPath().endsWith( "/" ) )
 67  
             {
 68  46
                 name = request.getPath().substring( 0, request.getPath().length() - 1 );
 69  
             }
 70  
             else
 71  
             {
 72  0
                 name = request.getPath();
 73  
             }
 74  
 
 75  46
             name = name.substring( name.lastIndexOf( '/' ) + 1, name.length() );
 76  
 
 77  
             // root is "/"
 78  46
             if ( !name.equals( "/" ) && name.endsWith( "/" ) )
 79  
             {
 80  0
                 name = name.substring( 0, name.length() - 1 );
 81  
             }
 82  
 
 83  
         }
 84  
         else
 85  
         {
 86  1
             name = "/";
 87  
         }
 88  
 
 89  
         // the root node depends on request we have, so let's see
 90  47
         TreeNode result = request.getFactory().createGNode( this, request, request.getPath(), name );
 91  
 
 92  47
         if ( request.hasFieldHints() )
 93  
         {
 94  0
             listChildren( result, request, null );
 95  
         }
 96  
         else
 97  
         {
 98  
             // non hinted way, the "old" way
 99  47
             if ( "/".equals( request.getPath() ) )
 100  
             {
 101  
                 // get root groups and finish
 102  1
                 Set<String> rootGroups = request.getIndexingContext().getRootGroups();
 103  
 
 104  1
                 for ( String group : rootGroups )
 105  
                 {
 106  12
                     if ( group.length() > 0 )
 107  
                     {
 108  12
                         result.getChildren().add(
 109  
                             request.getFactory().createGNode( this, request, request.getPath() + group + "/", group ) );
 110  
                     }
 111  
                 }
 112  1
             }
 113  
             else
 114  
             {
 115  46
                 Set<String> allGroups = request.getIndexingContext().getAllGroups();
 116  
 
 117  46
                 listChildren( result, request, allGroups );
 118  
             }
 119  
         }
 120  
 
 121  47
         return result;
 122  
     }
 123  
 
 124  
     /**
 125  
      * @param root
 126  
      * @param factory
 127  
      * @param allGroups
 128  
      * @throws IOException
 129  
      */
 130  
     protected void listChildren( TreeNode root, TreeViewRequest request, Set<String> allGroups )
 131  
         throws IOException
 132  
     {
 133  46
         String path = root.getPath();
 134  
 
 135  46
         Map<String, TreeNode> folders = new HashMap<String, TreeNode>();
 136  
 
 137  46
         String rootPartialGroupId = StringUtils.strip( root.getPath().replaceAll( "/", "." ), "." );
 138  
 
 139  46
         folders.put( Type.G + ":" + rootPartialGroupId, root );
 140  
 
 141  46
         IteratorSearchResponse artifacts = getArtifacts( root, request );
 142  
 
 143  
         try
 144  
         {
 145  46
             for ( ArtifactInfo ai : artifacts )
 146  
             {
 147  89
                 String versionKey = Type.V + ":" + ai.artifactId + ":" + ai.version;
 148  
 
 149  89
                 TreeNode versionResource = folders.get( versionKey );
 150  
 
 151  89
                 if ( versionResource == null )
 152  
                 {
 153  45
                     String artifactKey = Type.A + ":" + ai.artifactId;
 154  
 
 155  45
                     TreeNode artifactResource = folders.get( artifactKey );
 156  
 
 157  45
                     if ( artifactResource == null )
 158  
                     {
 159  36
                         TreeNode groupParentResource = root;
 160  
 
 161  36
                         TreeNode groupResource = root;
 162  
 
 163  
                         // here comes the twist: we have to search for parent G node
 164  36
                         String partialGroupId = null;
 165  
 
 166  36
                         String[] groupIdElems = ai.groupId.split( "\\." );
 167  
 
 168  87
                         for ( String groupIdElem : groupIdElems )
 169  
                         {
 170  85
                             if ( partialGroupId == null )
 171  
                             {
 172  36
                                 partialGroupId = groupIdElem;
 173  
                             }
 174  
                             else
 175  
                             {
 176  49
                                 partialGroupId = partialGroupId + "." + groupIdElem;
 177  
                             }
 178  
 
 179  85
                             String groupKey = Type.G + ":" + partialGroupId;
 180  
 
 181  85
                             groupResource = folders.get( groupKey );
 182  
 
 183  
                             // it needs to be created only if not found (is null) and is _below_ groupParentResource
 184  85
                             if ( groupResource == null
 185  
                                 && groupParentResource.getPath().length() < getPathForAi( ai, MAVEN.GROUP_ID ).length() )
 186  
                             {
 187  0
                                 String gNodeName =
 188  
                                     partialGroupId.lastIndexOf( '.' ) > -1 ? partialGroupId.substring(
 189  
                                         partialGroupId.lastIndexOf( '.' ) + 1, partialGroupId.length() )
 190  
                                         : partialGroupId;
 191  
 
 192  0
                                 groupResource =
 193  
                                     request.getFactory().createGNode( this, request,
 194  
                                         "/" + partialGroupId.replaceAll( "\\.", "/" ) + "/", gNodeName );
 195  
 
 196  0
                                 groupParentResource.getChildren().add( groupResource );
 197  
 
 198  0
                                 folders.put( groupKey, groupResource );
 199  
 
 200  0
                                 groupParentResource = groupResource;
 201  0
                             }
 202  85
                             else if ( groupResource != null )
 203  
                             {
 204  
                                 // we found it as already existing, break if this is the node we want
 205  34
                                 if ( groupResource.getPath().equals( getPathForAi( ai, MAVEN.GROUP_ID ) ) )
 206  
                                 {
 207  34
                                     break;
 208  
                                 }
 209  
 
 210  0
                                 groupParentResource = groupResource;
 211  
                             }
 212  
                         }
 213  
 
 214  36
                         artifactResource =
 215  
                             request.getFactory().createANode( this, request, ai, getPathForAi( ai, MAVEN.ARTIFACT_ID ) );
 216  
 
 217  36
                         groupParentResource.getChildren().add( artifactResource );
 218  
 
 219  36
                         folders.put( artifactKey, artifactResource );
 220  
                     }
 221  
 
 222  45
                     versionResource =
 223  
                         request.getFactory().createVNode( this, request, ai, getPathForAi( ai, MAVEN.VERSION ) );
 224  
 
 225  45
                     artifactResource.getChildren().add( versionResource );
 226  
 
 227  45
                     folders.put( versionKey, versionResource );
 228  
                 }
 229  
 
 230  89
                 String nodePath = getPathForAi( ai, null );
 231  
 
 232  89
                 versionResource.getChildren().add(
 233  
                     request.getFactory().createArtifactNode( this, request, ai, nodePath ) );
 234  89
             }
 235  
         }
 236  
         finally
 237  
         {
 238  46
             artifacts.close();
 239  46
         }
 240  
 
 241  46
         if ( !request.hasFieldHints() )
 242  
         {
 243  46
             Set<String> groups = getGroups( path, allGroups );
 244  
 
 245  46
             for ( String group : groups )
 246  
             {
 247  30
                 TreeNode groupResource = root.findChildByPath( path + group + "/", Type.G );
 248  
 
 249  30
                 if ( groupResource == null )
 250  
                 {
 251  30
                     groupResource = request.getFactory().createGNode( this, request, path + group + "/", group );
 252  
 
 253  30
                     root.getChildren().add( groupResource );
 254  
                 }
 255  
                 else
 256  
                 {
 257  
                     // if the folder has been created as an artifact name,
 258  
                     // we need to check for possible nested groups as well
 259  0
                     listChildren( groupResource, request, allGroups );
 260  
                 }
 261  30
             }
 262  
         }
 263  46
     }
 264  
 
 265  
     /**
 266  
      * Builds a path out from ArtifactInfo. The field parameter controls "how deep" the path goes. Possible values are
 267  
      * MAVEN.GROUP_ID (builds a path from groupId only), MAVEN.ARTIFACT_ID (builds a path from groupId + artifactId),
 268  
      * MAVEN.VERSION (builds a path up to version) or anything else (including null) will build "full" artifact path.
 269  
      * 
 270  
      * @param ai
 271  
      * @param field
 272  
      * @return path
 273  
      */
 274  
     protected String getPathForAi( ArtifactInfo ai, Field field )
 275  
     {
 276  255
         StringBuilder sb = new StringBuilder( "/" );
 277  
 
 278  255
         sb.append( ai.groupId.replaceAll( "\\.", "/" ) );
 279  
 
 280  255
         if ( MAVEN.GROUP_ID.equals( field ) )
 281  
         {
 282  
             // stop here
 283  85
             return sb.append( "/" ).toString();
 284  
         }
 285  
 
 286  170
         sb.append( "/" ).append( ai.artifactId );
 287  
 
 288  170
         if ( MAVEN.ARTIFACT_ID.equals( field ) )
 289  
         {
 290  
             // stop here
 291  36
             return sb.append( "/" ).toString();
 292  
         }
 293  
 
 294  134
         sb.append( "/" ).append( ai.version );
 295  
 
 296  134
         if ( MAVEN.VERSION.equals( field ) )
 297  
         {
 298  
             // stop here
 299  45
             return sb.append( "/" ).toString();
 300  
         }
 301  
 
 302  89
         sb.append( "/" ).append( ai.artifactId ).append( "-" ).append( ai.version );
 303  
 
 304  89
         if ( ai.classifier != null )
 305  
         {
 306  44
             sb.append( "-" ).append( ai.classifier );
 307  
         }
 308  
 
 309  89
         sb.append( "." ).append( ai.fextension == null ? "jar" : ai.fextension );
 310  
 
 311  89
         return sb.toString();
 312  
     }
 313  
 
 314  
     protected Set<String> getGroups( String path, Set<String> allGroups )
 315  
     {
 316  46
         path = path.substring( 1 ).replace( '/', '.' );
 317  
 
 318  46
         int n = path.length();
 319  
 
 320  46
         Set<String> result = new HashSet<String>();
 321  
 
 322  46
         for ( String group : allGroups )
 323  
         {
 324  828
             if ( group.startsWith( path ) )
 325  
             {
 326  36
                 group = group.substring( n );
 327  
 
 328  36
                 int nextDot = group.indexOf( '.' );
 329  
 
 330  36
                 if ( nextDot > -1 )
 331  
                 {
 332  20
                     group = group.substring( 0, nextDot );
 333  
                 }
 334  
 
 335  36
                 if ( group.length() > 0 && !result.contains( group ) )
 336  
                 {
 337  30
                     result.add( group );
 338  
                 }
 339  828
             }
 340  
         }
 341  
 
 342  46
         return result;
 343  
     }
 344  
 
 345  
     protected IteratorSearchResponse getArtifacts( TreeNode root, TreeViewRequest request )
 346  
         throws IOException
 347  
     {
 348  46
         if ( request.hasFieldHints() )
 349  
         {
 350  0
             return getHintedArtifacts( root, request );
 351  
         }
 352  
 
 353  46
         String path = root.getPath();
 354  
 
 355  46
         IteratorSearchResponse result = null;
 356  
 
 357  46
         String g = null;
 358  
 
 359  46
         String a = null;
 360  
 
 361  46
         String v = null;
 362  
 
 363  
         // "working copy" of path
 364  46
         String wp = null;
 365  
 
 366  
         // remove last / from path
 367  46
         if ( path.endsWith( "/" ) )
 368  
         {
 369  46
             path = path.substring( 0, path.length() - 1 );
 370  
         }
 371  
 
 372  
         // 1st try, let's consider path is a group
 373  
 
 374  
         // reset wp
 375  46
         wp = path;
 376  
 
 377  46
         g = wp.substring( 1 ).replace( '/', '.' );
 378  
 
 379  46
         result = getArtifactsByG( g, request );
 380  
 
 381  46
         if ( result.getTotalHitsCount() > 0 )
 382  
         {
 383  26
             return result;
 384  
         }
 385  
         else
 386  
         {
 387  20
             result.close();
 388  
         }
 389  
 
 390  
         // 2nd try, lets consider path a group + artifactId, we must ensure there is at least one / but not as root
 391  
 
 392  20
         if ( path.lastIndexOf( '/' ) > 0 )
 393  
         {
 394  
             // reset wp
 395  16
             wp = path;
 396  
 
 397  16
             a = wp.substring( wp.lastIndexOf( '/' ) + 1, wp.length() );
 398  
 
 399  16
             g = wp.substring( 1, wp.lastIndexOf( '/' ) ).replace( '/', '.' );
 400  
 
 401  16
             result = getArtifactsByGA( g, a, request );
 402  
 
 403  16
             if ( result.getTotalHitsCount() > 0 )
 404  
             {
 405  1
                 return result;
 406  
             }
 407  
             else
 408  
             {
 409  15
                 result.close();
 410  
             }
 411  
 
 412  
             // 3rd try, let's consider path a group + artifactId + version. There is no 100% way to detect this!
 413  
 
 414  
             try
 415  
             {
 416  
                 // reset wp
 417  15
                 wp = path;
 418  
 
 419  15
                 v = wp.substring( wp.lastIndexOf( '/' ) + 1, wp.length() );
 420  
 
 421  15
                 wp = wp.substring( 0, wp.lastIndexOf( '/' ) );
 422  
 
 423  15
                 a = wp.substring( wp.lastIndexOf( '/' ) + 1, wp.length() );
 424  
 
 425  15
                 g = wp.substring( 1, wp.lastIndexOf( '/' ) ).replace( '/', '.' );
 426  
 
 427  9
                 result = getArtifactsByGAV( g, a, v, request );
 428  
 
 429  9
                 if ( result.getTotalHitsCount() > 0 )
 430  
                 {
 431  1
                     return result;
 432  
                 }
 433  
                 else
 434  
                 {
 435  8
                     result.close();
 436  
                 }
 437  
             }
 438  6
             catch ( StringIndexOutOfBoundsException e )
 439  
             {
 440  
                 // nothing
 441  8
             }
 442  
         }
 443  
 
 444  
         // if we are here, no hits found
 445  18
         return IteratorSearchResponse.empty( result.getQuery() );
 446  
     }
 447  
 
 448  
     protected IteratorSearchResponse getHintedArtifacts( TreeNode root, TreeViewRequest request )
 449  
         throws IOException
 450  
     {
 451  
         // we know that hints are there: G hint, GA hint or GAV hint
 452  0
         if ( request.hasFieldHint( MAVEN.GROUP_ID, MAVEN.ARTIFACT_ID, MAVEN.VERSION ) )
 453  
         {
 454  0
             return getArtifactsByGAV( request.getFieldHint( MAVEN.GROUP_ID ),
 455  
                 request.getFieldHint( MAVEN.ARTIFACT_ID ), request.getFieldHint( MAVEN.VERSION ), request );
 456  
         }
 457  0
         else if ( request.hasFieldHint( MAVEN.GROUP_ID, MAVEN.ARTIFACT_ID ) )
 458  
         {
 459  0
             return getArtifactsByGA( request.getFieldHint( MAVEN.GROUP_ID ), request.getFieldHint( MAVEN.ARTIFACT_ID ),
 460  
                 request );
 461  
         }
 462  0
         else if ( request.hasFieldHint( MAVEN.GROUP_ID ) )
 463  
         {
 464  0
             return getArtifactsByG( request.getFieldHint( MAVEN.GROUP_ID ), request );
 465  
         }
 466  
         else
 467  
         {
 468  
             // if we are here, no hits found or something horribly went wrong?
 469  0
             return IteratorSearchResponse.empty( null );
 470  
         }
 471  
     }
 472  
 
 473  
     protected IteratorSearchResponse getArtifactsByG( String g, TreeViewRequest request )
 474  
         throws IOException
 475  
     {
 476  46
         return getArtifactsByGAVField( g, null, null, request );
 477  
     }
 478  
 
 479  
     protected IteratorSearchResponse getArtifactsByGA( String g, String a, TreeViewRequest request )
 480  
         throws IOException
 481  
     {
 482  16
         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  9
         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  71
         assert g != null;
 495  
 
 496  71
         Query groupIdQ = null;
 497  71
         Query artifactIdQ = null;
 498  71
         Query versionQ = null;
 499  
 
 500  
         // minimum must have
 501  71
         groupIdQ = getNexusIndexer().constructQuery( MAVEN.GROUP_ID, new SourcedSearchExpression( g ) );
 502  
 
 503  71
         if ( StringUtils.isNotBlank( a ) )
 504  
         {
 505  25
             artifactIdQ = getNexusIndexer().constructQuery( MAVEN.ARTIFACT_ID, new SourcedSearchExpression( a ) );
 506  
         }
 507  
 
 508  71
         if ( StringUtils.isNotBlank( v ) )
 509  
         {
 510  9
             versionQ = getNexusIndexer().constructQuery( MAVEN.VERSION, new SourcedSearchExpression( v ) );
 511  
         }
 512  
 
 513  71
         BooleanQuery q = new BooleanQuery();
 514  
 
 515  71
         q.add( new BooleanClause( groupIdQ, BooleanClause.Occur.MUST ) );
 516  
 
 517  71
         if ( artifactIdQ != null )
 518  
         {
 519  25
             q.add( new BooleanClause( artifactIdQ, BooleanClause.Occur.MUST ) );
 520  
         }
 521  
 
 522  71
         if ( versionQ != null )
 523  
         {
 524  9
             q.add( new BooleanClause( versionQ, BooleanClause.Occur.MUST ) );
 525  
         }
 526  
 
 527  71
         IteratorSearchRequest searchRequest = new IteratorSearchRequest( q, request.getArtifactInfoFilter() );
 528  
 
 529  71
         searchRequest.getContexts().add( request.getIndexingContext() );
 530  
 
 531  71
         IteratorSearchResponse result = getNexusIndexer().searchIterator( searchRequest );
 532  
 
 533  71
         return result;
 534  
     }
 535  
 }