/**
  * Logic is more-or-less copied from {@link
  * DefaultMatrixExecutionStrategyImpl#notifyStartBuild(java.util.List)}
  *
  * <p>Triggers the startBuild event on all aggregators. This should be called before any run is
  * started.
  *
  * @param aggregators The aggregators to be notified.
  * @param listener Listener from parent build that can be logged to.
  * @return True if all aggregators return true. If any aggregator returns false, false is
  *     immediately returned and no new aggregators are called.
  * @throws IOException
  * @throws InterruptedException
  */
 private boolean notifyStartBuild(List<MatrixAggregator> aggregators, BuildListener listener)
     throws IOException, InterruptedException {
   for (MatrixAggregator aggregator : aggregators) {
     if (!aggregator.startBuild()) {
       listener.error("Aggregator terminated build: " + aggregator.toString());
       return false;
     }
   }
   return true;
 }
 /**
  * Logic is copied from {@link
  * DefaultMatrixExecutionStrategyImpl#notifyEndBuild(hudson.matrix.MatrixRun, java.util.List)}
  */
 private void notifyEndRun(
     MatrixRun run, List<MatrixAggregator> aggregators, BuildListener listener)
     throws InterruptedException, IOException {
   if (run == null)
     return; // can happen if the configuration run gets cancelled before it gets started.
   for (MatrixAggregator aggregator : aggregators) {
     if (!aggregator.endRun(run)) {
       listener.error("Aggregator terminated build: " + aggregator.toString());
       throw new AbortException();
     }
   }
 }