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  // TODO: Auto-generated Javadoc
49  /**
50   * The Class EnforcerRuleUtils.
51   *
52   * @author <a href="mailto:brianf@apache.org">Brian Fox</a>
53   */
54  public class EnforcerRuleUtils
55  {
56  
57      /** The factory. */
58      ArtifactFactory factory;
59  
60      /** The resolver. */
61      ArtifactResolver resolver;
62  
63      /** The local. */
64      ArtifactRepository local;
65  
66      /** The remote repositories. */
67      List<ArtifactRepository> remoteRepositories;
68  
69      /** The log. */
70      Log log;
71  
72      /** The project. */
73      MavenProject project;
74  
75      private EnforcerRuleHelper helper;
76  
77      /**
78       * Instantiates a new enforcer rule utils.
79       *
80       * @param theFactory the the factory
81       * @param theResolver the the resolver
82       * @param theLocal the the local
83       * @param theRemoteRepositories the the remote repositories
84       * @param project the project
85       * @param theLog the the log
86       */
87      public EnforcerRuleUtils( ArtifactFactory theFactory, ArtifactResolver theResolver, ArtifactRepository theLocal,
88                                List<ArtifactRepository> theRemoteRepositories, MavenProject project, Log theLog )
89      {
90          super();
91          this.factory = theFactory;
92          this.resolver = theResolver;
93          this.local = theLocal;
94          this.remoteRepositories = theRemoteRepositories;
95          this.log = theLog;
96          this.project = project;
97      }
98  
99      /**
100      * Instantiates a new enforcer rule utils.
101      *
102      * @param helper the helper
103      */
104     @SuppressWarnings( "unchecked" )
105     public EnforcerRuleUtils( EnforcerRuleHelper helper )
106     {
107 
108         this.helper = helper;
109         // get the various expressions out of the
110         // helper.
111         try
112         {
113             factory = (ArtifactFactory) helper.getComponent( ArtifactFactory.class );
114             resolver = (ArtifactResolver) helper.getComponent( ArtifactResolver.class );
115             local = (ArtifactRepository) helper.evaluate( "${localRepository}" );
116             project = (MavenProject) helper.evaluate( "${project}" );
117             remoteRepositories = project.getRemoteArtifactRepositories();
118         }
119         catch ( ComponentLookupException e )
120         {
121             // TODO Auto-generated catch block
122             e.printStackTrace();
123         }
124         catch ( ExpressionEvaluationException e )
125         {
126             // TODO Auto-generated catch block
127             e.printStackTrace();
128         }
129     }
130 
131     /**
132      * Gets the pom model for this file.
133      *
134      * @param pom the pom
135      * @return the model
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. Looks first in the filesystem, then tries to get it from the
159      * repo.
160      *
161      * @param groupId the group id
162      * @param artifactId the artifact id
163      * @param version the version
164      * @param pom the pom
165      * @return the pom model
166      * @throws ArtifactResolutionException the artifact resolution exception
167      * @throws ArtifactNotFoundException the artifact not found exception
168      * @throws XmlPullParserException the xml pull parser exception
169      * @throws IOException Signals that an I/O exception has occurred.
170      */
171     private Model getPomModel( String groupId, String artifactId, String version, File pom )
172         throws ArtifactResolutionException, ArtifactNotFoundException, IOException, XmlPullParserException
173     {
174         Model model = null;
175 
176         // do we want to look in the reactor like the
177         // project builder? Would require @aggregator goal
178         // which causes problems in maven core right now
179         // because we also need dependency resolution in
180         // other
181         // rules. (MNG-2277)
182 
183         // look in the location specified by pom first.
184         boolean found = false;
185         try
186         {
187             model = readModel( pom );
188 
189             // i found a model, lets make sure it's the one
190             // I want
191             found = checkIfModelMatches( groupId, artifactId, version, model );
192         }
193         catch ( IOException e )
194         {
195             // nothing here, but lets look in the repo
196             // before giving up.
197         }
198         catch ( XmlPullParserException e )
199         {
200             // nothing here, but lets look in the repo
201             // before giving up.
202         }
203 
204         // i didn't find it in the local file system, go
205         // look in the repo
206         if ( !found )
207         {
208             Artifact pomArtifact = factory.createArtifact( groupId, artifactId, version, null, "pom" );
209             resolver.resolve( pomArtifact, remoteRepositories, local );
210             model = readModel( pomArtifact.getFile() );
211         }
212 
213         return model;
214     }
215 
216     /**
217      * This method loops through all the parents, getting each pom model and then its parent.
218      *
219      * @param groupId the group id
220      * @param artifactId the artifact id
221      * @param version the version
222      * @param pom the pom
223      * @return the models recursively
224      * @throws ArtifactResolutionException the artifact resolution exception
225      * @throws ArtifactNotFoundException the artifact not found exception
226      * @throws IOException Signals that an I/O exception has occurred.
227      * @throws XmlPullParserException the xml pull parser exception
228      */
229     public List<Model> getModelsRecursively( String groupId, String artifactId, String version, File pom )
230         throws ArtifactResolutionException, ArtifactNotFoundException, IOException, XmlPullParserException
231     {
232         List<Model> models = null;
233         Model model = getPomModel( groupId, artifactId, version, pom );
234 
235         Parent parent = model.getParent();
236 
237         // recurse into the parent
238         if ( parent != null )
239         {
240             // get the relative path
241             String relativePath = parent.getRelativePath();
242             if ( StringUtils.isEmpty( relativePath ) )
243             {
244                 relativePath = "../pom.xml";
245             }
246             // calculate the recursive path
247             File parentPom = new File( pom.getParent(), relativePath );
248 
249             // if relative path is a directory, append pom.xml
250             if ( parentPom.isDirectory() )
251             {
252                 parentPom = new File( parentPom, "pom.xml" );
253             }
254 
255             //@formatter:off
256             models = getModelsRecursively( parent.getGroupId(), parent.getArtifactId(), 
257                                            parent.getVersion(), parentPom );
258             //@formatter:on
259         }
260         else
261         {
262             // only create it here since I'm not at the top
263             models = new ArrayList<Model>();
264         }
265         models.add( model );
266 
267         return models;
268     }
269 
270     /**
271      * Make sure the model is the one I'm expecting.
272      *
273      * @param groupId the group id
274      * @param artifactId the artifact id
275      * @param version the version
276      * @param model Model being checked.
277      * @return true, if check if model matches
278      */
279     protected boolean checkIfModelMatches( String groupId, String artifactId, String version, Model model )
280     {
281         // try these first.
282         String modelGroup = model.getGroupId();
283         String modelArtifactId = model.getArtifactId();
284         String modelVersion = model.getVersion();
285 
286         try
287         {
288             if ( StringUtils.isEmpty( modelGroup ) )
289             {
290                 modelGroup = model.getParent().getGroupId();
291             }
292             else
293             {
294                 // MENFORCER-30, handle cases where the value is a property like ${project.parent.groupId}
295                 modelGroup = (String) helper.evaluate( modelGroup );
296             }
297 
298             if ( StringUtils.isEmpty( modelVersion ) )
299             {
300                 modelVersion = model.getParent().getVersion();
301             }
302             else
303             {
304                 // MENFORCER-30, handle cases where the value is a property like ${project.parent.version}
305                 modelVersion = (String) helper.evaluate( modelVersion );
306             }
307 
308             // Is this only required for Maven2?
309             modelArtifactId = (String) helper.evaluate( modelArtifactId );
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         // CHECKSTYLE_OFF: LineLength
324         return ( StringUtils.equals( groupId, modelGroup ) && StringUtils.equals( version, modelVersion ) && StringUtils.equals( artifactId,
325                                                                                                                                  modelArtifactId ) );
326         // CHECKSTYLE_ON: LineLength
327     }
328 
329     private void resolve( Plugin plugin )
330     {
331         try
332         {
333             plugin.setGroupId( (String) helper.evaluate( plugin.getGroupId() ) );
334             plugin.setArtifactId( (String) helper.evaluate( plugin.getArtifactId() ) );
335             plugin.setVersion( (String) helper.evaluate( plugin.getVersion() ) );
336         }
337         catch ( ExpressionEvaluationException e )
338         {
339             // this should have gone already before
340         }
341     }
342 
343     private void resolve( ReportPlugin plugin )
344     {
345         try
346         {
347             plugin.setGroupId( (String) helper.evaluate( plugin.getGroupId() ) );
348             plugin.setArtifactId( (String) helper.evaluate( plugin.getArtifactId() ) );
349             plugin.setVersion( (String) helper.evaluate( plugin.getVersion() ) );
350         }
351         catch ( ExpressionEvaluationException e )
352         {
353             // this should have gone already before
354         }
355     }
356 
357     public List<Plugin> resolvePlugins( List<Plugin> plugins )
358     {
359         for ( Plugin plugin : plugins )
360         {
361             resolve( plugin );
362         }
363         return plugins;
364     }
365 
366     public List<ReportPlugin> resolveReportPlugins( List<ReportPlugin> reportPlugins )
367     {
368         for ( ReportPlugin plugin : reportPlugins )
369         {
370             resolve( plugin );
371         }
372         return reportPlugins;
373     }
374 
375 }