View Javadoc

1   package org.apache.maven.plugin.invoker;
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.util.Collection;
25  import java.util.HashMap;
26  import java.util.Iterator;
27  import java.util.Map;
28  
29  import org.apache.maven.artifact.Artifact;
30  import org.apache.maven.artifact.factory.ArtifactFactory;
31  import org.apache.maven.artifact.installer.ArtifactInstallationException;
32  import org.apache.maven.artifact.installer.ArtifactInstaller;
33  import org.apache.maven.artifact.repository.ArtifactRepository;
34  import org.apache.maven.artifact.repository.ArtifactRepositoryFactory;
35  import org.apache.maven.plugin.AbstractMojo;
36  import org.apache.maven.plugin.MojoExecutionException;
37  import org.apache.maven.plugin.MojoFailureException;
38  import org.apache.maven.project.MavenProject;
39  
40  /**
41   * Installs the project artifacts into the local repository as a preparation to run the integration tests. More
42   * precisely, all artifacts of the project itself, all its locally reachable parent POMs and all its dependencies from
43   * the reactor will be installed to the local repository.
44   * 
45   * @goal install
46   * @phase pre-integration-test
47   * @requiresDependencyResolution runtime
48   * @since 1.2
49   * @author Paul Gier
50   * @author Benjamin Bentmann
51   * @version $Id: InstallMojo.java 679351 2008-07-24 10:51:40Z bentmann $
52   */
53  public class InstallMojo
54      extends AbstractMojo
55  {
56  
57      /**
58       * Maven artifact install component to copy artifacts to the local repository.
59       * 
60       * @component
61       */
62      private ArtifactInstaller installer;
63  
64      /**
65       * The component used to create artifacts.
66       * 
67       * @component
68       */
69      private ArtifactFactory artifactFactory;
70  
71      /**
72       * The component used to create artifacts.
73       * 
74       * @component
75       */
76      private ArtifactRepositoryFactory repositoryFactory;
77  
78      /**
79       * @parameter expression="${localRepository}"
80       * @required
81       * @readonly
82       */
83      protected ArtifactRepository localRepository;
84  
85      /**
86       * The path to the local repository into which the project artifacts should be installed for the integration tests.
87       * If not set, the regular local repository will be used. To prevent soiling of your regular local repository with
88       * possibly broken artifacts, it is strongly recommended to use an isolated repository for the integration tests
89       * (e.g. <code>${project.build.directory}/it-repo</code>).
90       * 
91       * @parameter expression="${invoker.localRepositoryPath}"
92       */
93      private File localRepositoryPath;
94  
95      /**
96       * The current Maven project.
97       * 
98       * @parameter expression="${project}"
99       * @required
100      * @readonly
101      */
102     private MavenProject project;
103 
104     /**
105      * The set of Maven projects in the reactor build.
106      * 
107      * @parameter default-value="${reactorProjects}"
108      * @readonly
109      */
110     private Collection reactorProjects;
111 
112     /**
113      * Performs this mojo's tasks.
114      */
115     public void execute()
116         throws MojoExecutionException, MojoFailureException
117     {
118         ArtifactRepository testRepository = createTestRepository();
119         installProjectArtifacts( project, testRepository );
120         installProjectParents( project, testRepository );
121         installProjectDependencies( project, reactorProjects, testRepository );
122     }
123 
124     /**
125      * Creates the local repository for the integration tests. If the user specified a custom repository location, the
126      * custom repository will have the same identifier, layout and policies as the real local repository. That means
127      * apart from the location, the custom repository will be indistinguishable from the real repository such that its
128      * usage is transparent to the integration tests.
129      * 
130      * @return The local repository for the integration tests, never <code>null</code>.
131      * @throws MojoExecutionException If the repository could not be created.
132      */
133     private ArtifactRepository createTestRepository()
134         throws MojoExecutionException
135     {
136         ArtifactRepository testRepository = localRepository;
137 
138         if ( localRepositoryPath != null )
139         {
140             try
141             {
142                 if ( !localRepositoryPath.exists() && !localRepositoryPath.mkdirs() )
143                 {
144                     throw new IOException( "Failed to create directory: " + localRepositoryPath );
145                 }
146 
147                 testRepository =
148                     repositoryFactory.createArtifactRepository( localRepository.getId(),
149                                                                 localRepositoryPath.toURL().toExternalForm(),
150                                                                 localRepository.getLayout(),
151                                                                 localRepository.getSnapshots(),
152                                                                 localRepository.getReleases() );
153             }
154             catch ( Exception e )
155             {
156                 throw new MojoExecutionException( "Failed to create local repository: " + localRepositoryPath, e );
157             }
158         }
159 
160         return testRepository;
161     }
162 
163     /**
164      * Installs the main artifact and any attached artifacts of the specified project to the local repository.
165      * 
166      * @param mvnProject The project whose artifacts should be installed, must not be <code>null</code>.
167      * @param testRepository The local repository to install the artifacts to, must not be <code>null</code>.
168      * @throws MojoExecutionException If any artifact could not be installed.
169      */
170     private void installProjectArtifacts( MavenProject mvnProject, ArtifactRepository testRepository )
171         throws MojoExecutionException
172     {
173         try
174         {
175             installProjectPom( mvnProject, testRepository );
176 
177             // Install the main project artifact
178             installer.install( mvnProject.getArtifact().getFile(), mvnProject.getArtifact(), testRepository );
179 
180             // Install any attached project artifacts
181             Collection attachedArtifacts = mvnProject.getAttachedArtifacts();
182             for ( Iterator artifactIter = attachedArtifacts.iterator(); artifactIter.hasNext(); )
183             {
184                 Artifact theArtifact = (Artifact) artifactIter.next();
185                 installer.install( theArtifact.getFile(), theArtifact, testRepository );
186             }
187         }
188         catch ( ArtifactInstallationException e )
189         {
190             throw new MojoExecutionException( "Failed to install project artifacts: " + mvnProject, e );
191         }
192     }
193 
194     /**
195      * Installs the (locally reachable) parent POMs of the specified project to the local repository. The parent POMs
196      * from the reactor must be installed or the forked IT builds will fail when using a clean repository.
197      * 
198      * @param mvnProject The project whose parent POMs should be installed, must not be <code>null</code>.
199      * @param testRepository The local repository to install the POMs to, must not be <code>null</code>.
200      * @throws MojoExecutionException If any POM could not be installed.
201      */
202     private void installProjectParents( MavenProject mvnProject, ArtifactRepository testRepository )
203         throws MojoExecutionException
204     {
205         for ( MavenProject parent = mvnProject.getParent(); parent != null; parent = parent.getParent() )
206         {
207             if ( parent.getFile() == null )
208             {
209                 break;
210             }
211             installProjectPom( parent, testRepository );
212         }
213     }
214 
215     /**
216      * Installs the POM of the specified project to the local repository.
217      * 
218      * @param mvnProject The project whose POM should be installed, must not be <code>null</code>.
219      * @param testRepository The local repository to install the POM to, must not be <code>null</code>.
220      * @throws MojoExecutionException If the POM could not be installed.
221      */
222     private void installProjectPom( MavenProject mvnProject, ArtifactRepository testRepository )
223         throws MojoExecutionException
224     {
225         try
226         {
227             Artifact pomArtifact =
228                 artifactFactory.createProjectArtifact( mvnProject.getGroupId(), mvnProject.getArtifactId(),
229                                                        mvnProject.getVersion() );
230             installer.install( mvnProject.getFile(), pomArtifact, testRepository );
231         }
232         catch ( Exception e )
233         {
234             throw new MojoExecutionException( "Failed to install POM: " + mvnProject, e );
235         }
236     }
237 
238     /**
239      * Installs the dependent projects from the reactor to the local repository. The dependencies on other modules from
240      * the reactor must be installed or the forked IT builds will fail when using a clean repository.
241      * 
242      * @param mvnProject The project whose dependent projects should be installed, must not be <code>null</code>.
243      * @param reactorProjects The set of projects in the reactor build, must not be <code>null</code>.
244      * @param testRepository The local repository to install the POMs to, must not be <code>null</code>.
245      * @throws MojoExecutionException If any dependency could not be installed.
246      */
247     private void installProjectDependencies( MavenProject mvnProject, Collection reactorProjects,
248                                              ArtifactRepository testRepository )
249         throws MojoExecutionException
250     {
251         Map projects = new HashMap();
252         for ( Iterator it = reactorProjects.iterator(); it.hasNext(); )
253         {
254             MavenProject reactorProject = (MavenProject) it.next();
255             projects.put( reactorProject.getId(), reactorProject );
256         }
257 
258         for ( Iterator it = mvnProject.getArtifacts().iterator(); it.hasNext(); )
259         {
260             Artifact artifact = (Artifact) it.next();
261             String id =
262                 artifact.getGroupId() + ':' + artifact.getArtifactId() + ':' + artifact.getType() + ':'
263                     + artifact.getVersion();
264             MavenProject requiredProject = (MavenProject) projects.remove( id );
265             if ( requiredProject != null )
266             {
267                 installProjectArtifacts( requiredProject, testRepository );
268                 installProjectParents( requiredProject, testRepository );
269             }
270         }
271     }
272 
273 }