1 package org.apache.maven.project;
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22 import org.apache.maven.artifact.ArtifactUtils;
23 import org.apache.maven.model.Dependency;
24 import org.apache.maven.model.Extension;
25 import org.apache.maven.model.Plugin;
26 import org.apache.maven.model.ReportPlugin;
27 import org.codehaus.plexus.util.dag.CycleDetectedException;
28 import org.codehaus.plexus.util.dag.DAG;
29 import org.codehaus.plexus.util.dag.TopologicalSorter;
30
31 import java.util.ArrayList;
32 import java.util.Collections;
33 import java.util.HashMap;
34 import java.util.Iterator;
35 import java.util.List;
36 import java.util.Map;
37
38
39
40
41
42
43
44 public class ProjectSorter
45 {
46 private final DAG dag;
47
48 private final List sortedProjects;
49
50 private MavenProject topLevelProject;
51
52
53
54
55
56
57
58
59
60
61
62
63
64 public ProjectSorter( List projects )
65 throws CycleDetectedException, DuplicateProjectException
66 {
67 dag = new DAG();
68
69 Map projectMap = new HashMap();
70
71 for ( Iterator i = projects.iterator(); i.hasNext(); )
72 {
73 MavenProject project = (MavenProject) i.next();
74
75 String id = ArtifactUtils.versionlessKey( project.getGroupId(), project.getArtifactId() );
76
77 if ( dag.getVertex( id ) != null )
78 {
79 throw new DuplicateProjectException( "Project '" + id + "' is duplicated in the reactor" );
80 }
81
82 dag.addVertex( id );
83
84 projectMap.put( id, project );
85 }
86
87 for ( Iterator i = projects.iterator(); i.hasNext(); )
88 {
89 MavenProject project = (MavenProject) i.next();
90
91 String id = ArtifactUtils.versionlessKey( project.getGroupId(), project.getArtifactId() );
92
93 for ( Iterator j = project.getDependencies().iterator(); j.hasNext(); )
94 {
95 Dependency dependency = (Dependency) j.next();
96
97 String dependencyId = ArtifactUtils
98 .versionlessKey( dependency.getGroupId(), dependency.getArtifactId() );
99
100 if ( dag.getVertex( dependencyId ) != null )
101 {
102 project.addProjectReference( (MavenProject) projectMap.get( dependencyId ) );
103
104 dag.addEdge( id, dependencyId );
105 }
106 }
107
108 MavenProject parent = project.getParent();
109 if ( parent != null )
110 {
111 String parentId = ArtifactUtils.versionlessKey( parent.getGroupId(), parent.getArtifactId() );
112 if ( dag.getVertex( parentId ) != null )
113 {
114
115 if ( dag.hasEdge( parentId, id ) )
116 {
117 dag.removeEdge( parentId, id );
118 }
119 dag.addEdge( id, parentId );
120 }
121 }
122
123 List buildPlugins = project.getBuildPlugins();
124 if ( buildPlugins != null )
125 {
126 for ( Iterator j = buildPlugins.iterator(); j.hasNext(); )
127 {
128 Plugin plugin = (Plugin) j.next();
129 String pluginId = ArtifactUtils.versionlessKey( plugin.getGroupId(), plugin.getArtifactId() );
130 if ( dag.getVertex( pluginId ) != null && !pluginId.equals( id ) )
131 {
132 addEdgeWithParentCheck( projectMap, pluginId, project, id );
133 }
134 }
135 }
136
137 List reportPlugins = project.getReportPlugins();
138 if ( reportPlugins != null )
139 {
140 for ( Iterator j = reportPlugins.iterator(); j.hasNext(); )
141 {
142 ReportPlugin plugin = (ReportPlugin) j.next();
143 String pluginId = ArtifactUtils.versionlessKey( plugin.getGroupId(), plugin.getArtifactId() );
144 if ( dag.getVertex( pluginId ) != null && !pluginId.equals( id ) )
145 {
146 addEdgeWithParentCheck( projectMap, pluginId, project, id );
147 }
148 }
149 }
150
151 for ( Iterator j = project.getBuildExtensions().iterator(); j.hasNext(); )
152 {
153 Extension extension = (Extension) j.next();
154 String extensionId = ArtifactUtils.versionlessKey( extension.getGroupId(), extension.getArtifactId() );
155 if ( dag.getVertex( extensionId ) != null )
156 {
157 addEdgeWithParentCheck( projectMap, extensionId, project, id );
158 }
159 }
160 }
161
162 List sortedProjects = new ArrayList();
163
164 for ( Iterator i = TopologicalSorter.sort( dag ).iterator(); i.hasNext(); )
165 {
166 String id = (String) i.next();
167
168 sortedProjects.add( projectMap.get( id ) );
169 }
170
171 this.sortedProjects = Collections.unmodifiableList( sortedProjects );
172 }
173
174 private void addEdgeWithParentCheck( Map projectMap, String projectRefId, MavenProject project, String id )
175 throws CycleDetectedException
176 {
177 MavenProject extProject = (MavenProject) projectMap.get( projectRefId );
178
179 if ( extProject == null )
180 {
181 return;
182 }
183
184 project.addProjectReference( extProject );
185
186 MavenProject extParent = extProject.getParent();
187 if ( extParent != null )
188 {
189 String parentId = ArtifactUtils.versionlessKey( extParent.getGroupId(), extParent.getArtifactId() );
190
191 if ( !dag.hasEdge( projectRefId, id ) || !parentId.equals( id ) )
192 {
193 dag.addEdge( id, projectRefId );
194 }
195 }
196 }
197
198
199 public MavenProject getTopLevelProject()
200 {
201 if ( topLevelProject == null )
202 {
203 for ( Iterator i = sortedProjects.iterator(); i.hasNext() && topLevelProject == null; )
204 {
205 MavenProject project = (MavenProject) i.next();
206 if ( project.isExecutionRoot() )
207 {
208 topLevelProject = project;
209 }
210 }
211 }
212
213 return topLevelProject;
214 }
215
216 public List getSortedProjects()
217 {
218 return sortedProjects;
219 }
220
221 public boolean hasMultipleProjects()
222 {
223 return sortedProjects.size() > 1;
224 }
225
226 public List getDependents( String id )
227 {
228 return dag.getParentLabels( id );
229 }
230 }