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.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 }