Coverage Report - org.apache.maven.shared.test.plugin.ProjectTool
 
Classes in this File Line Coverage Branch Coverage Complexity
ProjectTool
75%
90/119
44%
8/18
3,154
ProjectTool$PomInfo
100%
14/14
N/A
3,154
 
 1  
 package org.apache.maven.shared.test.plugin;
 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.io.Writer;
 26  
 import java.util.ArrayList;
 27  
 import java.util.Iterator;
 28  
 import java.util.List;
 29  
 import java.util.Properties;
 30  
 
 31  
 import org.apache.maven.artifact.Artifact;
 32  
 import org.apache.maven.artifact.UnknownRepositoryLayoutException;
 33  
 import org.apache.maven.artifact.factory.ArtifactFactory;
 34  
 import org.apache.maven.artifact.handler.ArtifactHandler;
 35  
 import org.apache.maven.artifact.handler.manager.ArtifactHandlerManager;
 36  
 import org.apache.maven.artifact.repository.ArtifactRepository;
 37  
 import org.apache.maven.artifact.repository.ArtifactRepositoryFactory;
 38  
 import org.apache.maven.model.Build;
 39  
 import org.apache.maven.model.DeploymentRepository;
 40  
 import org.apache.maven.model.DistributionManagement;
 41  
 import org.apache.maven.model.Model;
 42  
 import org.apache.maven.model.Plugin;
 43  
 import org.apache.maven.model.Repository;
 44  
 import org.apache.maven.model.Site;
 45  
 import org.apache.maven.model.io.xpp3.MavenXpp3Reader;
 46  
 import org.apache.maven.model.io.xpp3.MavenXpp3Writer;
 47  
 import org.apache.maven.project.DefaultProjectBuildingRequest;
 48  
 import org.apache.maven.project.MavenProject;
 49  
 import org.apache.maven.project.ProjectBuilder;
 50  
 import org.apache.maven.project.ProjectBuildingException;
 51  
 import org.apache.maven.project.ProjectBuildingRequest;
 52  
 import org.apache.maven.project.artifact.ProjectArtifactMetadata;
 53  
 import org.codehaus.plexus.util.FileUtils;
 54  
 import org.codehaus.plexus.util.IOUtil;
 55  
 import org.codehaus.plexus.util.ReaderFactory;
 56  
 import org.codehaus.plexus.util.WriterFactory;
 57  
 import org.codehaus.plexus.util.xml.Xpp3Dom;
 58  
 import org.codehaus.plexus.util.xml.pull.XmlPullParserException;
 59  
 
 60  
 /**
 61  
  * Testing tool used to read MavenProject instances from pom.xml files, and to create plugin jar
 62  
  * files (package phase of the normal build process) for distribution to a test local repository
 63  
  * directory.
 64  
  *
 65  
  * @plexus.component role="org.apache.maven.shared.test.plugin.ProjectTool" role-hint="default"
 66  
  * @author jdcasey
 67  
  * @version $Id: ProjectTool.java 830359 2009-10-27 22:02:16Z bentmann $
 68  
  */
 69  3
 public class ProjectTool
 70  
 {
 71  
     /** Plexus role */
 72  1
     public static final String ROLE = ProjectTool.class.getName();
 73  
 
 74  
     public static final String INTEGRATION_TEST_DEPLOYMENT_REPO_URL = "integration-test.deployment.repo.url";
 75  
 
 76  
     /**
 77  
      * @plexus.requirement role-hint="default"
 78  
      */
 79  
     private BuildTool buildTool;
 80  
 
 81  
     /**
 82  
      * @plexus.requirement role-hint="default"
 83  
      */
 84  
     private RepositoryTool repositoryTool;
 85  
 
 86  
     /**
 87  
      * @plexus.requirement
 88  
      */
 89  
     private ProjectBuilder projectBuilder;
 90  
 
 91  
     /**
 92  
      * @plexus.requirement
 93  
      */
 94  
     private ArtifactHandlerManager artifactHandlerManager;
 95  
 
 96  
     /**
 97  
      * @plexus.requirement
 98  
      */
 99  
     private ArtifactFactory artifactFactory;
 100  
 
 101  
     /**
 102  
      * @plexus.requirement
 103  
      */    
 104  
     private ArtifactRepositoryFactory artifactRepositoryFactory;
 105  
 
 106  
     /**
 107  
      * Construct a MavenProject instance from the specified POM file.
 108  
      *
 109  
      * @param pomFile current POM file
 110  
      * @return the Maven project from a file
 111  
      * @throws TestToolsException if any
 112  
      */
 113  
     public MavenProject readProject( File pomFile )
 114  
         throws TestToolsException
 115  
     {
 116  0
         return readProject( pomFile, repositoryTool.findLocalRepositoryDirectory() );
 117  
     }
 118  
 
 119  
     /**
 120  
      * Construct a MavenProject instance from the specified POM file, using the specified local
 121  
      * repository directory to resolve ancestor POMs as needed.
 122  
      *
 123  
      * @param pomFile current POM file
 124  
      * @param localRepositoryBasedir
 125  
      * @return the Maven project from a file and a local repo
 126  
      * @throws TestToolsException if any
 127  
      */
 128  
     public MavenProject readProject( File pomFile, File localRepositoryBasedir )
 129  
         throws TestToolsException
 130  
     {
 131  
         try
 132  
         {
 133  0
             ArtifactRepository localRepository = repositoryTool
 134  
                 .createLocalArtifactRepositoryInstance( localRepositoryBasedir );
 135  
 
 136  0
             ProjectBuildingRequest request = new DefaultProjectBuildingRequest();
 137  0
             return projectBuilder.build( pomFile, request ).getProject();
 138  
         }
 139  0
         catch ( ProjectBuildingException e )
 140  
         {
 141  0
             throw new TestToolsException( "Error building MavenProject instance from test pom: " + pomFile, e );
 142  
         }
 143  
     }
 144  
 
 145  
     /**
 146  
      * Construct a MavenProject instance from the specified POM file with dependencies.
 147  
      *
 148  
      * @param pomFile current POM file
 149  
      * @return the Maven project with dependencies from a file
 150  
      * @throws TestToolsException if any
 151  
      */
 152  
     public MavenProject readProjectWithDependencies( File pomFile )
 153  
         throws TestToolsException
 154  
     {
 155  0
         return readProjectWithDependencies( pomFile, repositoryTool.findLocalRepositoryDirectory() );
 156  
     }
 157  
 
 158  
     /**
 159  
      * Construct a MavenProject instance from the specified POM file with dependencies, using the specified local
 160  
      * repository directory to resolve ancestor POMs as needed.
 161  
      *
 162  
      * @param pomFile current POM file
 163  
      * @param localRepositoryBasedir
 164  
      * @return the Maven project with dependencies from a file and a local repo
 165  
      * @throws TestToolsException if any
 166  
      */
 167  
     public MavenProject readProjectWithDependencies( File pomFile, File localRepositoryBasedir )
 168  
         throws TestToolsException
 169  
     {
 170  
         try
 171  
         {
 172  0
             ArtifactRepository localRepository = repositoryTool
 173  
                 .createLocalArtifactRepositoryInstance( localRepositoryBasedir );
 174  
 
 175  0
             ProjectBuildingRequest request = new DefaultProjectBuildingRequest();
 176  0
             return projectBuilder.build( pomFile, request ).getProject();
 177  
         }
 178  0
         catch ( ProjectBuildingException e )
 179  
         {
 180  0
             throw new TestToolsException( "Error building MavenProject instance from test pom: " + pomFile, e );
 181  
         }
 182  
     }
 183  
 
 184  
     /**
 185  
      * Run the plugin's Maven build up to the package phase, in order to produce a jar file for
 186  
      * distribution to a test-time local repository. The testVersion parameter specifies the version
 187  
      * to be used in the <version/> element of the plugin configuration, and also in fully
 188  
      * qualified, unambiguous goal invocations (as in
 189  
      * org.apache.maven.plugins:maven-eclipse-plugin:test:eclipse).
 190  
      *
 191  
      * @param pomFile The plugin's POM
 192  
      * @param testVersion The version to use for testing this plugin. To promote test resiliency,
 193  
      *   this version should remain unchanged, regardless of what plugin version is under
 194  
      *   development.
 195  
      * @param skipUnitTests In cases where test builds occur during the unit-testing phase (usually
 196  
      *   a bad testing smell), the plugin jar must be produced <b>without</b> running unit tests.
 197  
      *   Otherwise, the testing process will result in a recursive loop of building a plugin jar and
 198  
      *   trying to unit test it during the build. In these cases, set this flag to <code>true</code>.
 199  
      * @return The resulting MavenProject, after the test version and skip flag (for unit tests)
 200  
      *   have been appropriately configured.
 201  
      * @throws TestToolsException if any
 202  
      */
 203  
     public MavenProject packageProjectArtifact( File pomFile, String testVersion, boolean skipUnitTests )
 204  
         throws TestToolsException
 205  
     {
 206  2
         return packageProjectArtifact( pomFile, testVersion, skipUnitTests, null );
 207  
     }
 208  
 
 209  
     /**
 210  
      * Run the plugin's Maven build up to the package phase, in order to produce a jar file for
 211  
      * distribution to a test-time local repository. The testVersion parameter specifies the version
 212  
      * to be used in the &lt;version/&gt; element of the plugin configuration, and also in fully
 213  
      * qualified, unambiguous goal invocations (as in
 214  
      * org.apache.maven.plugins:maven-eclipse-plugin:test:eclipse).
 215  
      *
 216  
      * @param pomFile The plugin's POM
 217  
      * @param testVersion The version to use for testing this plugin. To promote test resiliency,
 218  
      *   this version should remain unchanged, regardless of what plugin version is under
 219  
      *   development.
 220  
      * @param skipUnitTests In cases where test builds occur during the unit-testing phase (usually
 221  
      *   a bad testing smell), the plugin jar must be produced <b>without</b> running unit tests.
 222  
      *   Otherwise, the testing process will result in a recursive loop of building a plugin jar and
 223  
      *   trying to unit test it during the build. In these cases, set this flag to <code>true</code>.
 224  
      * @param logFile The file to which build output should be logged, in order to allow later
 225  
      *   inspection in case this build fails.
 226  
      * @return The resulting MavenProject, after the test version and skip flag (for unit tests)
 227  
      *   have been appropriately configured.
 228  
      * @throws TestToolsException if any
 229  
      */
 230  
     public MavenProject packageProjectArtifact( File pomFile, String testVersion, boolean skipUnitTests, File logFile )
 231  
         throws TestToolsException
 232  
     {
 233  2
         PomInfo pomInfo = manglePomForTesting( pomFile, testVersion, skipUnitTests );
 234  
 
 235  2
         Properties properties = new Properties();
 236  
 
 237  2
         List goals = new ArrayList();
 238  2
         goals.add( "package" );
 239  
 
 240  2
         File buildLog = logFile == null ? pomInfo.getBuildLogFile() : logFile;
 241  2
         System.out.println( "Now Building test version of the plugin...\nUsing staged plugin-pom: "
 242  
             + pomInfo.getPomFile().getAbsolutePath() );
 243  
 
 244  2
         buildTool.executeMaven( pomInfo.getPomFile(), properties, goals, buildLog );
 245  
 
 246  2
         File artifactFile = new File( pomInfo.getPomFile().getParentFile(),
 247  
                                       pomInfo.getBuildDirectory() + "/" + pomInfo.getFinalName() );
 248  2
         System.out.println( "Using IT Plugin Jar: " + artifactFile.getAbsolutePath() );
 249  
         try
 250  
         {
 251  2
             ProjectBuildingRequest request = new DefaultProjectBuildingRequest();
 252  2
             request.setLocalRepository( artifactRepositoryFactory.createArtifactRepository( "local", new File( "target/localrepo" ).getCanonicalFile().toURL().toExternalForm(), "default", null, null ) );
 253  2
             MavenProject project = projectBuilder.build( pomInfo.getPomFile(), request ).getProject();
 254  
 
 255  2
             Artifact artifact = artifactFactory.createArtifact( project.getGroupId(), project.getArtifactId(), project
 256  
                 .getVersion(), null, project.getPackaging() );
 257  
 
 258  2
             artifact.setFile( artifactFile );
 259  2
             artifact.addMetadata( new ProjectArtifactMetadata( artifact, project.getFile() ) );
 260  
 
 261  2
             project.setArtifact( artifact );
 262  
 
 263  2
             return project;
 264  
         }
 265  0
         catch ( ProjectBuildingException e )
 266  
         {
 267  0
             throw new TestToolsException(
 268  
                                           "Error building MavenProject instance from test pom: " + pomInfo.getPomFile(),
 269  
                                           e );
 270  
         }
 271  0
         catch ( UnknownRepositoryLayoutException e )
 272  
         {
 273  0
             throw new TestToolsException(
 274  
                                          "Error building ArtifactRepository instance from test pom: " + pomInfo.getPomFile(),
 275  
                                          e );
 276  
         }
 277  0
         catch ( IOException e )
 278  
         {
 279  0
             throw new TestToolsException(
 280  
                                          "Error building ArtifactRepository instance from test pom: " + pomInfo.getPomFile(),
 281  
                                          e );
 282  
         }
 283  
     }
 284  
 
 285  
     /**
 286  
      * Inject a special version for testing, to allow tests to unambiguously reference the plugin
 287  
      * currently under test. If test builds will be executed from the unit-testing phase, also inject
 288  
      * &lt;skip&gt;true&lt;/skip&gt; into the configuration of the <code>maven-surefire-plugin</code>
 289  
      * to allow production of a test-only version of the plugin jar without running unit tests.
 290  
      *
 291  
      * @param pomFile The plugin POM
 292  
      * @param testVersion The version that allows test builds to reference the plugin under test
 293  
      * @param skipUnitTests If true, configure the surefire plugin to skip unit tests
 294  
      * @return Information about mangled POM, including the temporary file to which it was written.
 295  
      * @throws TestToolsException if any
 296  
      */
 297  
     protected PomInfo manglePomForTesting( File pomFile, String testVersion, boolean skipUnitTests )
 298  
         throws TestToolsException
 299  
     {
 300  3
         File input = pomFile;
 301  
 
 302  3
         File output = new File( pomFile.getParentFile(), "pom-" + testVersion + ".xml" );
 303  3
         output.deleteOnExit();
 304  
 
 305  3
         Reader reader = null;
 306  3
         Writer writer = null;
 307  
 
 308  3
         Model model = null;
 309  3
         String finalName = null;
 310  3
         String buildDirectory = null;
 311  
 
 312  
         try
 313  
         {
 314  3
             reader = ReaderFactory.newXmlReader( input );
 315  
 
 316  3
             model = new MavenXpp3Reader().read( reader );
 317  
         }
 318  0
         catch ( IOException e )
 319  
         {
 320  0
             throw new TestToolsException( "Error creating test-time version of POM for: " + input, e );
 321  
         }
 322  0
         catch ( XmlPullParserException e )
 323  
         {
 324  0
             throw new TestToolsException( "Error creating test-time version of POM for: " + input, e );
 325  
         }
 326  
         finally
 327  
         {
 328  3
             IOUtil.close( reader );
 329  3
         }
 330  
 
 331  
         try
 332  
         {
 333  3
             model.setVersion( testVersion );
 334  
 
 335  3
             Build build = model.getBuild();
 336  3
             if ( build == null )
 337  
             {
 338  3
                 build = new Build();
 339  
             }
 340  3
             buildDirectory = build.getDirectory();
 341  
 
 342  3
             if ( buildDirectory == null )
 343  
             {
 344  3
                 buildDirectory = "target";
 345  
             }
 346  
 
 347  3
             buildDirectory = ( buildDirectory + File.separatorChar + "it-build-target" );
 348  3
             build.setDirectory( buildDirectory );
 349  3
             build.setOutputDirectory( buildDirectory + File.separatorChar + "classes" );
 350  3
             System.out.println( "Using " + build.getDirectory() + " and " + build.getOutputDirectory()
 351  
                 + " to build IT version of plugin" );
 352  3
             model.setBuild( build );
 353  
 
 354  3
             finalName = build.getFinalName();
 355  
 
 356  3
             if ( finalName == null )
 357  
             {
 358  3
                 ArtifactHandler handler = artifactHandlerManager.getArtifactHandler( model.getPackaging() );
 359  
 
 360  3
                 String ext = handler.getExtension();
 361  
 
 362  3
                 finalName = model.getArtifactId() + "-" + model.getVersion() + "." + ext;
 363  
             }
 364  
 
 365  3
             DistributionManagement distMgmt = new DistributionManagement();
 366  
 
 367  3
             DeploymentRepository deployRepo = new DeploymentRepository();
 368  
 
 369  3
             deployRepo.setId( "integration-test.output" );
 370  
 
 371  3
             File tmpDir = FileUtils.createTempFile( "integration-test-repo", "", null );
 372  3
             String tmpUrl = tmpDir.toURL().toExternalForm();
 373  
 
 374  3
             deployRepo.setUrl( tmpUrl );
 375  
 
 376  3
             distMgmt.setRepository( deployRepo );
 377  3
             distMgmt.setSnapshotRepository( deployRepo );
 378  
 
 379  3
             Repository localAsRemote = new Repository();
 380  3
             localAsRemote.setId( "testing.mainLocalAsRemote" );
 381  
 
 382  3
             File localRepoDir = repositoryTool.findLocalRepositoryDirectory();
 383  3
             localAsRemote.setUrl( localRepoDir.toURL().toExternalForm() );
 384  
 
 385  3
             model.addRepository( localAsRemote );
 386  3
             model.addPluginRepository( localAsRemote );
 387  
 
 388  3
             Site site = new Site();
 389  
 
 390  3
             site.setId( "integration-test.output" );
 391  3
             site.setUrl( tmpUrl );
 392  
 
 393  3
             distMgmt.setSite( site );
 394  
 
 395  3
             model.setDistributionManagement( distMgmt );
 396  
 
 397  3
             model.addProperty( INTEGRATION_TEST_DEPLOYMENT_REPO_URL, tmpUrl );
 398  
 
 399  3
             if ( skipUnitTests )
 400  
             {
 401  3
                 List plugins = build.getPlugins();
 402  3
                 Plugin plugin = null;
 403  3
                 for ( Iterator iter = plugins.iterator(); iter.hasNext(); )
 404  
                 {
 405  0
                     Plugin plug = (Plugin) iter.next();
 406  
 
 407  0
                     if ( "maven-surefire-plugin".equals( plug.getArtifactId() ) )
 408  
                     {
 409  0
                         plugin = plug;
 410  0
                         break;
 411  
                     }
 412  0
                 }
 413  
 
 414  3
                 if ( plugin == null )
 415  
                 {
 416  3
                     plugin = new Plugin();
 417  3
                     plugin.setArtifactId( "maven-surefire-plugin" );
 418  3
                     build.addPlugin( plugin );
 419  
                 }
 420  
 
 421  3
                 Xpp3Dom configDom = (Xpp3Dom) plugin.getConfiguration();
 422  3
                 if ( configDom == null )
 423  
                 {
 424  3
                     configDom = new Xpp3Dom( "configuration" );
 425  3
                     plugin.setConfiguration( configDom );
 426  
                 }
 427  
 
 428  3
                 Xpp3Dom skipDom = new Xpp3Dom( "skip" );
 429  3
                 skipDom.setValue( "true" );
 430  
 
 431  3
                 configDom.addChild( skipDom );
 432  
             }
 433  
 
 434  3
             writer = WriterFactory.newXmlWriter( output );
 435  
 
 436  3
             new MavenXpp3Writer().write( writer, model );
 437  
         }
 438  0
         catch ( IOException e )
 439  
         {
 440  0
             throw new TestToolsException( "Error creating test-time version of POM for: " + input, e );
 441  
         }
 442  
         finally
 443  
         {
 444  3
             IOUtil.close( writer );
 445  3
         }
 446  
 
 447  3
         return new PomInfo( output, model.getGroupId(), model.getArtifactId(), model.getVersion(),
 448  
                             model.getBuild().getDirectory(), model.getBuild().getOutputDirectory(), finalName );
 449  
     }
 450  
 
 451  3
     static final class PomInfo
 452  
     {
 453  
         private final File pomFile;
 454  
 
 455  
         private final String groupId;
 456  
 
 457  
         private final String artifactId;
 458  
 
 459  
         private final String version;
 460  
 
 461  
         private final String finalName;
 462  
 
 463  
         private final String buildDirectory;
 464  
 
 465  
         private final String buildOutputDirectory;
 466  
 
 467  
         PomInfo( File pomFile, String groupId, String artifactId, String version, String buildDirectory,
 468  
                  String buildOutputDirectory, String finalName )
 469  3
         {
 470  3
             this.pomFile = pomFile;
 471  3
             this.groupId = groupId;
 472  3
             this.artifactId = artifactId;
 473  3
             this.version = version;
 474  3
             this.buildDirectory = buildDirectory;
 475  3
             this.buildOutputDirectory = buildOutputDirectory;
 476  3
             this.finalName = finalName;
 477  3
         }
 478  
 
 479  
         File getPomFile()
 480  
         {
 481  8
             return pomFile;
 482  
         }
 483  
 
 484  
         String getBuildDirectory()
 485  
         {
 486  3
             return buildDirectory;
 487  
         }
 488  
 
 489  
         String getBuildOutputDirectory()
 490  
         {
 491  1
             return buildOutputDirectory;
 492  
         }
 493  
 
 494  
         String getFinalName()
 495  
         {
 496  3
             return finalName;
 497  
         }
 498  
 
 499  
         File getBuildLogFile()
 500  
         {
 501  2
             return new File( buildDirectory + "/test-build-logs/" + groupId + "_" + artifactId + "_" + version
 502  
                 + ".build.log" );
 503  
         }
 504  
     }
 505  
 }