001package org.apache.maven.plugins.enforcer.utils; 002 003/* 004 * Licensed to the Apache Software Foundation (ASF) under one 005 * or more contributor license agreements. See the NOTICE file 006 * distributed with this work for additional information 007 * regarding copyright ownership. The ASF licenses this file 008 * to you under the Apache License, Version 2.0 (the 009 * "License"); you may not use this file except in compliance 010 * with the License. You may obtain a copy of the License at 011 * 012 * http://www.apache.org/licenses/LICENSE-2.0 013 * 014 * Unless required by applicable law or agreed to in writing, 015 * software distributed under the License is distributed on an 016 * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY 017 * KIND, either express or implied. See the License for the 018 * specific language governing permissions and limitations 019 * under the License. 020 */ 021 022import java.io.File; 023import java.io.IOException; 024import java.io.Reader; 025import java.util.ArrayList; 026import java.util.List; 027 028import org.apache.maven.artifact.Artifact; 029import org.apache.maven.artifact.factory.ArtifactFactory; 030import org.apache.maven.artifact.repository.ArtifactRepository; 031import org.apache.maven.artifact.resolver.ArtifactNotFoundException; 032import org.apache.maven.artifact.resolver.ArtifactResolutionException; 033import org.apache.maven.artifact.resolver.ArtifactResolver; 034import org.apache.maven.enforcer.rule.api.EnforcerRuleHelper; 035import org.apache.maven.model.Model; 036import org.apache.maven.model.Parent; 037import org.apache.maven.model.Plugin; 038import org.apache.maven.model.ReportPlugin; 039import org.apache.maven.model.io.xpp3.MavenXpp3Reader; 040import org.apache.maven.plugin.logging.Log; 041import org.apache.maven.project.MavenProject; 042import org.codehaus.plexus.component.configurator.expression.ExpressionEvaluationException; 043import org.codehaus.plexus.component.repository.exception.ComponentLookupException; 044import org.codehaus.plexus.util.ReaderFactory; 045import org.codehaus.plexus.util.StringUtils; 046import org.codehaus.plexus.util.xml.pull.XmlPullParserException; 047 048// TODO: Auto-generated Javadoc 049/** 050 * The Class EnforcerRuleUtils. 051 * 052 * @author <a href="mailto:brianf@apache.org">Brian Fox</a> 053 */ 054public class EnforcerRuleUtils 055{ 056 057 /** The factory. */ 058 ArtifactFactory factory; 059 060 /** The resolver. */ 061 ArtifactResolver resolver; 062 063 /** The local. */ 064 ArtifactRepository local; 065 066 /** The remote repositories. */ 067 List<ArtifactRepository> remoteRepositories; 068 069 /** The log. */ 070 Log log; 071 072 /** The project. */ 073 MavenProject project; 074 075 private EnforcerRuleHelper helper; 076 077 /** 078 * Instantiates a new enforcer rule utils. 079 * 080 * @param theFactory the the factory 081 * @param theResolver the the resolver 082 * @param theLocal the the local 083 * @param theRemoteRepositories the the remote repositories 084 * @param project the project 085 * @param theLog the the log 086 */ 087 public EnforcerRuleUtils( ArtifactFactory theFactory, ArtifactResolver theResolver, ArtifactRepository theLocal, 088 List<ArtifactRepository> theRemoteRepositories, MavenProject project, Log theLog ) 089 { 090 super(); 091 this.factory = theFactory; 092 this.resolver = theResolver; 093 this.local = theLocal; 094 this.remoteRepositories = theRemoteRepositories; 095 this.log = theLog; 096 this.project = project; 097 } 098 099 /** 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 * 136 * @return the model 137 * 138 * @throws IOException Signals that an I/O exception has occurred. 139 * @throws XmlPullParserException the xml pull parser exception 140 */ 141 private Model readModel ( File pom ) 142 throws IOException, XmlPullParserException 143 { 144 Reader reader = ReaderFactory.newXmlReader( pom ); 145 MavenXpp3Reader xpp3 = new MavenXpp3Reader(); 146 Model model = null; 147 try 148 { 149 model = xpp3.read( reader ); 150 } 151 finally 152 { 153 reader.close(); 154 reader = null; 155 } 156 return model; 157 } 158 159 /** 160 * This method gets the model for the defined artifact. 161 * Looks first in the filesystem, then tries to get it 162 * from the repo. 163 * 164 * @param groupId the group id 165 * @param artifactId the artifact id 166 * @param version the version 167 * @param pom the pom 168 * 169 * @return the pom model 170 * 171 * @throws ArtifactResolutionException the artifact resolution exception 172 * @throws ArtifactNotFoundException the artifact not found exception 173 * @throws XmlPullParserException the xml pull parser exception 174 * @throws IOException Signals that an I/O exception has occurred. 175 */ 176 private Model getPomModel ( String groupId, String artifactId, String version, File pom ) 177 throws ArtifactResolutionException, ArtifactNotFoundException, IOException, XmlPullParserException 178 { 179 Model model = null; 180 181 // do we want to look in the reactor like the 182 // project builder? Would require @aggregator goal 183 // which causes problems in maven core right now 184 // because we also need dependency resolution in 185 // other 186 // rules. (MNG-2277) 187 188 // look in the location specified by pom first. 189 boolean found = false; 190 try 191 { 192 model = readModel( pom ); 193 194 // i found a model, lets make sure it's the one 195 // I want 196 found = checkIfModelMatches( groupId, artifactId, version, model ); 197 } 198 catch ( IOException e ) 199 { 200 // nothing here, but lets look in the repo 201 // before giving up. 202 } 203 catch ( XmlPullParserException e ) 204 { 205 // nothing here, but lets look in the repo 206 // before giving up. 207 } 208 209 // i didn't find it in the local file system, go 210 // look in the repo 211 if ( !found ) 212 { 213 Artifact pomArtifact = factory.createArtifact( groupId, artifactId, version, null, "pom" ); 214 resolver.resolve( pomArtifact, remoteRepositories, local ); 215 model = readModel( pomArtifact.getFile() ); 216 } 217 218 return model; 219 } 220 221 /** 222 * This method loops through all the parents, getting 223 * each pom model and then its parent. 224 * 225 * @param groupId the group id 226 * @param artifactId the artifact id 227 * @param version the version 228 * @param pom the pom 229 * 230 * @return the models recursively 231 * 232 * @throws ArtifactResolutionException the artifact resolution exception 233 * @throws ArtifactNotFoundException the artifact not found exception 234 * @throws IOException Signals that an I/O exception has occurred. 235 * @throws XmlPullParserException the xml pull parser exception 236 */ 237 public List<Model> getModelsRecursively ( String groupId, String artifactId, String version, File pom ) 238 throws ArtifactResolutionException, ArtifactNotFoundException, IOException, XmlPullParserException 239 { 240 List<Model> models = null; 241 Model model = getPomModel( groupId, artifactId, version, pom ); 242 243 Parent parent = model.getParent(); 244 245 // recurse into the parent 246 if ( parent != null ) 247 { 248 // get the relative path 249 String relativePath = parent.getRelativePath(); 250 if ( StringUtils.isEmpty( relativePath ) ) 251 { 252 relativePath = "../pom.xml"; 253 } 254 // calculate the recursive path 255 File parentPom = new File( pom.getParent(), relativePath ); 256 257 // if relative path is a directory, append pom.xml 258 if ( parentPom.isDirectory() ) 259 { 260 parentPom = new File( parentPom, "pom.xml" ); 261 } 262 263 models = getModelsRecursively( parent.getGroupId(), parent.getArtifactId(), parent.getVersion(), parentPom ); 264 } 265 else 266 { 267 // only create it here since I'm not at the top 268 models = new ArrayList<Model>(); 269 } 270 models.add( model ); 271 272 return models; 273 } 274 275 /** 276 * Make sure the model is the one I'm expecting. 277 * 278 * @param groupId the group id 279 * @param artifactId the artifact id 280 * @param version the version 281 * @param model Model being checked. 282 * 283 * @return true, if check if model matches 284 */ 285 protected boolean checkIfModelMatches ( String groupId, String artifactId, String version, Model model ) 286 { 287 // try these first. 288 String modelGroup = model.getGroupId(); 289 String modelArtifactId = model.getArtifactId(); 290 String modelVersion = model.getVersion(); 291 292 try 293 { 294 if ( StringUtils.isEmpty( modelGroup ) ) 295 { 296 modelGroup = model.getParent().getGroupId(); 297 } 298 else 299 { 300 // MENFORCER-30, handle cases where the value is a property like ${project.parent.groupId} 301 modelGroup = (String) helper.evaluate( modelGroup ); 302 } 303 304 if ( StringUtils.isEmpty( modelVersion ) ) 305 { 306 modelVersion = model.getParent().getVersion(); 307 } 308 else 309 { 310 // MENFORCER-30, handle cases where the value is a property like ${project.parent.version} 311 modelVersion = (String) helper.evaluate( modelVersion ); 312 } 313 314 // Is this only required for Maven2? 315 modelArtifactId = (String) helper.evaluate( modelArtifactId ); 316 } 317 catch ( NullPointerException e ) 318 { 319 // this is probably bad. I don't have a valid 320 // group or version and I can't find a 321 // parent???? 322 // lets see if it's what we're looking for 323 // anyway. 324 } 325 catch ( ExpressionEvaluationException e ) 326 { 327 // as above 328 } 329 return ( StringUtils.equals( groupId, modelGroup ) && StringUtils.equals( version, modelVersion ) && StringUtils 330 .equals( artifactId, modelArtifactId ) ); 331 } 332 333 334 private void resolve( Plugin plugin ) 335 { 336 try 337 { 338 plugin.setGroupId( (String) helper.evaluate( plugin.getGroupId() ) ); 339 plugin.setArtifactId( (String) helper.evaluate( plugin.getArtifactId() ) ); 340 plugin.setVersion( (String) helper.evaluate( plugin.getVersion() ) ); 341 } 342 catch ( ExpressionEvaluationException e ) 343 { 344 // this should have gone already before 345 } 346 } 347 348 private void resolve( ReportPlugin plugin ) 349 { 350 try 351 { 352 plugin.setGroupId( (String) helper.evaluate( plugin.getGroupId() ) ); 353 plugin.setArtifactId( (String) helper.evaluate( plugin.getArtifactId() ) ); 354 plugin.setVersion( (String) helper.evaluate( plugin.getVersion() ) ); 355 } 356 catch ( ExpressionEvaluationException e ) 357 { 358 // this should have gone already before 359 } 360 } 361 362 public List<Plugin> resolvePlugins( List<Plugin> plugins ) 363 { 364 for ( Plugin plugin : plugins ) 365 { 366 resolve( plugin ); 367 } 368 return plugins; 369 } 370 371 public List<ReportPlugin> resolveReportPlugins( List<ReportPlugin> reportPlugins ) 372 { 373 for ( ReportPlugin plugin : reportPlugins ) 374 { 375 resolve( plugin ); 376 } 377 return reportPlugins; 378 } 379 380 381}