@Override public AnalysisResultFuture run(final AnalysisJob job) { final Queue<JobAndResult> resultQueue = new LinkedBlockingQueue<>(); // This analysis listener will keep track of all collected errors final ErrorAwareAnalysisListener errorListener = new ErrorAwareAnalysisListener(); // This analysis listener is a composite for all other listeners final CompositeAnalysisListener analysisListener = new CompositeAnalysisListener(errorListener, _sharedAnalysisListeners); if (DebugLoggingAnalysisListener.isEnabled()) { // enable debug logging? analysisListener.addDelegate(new DebugLoggingAnalysisListener()); } else if (InfoLoggingAnalysisListener.isEnabled()) { analysisListener.addDelegate(new InfoLoggingAnalysisListener()); } // set up the task runner that is aware of errors final TaskRunner taskRunner = new ErrorAwareTaskRunnerWrapper(errorListener, _configuration.getEnvironment().getTaskRunner()); final boolean includedNonDistributed = isNonDistributedTasksIncluded(); // the delegate will do all the actual work final AnalysisRunnerJobDelegate delegate = new AnalysisRunnerJobDelegate(job, _configuration, taskRunner, analysisListener, resultQueue, errorListener, includedNonDistributed); return delegate.run(); }