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