Coverage Report - org.apache.maven.index.cli.NexusIndexerCli
 
Classes in this File Line Coverage Branch Coverage Complexity
NexusIndexerCli
84 %
136/161
57 %
31/54
2,75
NexusIndexerCli$1
100 %
2/2
N/A
2,75
NexusIndexerCli$IndexerListener
96 %
31/32
86 %
19/22
2,75
 
 1  
 package org.apache.maven.index.cli;
 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 org.apache.commons.cli.CommandLine;
 23  
 import org.apache.commons.cli.HelpFormatter;
 24  
 import org.apache.commons.cli.OptionBuilder;
 25  
 import org.apache.commons.cli.Options;
 26  
 import org.apache.commons.cli.ParseException;
 27  
 import org.apache.lucene.store.FSDirectory;
 28  
 import org.apache.maven.index.ArtifactContext;
 29  
 import org.apache.maven.index.ArtifactInfo;
 30  
 import org.apache.maven.index.ArtifactScanningListener;
 31  
 import org.apache.maven.index.NexusIndexer;
 32  
 import org.apache.maven.index.ScanningResult;
 33  
 import org.apache.maven.index.context.DefaultIndexingContext;
 34  
 import org.apache.maven.index.context.IndexCreator;
 35  
 import org.apache.maven.index.context.IndexingContext;
 36  
 import org.apache.maven.index.context.UnsupportedExistingLuceneIndexException;
 37  
 import org.apache.maven.index.packer.IndexPacker;
 38  
 import org.apache.maven.index.packer.IndexPackingRequest;
 39  
 import org.apache.maven.index.packer.IndexPackingRequest.IndexFormat;
 40  
 import org.apache.maven.index.updater.DefaultIndexUpdater;
 41  
 import org.codehaus.plexus.PlexusContainer;
 42  
 import org.codehaus.plexus.classworlds.ClassWorld;
 43  
 import org.codehaus.plexus.component.repository.exception.ComponentLookupException;
 44  
 import org.codehaus.plexus.logging.Logger;
 45  
 import org.codehaus.plexus.logging.LoggerManager;
 46  
 import org.codehaus.plexus.tools.cli.AbstractCli;
 47  
 import org.codehaus.plexus.util.IOUtil;
 48  
 
 49  
 import java.io.BufferedInputStream;
 50  
 import java.io.File;
 51  
 import java.io.FileInputStream;
 52  
 import java.io.IOException;
 53  
 import java.lang.reflect.Proxy;
 54  
 import java.util.ArrayList;
 55  
 import java.util.Arrays;
 56  
 import java.util.List;
 57  
 
 58  
 /**
 59  
  * A command line tool that can be used to index local Maven repository.
 60  
  * <p/>
 61  
  * The following command line options are supported:
 62  
  * <ul>
 63  
  * <li>-repository <path> : required path to repository to be indexed</li>
 64  
  * <li>-index <path> : required index folder used to store created index or where previously created index is stored</li>
 65  
  * <li>-name <path> : required repository name/id</li>
 66  
  * <li>-target <path> : optional folder name where to save produced index files</li>
 67  
  * <li>-type <path> : optional indexer types</li>
 68  
  * <li>-format <path> : optional indexer formats</li>
 69  
  * </ul>
 70  
  * When index folder contains previously created index, the tool will use it as a base line and will generate chunks for
 71  
  * the incremental updates.
 72  
  * <p/>
 73  
  * The indexer types could be one of default, min or full. You can also specify list of comma-separated custom index
 74  
  * creators. An index creator should be a regular Plexus component, see {@link org.apache.maven.index.creator.MinimalArtifactInfoIndexCreator} and
 75  
  * {@link org.apache.maven.index.creator.JarFileContentsIndexCreator}.
 76  
  */
 77  10
 public class NexusIndexerCli
 78  
     extends AbstractCli
 79  
 {
 80  
     // Command line options
 81  
 
 82  
     public static final char REPO = 'r';
 83  
 
 84  
     public static final char INDEX = 'i';
 85  
 
 86  
     public static final char NAME = 'n';
 87  
 
 88  
     public static final char TYPE = 't';
 89  
 
 90  
     public static final char TARGET_DIR = 'd';
 91  
 
 92  
     public static final char CREATE_INCREMENTAL_CHUNKS = 'c';
 93  
 
 94  
     public static final char CREATE_FILE_CHECKSUMS = 's';
 95  
 
 96  
     public static final char INCREMENTAL_CHUNK_KEEP_COUNT = 'k';
 97  
 
 98  
     public static final char LEGACY = 'l';
 99  
 
 100  
     public static final char UNPACK = 'u';
 101  
 
 102  
     private static final long MB = 1024 * 1024;
 103  
 
 104  
     private Options options;
 105  
 
 106  10
     private int status = 0;
 107  
 
 108  
     public static void main( String[] args )
 109  
         throws Exception
 110  
     {
 111  0
         NexusIndexerCli cli = new NexusIndexerCli();
 112  
 
 113  0
         cli.execute( args );
 114  
 
 115  0
         System.exit( cli.status );
 116  0
     }
 117  
 
 118  
     @Override
 119  
     public int execute( String[] arg0, ClassWorld arg1 )
 120  
     {
 121  14
         int value = super.execute( arg0, arg1 );
 122  
 
 123  14
         if ( status == 0 )
 124  
         {
 125  8
             status = value;
 126  
         }
 127  
 
 128  14
         return status;
 129  
     }
 130  
 
 131  
     @Override
 132  
     public int execute( String[] args )
 133  
     {
 134  14
         int value = super.execute( args );
 135  
 
 136  14
         if ( status == 0 )
 137  
         {
 138  8
             status = value;
 139  
         }
 140  
 
 141  14
         return status;
 142  
     }
 143  
 
 144  
     @Override
 145  
     protected void showError( String message, Exception e, boolean show )
 146  
     {
 147  1
         status = 1;
 148  1
         super.showError( message, e, show );
 149  1
     }
 150  
 
 151  
     @Override
 152  
     protected int showFatalError( String message, Exception e, boolean show )
 153  
     {
 154  0
         status = 1;
 155  0
         return super.showFatalError( message, e, show );
 156  
     }
 157  
 
 158  
     @Override
 159  
     public CommandLine parse( String[] args )
 160  
         throws ParseException
 161  
     {
 162  
         try
 163  
         {
 164  14
             return super.parse( args );
 165  
         }
 166  4
         catch ( ParseException e )
 167  
         {
 168  4
             status = 1;
 169  4
             throw e;
 170  
         }
 171  
     }
 172  
 
 173  
     @Override
 174  
     public String getPomPropertiesPath()
 175  
     {
 176  1
         return "META-INF/maven/org.sonatype.nexus/nexus-indexer/pom.properties";
 177  
     }
 178  
 
 179  
     @Override
 180  
     @SuppressWarnings( "static-access" )
 181  
     public Options buildCliOptions( Options options )
 182  
     {
 183  14
         this.options = options;
 184  
 
 185  14
         options.addOption( OptionBuilder.withLongOpt( "index" ).hasArg() //
 186  
                                .withDescription( "Path to the index folder." ).create( INDEX ) );
 187  
 
 188  14
         options.addOption( OptionBuilder.withLongOpt( "destination" ).hasArg() //
 189  
                                .withDescription( "Target folder." ).create( TARGET_DIR ) );
 190  
 
 191  14
         options.addOption( OptionBuilder.withLongOpt( "repository" ).hasArg() //
 192  
                                .withDescription( "Path to the Maven repository." ).create( REPO ) );
 193  
 
 194  14
         options.addOption( OptionBuilder.withLongOpt( "name" ).hasArg() //
 195  
                                .withDescription( "Repository name." ).create( NAME ) );
 196  
 
 197  14
         options.addOption( OptionBuilder.withLongOpt( "chunks" ) //
 198  
                                .withDescription( "Create incremental chunks." ).create( CREATE_INCREMENTAL_CHUNKS ) );
 199  
 
 200  14
         options.addOption( OptionBuilder.withLongOpt( "keep" ).hasArg().withDescription(
 201  
             "Number of incremental chunks to keep." ).create( INCREMENTAL_CHUNK_KEEP_COUNT ) );
 202  
 
 203  14
         options.addOption( OptionBuilder.withLongOpt( "checksums" ) //
 204  
                                .withDescription( "Create checksums for all files (sha1, md5)." ).create(
 205  
                 CREATE_FILE_CHECKSUMS ) );
 206  
 
 207  14
         options.addOption( OptionBuilder.withLongOpt( "type" ).hasArg() //
 208  
                                .withDescription(
 209  
                                    "Indexer type (default, min, full or coma separated list of custom types)." ).create(
 210  
                 TYPE ) );
 211  
 
 212  14
         options.addOption( OptionBuilder.withLongOpt( "legacy" ) //
 213  
                                .withDescription( "Build legacy .zip index file" ).create( LEGACY ) );
 214  
 
 215  14
         options.addOption( OptionBuilder.withLongOpt( "unpack" ) //
 216  
                                .withDescription( "Unpack an index file" ).create( UNPACK ) );
 217  
 
 218  14
         return options;
 219  
     }
 220  
 
 221  
     @Override
 222  
     public void displayHelp()
 223  
     {
 224  5
         System.out.println();
 225  
 
 226  5
         HelpFormatter formatter = new HelpFormatter();
 227  
 
 228  5
         formatter.printHelp( "nexus-indexer [options]", "\nOptions:", options, "\n" );
 229  5
     }
 230  
 
 231  
     public void displayHelp( String message )
 232  
     {
 233  1
         System.out.println();
 234  
 
 235  1
         System.out.println( message );
 236  
 
 237  1
         System.out.println();
 238  
 
 239  1
         displayHelp();
 240  1
     }
 241  
 
 242  
     @Override
 243  
     public void invokePlexusComponent( final CommandLine cli, PlexusContainer plexus )
 244  
         throws Exception
 245  
     {
 246  10
         if ( cli.hasOption( QUIET ) )
 247  
         {
 248  1
             setLogLevel( plexus, Logger.LEVEL_DISABLED );
 249  
         }
 250  9
         else if ( cli.hasOption( DEBUG ) )
 251  
         {
 252  1
             setLogLevel( plexus, Logger.LEVEL_DEBUG );
 253  
         }
 254  8
         else if ( cli.hasOption( ERRORS ) )
 255  
         {
 256  1
             setLogLevel( plexus, Logger.LEVEL_ERROR );
 257  
         }
 258  
 
 259  10
         if ( cli.hasOption( UNPACK ) )
 260  
         {
 261  1
             unpack( cli, plexus );
 262  
         }
 263  9
         else if ( cli.hasOption( INDEX ) && cli.hasOption( REPO ) )
 264  
         {
 265  8
             index( cli, plexus );
 266  
         }
 267  
         else
 268  
         {
 269  1
             status = 1;
 270  
 
 271  1
             displayHelp( "Use either unpack (\"" + UNPACK + "\") or index (\"" + INDEX + "\" and \"" + REPO
 272  
                              + "\") options, but none has been found!" );
 273  
         }
 274  9
     }
 275  
 
 276  
     private void setLogLevel( PlexusContainer plexus, int logLevel )
 277  
         throws ComponentLookupException
 278  
     {
 279  3
         plexus.lookup( LoggerManager.class ).setThresholds( logLevel );
 280  3
     }
 281  
 
 282  
     private void index( final CommandLine cli, PlexusContainer plexus )
 283  
         throws ComponentLookupException, IOException, UnsupportedExistingLuceneIndexException
 284  
     {
 285  8
         String indexDirectoryName = cli.getOptionValue( INDEX );
 286  
 
 287  8
         File indexFolder = new File( indexDirectoryName );
 288  
 
 289  8
         String outputDirectoryName = cli.getOptionValue( TARGET_DIR, "." );
 290  
 
 291  8
         File outputFolder = new File( outputDirectoryName );
 292  
 
 293  8
         File repositoryFolder = new File( cli.getOptionValue( REPO ) );
 294  
 
 295  8
         String repositoryName = cli.getOptionValue( NAME, indexFolder.getName() );
 296  
 
 297  8
         List<IndexCreator> indexers = getIndexers( cli, plexus );
 298  
 
 299  8
         boolean createChecksums = cli.hasOption( CREATE_FILE_CHECKSUMS );
 300  
 
 301  8
         boolean createIncrementalChunks = cli.hasOption( CREATE_INCREMENTAL_CHUNKS );
 302  
 
 303  8
         boolean createLegacyIndex = cli.hasOption( LEGACY );
 304  
 
 305  8
         boolean debug = cli.hasOption( DEBUG );
 306  
 
 307  8
         boolean quiet = cli.hasOption( QUIET );
 308  
 
 309  8
         Integer chunkCount = cli.hasOption( INCREMENTAL_CHUNK_KEEP_COUNT ) ? Integer.parseInt(
 310  
             cli.getOptionValue( INCREMENTAL_CHUNK_KEEP_COUNT ) ) : null;
 311  
 
 312  8
         if ( !quiet )
 313  
         {
 314  7
             System.err.printf( "Repository Folder: %s\n", repositoryFolder.getAbsolutePath() );
 315  7
             System.err.printf( "Index Folder:      %s\n", indexFolder.getAbsolutePath() );
 316  7
             System.err.printf( "Output Folder:     %s\n", outputFolder.getAbsolutePath() );
 317  7
             System.err.printf( "Repository name:   %s\n", repositoryName );
 318  7
             System.err.printf( "Indexers: %s\n", indexers.toString() );
 319  
 
 320  7
             if ( createChecksums )
 321  
             {
 322  0
                 System.err.printf( "Will create checksum files for all published files (sha1, md5).\n" );
 323  
             }
 324  
             else
 325  
             {
 326  7
                 System.err.printf( "Will not create checksum files.\n" );
 327  
             }
 328  
 
 329  7
             if ( createIncrementalChunks )
 330  
             {
 331  0
                 System.err.printf( "Will create incremental chunks for changes, along with baseline file.\n" );
 332  
             }
 333  
             else
 334  
             {
 335  7
                 System.err.printf( "Will create baseline file.\n" );
 336  
             }
 337  
 
 338  7
             if ( createLegacyIndex )
 339  
             {
 340  0
                 System.err.printf( "Will also create legacy .zip index file.\n" );
 341  
             }
 342  
         }
 343  
 
 344  8
         NexusIndexer indexer = plexus.lookup( NexusIndexer.class );
 345  
         // this is a CLI/batch invocation, don't coggle it with threads
 346  8
         DefaultIndexingContext.BLOCKING_COMMIT = true;
 347  
 
 348  8
             long tstart = System.currentTimeMillis();
 349  
 
 350  8
         IndexingContext context = indexer.addIndexingContext( //
 351  
                                                   repositoryName, // context id
 352  
                                                   repositoryName, // repository id
 353  
                                                   repositoryFolder, // repository folder
 354  
                                                   indexFolder, // index folder
 355  
                                                   null, // repositoryUrl
 356  
                                                   null, // index update url
 357  
                                                   indexers );
 358  
 
 359  
         try
 360  
         {
 361  8
             IndexPacker packer = plexus.lookup( IndexPacker.class );
 362  
 
 363  8
             ArtifactScanningListener listener = new IndexerListener( context, debug, quiet );
 364  
 
 365  8
             indexer.scan( context, listener, true );
 366  
 
 367  7
             IndexPackingRequest request = new IndexPackingRequest( context, outputFolder );
 368  
 
 369  7
             request.setCreateChecksumFiles( createChecksums );
 370  
 
 371  7
             request.setCreateIncrementalChunks( createIncrementalChunks );
 372  
 
 373  7
             if ( createLegacyIndex )
 374  
             {
 375  0
                 request.setFormats( Arrays.asList( IndexFormat.FORMAT_LEGACY, IndexFormat.FORMAT_V1 ) );
 376  
             }
 377  
             else
 378  
             {
 379  7
                 request.setFormats( Arrays.asList( IndexFormat.FORMAT_V1 ) );
 380  
             }
 381  
 
 382  7
             if ( chunkCount != null )
 383  
             {
 384  0
                 request.setMaxIndexChunks( chunkCount.intValue() );
 385  
             }
 386  
 
 387  7
             packIndex( packer, request, debug, quiet );
 388  
 
 389  7
             if ( !quiet )
 390  
             {
 391  6
                 printStats( tstart );
 392  
             }
 393  
         }
 394  
         finally
 395  
         {
 396  8
             indexer.removeIndexingContext( context, false );
 397  7
         }
 398  7
     }
 399  
 
 400  
     private void unpack( CommandLine cli, PlexusContainer plexus )
 401  
         throws ComponentLookupException, IOException
 402  
     {
 403  1
         final String indexDirectoryName = cli.getOptionValue( INDEX, "." );
 404  1
         final File indexFolder = new File( indexDirectoryName ).getCanonicalFile();
 405  1
         final File indexArchive = new File( indexFolder, IndexingContext.INDEX_FILE_PREFIX + ".gz" );
 406  
 
 407  1
         final String outputDirectoryName = cli.getOptionValue( TARGET_DIR, "." );
 408  1
         final File outputFolder = new File( outputDirectoryName ).getCanonicalFile();
 409  
 
 410  1
         final boolean quiet = cli.hasOption( QUIET );
 411  1
         if ( !quiet )
 412  
         {
 413  1
             System.err.printf( "Index Folder:      %s\n", indexFolder.getAbsolutePath() );
 414  1
             System.err.printf( "Output Folder:     %s\n", outputFolder.getAbsolutePath() );
 415  
         }
 416  
 
 417  1
         long tstart = System.currentTimeMillis();
 418  
 
 419  1
         final FSDirectory directory = FSDirectory.open( outputFolder );
 420  
 
 421  1
         final List<IndexCreator> indexers = getIndexers( cli, plexus );
 422  
 
 423  1
         BufferedInputStream is = null;
 424  
         try
 425  
         {
 426  1
             is = new BufferedInputStream( new FileInputStream( indexArchive ) );
 427  1
             DefaultIndexUpdater.unpackIndexData( is, directory,
 428  
                                                  (IndexingContext) Proxy.newProxyInstance( getClass().getClassLoader(),
 429  
                                                                                            new Class[]{
 430  
                                                                                                IndexingContext.class },
 431  
                                                                                            new PartialImplementation()
 432  1
                                                                                            {
 433  
                                                                                                public List<IndexCreator> getIndexCreators()
 434  
                                                                                                {
 435  98
                                                                                                    return indexers;
 436  
                                                                                                }
 437  
                                                                                            } )
 438  
 
 439  
             );
 440  
         }
 441  
         finally
 442  
         {
 443  1
             IOUtil.close( is );
 444  1
             if ( directory != null )
 445  
             {
 446  1
                 directory.close();
 447  
             }
 448  
         }
 449  
 
 450  1
         if ( !quiet )
 451  
         {
 452  1
             printStats( tstart );
 453  
         }
 454  1
     }
 455  
 
 456  
     private List<IndexCreator> getIndexers( final CommandLine cli, PlexusContainer plexus )
 457  
         throws ComponentLookupException
 458  
     {
 459  9
         String type = "default";
 460  
 
 461  9
         if ( cli.hasOption( TYPE ) )
 462  
         {
 463  0
             type = cli.getOptionValue( TYPE );
 464  
         }
 465  
 
 466  9
         List<IndexCreator> indexers = new ArrayList<IndexCreator>(); // NexusIndexer.DEFAULT_INDEX;
 467  
 
 468  9
         if ( "default".equals( type ) )
 469  
         {
 470  9
             indexers.add( plexus.lookup( IndexCreator.class, "min" ) );
 471  9
             indexers.add( plexus.lookup( IndexCreator.class, "jarContent" ) );
 472  
         }
 473  0
         else if ( "full".equals( type ) )
 474  
         {
 475  0
             for ( Object component : plexus.lookupList( IndexCreator.class ) )
 476  
             {
 477  0
                 indexers.add( (IndexCreator) component );
 478  
             }
 479  
         }
 480  
         else
 481  
         {
 482  0
             for ( String hint : type.split( "," ) )
 483  
             {
 484  0
                 indexers.add( plexus.lookup( IndexCreator.class, hint ) );
 485  
             }
 486  
         }
 487  9
         return indexers;
 488  
     }
 489  
 
 490  
     private void packIndex( IndexPacker packer, IndexPackingRequest request, boolean debug, boolean quiet )
 491  
     {
 492  
         try
 493  
         {
 494  7
             packer.packIndex( request );
 495  
         }
 496  0
         catch ( IOException e )
 497  
         {
 498  0
             if ( !quiet )
 499  
             {
 500  0
                 System.err.printf( "Cannot zip index; \n", e.getMessage() );
 501  
 
 502  0
                 if ( debug )
 503  
                 {
 504  0
                     e.printStackTrace();
 505  
                 }
 506  
             }
 507  7
         }
 508  7
     }
 509  
 
 510  
     private void printStats( final long startTimeInMillis )
 511  
     {
 512  7
         long t = System.currentTimeMillis() - startTimeInMillis;
 513  
 
 514  7
         long s = t / 1000L;
 515  7
         if ( t > 60 * 1000 )
 516  
         {
 517  0
             long m = t / 1000L / 60L;
 518  
 
 519  0
             System.err.printf( "Total time:   %d min %d sec\n", m, s - ( m * 60 ) );
 520  0
         }
 521  
         else
 522  
         {
 523  7
             System.err.printf( "Total time:   %d sec\n", s );
 524  
         }
 525  
 
 526  7
         Runtime r = Runtime.getRuntime();
 527  
 
 528  7
         System.err.printf( "Final memory: %dM/%dM\n", //
 529  
                            ( r.totalMemory() - r.freeMemory() ) / MB, r.totalMemory() / MB );
 530  7
     }
 531  
 
 532  
     /**
 533  
      * Scanner listener
 534  
      */
 535  10
     private static final class IndexerListener
 536  
         implements ArtifactScanningListener
 537  
     {
 538  
         private final IndexingContext context;
 539  
 
 540  
         private final boolean debug;
 541  
 
 542  
         private boolean quiet;
 543  
 
 544  8
         private long ts = System.currentTimeMillis();
 545  
 
 546  
         private int count;
 547  
 
 548  
         IndexerListener( IndexingContext context, boolean debug, boolean quiet )
 549  8
         {
 550  8
             this.context = context;
 551  8
             this.debug = debug;
 552  8
             this.quiet = quiet;
 553  8
         }
 554  
 
 555  
         public void scanningStarted( IndexingContext context )
 556  
         {
 557  7
             if ( !quiet )
 558  
             {
 559  6
                 System.err.println( "Scanning started" );
 560  
             }
 561  7
         }
 562  
 
 563  
         public void artifactDiscovered( ArtifactContext ac )
 564  
         {
 565  343
             count++;
 566  
 
 567  343
             long t = System.currentTimeMillis();
 568  
 
 569  343
             ArtifactInfo ai = ac.getArtifactInfo();
 570  
 
 571  343
             if ( !quiet && debug && "maven-plugin".equals( ai.packaging ) )
 572  
             {
 573  0
                 System.err.printf( "Plugin: %s:%s:%s - %s %s\n", //
 574  
                                    ai.groupId, ai.artifactId, ai.version, ai.prefix, "" + ai.goals );
 575  
             }
 576  
 
 577  343
             if ( !quiet && ( debug || ( t - ts ) > 2000L ) )
 578  
             {
 579  49
                 System.err.printf( "  %6d %s\n", count, formatFile( ac.getPom() ) );
 580  49
                 ts = t;
 581  
             }
 582  343
         }
 583  
 
 584  
         public void artifactError( ArtifactContext ac, Exception e )
 585  
         {
 586  7
             if ( !quiet )
 587  
             {
 588  6
                 System.err.printf( "! %6d %s - %s\n", count, formatFile( ac.getPom() ), e.getMessage() );
 589  
 
 590  6
                 System.err.printf( "         %s\n", formatFile( ac.getArtifact() ) );
 591  
 
 592  6
                 if ( debug )
 593  
                 {
 594  1
                     e.printStackTrace();
 595  
                 }
 596  
             }
 597  
 
 598  7
             ts = System.currentTimeMillis();
 599  7
         }
 600  
 
 601  
         private String formatFile( File file )
 602  
         {
 603  61
             return file.getAbsolutePath().substring( context.getRepository().getAbsolutePath().length() + 1 );
 604  
         }
 605  
 
 606  
         public void scanningFinished( IndexingContext context, ScanningResult result )
 607  
         {
 608  7
             if ( !quiet )
 609  
             {
 610  6
                 if ( result.hasExceptions() )
 611  
                 {
 612  6
                     System.err.printf( "Scanning errors:   %s\n", result.getExceptions().size() );
 613  
                 }
 614  
 
 615  6
                 System.err.printf( "Artifacts added:   %s\n", result.getTotalFiles() );
 616  6
                 System.err.printf( "Artifacts deleted: %s\n", result.getDeletedFiles() );
 617  
             }
 618  7
         }
 619  
     }
 620  
 
 621  
 }