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.Collections;
24 import java.util.List;
25
26 import org.apache.maven.artifact.Artifact;
27 import org.apache.maven.artifact.factory.ArtifactFactory;
28 import org.apache.maven.artifact.metadata.ArtifactMetadataSource;
29 import org.apache.maven.artifact.repository.ArtifactRepository;
30 import org.apache.maven.artifact.resolver.ArtifactCollector;
31 import org.apache.maven.artifact.resolver.filter.ArtifactFilter;
32 import org.apache.maven.enforcer.rule.api.EnforcerRule;
33 import org.apache.maven.enforcer.rule.api.EnforcerRuleException;
34 import org.apache.maven.enforcer.rule.api.EnforcerRuleHelper;
35 import org.apache.maven.plugin.logging.Log;
36 import org.apache.maven.plugins.enforcer.utils.DependencyVersionMap;
37 import org.apache.maven.project.MavenProject;
38 import org.apache.maven.shared.dependency.tree.DependencyNode;
39 import org.apache.maven.shared.dependency.tree.DependencyTreeBuilder;
40 import org.apache.maven.shared.dependency.tree.DependencyTreeBuilderException;
41 import org.codehaus.plexus.component.configurator.expression.ExpressionEvaluationException;
42 import org.codehaus.plexus.component.repository.exception.ComponentLookupException;
43 import org.codehaus.plexus.i18n.I18N;
44
45
46
47
48 public class DependencyConvergence
49 implements EnforcerRule
50 {
51
52 private static Log log;
53
54 private static I18N i18n;
55
56 private boolean uniqueVersions;
57
58 public void setUniqueVersions( boolean uniqueVersions )
59 {
60 this.uniqueVersions = uniqueVersions;
61 }
62
63
64
65
66
67
68
69
70
71
72
73
74
75 private DependencyNode getNode( EnforcerRuleHelper helper )
76 throws EnforcerRuleException
77 {
78 try
79 {
80 MavenProject project = (MavenProject) helper.evaluate( "${project}" );
81 DependencyTreeBuilder dependencyTreeBuilder =
82 (DependencyTreeBuilder) helper.getComponent( DependencyTreeBuilder.class );
83 ArtifactRepository repository = (ArtifactRepository) helper.evaluate( "${localRepository}" );
84 ArtifactFactory factory = (ArtifactFactory) helper.getComponent( ArtifactFactory.class );
85 ArtifactMetadataSource metadataSource =
86 (ArtifactMetadataSource) helper.getComponent( ArtifactMetadataSource.class );
87 ArtifactCollector collector = (ArtifactCollector) helper.getComponent( ArtifactCollector.class );
88 ArtifactFilter filter = null;
89 DependencyNode node =
90 dependencyTreeBuilder.buildDependencyTree( project, repository, factory, metadataSource, filter,
91 collector );
92 return node;
93 }
94 catch ( ExpressionEvaluationException e )
95 {
96 throw new EnforcerRuleException( "Unable to lookup an expression " + e.getLocalizedMessage(), e );
97 }
98 catch ( ComponentLookupException e )
99 {
100 throw new EnforcerRuleException( "Unable to lookup a component " + e.getLocalizedMessage(), e );
101 }
102 catch ( DependencyTreeBuilderException e )
103 {
104 throw new EnforcerRuleException( "Could not build dependency tree " + e.getLocalizedMessage(), e );
105 }
106 }
107
108 public void execute( EnforcerRuleHelper helper )
109 throws EnforcerRuleException
110 {
111 if ( log == null )
112 {
113 log = helper.getLog();
114 }
115 try
116 {
117 if ( i18n == null )
118 {
119 i18n = (I18N) helper.getComponent( I18N.class );
120 }
121 DependencyNode node = getNode( helper );
122 DependencyVersionMap visitor = new DependencyVersionMap( log );
123 visitor.setUniqueVersions( uniqueVersions );
124 node.accept( visitor );
125 List<CharSequence> errorMsgs = new ArrayList<CharSequence>();
126 errorMsgs.addAll( getConvergenceErrorMsgs( visitor.getConflictedVersionNumbers() ) );
127 for ( CharSequence errorMsg : errorMsgs )
128 {
129 log.warn( errorMsg );
130 }
131 if ( errorMsgs.size() > 0 )
132 {
133 throw new EnforcerRuleException( "Failed while enforcing releasability the error(s) are " + errorMsgs );
134 }
135 }
136 catch ( ComponentLookupException e )
137 {
138 throw new EnforcerRuleException( "Unable to lookup a component " + e.getLocalizedMessage(), e );
139 }
140 catch ( Exception e )
141 {
142 throw new EnforcerRuleException( e.getLocalizedMessage(), e );
143 }
144 }
145
146 private String getFullArtifactName( Artifact artifact )
147 {
148 return artifact.getGroupId() + ":" + artifact.getArtifactId() + ":" + artifact.getVersion();
149 }
150
151 private StringBuilder buildTreeString( DependencyNode node )
152 {
153 List<String> loc = new ArrayList<String>();
154 DependencyNode currentNode = node;
155 while ( currentNode != null )
156 {
157 loc.add( getFullArtifactName( currentNode.getArtifact() ) );
158 currentNode = currentNode.getParent();
159 }
160 Collections.reverse( loc );
161 StringBuilder builder = new StringBuilder();
162 for ( int i = 0; i < loc.size(); i++ )
163 {
164 for ( int j = 0; j < i; j++ )
165 {
166 builder.append( " " );
167 }
168 builder.append( "+-" + loc.get( i ) );
169 builder.append( "\n" );
170 }
171 return builder;
172 }
173
174 private List<String> getConvergenceErrorMsgs( List<List<DependencyNode>> errors )
175 {
176 List<String> errorMsgs = new ArrayList<String>();
177 for ( List<DependencyNode> nodeList : errors )
178 {
179 errorMsgs.add( buildConvergenceErrorMsg( nodeList ) );
180 }
181 return errorMsgs;
182 }
183
184 private String buildConvergenceErrorMsg( List<DependencyNode> nodeList )
185 {
186 StringBuilder builder = new StringBuilder();
187 builder.append( "\nDependency convergence error for " + getFullArtifactName( nodeList.get( 0 ).getArtifact() )
188 + " paths to dependency are:\n" );
189 if ( nodeList.size() > 0 )
190 {
191 builder.append( buildTreeString( nodeList.get( 0 ) ) );
192 }
193 for ( DependencyNode node : nodeList.subList( 1, nodeList.size() ) )
194 {
195 builder.append( "and\n" );
196 builder.append( buildTreeString( node ) );
197 }
198 return builder.toString();
199 }
200
201
202
203
204
205
206
207 public String getCacheId()
208 {
209 return "";
210 }
211
212
213
214
215
216
217 public boolean isCacheable()
218 {
219 return false;
220 }
221
222
223
224
225
226
227
228
229
230 public boolean isResultValid( EnforcerRule rule )
231 {
232 return false;
233 }
234 }