Coverage Report - org.apache.maven.shared.test.plugin.RepositoryTool
 
Classes in this File Line Coverage Branch Coverage Complexity
RepositoryTool
61%
53/86
41%
10/24
6.167
 
 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.net.MalformedURLException;
 26  
 
 27  
 import org.apache.maven.artifact.Artifact;
 28  
 import org.apache.maven.artifact.factory.ArtifactFactory;
 29  
 import org.apache.maven.artifact.installer.ArtifactInstallationException;
 30  
 import org.apache.maven.artifact.installer.ArtifactInstaller;
 31  
 import org.apache.maven.artifact.repository.ArtifactRepository;
 32  
 import org.apache.maven.artifact.repository.ArtifactRepositoryFactory;
 33  
 import org.apache.maven.artifact.repository.layout.ArtifactRepositoryLayout;
 34  
 import org.apache.maven.execution.DefaultMavenExecutionRequest;
 35  
 import org.apache.maven.execution.DefaultMavenExecutionResult;
 36  
 import org.apache.maven.execution.MavenSession;
 37  
 import org.apache.maven.model.Model;
 38  
 import org.apache.maven.model.Parent;
 39  
 import org.apache.maven.model.io.xpp3.MavenXpp3Reader;
 40  
 import org.apache.maven.plugin.LegacySupport;
 41  
 import org.apache.maven.project.MavenProject;
 42  
 import org.apache.maven.project.artifact.ProjectArtifactMetadata;
 43  
 import org.apache.maven.repository.internal.MavenRepositorySystemSession;
 44  
 import org.apache.maven.settings.MavenSettingsBuilder;
 45  
 import org.apache.maven.settings.Settings;
 46  
 import org.codehaus.plexus.PlexusConstants;
 47  
 import org.codehaus.plexus.PlexusContainer;
 48  
 import org.codehaus.plexus.component.annotations.Component;
 49  
 import org.codehaus.plexus.component.annotations.Requirement;
 50  
 import org.codehaus.plexus.component.repository.exception.ComponentLookupException;
 51  
 import org.codehaus.plexus.context.Context;
 52  
 import org.codehaus.plexus.context.ContextException;
 53  
 import org.codehaus.plexus.personality.plexus.lifecycle.phase.Contextualizable;
 54  
 import org.codehaus.plexus.util.IOUtil;
 55  
 import org.codehaus.plexus.util.ReaderFactory;
 56  
 import org.codehaus.plexus.util.StringUtils;
 57  
 import org.codehaus.plexus.util.xml.pull.XmlPullParserException;
 58  
 
 59  
 /**
 60  
  * Tools to access and manage Maven repositories for test builds, including construction of a local
 61  
  * repository directory structure.
 62  
  *
 63  
  * <p>
 64  
  * <b>WARNING:</b> Currently, the <code>createLocalRepositoryFromPlugin</code> method will not
 65  
  * resolve parent POMs that exist <b>only</b> in your normal local repository, and are not reachable
 66  
  * using the relativePath element. This may result in failed test builds, as one or more of the
 67  
  * plugin's ancestor POMs cannot be resolved.
 68  
  * </p>
 69  
  *
 70  
  * @author jdcasey
 71  
  * @version $Id: RepositoryTool.java 1185951 2011-10-19 02:43:50Z ifedorenko $
 72  
  */
 73  
 @Component( role = RepositoryTool.class )
 74  8
 public class RepositoryTool
 75  
     implements Contextualizable
 76  
 {
 77  
     /** Plexus role */
 78  2
     public static final String ROLE = RepositoryTool.class.getName();
 79  
 
 80  
     @Requirement
 81  
     private ArtifactRepositoryFactory repositoryFactory;
 82  
 
 83  
     @Requirement
 84  
     private MavenSettingsBuilder settingsBuilder;
 85  
 
 86  
     @Requirement
 87  
     private ArtifactFactory artifactFactory;
 88  
 
 89  
     @Requirement
 90  
     private ArtifactInstaller artifactInstaller;
 91  
 
 92  
     @Requirement
 93  
     private LegacySupport legacySupport;
 94  
 
 95  
     // contextualized.
 96  
     private PlexusContainer container;
 97  
 
 98  
     /**
 99  
      * Lookup and return the location of the normal Maven local repository.
 100  
      *
 101  
      * @return the location of the normal Maven local repository.
 102  
      * @throws TestToolsException if any
 103  
      */
 104  
     public File findLocalRepositoryDirectory()
 105  
         throws TestToolsException
 106  
     {
 107  6
         String localRepo = System.getProperty( "maven.local.repo" );
 108  6
         if ( StringUtils.isNotEmpty( localRepo ) )
 109  
         {
 110  0
             return new File( localRepo );
 111  
         }
 112  
 
 113  
         Settings settings;
 114  
         try
 115  
         {
 116  6
             DefaultMavenExecutionRequest request = new DefaultMavenExecutionRequest();
 117  6
             request.setUserSettingsFile( new File( System.getProperty( "user.home" ), ".m2/settings.xml" ) );
 118  6
             request.setGlobalSettingsFile( new File( System.getProperty( "maven.home" ), "conf/settings.xml" ) );
 119  6
             settings = settingsBuilder.buildSettings( request );
 120  
         }
 121  0
         catch ( IOException e )
 122  
         {
 123  0
             throw new TestToolsException( "Error building Maven settings.", e );
 124  
         }
 125  0
         catch ( XmlPullParserException e )
 126  
         {
 127  0
             throw new TestToolsException( "Error building Maven settings.", e );
 128  6
         }
 129  
 
 130  6
         if ( settings == null || settings.getLocalRepository() == null
 131  
             || settings.getLocalRepository().trim().length() < 1 )
 132  
         {
 133  6
             return new File( System.getProperty( "user.home" ), ".m2/repository" );
 134  
         }
 135  
 
 136  0
         return new File( settings.getLocalRepository() );
 137  
     }
 138  
 
 139  
     /**
 140  
      * Construct an ArtifactRepository instance that refers to the normal Maven local repository.
 141  
      *
 142  
      * @return an ArtifactRepository instance
 143  
      * @throws TestToolsException if any
 144  
      */
 145  
     public ArtifactRepository createLocalArtifactRepositoryInstance()
 146  
         throws TestToolsException
 147  
     {
 148  0
         File localRepoDir = findLocalRepositoryDirectory();
 149  
 
 150  0
         return createLocalArtifactRepositoryInstance( localRepoDir );
 151  
     }
 152  
 
 153  
     /**
 154  
      * Construct an ArtifactRepository instance that refers to the test-time Maven local repository.
 155  
      *
 156  
      * @param localRepositoryDirectory The location of the local repository to be used for test builds.
 157  
      * @return an ArtifactRepository instance
 158  
      * @throws TestToolsException if any
 159  
      */
 160  
     public ArtifactRepository createLocalArtifactRepositoryInstance( File localRepositoryDirectory )
 161  
         throws TestToolsException
 162  
     {
 163  
         ArtifactRepositoryLayout defaultLayout;
 164  
         try
 165  
         {
 166  2
             defaultLayout = (ArtifactRepositoryLayout) container.lookup( ArtifactRepositoryLayout.ROLE, "default" );
 167  
         }
 168  0
         catch ( ComponentLookupException e )
 169  
         {
 170  0
             throw new TestToolsException( "Error retrieving default repository layout.", e );
 171  2
         }
 172  
 
 173  
         try
 174  
         {
 175  2
             return repositoryFactory.createArtifactRepository( "local", localRepositoryDirectory.toURL()
 176  
                 .toExternalForm(), defaultLayout, null, null );
 177  
         }
 178  0
         catch ( MalformedURLException e )
 179  
         {
 180  0
             throw new TestToolsException( "Error converting local repo directory to a URL.", e );
 181  
         }
 182  
     }
 183  
 
 184  
     /**
 185  
      * Install a test version of a plugin - along with its POM, and as many ancestor POMs as can be
 186  
      * reached using the &lt;relativePath/&gt; element - to a clean local repository directory for
 187  
      * use in test builds.
 188  
      *
 189  
      * <p>
 190  
      * <b>WARNING:</b> Currently, this method will not resolve parent POMs that exist <b>only</b> in
 191  
      * your normal local repository, and are not reachable using the relativePath element. This may
 192  
      * result in failed test builds, as one or more of the plugin's ancestor POMs cannot be resolved.
 193  
      * </p>
 194  
      *
 195  
      * @param project
 196  
      * @param realPomFile
 197  
      * @param targetLocalRepoBasedir
 198  
      * @throws TestToolsException if any
 199  
      */
 200  
     public void createLocalRepositoryFromComponentProject( MavenProject project, File realPomFile,
 201  
                                                            File targetLocalRepoBasedir )
 202  
         throws TestToolsException
 203  
     {
 204  2
         Artifact artifact = project.getArtifact();
 205  
 
 206  2
         if ( "pom".equals( project.getPackaging() ) )
 207  
         {
 208  0
             artifact.setFile( project.getFile() );
 209  
         }
 210  
 
 211  2
         ArtifactRepository localRepository = createLocalArtifactRepositoryInstance( targetLocalRepoBasedir );
 212  
 
 213  2
         String localPath = localRepository.pathOf( artifact );
 214  
 
 215  2
         File destination = new File( localRepository.getBasedir(), localPath );
 216  2
         if ( !destination.getParentFile().exists() )
 217  
         {
 218  2
             destination.getParentFile().mkdirs();
 219  
         }
 220  
 
 221  2
         legacySupport.setSession( new MavenSession( container, new MavenRepositorySystemSession(),
 222  
                                                     new DefaultMavenExecutionRequest(),
 223  
                                                     new DefaultMavenExecutionResult() ) );
 224  
         try
 225  
         {
 226  2
             artifactInstaller.install( artifact.getFile(), artifact, localRepository );
 227  
         }
 228  0
         catch ( ArtifactInstallationException e )
 229  
         {
 230  0
             throw new TestToolsException( "Error installing plugin artifact to target local repository: "
 231  
                 + targetLocalRepoBasedir, e );
 232  
         }
 233  
         finally
 234  
         {
 235  2
             legacySupport.setSession( null );
 236  2
         }
 237  
 
 238  2
         installLocallyReachableAncestorPoms( realPomFile, localRepository );
 239  2
     }
 240  
 
 241  
     /**
 242  
      * Traverse &lt;relativePath/&gt; links for successive POMs in the plugin's ancestry, installing
 243  
      * each one into the test-time local repository.
 244  
      *
 245  
      * @param realPomFile The real plugin POM; a starting point, but the POM is already installed,
 246  
      *   so we won't actually install this file, only use it to locate parents.
 247  
      * @param localRepo The test-time local repository instance
 248  
      * @throws TestToolsException if any
 249  
      */
 250  
     private void installLocallyReachableAncestorPoms( File realPomFile, ArtifactRepository localRepo )
 251  
         throws TestToolsException
 252  
     {
 253  2
         MavenXpp3Reader pomReader = new MavenXpp3Reader();
 254  
 
 255  2
         File pom = realPomFile;
 256  
 
 257  2
         boolean firstPass = true;
 258  
 
 259  4
         while ( pom != null )
 260  
         {
 261  
 
 262  2
             if ( !pom.exists() )
 263  
             {
 264  0
                 pom = null;
 265  0
                 break;
 266  
             }
 267  
 
 268  2
             String pomGroupId = null;
 269  2
             String pomArtifactId = null;
 270  2
             String pomVersion = null;
 271  
 
 272  2
             Reader reader = null;
 273  
 
 274  2
             File currentPom = pom;
 275  
 
 276  
             try
 277  
             {
 278  2
                 reader = ReaderFactory.newXmlReader( pom );
 279  
 
 280  2
                 Model model = pomReader.read( reader );
 281  
 
 282  2
                 pomGroupId = model.getGroupId();
 283  2
                 pomArtifactId = model.getArtifactId();
 284  2
                 pomVersion = model.getVersion();
 285  
 
 286  2
                 Parent parent = model.getParent();
 287  2
                 if ( parent != null )
 288  
                 {
 289  0
                     pom = new File( pom.getParentFile(), parent.getRelativePath() );
 290  
 
 291  0
                     if ( pomGroupId == null )
 292  
                     {
 293  0
                         pomGroupId = parent.getGroupId();
 294  
                     }
 295  
 
 296  0
                     if ( pomVersion == null )
 297  
                     {
 298  0
                         pomVersion = parent.getVersion();
 299  
                     }
 300  
                 }
 301  
                 else
 302  
                 {
 303  2
                     pom = null;
 304  
                 }
 305  
             }
 306  0
             catch ( IOException e )
 307  
             {
 308  0
                 throw new TestToolsException( "Error reading ancestor POM: " + currentPom, e );
 309  
             }
 310  0
             catch ( XmlPullParserException e )
 311  
             {
 312  0
                 throw new TestToolsException( "Error reading ancestor POM: " + currentPom, e );
 313  
             }
 314  
             finally
 315  
             {
 316  2
                 IOUtil.close( reader );
 317  2
             }
 318  
 
 319  2
             if ( !firstPass )
 320  
             {
 321  0
                 Artifact pomArtifact = artifactFactory.createProjectArtifact( pomGroupId, pomArtifactId, pomVersion );
 322  0
                 pomArtifact.addMetadata( new ProjectArtifactMetadata( pomArtifact, currentPom ) );
 323  
 
 324  
                 try
 325  
                 {
 326  0
                     artifactInstaller.install( currentPom, pomArtifact, localRepo );
 327  
                 }
 328  0
                 catch ( ArtifactInstallationException e )
 329  
                 {
 330  0
                     throw new TestToolsException( "Error installing ancestor POM: " + currentPom
 331  
                         + " to target local repository: " + localRepo.getBasedir(), e );
 332  0
                 }
 333  0
             }
 334  
             else
 335  
             {
 336  2
                 firstPass = false;
 337  
             }
 338  2
         }
 339  2
     }
 340  
 
 341  
     /**
 342  
      * Retrieve the PlexusContainer instance used to instantiate this component. The container is
 343  
      * used to retrieve the default ArtifactRepositoryLayout component, for use in constructing
 344  
      * instances of ArtifactRepository that can be used to access local repositories.
 345  
      *
 346  
      * @see org.codehaus.plexus.personality.plexus.lifecycle.phase.Contextualizable#contextualize(org.codehaus.plexus.context.Context)
 347  
      */
 348  
     public void contextualize( Context context )
 349  
         throws ContextException
 350  
     {
 351  8
         this.container = (PlexusContainer) context.get( PlexusConstants.PLEXUS_KEY );
 352  8
     }
 353  
 }