1 package org.apache.maven.plugins.enforcer;
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.HashMap;
24 import java.util.List;
25 import java.util.Map;
26 import java.util.Map.Entry;
27
28 import org.apache.commons.lang.SystemUtils;
29 import org.apache.maven.enforcer.rule.api.EnforcerRuleException;
30 import org.apache.maven.enforcer.rule.api.EnforcerRuleHelper;
31 import org.apache.maven.execution.MavenSession;
32 import org.apache.maven.model.Dependency;
33 import org.apache.maven.plugin.logging.Log;
34 import org.apache.maven.project.MavenProject;
35 import org.codehaus.plexus.component.configurator.expression.ExpressionEvaluationException;
36 import org.codehaus.plexus.util.StringUtils;
37
38
39
40
41
42
43
44 public class ReactorModuleConvergence
45 extends AbstractNonCacheableEnforcerRule
46 {
47 private boolean ignoreModuleDependencies = false;
48
49 private Log logger;
50
51 public void execute( EnforcerRuleHelper helper )
52 throws EnforcerRuleException
53 {
54 logger = helper.getLog();
55
56 MavenSession session;
57 try
58 {
59 session = (MavenSession) helper.evaluate( "${session}" );
60 }
61 catch ( ExpressionEvaluationException eee )
62 {
63 throw new EnforcerRuleException( "Unable to retrieve the MavenSession: ", eee );
64 }
65
66 List<MavenProject> sortedProjects = session.getSortedProjects();
67 if ( sortedProjects != null && !sortedProjects.isEmpty() )
68 {
69 checkReactor( sortedProjects );
70 checkParentsInReactor( sortedProjects );
71 checkMissingParentsInReactor( sortedProjects );
72 checkParentsPartOfTheReactor( sortedProjects );
73 if ( !isIgnoreModuleDependencies() )
74 {
75 checkDependenciesWithinReactor( sortedProjects );
76 }
77 }
78
79 }
80
81 private void checkParentsPartOfTheReactor( List<MavenProject> sortedProjects )
82 throws EnforcerRuleException
83 {
84 List<MavenProject> parentsWhichAreNotPartOfTheReactor =
85 existParentsWhichAreNotPartOfTheReactor( sortedProjects );
86 if ( !parentsWhichAreNotPartOfTheReactor.isEmpty() )
87 {
88 StringBuilder sb = new StringBuilder().append( SystemUtils.LINE_SEPARATOR );
89 addMessageIfExist( sb );
90 for ( MavenProject mavenProject : parentsWhichAreNotPartOfTheReactor )
91 {
92 sb.append( " module: " );
93 sb.append( mavenProject.getId() );
94 sb.append( SystemUtils.LINE_SEPARATOR );
95 }
96 throw new EnforcerRuleException( "Module parents have been found which could not be found in the reactor."
97 + sb.toString() );
98 }
99 }
100
101
102
103
104
105
106
107 private void checkMissingParentsInReactor( List<MavenProject> sortedProjects )
108 throws EnforcerRuleException
109 {
110 List<MavenProject> modulesWithoutParentsInReactor = existModulesWithoutParentsInReactor( sortedProjects );
111 if ( !modulesWithoutParentsInReactor.isEmpty() )
112 {
113 StringBuilder sb = new StringBuilder().append( SystemUtils.LINE_SEPARATOR );
114 addMessageIfExist( sb );
115 for ( MavenProject mavenProject : modulesWithoutParentsInReactor )
116 {
117 sb.append( " module: " );
118 sb.append( mavenProject.getId() );
119 sb.append( SystemUtils.LINE_SEPARATOR );
120 }
121 throw new EnforcerRuleException( "Reactor contains modules without parents." + sb.toString() );
122 }
123 }
124
125 private void checkDependenciesWithinReactor( List<MavenProject> sortedProjects )
126 throws EnforcerRuleException
127 {
128
129 String reactorVersion = sortedProjects.get( 0 ).getVersion();
130
131 Map<MavenProject, List<Dependency>> areThereDependenciesWhichAreNotPartOfTheReactor =
132 areThereDependenciesWhichAreNotPartOfTheReactor( reactorVersion, sortedProjects );
133 if ( !areThereDependenciesWhichAreNotPartOfTheReactor.isEmpty() )
134 {
135 StringBuilder sb = new StringBuilder().append( SystemUtils.LINE_SEPARATOR );
136 addMessageIfExist( sb );
137
138 for ( Entry<MavenProject, List<Dependency>> item : areThereDependenciesWhichAreNotPartOfTheReactor.entrySet() )
139 {
140 sb.append( " module: " );
141 sb.append( item.getKey().getId() );
142 sb.append( SystemUtils.LINE_SEPARATOR );
143 for ( Dependency dependency : item.getValue() )
144 {
145 String id =
146 dependency.getGroupId() + ":" + dependency.getArtifactId() + ":" + dependency.getVersion();
147 sb.append( " dependency: " );
148 sb.append( id );
149 sb.append( SystemUtils.LINE_SEPARATOR );
150 }
151 }
152 throw new EnforcerRuleException(
153 "Reactor modules contains dependencies which do not reference the reactor."
154 + sb.toString() );
155
156 }
157 }
158
159
160
161
162
163
164
165 private void checkParentsInReactor( List<MavenProject> sortedProjects )
166 throws EnforcerRuleException
167 {
168
169 String reactorVersion = sortedProjects.get( 0 ).getVersion();
170
171 List<MavenProject> areParentsFromTheReactor = areParentsFromTheReactor( reactorVersion, sortedProjects );
172 if ( !areParentsFromTheReactor.isEmpty() )
173 {
174 StringBuilder sb = new StringBuilder().append( SystemUtils.LINE_SEPARATOR );
175 addMessageIfExist( sb );
176 for ( MavenProject mavenProject : areParentsFromTheReactor )
177 {
178 sb.append( " --> " );
179 sb.append( mavenProject.getId() );
180 sb.append( " parent:" );
181 sb.append( mavenProject.getParent().getId() );
182 sb.append( SystemUtils.LINE_SEPARATOR );
183 }
184 throw new EnforcerRuleException( "Reactor modules have parents which contain a wrong version."
185 + sb.toString() );
186 }
187 }
188
189
190
191
192
193
194
195 private void checkReactor( List<MavenProject> sortedProjects )
196 throws EnforcerRuleException
197 {
198 List<MavenProject> consistenceCheckResult = isReactorVersionConsistent( sortedProjects );
199 if ( !consistenceCheckResult.isEmpty() )
200 {
201 StringBuilder sb = new StringBuilder().append( SystemUtils.LINE_SEPARATOR );
202 addMessageIfExist( sb );
203 for ( MavenProject mavenProject : consistenceCheckResult )
204 {
205 sb.append( " --> " );
206 sb.append( mavenProject.getId() );
207 sb.append( SystemUtils.LINE_SEPARATOR );
208 }
209 throw new EnforcerRuleException( "The reactor contains different versions." + sb.toString() );
210 }
211 }
212
213 private List<MavenProject> areParentsFromTheReactor( String reactorVersion, List<MavenProject> sortedProjects )
214 {
215 List<MavenProject> result = new ArrayList<MavenProject>();
216
217 for ( MavenProject mavenProject : sortedProjects )
218 {
219 logger.debug( "Project: " + mavenProject.getId() );
220 if ( hasParent( mavenProject ) )
221 {
222 if ( !mavenProject.isExecutionRoot() )
223 {
224 MavenProject parent = mavenProject.getParent();
225 if ( !reactorVersion.equals( parent.getVersion() ) )
226 {
227 logger.debug( "The project: " + mavenProject.getId()
228 + " has a parent which version does not match the other elements in reactor" );
229 result.add( mavenProject );
230 }
231 }
232 }
233 else
234 {
235
236 }
237 }
238
239 return result;
240 }
241
242 private List<MavenProject> existParentsWhichAreNotPartOfTheReactor( List<MavenProject> sortedProjects )
243 {
244 List<MavenProject> result = new ArrayList<MavenProject>();
245
246 for ( MavenProject mavenProject : sortedProjects )
247 {
248 logger.debug( "Project: " + mavenProject.getId() );
249 if ( hasParent( mavenProject ) )
250 {
251 if ( !mavenProject.isExecutionRoot() )
252 {
253 MavenProject parent = mavenProject.getParent();
254 if ( !isProjectPartOfTheReactor( parent, sortedProjects ) )
255 {
256 result.add( mavenProject );
257 }
258 }
259 }
260 }
261
262 return result;
263 }
264
265
266
267
268
269
270
271
272
273 private boolean isProjectPartOfTheReactor( MavenProject project, List<MavenProject> sortedProjects )
274 {
275 return isGAPartOfTheReactor( project.getGroupId(), project.getArtifactId(), sortedProjects );
276 }
277
278 private boolean isDependencyPartOfTheReactor( Dependency dependency, List<MavenProject> sortedProjects )
279 {
280 return isGAPartOfTheReactor( dependency.getGroupId(), dependency.getArtifactId(), sortedProjects );
281 }
282
283
284
285
286
287
288
289
290
291 private boolean isGAPartOfTheReactor( String groupId, String artifactId, List<MavenProject> sortedProjects )
292 {
293 boolean result = false;
294 for ( MavenProject mavenProject : sortedProjects )
295 {
296 String parentId = groupId + ":" + artifactId;
297 String projectId = mavenProject.getGroupId() + ":" + mavenProject.getArtifactId();
298 if ( parentId.equals( projectId ) )
299 {
300 result = true;
301 }
302 }
303 return result;
304 }
305
306
307
308
309
310
311
312
313
314 private List<MavenProject> existModulesWithoutParentsInReactor( List<MavenProject> sortedProjects )
315 {
316 List<MavenProject> result = new ArrayList<MavenProject>();
317
318 for ( MavenProject mavenProject : sortedProjects )
319 {
320 logger.debug( "Project: " + mavenProject.getId() );
321 if ( !hasParent( mavenProject ) )
322 {
323
324 if ( mavenProject.isExecutionRoot() )
325 {
326 logger.debug( "The root does not need having a parent." );
327 }
328 else
329 {
330 logger.debug( "The module: " + mavenProject.getId() + " has no parent." );
331 result.add( mavenProject );
332 }
333 }
334 }
335
336 return result;
337 }
338
339
340
341
342
343
344
345
346 private void addDep( Map<MavenProject, List<Dependency>> result, MavenProject project, Dependency dependency )
347 {
348 if ( result.containsKey( project ) )
349 {
350 List<Dependency> list = result.get( project );
351 if ( list == null )
352 {
353 list = new ArrayList<Dependency>();
354 }
355 list.add( dependency );
356 result.put( project, list );
357 }
358 else
359 {
360 List<Dependency> list = new ArrayList<Dependency>();
361 list.add( dependency );
362 result.put( project, list );
363 }
364 }
365
366
367
368
369
370
371
372
373
374
375
376 private Map<MavenProject, List<Dependency>> areThereDependenciesWhichAreNotPartOfTheReactor( String reactorVersion,
377 List<MavenProject> sortedProjects )
378
379 {
380 Map<MavenProject, List<Dependency>> result = new HashMap<MavenProject, List<Dependency>>();
381 for ( MavenProject mavenProject : sortedProjects )
382 {
383 logger.debug( "Project: " + mavenProject.getId() );
384
385 @SuppressWarnings( "unchecked" )
386 List<Dependency> dependencies = mavenProject.getDependencies();
387 if ( hasDependencies( dependencies ) )
388 {
389 for ( Dependency dependency : dependencies )
390 {
391 logger.debug( " -> Dep:" + dependency.getGroupId() + ":" + dependency.getArtifactId() + ":"
392 + dependency.getVersion() );
393 if ( isDependencyPartOfTheReactor( dependency, sortedProjects ) )
394 {
395 if ( !dependency.getVersion().equals( reactorVersion ) )
396 {
397 addDep( result, mavenProject, dependency );
398 }
399 }
400 }
401 }
402 }
403
404 return result;
405 }
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424 private List<MavenProject> isReactorVersionConsistent( List<MavenProject> projectList )
425 {
426 List<MavenProject> result = new ArrayList<MavenProject>();
427
428 if ( projectList != null && !projectList.isEmpty() )
429 {
430 String version = projectList.get( 0 ).getVersion();
431 logger.debug( "First version:" + version );
432 for ( MavenProject mavenProject : projectList )
433 {
434 logger.debug( " -> checking " + mavenProject.getId() );
435 if ( !version.equals( mavenProject.getVersion() ) )
436 {
437 result.add( mavenProject );
438 }
439 }
440 }
441 return result;
442 }
443
444 private boolean hasDependencies( List<Dependency> dependencies )
445 {
446 return dependencies != null && !dependencies.isEmpty();
447 }
448
449 private boolean hasParent( MavenProject mavenProject )
450 {
451 return mavenProject.getParent() != null;
452 }
453
454 public boolean isIgnoreModuleDependencies()
455 {
456 return ignoreModuleDependencies;
457 }
458
459 public void setIgnoreModuleDependencies( boolean ignoreModuleDependencies )
460 {
461 this.ignoreModuleDependencies = ignoreModuleDependencies;
462 }
463
464
465
466
467
468
469 private void addMessageIfExist( StringBuilder sb )
470 {
471 if ( !StringUtils.isEmpty( getMessage() ) )
472 {
473 sb.append( getMessage() );
474 sb.append( SystemUtils.LINE_SEPARATOR );
475 }
476 }
477
478 }