@ Override public ScanResult call ( ) throws InterruptedException , CancellationException , ExecutionException { ScanResult scanResult = null ; Exception exception = null ; final long scanStart = System . currentTimeMillis ( ) ; try { // Perform the scan scanResult = openClasspathElementsThenScan ( ) ; // Log total time after scan completes, and flush log if ( topLevelLog != null ) { topLevelLog . log ( "~" , String . format ( "Total time: %.3f sec" , ( System . currentTimeMillis ( ) - scanStart ) * .001 ) ) ; topLevelLog . flush ( ) ; } // Call the ScanResultProcessor, if one was provided if ( scanResultProcessor != null ) { try { scanResultProcessor . processScanResult ( scanResult ) ; } finally { scanResult . close ( ) ; } } } catch ( final InterruptedException e ) { if ( topLevelLog != null ) { topLevelLog . log ( "~" , "Scan interrupted" ) ; } exception = e ; interruptionChecker . interrupt ( ) ; if ( failureHandler == null ) { // Re-throw throw e ; } } catch ( final CancellationException e ) { if ( topLevelLog != null ) { topLevelLog . log ( "~" , "Scan cancelled" ) ; } exception = e ; if ( failureHandler == null ) { // Re-throw throw e ; } } catch ( final ExecutionException e ) { if ( topLevelLog != null ) { topLevelLog . log ( "~" , "Uncaught exception during scan" , InterruptionChecker . getCause ( e ) ) ; } exception = e ; if ( failureHandler == null ) { // Re-throw throw e ; } } catch ( final RuntimeException e ) { if ( topLevelLog != null ) { topLevelLog . log ( "~" , "Uncaught exception during scan" , e ) ; } exception = e ; if ( failureHandler == null ) { // Wrap unchecked exceptions in a new ExecutionException throw new ExecutionException ( "Exception while scanning" , e ) ; } } finally { if ( exception != null || scanSpec . removeTemporaryFilesAfterScan ) { // If an exception was thrown or removeTemporaryFilesAfterScan was set, remove temporary files // and close resources, zipfiles, and modules nestedJarHandler . close ( topLevelLog ) ; } } if ( exception != null ) { // If an exception was thrown, log the cause, and flush the toplevel log if ( topLevelLog != null ) { final Throwable cause = InterruptionChecker . getCause ( exception ) ; topLevelLog . log ( "~" , "An uncaught exception was thrown:" , cause ) ; topLevelLog . flush ( ) ; } // If exception is null, then failureHandler must be non-null at this point try { // Call the FailureHandler failureHandler . onFailure ( exception ) ; } catch ( final Exception f ) { // The failure handler failed if ( topLevelLog != null ) { topLevelLog . log ( "~" , "The failure handler threw an exception:" , f ) ; } // Group the two exceptions into one, using the suppressed exception mechanism // to show the scan exception below the failure handler exception final ExecutionException failureHandlerException = new ExecutionException ( "Exception while calling failure handler" , f ) ; failureHandlerException . addSuppressed ( exception ) ; // Throw a new ExecutionException (although this will probably be ignored, // since any job with a FailureHandler was started with ExecutorService::execute // rather than ExecutorService::submit) throw failureHandlerException ; } } return scanResult ; }
Determine the unique ordered classpath elements and run a scan looking for file or classfile matches if necessary .