View Javadoc
1   /*
2    * Licensed to the Apache Software Foundation (ASF) under one
3    * or more contributor license agreements.  See the NOTICE file
4    * distributed with this work for additional information
5    * regarding copyright ownership.  The ASF licenses this file
6    * to you under the Apache License, Version 2.0 (the
7    * "License"); you may not use this file except in compliance
8    * with the License.  You may obtain a copy of the License at
9    *
10   *   http://www.apache.org/licenses/LICENSE-2.0
11   *
12   * Unless required by applicable law or agreed to in writing,
13   * software distributed under the License is distributed on an
14   * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
15   * KIND, either express or implied.  See the License for the
16   * specific language governing permissions and limitations
17   * under the License.
18   */
19  package org.apache.maven.plugins.invoker;
20  
21  /*
22   * Licensed to the Apache Software Foundation (ASF) under one
23   * or more contributor license agreements.  See the NOTICE file
24   * distributed with this work for additional information
25   * regarding copyright ownership.  The ASF licenses this file
26   * to you under the Apache License, Version 2.0 (the
27   * "License"); you may not use this file except in compliance
28   * with the License.  You may obtain a copy of the License at
29   *
30   *  http://www.apache.org/licenses/LICENSE-2.0
31   *
32   * Unless required by applicable law or agreed to in writing,
33   * software distributed under the License is distributed on an
34   * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
35   * KIND, either express or implied.  See the License for the
36   * specific language governing permissions and limitations
37   * under the License.
38   */
39  
40  import java.util.LinkedHashMap;
41  import java.util.List;
42  import java.util.Map;
43  import java.util.concurrent.Callable;
44  import java.util.concurrent.ExecutorService;
45  import java.util.concurrent.Executors;
46  import java.util.stream.Collectors;
47  
48  import org.apache.maven.plugins.invoker.model.BuildJob;
49  
50  /**
51   * Execute build jobs with parallel.
52   *
53   * @author Slawomir Jaranowski
54   */
55  class JobExecutor {
56      interface ThrowableJobConsumer {
57          void accept(BuildJob t) throws Throwable;
58      }
59  
60      private final List<BuildJob> jobs;
61      private final int threadsCount;
62  
63      JobExecutor(List<BuildJob> jobs, int threadsCount) {
64          this.jobs = jobs;
65          this.threadsCount = threadsCount;
66      }
67  
68      public void forEach(ThrowableJobConsumer jobConsumer) {
69          // group and sort jobs by ordinal
70          Map<Integer, List<BuildJob>> groupedJobs = jobs.stream()
71                  .sorted((j1, j2) -> Integer.compare(j2.getOrdinal(), j1.getOrdinal()))
72                  .collect(Collectors.groupingBy(BuildJob::getOrdinal, LinkedHashMap::new, Collectors.toList()));
73  
74          ExecutorService executorService = Executors.newFixedThreadPool(threadsCount);
75  
76          groupedJobs.forEach((key, value) -> {
77              // prepare list of callable tasks
78              List<Callable<Void>> callableJobs = value.stream()
79                      .map(buildJob -> (Callable<Void>) () -> {
80                          try {
81                              jobConsumer.accept(buildJob);
82                          } catch (Throwable e) {
83                              buildJob.setResult(BuildJob.Result.ERROR);
84                              buildJob.setFailureMessage(String.valueOf(e));
85                          }
86                          return null;
87                      })
88                      .collect(Collectors.toList());
89  
90              try {
91                  executorService.invokeAll(callableJobs);
92              } catch (InterruptedException e) {
93                  Thread.currentThread().interrupt();
94                  throw new RuntimeException(e);
95              }
96          });
97  
98          // all task are finished here
99          executorService.shutdownNow();
100     }
101 }