View Javadoc
1   package org.apache.maven.lifecycle.internal.builder.multithreaded;
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.maven.execution.ProjectDependencyGraph;
23  import org.apache.maven.lifecycle.internal.ProjectBuildList;
24  import org.apache.maven.lifecycle.internal.ProjectSegment;
25  import org.apache.maven.project.MavenProject;
26  
27  import java.util.ArrayList;
28  import java.util.HashSet;
29  import java.util.List;
30  import java.util.Set;
31  
32  /**
33   * Presents a view of the Dependency Graph that is suited for concurrent building.
34   *
35   * @since 3.0
36   * @author Kristian Rosenvold
37   *         <p/>
38   *         NOTE: This class is not part of any public api and can be changed or deleted without prior notice.
39   */
40  public class ConcurrencyDependencyGraph
41  {
42  
43      private final ProjectBuildList projectBuilds;
44  
45      private final ProjectDependencyGraph projectDependencyGraph;
46  
47      private final HashSet<MavenProject> finishedProjects = new HashSet<>();
48  
49      public ConcurrencyDependencyGraph( ProjectBuildList projectBuilds, ProjectDependencyGraph projectDependencyGraph )
50      {
51          this.projectDependencyGraph = projectDependencyGraph;
52          this.projectBuilds = projectBuilds;
53      }
54  
55      public int getNumberOfBuilds()
56      {
57          return projectBuilds.size();
58      }
59  
60      /**
61       * Gets all the builds that have no reactor-dependencies
62       *
63       * @return A list of all the initial builds
64       */
65  
66      public List<MavenProject> getRootSchedulableBuilds()
67      {
68          List<MavenProject> result = new ArrayList<>();
69          for ( ProjectSegment projectBuild : projectBuilds )
70          {
71              if ( projectDependencyGraph.getUpstreamProjects( projectBuild.getProject(), false ).size() == 0 )
72              {
73                  result.add( projectBuild.getProject() );
74              }
75          }
76          return result;
77      }
78  
79      /**
80       * Marks the provided project as finished. Returns a list of
81       *
82       * @param mavenProject The project
83       * @return The list of builds that are eligible for starting now that the provided project is done
84       */
85      public List<MavenProject> markAsFinished( MavenProject mavenProject )
86      {
87          finishedProjects.add( mavenProject );
88          return getSchedulableNewProcesses( mavenProject );
89      }
90  
91      private List<MavenProject> getSchedulableNewProcesses( MavenProject finishedProject )
92      {
93          List<MavenProject> result = new ArrayList<>();
94          // schedule dependent projects, if all of their requirements are met
95          for ( MavenProject dependentProject : projectDependencyGraph.getDownstreamProjects( finishedProject, false ) )
96          {
97              final List<MavenProject> upstreamProjects =
98                  projectDependencyGraph.getUpstreamProjects( dependentProject, false );
99              if ( finishedProjects.containsAll( upstreamProjects ) )
100             {
101                 result.add( dependentProject );
102             }
103         }
104         return result;
105     }
106 
107     /**
108      * @return set of projects that have yet to be processed successfully by the build.
109      */
110     public Set<MavenProject> getUnfinishedProjects()
111     {
112         Set<MavenProject> unfinished = new HashSet<>( projectBuilds.getProjects() );
113         unfinished.remove( finishedProjects );
114         return unfinished;
115     }
116 
117     /**
118      * @return set of projects that have been successfully processed by the build.
119      */
120     protected Set<MavenProject> getFinishedProjects()
121     {
122         return finishedProjects;
123     }
124 
125     protected ProjectBuildList getProjectBuilds()
126     {
127         return projectBuilds;
128     }
129 
130     /**
131      * For the given {@link MavenProject} {@code p}, return all of {@code p}'s dependencies.
132      *
133      * @param p
134      * @return List of prerequisite projects
135      */
136     protected List<MavenProject> getDependencies( MavenProject p )
137     {
138         return projectDependencyGraph.getUpstreamProjects( p, false );
139     }
140 
141     /**
142      * For the given {@link MavenProject} {@code p} return {@code p}'s uncompleted dependencies.
143      *
144      * @param p
145      * @return List of uncompleted prerequisite projects
146      */
147     public List<MavenProject> getActiveDependencies( MavenProject p )
148     {
149         List<MavenProject> activeDependencies = projectDependencyGraph.getUpstreamProjects( p, false );
150         activeDependencies.removeAll( finishedProjects );
151         return activeDependencies;
152     }
153 }