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