1 package org.apache.maven.plugins.enforcer.utils;
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 java.io.File;
23 import java.io.IOException;
24 import java.io.Reader;
25 import java.util.ArrayList;
26 import java.util.List;
27
28 import org.apache.maven.artifact.Artifact;
29 import org.apache.maven.artifact.factory.ArtifactFactory;
30 import org.apache.maven.artifact.repository.ArtifactRepository;
31 import org.apache.maven.artifact.resolver.ArtifactNotFoundException;
32 import org.apache.maven.artifact.resolver.ArtifactResolutionException;
33 import org.apache.maven.artifact.resolver.ArtifactResolver;
34 import org.apache.maven.enforcer.rule.api.EnforcerRuleHelper;
35 import org.apache.maven.model.Model;
36 import org.apache.maven.model.Parent;
37 import org.apache.maven.model.io.xpp3.MavenXpp3Reader;
38 import org.apache.maven.plugin.logging.Log;
39 import org.apache.maven.project.MavenProject;
40 import org.codehaus.plexus.component.configurator.expression.ExpressionEvaluationException;
41 import org.codehaus.plexus.component.repository.exception.ComponentLookupException;
42 import org.codehaus.plexus.util.ReaderFactory;
43 import org.codehaus.plexus.util.StringUtils;
44 import org.codehaus.plexus.util.xml.pull.XmlPullParserException;
45
46 // TODO: Auto-generated Javadoc
47 /**
48 * The Class EnforcerRuleUtils.
49 *
50 * @author <a href="mailto:brianf@apache.org">Brian Fox</a>
51 */
52 public class EnforcerRuleUtils
53 {
54
55 /** The factory. */
56 ArtifactFactory factory;
57
58 /** The resolver. */
59 ArtifactResolver resolver;
60
61 /** The local. */
62 ArtifactRepository local;
63
64 /** The remote repositories. */
65 List<ArtifactRepository> remoteRepositories;
66
67 /** The log. */
68 Log log;
69
70 /** The project. */
71 MavenProject project;
72
73 private EnforcerRuleHelper helper;
74
75 /**
76 * Instantiates a new enforcer rule utils.
77 *
78 * @param theFactory the the factory
79 * @param theResolver the the resolver
80 * @param theLocal the the local
81 * @param theRemoteRepositories the the remote repositories
82 * @param project the project
83 * @param theLog the the log
84 */
85 public EnforcerRuleUtils( ArtifactFactory theFactory, ArtifactResolver theResolver, ArtifactRepository theLocal,
86 List<ArtifactRepository> theRemoteRepositories, MavenProject project, Log theLog )
87 {
88 super();
89 this.factory = theFactory;
90 this.resolver = theResolver;
91 this.local = theLocal;
92 this.remoteRepositories = theRemoteRepositories;
93 this.log = theLog;
94 this.project = project;
95 }
96
97 /**
98 * Instantiates a new enforcer rule utils.
99 *
100 * @param helper the helper
101 */
102 @SuppressWarnings( "unchecked" )
103 public EnforcerRuleUtils( EnforcerRuleHelper helper )
104 {
105
106 this.helper = helper;
107 // get the various expressions out of the
108 // helper.
109 try
110 {
111 factory = (ArtifactFactory) helper.getComponent( ArtifactFactory.class );
112 resolver = (ArtifactResolver) helper.getComponent( ArtifactResolver.class );
113 local = (ArtifactRepository) helper.evaluate( "${localRepository}" );
114 project = (MavenProject) helper.evaluate( "${project}" );
115 remoteRepositories = project.getRemoteArtifactRepositories();
116 }
117 catch ( ComponentLookupException e )
118 {
119 // TODO Auto-generated catch block
120 e.printStackTrace();
121 }
122 catch ( ExpressionEvaluationException e )
123 {
124 // TODO Auto-generated catch block
125 e.printStackTrace();
126 }
127 }
128
129 /**
130 * Gets the pom model for this file.
131 *
132 * @param pom the pom
133 *
134 * @return the model
135 *
136 * @throws IOException Signals that an I/O exception has occurred.
137 * @throws XmlPullParserException the xml pull parser exception
138 */
139 private Model readModel ( File pom )
140 throws IOException, XmlPullParserException
141 {
142 Reader reader = ReaderFactory.newXmlReader( pom );
143 MavenXpp3Reader xpp3 = new MavenXpp3Reader();
144 Model model = null;
145 try
146 {
147 model = xpp3.read( reader );
148 }
149 finally
150 {
151 reader.close();
152 reader = null;
153 }
154 return model;
155 }
156
157 /**
158 * This method gets the model for the defined artifact.
159 * Looks first in the filesystem, then tries to get it
160 * from the repo.
161 *
162 * @param groupId the group id
163 * @param artifactId the artifact id
164 * @param version the version
165 * @param pom the pom
166 *
167 * @return the pom model
168 *
169 * @throws ArtifactResolutionException the artifact resolution exception
170 * @throws ArtifactNotFoundException the artifact not found exception
171 * @throws XmlPullParserException the xml pull parser exception
172 * @throws IOException Signals that an I/O exception has occurred.
173 */
174 private Model getPomModel ( String groupId, String artifactId, String version, File pom )
175 throws ArtifactResolutionException, ArtifactNotFoundException, IOException, XmlPullParserException
176 {
177 Model model = null;
178
179 // do we want to look in the reactor like the
180 // project builder? Would require @aggregator goal
181 // which causes problems in maven core right now
182 // because we also need dependency resolution in
183 // other
184 // rules. (MNG-2277)
185
186 // look in the location specified by pom first.
187 boolean found = false;
188 try
189 {
190 model = readModel( pom );
191
192 // i found a model, lets make sure it's the one
193 // I want
194 found = checkIfModelMatches( groupId, artifactId, version, model );
195 }
196 catch ( IOException e )
197 {
198 // nothing here, but lets look in the repo
199 // before giving up.
200 }
201 catch ( XmlPullParserException e )
202 {
203 // nothing here, but lets look in the repo
204 // before giving up.
205 }
206
207 // i didn't find it in the local file system, go
208 // look in the repo
209 if ( !found )
210 {
211 Artifact pomArtifact = factory.createArtifact( groupId, artifactId, version, null, "pom" );
212 resolver.resolve( pomArtifact, remoteRepositories, local );
213 model = readModel( pomArtifact.getFile() );
214 }
215
216 return model;
217 }
218
219 /**
220 * This method loops through all the parents, getting
221 * each pom model and then its parent.
222 *
223 * @param groupId the group id
224 * @param artifactId the artifact id
225 * @param version the version
226 * @param pom the pom
227 *
228 * @return the models recursively
229 *
230 * @throws ArtifactResolutionException the artifact resolution exception
231 * @throws ArtifactNotFoundException the artifact not found exception
232 * @throws IOException Signals that an I/O exception has occurred.
233 * @throws XmlPullParserException the xml pull parser exception
234 */
235 public List<Model> getModelsRecursively ( String groupId, String artifactId, String version, File pom )
236 throws ArtifactResolutionException, ArtifactNotFoundException, IOException, XmlPullParserException
237 {
238 List<Model> models = null;
239 Model model = getPomModel( groupId, artifactId, version, pom );
240
241 Parent parent = model.getParent();
242
243 // recurse into the parent
244 if ( parent != null )
245 {
246 // get the relative path
247 String relativePath = parent.getRelativePath();
248 if ( StringUtils.isEmpty( relativePath ) )
249 {
250 relativePath = "../pom.xml";
251 }
252 // calculate the recursive path
253 File parentPom = new File( pom.getParent(), relativePath );
254
255 // if relative path is a directory, append pom.xml
256 if ( parentPom.isDirectory() )
257 {
258 parentPom = new File( parentPom, "pom.xml" );
259 }
260
261 models = getModelsRecursively( parent.getGroupId(), parent.getArtifactId(), parent.getVersion(), parentPom );
262 }
263 else
264 {
265 // only create it here since I'm not at the top
266 models = new ArrayList<Model>();
267 }
268 models.add( model );
269
270 return models;
271 }
272
273 /**
274 * Make sure the model is the one I'm expecting.
275 *
276 * @param groupId the group id
277 * @param artifactId the artifact id
278 * @param version the version
279 * @param model Model being checked.
280 *
281 * @return true, if check if model matches
282 */
283 protected boolean checkIfModelMatches ( String groupId, String artifactId, String version, Model model )
284 {
285 // try these first.
286 String modelGroup = model.getGroupId();
287 String modelVersion = model.getVersion();
288
289 try
290 {
291 if ( StringUtils.isEmpty( modelGroup ) )
292 {
293 modelGroup = model.getParent().getGroupId();
294 }
295 else
296 {
297 //MENFORCER-30, handle cases where the value is a property like ${project.parent.groupId}
298 modelGroup = (String) helper.evaluate( modelGroup );
299 }
300
301 if ( StringUtils.isEmpty( modelVersion ) )
302 {
303 modelVersion = model.getParent().getVersion();
304 }
305 else
306 {
307 //MENFORCER-30, handle cases where the value is a property like ${project.parent.version}
308 modelVersion = (String) helper.evaluate( modelVersion );
309 }
310 }
311 catch ( NullPointerException e )
312 {
313 // this is probably bad. I don't have a valid
314 // group or version and I can't find a
315 // parent????
316 // lets see if it's what we're looking for
317 // anyway.
318 }
319 catch ( ExpressionEvaluationException e )
320 {
321 // as above
322 }
323 return ( StringUtils.equals( groupId, modelGroup ) && StringUtils.equals( version, modelVersion ) && StringUtils
324 .equals( artifactId, model.getArtifactId() ) );
325 }
326 }