Coverage Report - org.apache.maven.shared.test.plugin.ProjectTool
 
Classes in this File Line Coverage Branch Coverage Complexity
ProjectTool
100%
62/62
N/A
2,8
ProjectTool$PomInfo
100%
12/12
N/A
2,8
 
 1  
 /*
 2  
  * Licensed to the Apache Software Foundation (ASF) under one
 3  
  * or more contributor license agreements.  See the NOTICE file
 4  
  * distributed with this work for additional information
 5  
  * regarding copyright ownership.  The ASF licenses this file
 6  
  * to you under the Apache License, Version 2.0 (the
 7  
  * "License"); you may not use this file except in compliance
 8  
  * with the License.  You may obtain a copy of the License at
 9  
  *
 10  
  *   http://www.apache.org/licenses/LICENSE-2.0
 11  
  *
 12  
  * Unless required by applicable law or agreed to in writing,
 13  
  * software distributed under the License is distributed on an
 14  
  * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
 15  
  * KIND, either express or implied.  See the License for the
 16  
  * specific language governing permissions and limitations
 17  
  * under the License.
 18  
  */
 19  
 package org.apache.maven.shared.test.plugin;
 20  
 
 21  
 import java.io.File;
 22  
 import java.io.FileReader;
 23  
 import java.io.FileWriter;
 24  
 import java.io.IOException;
 25  
 import java.util.ArrayList;
 26  
 import java.util.Iterator;
 27  
 import java.util.List;
 28  
 import java.util.Properties;
 29  
 
 30  
 import org.apache.maven.artifact.Artifact;
 31  
 import org.apache.maven.artifact.factory.ArtifactFactory;
 32  
 import org.apache.maven.artifact.handler.ArtifactHandler;
 33  
 import org.apache.maven.artifact.handler.manager.ArtifactHandlerManager;
 34  
 import org.apache.maven.artifact.repository.ArtifactRepository;
 35  
 import org.apache.maven.model.Build;
 36  
 import org.apache.maven.model.Model;
 37  
 import org.apache.maven.model.Plugin;
 38  
 import org.apache.maven.model.io.xpp3.MavenXpp3Reader;
 39  
 import org.apache.maven.model.io.xpp3.MavenXpp3Writer;
 40  
 import org.apache.maven.project.MavenProject;
 41  
 import org.apache.maven.project.MavenProjectBuilder;
 42  
 import org.apache.maven.project.ProjectBuildingException;
 43  
 import org.apache.maven.project.artifact.ProjectArtifactMetadata;
 44  
 import org.codehaus.plexus.util.IOUtil;
 45  
 import org.codehaus.plexus.util.xml.Xpp3Dom;
 46  
 import org.codehaus.plexus.util.xml.pull.XmlPullParserException;
 47  
 
 48  
 /**
 49  
  * Testing tool used to read MavenProject instances from pom.xml files, and to create plugin jar
 50  
  * files (package phase of the normal build process) for distribution to a test local repository
 51  
  * directory.
 52  
  * 
 53  
  * @plexus.component role="org.apache.maven.shared.test.plugin.ProjectTool" role-hint="default"
 54  
  * @author jdcasey
 55  
  */
 56  3
 public class ProjectTool
 57  
 {
 58  2
     public static final String ROLE = ProjectTool.class.getName();
 59  
 
 60  
     /**
 61  
      * @plexus.requirement role-hint="default"
 62  
      */
 63  
     private BuildTool buildTool;
 64  
 
 65  
     /**
 66  
      * @plexus.requirement role-hint="default"
 67  
      */
 68  
     private RepositoryTool repositoryTool;
 69  
 
 70  
     /**
 71  
      * @plexus.requirement
 72  
      */
 73  
     private MavenProjectBuilder projectBuilder;
 74  
 
 75  
     /**
 76  
      * @plexus.requirement
 77  
      */
 78  
     private ArtifactHandlerManager artifactHandlerManager;
 79  
 
 80  
     /**
 81  
      * @plexus.requirement
 82  
      */
 83  
     private ArtifactFactory artifactFactory;
 84  
 
 85  
     /**
 86  
      * Construct a MavenProject instance from the specified POM file.
 87  
      */
 88  
     public MavenProject readProject( File pomFile )
 89  
         throws TestToolsException
 90  
     {
 91  
         return readProject( pomFile, repositoryTool.findLocalRepositoryDirectory() );
 92  
     }
 93  
 
 94  
     /**
 95  
      * Construct a MavenProject instance from the specified POM file, using the specified local
 96  
      * repository directory to resolve ancestor POMs as needed.
 97  
      */
 98  
     public MavenProject readProject( File pomFile, File localRepositoryBasedir )
 99  
         throws TestToolsException
 100  
     {
 101  
         try
 102  
         {
 103  
             ArtifactRepository localRepository = repositoryTool
 104  
                 .createLocalArtifactRepositoryInstance( localRepositoryBasedir );
 105  
 
 106  
             return projectBuilder.build( pomFile, localRepository, null );
 107  
         }
 108  
         catch ( ProjectBuildingException e )
 109  
         {
 110  
             throw new TestToolsException( "Error building MavenProject instance from test pom: " + pomFile, e );
 111  
         }
 112  
     }
 113  
 
 114  
     /**
 115  
      * Run the plugin's Maven build up to the package phase, in order to produce a jar file for 
 116  
      * distribution to a test-time local repository. The testVersion parameter specifies the version
 117  
      * to be used in the <version/> element of the plugin configuration, and also in fully
 118  
      * qualified, unambiguous goal invocations (as in 
 119  
      * org.apache.maven.plugins:maven-eclipse-plugin:test:eclipse).
 120  
      * 
 121  
      * @param pomFile The plugin's POM
 122  
      * @param testVersion The version to use for testing this plugin. To promote test resiliency, 
 123  
      *   this version should remain unchanged, regardless of what plugin version is under 
 124  
      *   development.
 125  
      * @param skipUnitTests In cases where test builds occur during the unit-testing phase (usually
 126  
      *   a bad testing smell), the plugin jar must be produced <b>without</b> running unit tests.
 127  
      *   Otherwise, the testing process will result in a recursive loop of building a plugin jar and
 128  
      *   trying to unit test it during the build. In these cases, set this flag to <code>true</code>.
 129  
      * @return The resulting MavenProject, after the test version and skip flag (for unit tests) 
 130  
      *   have been appropriately configured.
 131  
      */
 132  
     public MavenProject packageProjectArtifact( File pomFile, String testVersion, boolean skipUnitTests )
 133  
         throws TestToolsException
 134  
     {
 135  2
         return packageProjectArtifact( pomFile, testVersion, skipUnitTests, null );
 136  
     }
 137  
 
 138  
     /**
 139  
      * Run the plugin's Maven build up to the package phase, in order to produce a jar file for 
 140  
      * distribution to a test-time local repository. The testVersion parameter specifies the version
 141  
      * to be used in the &lt;version/&gt; element of the plugin configuration, and also in fully
 142  
      * qualified, unambiguous goal invocations (as in 
 143  
      * org.apache.maven.plugins:maven-eclipse-plugin:test:eclipse).
 144  
      * 
 145  
      * @param pomFile The plugin's POM
 146  
      * @param testVersion The version to use for testing this plugin. To promote test resiliency, 
 147  
      *   this version should remain unchanged, regardless of what plugin version is under 
 148  
      *   development.
 149  
      * @param skipUnitTests In cases where test builds occur during the unit-testing phase (usually
 150  
      *   a bad testing smell), the plugin jar must be produced <b>without</b> running unit tests.
 151  
      *   Otherwise, the testing process will result in a recursive loop of building a plugin jar and
 152  
      *   trying to unit test it during the build. In these cases, set this flag to <code>true</code>.
 153  
      * @param logFile The file to which build output should be logged, in order to allow later 
 154  
      *   inspection in case this build fails.
 155  
      * @return The resulting MavenProject, after the test version and skip flag (for unit tests) 
 156  
      *   have been appropriately configured.
 157  
      */
 158  
     public MavenProject packageProjectArtifact( File pomFile, String testVersion, boolean skipUnitTests, File logFile )
 159  
         throws TestToolsException
 160  
     {
 161  2
         PomInfo pomInfo = manglePomForTesting( pomFile, testVersion, skipUnitTests );
 162  
 
 163  2
         Properties properties = new Properties();
 164  
 
 165  2
         List goals = new ArrayList();
 166  2
         goals.add( "package" );
 167  
 
 168  2
         File buildLog = logFile == null ? pomInfo.getBuildLogFile() : logFile;
 169  
 
 170  2
         buildTool.executeMaven( pomInfo.getPomFile(), properties, goals, buildLog );
 171  
 
 172  2
         File artifactFile = new File( pomInfo.getBuildOutputDirectory() + "/" + pomInfo.getFinalName() );
 173  
 
 174  
         try
 175  
         {
 176  2
             MavenProject project = projectBuilder.build( pomInfo.getPomFile(), repositoryTool
 177  
                 .createLocalArtifactRepositoryInstance(), null );
 178  
 
 179  2
             Artifact artifact = artifactFactory.createArtifact( project.getGroupId(), project.getArtifactId(), project
 180  
                 .getVersion(), null, project.getPackaging() );
 181  
 
 182  2
             artifact.setFile( artifactFile );
 183  2
             artifact.addMetadata( new ProjectArtifactMetadata( artifact, project.getFile() ) );
 184  
 
 185  2
             project.setArtifact( artifact );
 186  
 
 187  2
             return project;
 188  
         }
 189  
         catch ( ProjectBuildingException e )
 190  
         {
 191  
             throw new TestToolsException(
 192  
                                           "Error building MavenProject instance from test pom: " + pomInfo.getPomFile(),
 193  
                                           e );
 194  
         }
 195  
     }
 196  
 
 197  
     /**
 198  
      * Inject a special version for testing, to allow tests to unambiguously reference the plugin
 199  
      * currently under test. If test builds will be executed from the unit-testing phase, also inject
 200  
      * &lt;skip&gt;true&lt;/skip&gt; into the configuration of the <code>maven-surefire-plugin</code>
 201  
      * to allow production of a test-only version of the plugin jar without running unit tests.
 202  
      * 
 203  
      * @param pomFile The plugin POM
 204  
      * @param testVersion The version that allows test builds to reference the plugin under test
 205  
      * @param skipUnitTests If true, configure the surefire plugin to skip unit tests
 206  
      * @return Information about mangled POM, including the temporary file to which it was written.
 207  
      */
 208  
     protected PomInfo manglePomForTesting( File pomFile, String testVersion, boolean skipUnitTests )
 209  
         throws TestToolsException
 210  
     {
 211  3
         File input = new File( "pom.xml" );
 212  
 
 213  3
         File output = new File( "pom-test.xml" );
 214  3
         output.deleteOnExit();
 215  
 
 216  3
         FileReader reader = null;
 217  3
         FileWriter writer = null;
 218  
 
 219  3
         Model model = null;
 220  3
         String finalName = null;
 221  3
         String buildOutputDirectory = null;
 222  
 
 223  
         try
 224  
         {
 225  3
             reader = new FileReader( input );
 226  3
             writer = new FileWriter( output );
 227  
 
 228  3
             model = new MavenXpp3Reader().read( reader );
 229  
 
 230  3
             model.setVersion( testVersion );
 231  
 
 232  3
             Build build = model.getBuild();
 233  3
             if ( build == null )
 234  
             {
 235  
                 build = new Build();
 236  
                 model.setBuild( build );
 237  
             }
 238  
 
 239  3
             finalName = build.getFinalName();
 240  
 
 241  3
             if ( finalName == null )
 242  
             {
 243  3
                 ArtifactHandler handler = artifactHandlerManager.getArtifactHandler( model.getPackaging() );
 244  
 
 245  3
                 String ext = handler.getExtension();
 246  
 
 247  3
                 finalName = model.getArtifactId() + "-" + model.getVersion() + "." + ext;
 248  
             }
 249  
 
 250  3
             buildOutputDirectory = build.getOutputDirectory();
 251  
 
 252  3
             if ( buildOutputDirectory == null )
 253  
             {
 254  3
                 buildOutputDirectory = "target";
 255  
             }
 256  
 
 257  3
             if ( skipUnitTests )
 258  
             {
 259  3
                 List plugins = build.getPlugins();
 260  3
                 Plugin plugin = null;
 261  3
                 for ( Iterator iter = plugins.iterator(); iter.hasNext(); )
 262  
                 {
 263  3
                     Plugin plug = (Plugin) iter.next();
 264  
 
 265  3
                     if ( "maven-surefire-plugin".equals( plug.getArtifactId() ) )
 266  
                     {
 267  
                         plugin = plug;
 268  
                         break;
 269  
                     }
 270  3
                 }
 271  
 
 272  3
                 if ( plugin == null )
 273  
                 {
 274  3
                     plugin = new Plugin();
 275  3
                     plugin.setArtifactId( "maven-surefire-plugin" );
 276  3
                     build.addPlugin( plugin );
 277  
                 }
 278  
 
 279  3
                 Xpp3Dom configDom = (Xpp3Dom) plugin.getConfiguration();
 280  3
                 if ( configDom == null )
 281  
                 {
 282  3
                     configDom = new Xpp3Dom( "configuration" );
 283  3
                     plugin.setConfiguration( configDom );
 284  
                 }
 285  
 
 286  3
                 Xpp3Dom skipDom = new Xpp3Dom( "skip" );
 287  3
                 skipDom.setValue( "true" );
 288  
 
 289  3
                 configDom.addChild( skipDom );
 290  
             }
 291  
 
 292  3
             new MavenXpp3Writer().write( writer, model );
 293  
         }
 294  
         catch ( IOException e )
 295  
         {
 296  
             throw new TestToolsException( "Error creating test-time version of POM for: " + input, e );
 297  
         }
 298  
         catch ( XmlPullParserException e )
 299  
         {
 300  
             throw new TestToolsException( "Error creating test-time version of POM for: " + input, e );
 301  
         }
 302  
         finally
 303  
         {
 304  3
             IOUtil.close( reader );
 305  3
             IOUtil.close( writer );
 306  3
         }
 307  
 
 308  3
         return new PomInfo( output, model.getGroupId(), model.getArtifactId(), model.getVersion(),
 309  
                             buildOutputDirectory, finalName );
 310  
     }
 311  
 
 312  3
     static final class PomInfo
 313  
     {
 314  
         private final File pomFile;
 315  
 
 316  
         private final String groupId;
 317  
 
 318  
         private final String artifactId;
 319  
 
 320  
         private final String version;
 321  
 
 322  
         private final String finalName;
 323  
 
 324  
         private final String buildOutputDirectory;
 325  
 
 326  
         PomInfo( File pomFile, String groupId, String artifactId, String version, String buildOutputDirectory,
 327  
                  String finalName )
 328  3
         {
 329  3
             this.pomFile = pomFile;
 330  3
             this.groupId = groupId;
 331  3
             this.artifactId = artifactId;
 332  3
             this.version = version;
 333  3
             this.buildOutputDirectory = buildOutputDirectory;
 334  3
             this.finalName = finalName;
 335  3
         }
 336  
 
 337  
         File getPomFile()
 338  
         {
 339  4
             return pomFile;
 340  
         }
 341  
 
 342  
         String getBuildOutputDirectory()
 343  
         {
 344  3
             return buildOutputDirectory;
 345  
         }
 346  
 
 347  
         String getFinalName()
 348  
         {
 349  3
             return finalName;
 350  
         }
 351  
 
 352  
         File getBuildLogFile()
 353  
         {
 354  2
             return new File( buildOutputDirectory + "/test-build-logs/" + groupId + "_" + artifactId + "_" + version
 355  
                 + ".build.log" );
 356  
         }
 357  
 
 358  
     }
 359  
 
 360  
 }