Classes in this File | Line Coverage | Branch Coverage | Complexity | ||||
InstallMojo |
|
| 5.571428571428571;5.571 |
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.HashSet; | |
27 | import java.util.Iterator; | |
28 | import java.util.Map; | |
29 | ||
30 | import org.apache.maven.artifact.Artifact; | |
31 | import org.apache.maven.artifact.ArtifactUtils; | |
32 | import org.apache.maven.artifact.factory.ArtifactFactory; | |
33 | import org.apache.maven.artifact.installer.ArtifactInstaller; | |
34 | import org.apache.maven.artifact.repository.ArtifactRepository; | |
35 | import org.apache.maven.artifact.repository.ArtifactRepositoryFactory; | |
36 | import org.apache.maven.plugin.AbstractMojo; | |
37 | import org.apache.maven.plugin.MojoExecutionException; | |
38 | import org.apache.maven.project.MavenProject; | |
39 | ||
40 | /** | |
41 | * Installs the project artifacts of the main build into the local repository as a preparation to run the sub projects. | |
42 | * More precisely, all artifacts of the project itself, all its locally reachable parent POMs and all its dependencies | |
43 | * from 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 698334 2008-09-23 20:16:00Z bentmann $ | |
52 | */ | |
53 | 0 | 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 | private 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 | * @throws MojoExecutionException If the artifacts could not be installed. | |
116 | */ | |
117 | public void execute() | |
118 | throws MojoExecutionException | |
119 | { | |
120 | 0 | ArtifactRepository testRepository = createTestRepository(); |
121 | ||
122 | 0 | installProjectArtifacts( project, testRepository ); |
123 | 0 | installProjectParents( project, testRepository ); |
124 | 0 | installProjectDependencies( project, reactorProjects, testRepository ); |
125 | 0 | } |
126 | ||
127 | /** | |
128 | * Creates the local repository for the integration tests. If the user specified a custom repository location, the | |
129 | * custom repository will have the same identifier, layout and policies as the real local repository. That means | |
130 | * apart from the location, the custom repository will be indistinguishable from the real repository such that its | |
131 | * usage is transparent to the integration tests. | |
132 | * | |
133 | * @return The local repository for the integration tests, never <code>null</code>. | |
134 | * @throws MojoExecutionException If the repository could not be created. | |
135 | */ | |
136 | private ArtifactRepository createTestRepository() | |
137 | throws MojoExecutionException | |
138 | { | |
139 | 0 | ArtifactRepository testRepository = localRepository; |
140 | ||
141 | 0 | if ( localRepositoryPath != null ) |
142 | { | |
143 | try | |
144 | { | |
145 | 0 | if ( !localRepositoryPath.exists() && !localRepositoryPath.mkdirs() ) |
146 | { | |
147 | 0 | throw new IOException( "Failed to create directory: " + localRepositoryPath ); |
148 | } | |
149 | ||
150 | 0 | testRepository = |
151 | repositoryFactory.createArtifactRepository( localRepository.getId(), | |
152 | localRepositoryPath.toURL().toExternalForm(), | |
153 | localRepository.getLayout(), | |
154 | localRepository.getSnapshots(), | |
155 | localRepository.getReleases() ); | |
156 | } | |
157 | 0 | catch ( Exception e ) |
158 | { | |
159 | 0 | throw new MojoExecutionException( "Failed to create local repository: " + localRepositoryPath, e ); |
160 | 0 | } |
161 | } | |
162 | ||
163 | 0 | return testRepository; |
164 | } | |
165 | ||
166 | /** | |
167 | * Installs the specified artifact to the local repository. | |
168 | * | |
169 | * @param file The file associated with the artifact, must not be <code>null</code>. This is in most cases the value | |
170 | * of <code>artifact.getFile()</code> with the exception of the main artifact from a project with | |
171 | * packaging "pom". Projects with packaging "pom" have no main artifact file. They have however artifact | |
172 | * metadata (e.g. site descriptors) which needs to be installed. | |
173 | * @param artifact The artifact to install, must not be <code>null</code>. | |
174 | * @param testRepository The local repository to install the artifact to, must not be <code>null</code>. | |
175 | * @throws MojoExecutionException If the artifact could not be installed (e.g. has no associated file). | |
176 | */ | |
177 | private void installArtifact( File file, Artifact artifact, ArtifactRepository testRepository ) | |
178 | throws MojoExecutionException | |
179 | { | |
180 | try | |
181 | { | |
182 | 0 | if ( file == null ) |
183 | { | |
184 | 0 | throw new IllegalStateException( "Artifact has no associated file: " + file ); |
185 | } | |
186 | 0 | if ( !file.isFile() ) |
187 | { | |
188 | 0 | throw new IllegalStateException( "Artifact is not fully assembled: " + file ); |
189 | } | |
190 | 0 | installer.install( file, artifact, testRepository ); |
191 | } | |
192 | 0 | catch ( Exception e ) |
193 | { | |
194 | 0 | throw new MojoExecutionException( "Failed to install artifact: " + artifact, e ); |
195 | 0 | } |
196 | 0 | } |
197 | ||
198 | /** | |
199 | * Installs the main artifact and any attached artifacts of the specified project to the local repository. | |
200 | * | |
201 | * @param mvnProject The project whose artifacts should be installed, must not be <code>null</code>. | |
202 | * @param testRepository The local repository to install the artifacts to, must not be <code>null</code>. | |
203 | * @throws MojoExecutionException If any artifact could not be installed. | |
204 | */ | |
205 | private void installProjectArtifacts( MavenProject mvnProject, ArtifactRepository testRepository ) | |
206 | throws MojoExecutionException | |
207 | { | |
208 | try | |
209 | { | |
210 | 0 | installProjectPom( mvnProject, testRepository ); |
211 | ||
212 | // Install the main project artifact (if the project has one, e.g. has no "pom" packaging) | |
213 | 0 | Artifact mainArtifact = mvnProject.getArtifact(); |
214 | 0 | if ( mainArtifact.getFile() != null ) |
215 | { | |
216 | 0 | installArtifact( mainArtifact.getFile(), mainArtifact, testRepository ); |
217 | } | |
218 | ||
219 | // Install any attached project artifacts | |
220 | 0 | Collection attachedArtifacts = mvnProject.getAttachedArtifacts(); |
221 | 0 | for ( Iterator artifactIter = attachedArtifacts.iterator(); artifactIter.hasNext(); ) |
222 | { | |
223 | 0 | Artifact attachedArtifact = (Artifact) artifactIter.next(); |
224 | 0 | installArtifact( attachedArtifact.getFile(), attachedArtifact, testRepository ); |
225 | } | |
226 | } | |
227 | 0 | catch ( Exception e ) |
228 | { | |
229 | 0 | throw new MojoExecutionException( "Failed to install project artifacts: " + mvnProject, e ); |
230 | 0 | } |
231 | 0 | } |
232 | ||
233 | /** | |
234 | * Installs the (locally reachable) parent POMs of the specified project to the local repository. The parent POMs | |
235 | * from the reactor must be installed or the forked IT builds will fail when using a clean repository. | |
236 | * | |
237 | * @param mvnProject The project whose parent POMs should be installed, must not be <code>null</code>. | |
238 | * @param testRepository The local repository to install the POMs to, must not be <code>null</code>. | |
239 | * @throws MojoExecutionException If any POM could not be installed. | |
240 | */ | |
241 | private void installProjectParents( MavenProject mvnProject, ArtifactRepository testRepository ) | |
242 | throws MojoExecutionException | |
243 | { | |
244 | try | |
245 | { | |
246 | 0 | for ( MavenProject parent = mvnProject.getParent(); parent != null; parent = parent.getParent() ) |
247 | { | |
248 | 0 | if ( parent.getFile() == null ) |
249 | { | |
250 | 0 | break; |
251 | } | |
252 | 0 | installProjectPom( parent, testRepository ); |
253 | } | |
254 | } | |
255 | 0 | catch ( Exception e ) |
256 | { | |
257 | 0 | throw new MojoExecutionException( "Failed to install project parents: " + mvnProject, e ); |
258 | 0 | } |
259 | 0 | } |
260 | ||
261 | /** | |
262 | * Installs the POM of the specified project to the local repository. | |
263 | * | |
264 | * @param mvnProject The project whose POM should be installed, must not be <code>null</code>. | |
265 | * @param testRepository The local repository to install the POM to, must not be <code>null</code>. | |
266 | * @throws MojoExecutionException If the POM could not be installed. | |
267 | */ | |
268 | private void installProjectPom( MavenProject mvnProject, ArtifactRepository testRepository ) | |
269 | throws MojoExecutionException | |
270 | { | |
271 | try | |
272 | { | |
273 | 0 | Artifact pomArtifact = null; |
274 | 0 | if ( "pom".equals( mvnProject.getPackaging() ) ) |
275 | { | |
276 | 0 | pomArtifact = mvnProject.getArtifact(); |
277 | } | |
278 | 0 | if ( pomArtifact == null ) |
279 | { | |
280 | 0 | pomArtifact = |
281 | artifactFactory.createProjectArtifact( mvnProject.getGroupId(), mvnProject.getArtifactId(), | |
282 | mvnProject.getVersion() ); | |
283 | } | |
284 | 0 | installArtifact( mvnProject.getFile(), pomArtifact, testRepository ); |
285 | } | |
286 | 0 | catch ( Exception e ) |
287 | { | |
288 | 0 | throw new MojoExecutionException( "Failed to install POM: " + mvnProject, e ); |
289 | 0 | } |
290 | 0 | } |
291 | ||
292 | /** | |
293 | * Installs the dependent projects from the reactor to the local repository. The dependencies on other modules from | |
294 | * the reactor must be installed or the forked IT builds will fail when using a clean repository. | |
295 | * | |
296 | * @param mvnProject The project whose dependent projects should be installed, must not be <code>null</code>. | |
297 | * @param reactorProjects The set of projects in the reactor build, must not be <code>null</code>. | |
298 | * @param testRepository The local repository to install the POMs to, must not be <code>null</code>. | |
299 | * @throws MojoExecutionException If any dependency could not be installed. | |
300 | */ | |
301 | private void installProjectDependencies( MavenProject mvnProject, Collection reactorProjects, | |
302 | ArtifactRepository testRepository ) | |
303 | throws MojoExecutionException | |
304 | { | |
305 | // index available reactor projects | |
306 | 0 | Map projects = new HashMap(); |
307 | 0 | for ( Iterator it = reactorProjects.iterator(); it.hasNext(); ) |
308 | { | |
309 | 0 | MavenProject reactorProject = (MavenProject) it.next(); |
310 | 0 | String id = reactorProject.getGroupId() + ':' + reactorProject.getArtifactId(); |
311 | 0 | projects.put( id, reactorProject ); |
312 | } | |
313 | ||
314 | // collect transitive dependencies | |
315 | 0 | Collection dependencies = new HashSet(); |
316 | 0 | for ( Iterator it = mvnProject.getRuntimeArtifacts().iterator(); it.hasNext(); ) |
317 | { | |
318 | 0 | Artifact artifact = (Artifact) it.next(); |
319 | 0 | String id = ArtifactUtils.versionlessKey( artifact ); |
320 | ||
321 | 0 | dependencies.add( id ); |
322 | } | |
323 | ||
324 | // install dependencies | |
325 | try | |
326 | { | |
327 | // install dependencies from reactor | |
328 | 0 | for ( Iterator it = dependencies.iterator(); it.hasNext(); ) |
329 | { | |
330 | 0 | String id = (String) it.next(); |
331 | 0 | MavenProject requiredProject = (MavenProject) projects.remove( id ); |
332 | 0 | if ( requiredProject != null ) |
333 | { | |
334 | 0 | it.remove(); |
335 | 0 | installProjectArtifacts( requiredProject, testRepository ); |
336 | 0 | installProjectParents( requiredProject, testRepository ); |
337 | } | |
338 | } | |
339 | ||
340 | // install remaining dependencies from local repository | |
341 | 0 | for ( Iterator it = mvnProject.getRuntimeArtifacts().iterator(); it.hasNext(); ) |
342 | { | |
343 | 0 | Artifact artifact = (Artifact) it.next(); |
344 | 0 | String id = ArtifactUtils.versionlessKey( artifact ); |
345 | ||
346 | 0 | if ( dependencies.contains( id ) ) |
347 | { | |
348 | 0 | File artifactFile = artifact.getFile(); |
349 | ||
350 | 0 | installArtifact( artifactFile, artifact, testRepository ); |
351 | ||
352 | 0 | Artifact pomArtifact = |
353 | artifactFactory.createArtifact( artifact.getGroupId(), artifact.getArtifactId(), | |
354 | artifact.getVersion(), null, "pom" ); | |
355 | ||
356 | 0 | File pomFile = new File( localRepository.getBasedir(), localRepository.pathOf( pomArtifact ) ); |
357 | ||
358 | 0 | if ( pomFile.exists() ) |
359 | { | |
360 | 0 | installArtifact( pomFile, pomArtifact, testRepository ); |
361 | } | |
362 | } | |
363 | } | |
364 | } | |
365 | 0 | catch ( Exception e ) |
366 | { | |
367 | 0 | throw new MojoExecutionException( "Failed to install project dependencies: " + mvnProject, e ); |
368 | 0 | } |
369 | 0 | } |
370 | ||
371 | } |