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