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 }