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