1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19 package org.apache.maven.plugins.invoker;
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40 import java.io.File;
41 import java.io.IOException;
42 import java.util.Collection;
43 import java.util.Collections;
44 import java.util.HashMap;
45 import java.util.HashSet;
46 import java.util.LinkedHashSet;
47 import java.util.Map;
48
49 import org.apache.maven.artifact.Artifact;
50 import org.apache.maven.artifact.factory.ArtifactFactory;
51 import org.apache.maven.artifact.repository.ArtifactRepository;
52 import org.apache.maven.execution.MavenSession;
53 import org.apache.maven.model.Model;
54 import org.apache.maven.model.Parent;
55 import org.apache.maven.plugin.AbstractMojo;
56 import org.apache.maven.plugin.MojoExecutionException;
57 import org.apache.maven.plugins.annotations.Component;
58 import org.apache.maven.plugins.annotations.LifecyclePhase;
59 import org.apache.maven.plugins.annotations.Mojo;
60 import org.apache.maven.plugins.annotations.Parameter;
61 import org.apache.maven.plugins.annotations.ResolutionScope;
62 import org.apache.maven.project.MavenProject;
63 import org.apache.maven.project.ProjectBuildingRequest;
64 import org.apache.maven.shared.artifact.filter.resolve.PatternExclusionsFilter;
65 import org.apache.maven.shared.transfer.artifact.install.ArtifactInstaller;
66 import org.apache.maven.shared.transfer.dependencies.DefaultDependableCoordinate;
67 import org.apache.maven.shared.transfer.dependencies.resolve.DependencyResolver;
68 import org.apache.maven.shared.transfer.dependencies.resolve.DependencyResolverException;
69 import org.apache.maven.shared.transfer.repository.RepositoryManager;
70 import org.codehaus.plexus.util.FileUtils;
71
72
73
74
75
76
77
78
79
80
81
82
83 @Mojo(
84 name = "install",
85 defaultPhase = LifecyclePhase.PRE_INTEGRATION_TEST,
86 requiresDependencyResolution = ResolutionScope.RUNTIME,
87 threadSafe = true)
88
89 public class InstallMojo extends AbstractMojo {
90
91
92
93
94 @Component
95 private ArtifactInstaller installer;
96
97 @Component
98 private RepositoryManager repositoryManager;
99
100
101
102
103 @Component
104 private ArtifactFactory artifactFactory;
105
106
107
108 @Parameter(property = "localRepository", required = true, readonly = true)
109 private ArtifactRepository localRepository;
110
111
112
113
114
115
116
117 @Parameter(
118 property = "invoker.localRepositoryPath",
119 defaultValue = "${session.localRepository.basedir}",
120 required = true)
121 private File localRepositoryPath;
122
123
124
125
126 @Parameter(defaultValue = "${project}", readonly = true, required = true)
127 private MavenProject project;
128
129 @Parameter(defaultValue = "${session}", readonly = true, required = true)
130 private MavenSession session;
131
132
133
134
135 @Parameter(defaultValue = "${reactorProjects}", readonly = true)
136 private Collection<MavenProject> reactorProjects;
137
138
139
140
141
142
143
144 @Parameter(property = "invoker.skip", defaultValue = "false")
145 private boolean skipInstallation;
146
147
148
149
150 private Collection<String> installedArtifacts;
151
152
153
154
155 private Collection<String> copiedArtifacts;
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177 @Parameter
178 private String[] extraArtifacts;
179
180
181
182 @Component
183 private DependencyResolver resolver;
184
185
186
187
188
189
190 @Parameter(property = "invoker.useLocalRepository", defaultValue = "false")
191 private boolean useLocalRepository;
192
193 private ProjectBuildingRequest projectBuildingRequest;
194
195
196
197
198
199
200 public void execute() throws MojoExecutionException {
201 if (skipInstallation) {
202 getLog().info("Skipping artifact installation per configuration.");
203 return;
204 }
205
206 createTestRepository();
207
208 installedArtifacts = new HashSet<>();
209 copiedArtifacts = new HashSet<>();
210
211 installProjectDependencies(project, reactorProjects);
212 installProjectParents(project);
213 installProjectArtifacts(project);
214
215 installExtraArtifacts(extraArtifacts);
216 }
217
218
219
220
221
222
223
224
225
226 private void createTestRepository() throws MojoExecutionException {
227
228 if (!localRepositoryPath.exists() && !localRepositoryPath.mkdirs()) {
229 throw new MojoExecutionException("Failed to create directory: " + localRepositoryPath);
230 }
231 projectBuildingRequest =
232 repositoryManager.setLocalRepositoryBasedir(session.getProjectBuildingRequest(), localRepositoryPath);
233 }
234
235
236
237
238
239
240
241
242
243
244
245
246
247 private void installArtifact(File file, Artifact artifact) throws MojoExecutionException {
248 try {
249 if (file == null) {
250 throw new IllegalStateException("Artifact has no associated file: " + artifact.getId());
251 }
252 if (!file.isFile()) {
253 throw new IllegalStateException("Artifact is not fully assembled: " + file);
254 }
255
256 if (installedArtifacts.add(artifact.getId())) {
257 artifact.setFile(file);
258 installer.install(projectBuildingRequest, localRepositoryPath, Collections.singletonList(artifact));
259 } else {
260 getLog().debug("Not re-installing " + artifact + ", " + file);
261 }
262 } catch (Exception e) {
263 throw new MojoExecutionException("Failed to install artifact: " + artifact, e);
264 }
265 }
266
267
268
269
270
271
272
273
274
275
276
277
278 private void copyArtifact(File file, Artifact artifact) throws MojoExecutionException {
279 try {
280 if (file == null) {
281 throw new IllegalStateException("Artifact has no associated file: " + artifact.getId());
282 }
283 if (!file.isFile()) {
284 throw new IllegalStateException("Artifact is not fully assembled: " + file);
285 }
286
287 if (copiedArtifacts.add(artifact.getId())) {
288 File destination = new File(
289 localRepositoryPath,
290 repositoryManager.getPathForLocalArtifact(projectBuildingRequest, artifact));
291
292 getLog().debug("Installing " + file + " to " + destination);
293
294 copyFileIfDifferent(file, destination);
295
296 MetadataUtils.createMetadata(destination, artifact);
297 } else {
298 getLog().debug("Not re-installing " + artifact + ", " + file);
299 }
300 } catch (Exception e) {
301 throw new MojoExecutionException("Failed to stage artifact: " + artifact, e);
302 }
303 }
304
305 private void copyFileIfDifferent(File src, File dst) throws IOException {
306 if (src.lastModified() != dst.lastModified() || src.length() != dst.length()) {
307 FileUtils.copyFile(src, dst);
308 dst.setLastModified(src.lastModified());
309 }
310 }
311
312
313
314
315
316
317
318 private void installProjectArtifacts(MavenProject mvnProject) throws MojoExecutionException {
319 try {
320
321 installProjectPom(mvnProject);
322
323
324 Artifact mainArtifact = mvnProject.getArtifact();
325 if (mainArtifact.getFile() != null) {
326 installArtifact(mainArtifact.getFile(), mainArtifact);
327 }
328
329
330 Collection<Artifact> attachedArtifacts = mvnProject.getAttachedArtifacts();
331 for (Artifact attachedArtifact : attachedArtifacts) {
332 installArtifact(attachedArtifact.getFile(), attachedArtifact);
333 }
334 } catch (Exception e) {
335 throw new MojoExecutionException("Failed to install project artifacts: " + mvnProject, e);
336 }
337 }
338
339
340
341
342
343
344
345
346 private void installProjectParents(MavenProject mvnProject) throws MojoExecutionException {
347 try {
348 for (MavenProject parent = mvnProject.getParent(); parent != null; parent = parent.getParent()) {
349 if (parent.getFile() == null) {
350 copyParentPoms(parent.getGroupId(), parent.getArtifactId(), parent.getVersion());
351 break;
352 }
353 installProjectPom(parent);
354 }
355 } catch (Exception e) {
356 throw new MojoExecutionException("Failed to install project parents: " + mvnProject, e);
357 }
358 }
359
360
361
362
363
364
365
366 private void installProjectPom(MavenProject mvnProject) throws MojoExecutionException {
367 try {
368 Artifact pomArtifact = null;
369 if ("pom".equals(mvnProject.getPackaging())) {
370 pomArtifact = mvnProject.getArtifact();
371 }
372 if (pomArtifact == null) {
373 pomArtifact = artifactFactory.createProjectArtifact(
374 mvnProject.getGroupId(), mvnProject.getArtifactId(), mvnProject.getVersion());
375 }
376 installArtifact(mvnProject.getFile(), pomArtifact);
377 } catch (Exception e) {
378 throw new MojoExecutionException("Failed to install POM: " + mvnProject, e);
379 }
380 }
381
382
383
384
385
386
387
388
389
390 private void installProjectDependencies(MavenProject mvnProject, Collection<MavenProject> reactorProjects)
391 throws MojoExecutionException {
392
393 Collection<String> dependencyProjects = new LinkedHashSet<>();
394 collectAllProjectReferences(mvnProject, dependencyProjects);
395
396
397 Map<String, MavenProject> projects = new HashMap<>(reactorProjects.size());
398 for (MavenProject reactorProject : reactorProjects) {
399 String projectId = reactorProject.getGroupId()
400 + ':'
401 + reactorProject.getArtifactId()
402 + ':'
403 + reactorProject.getVersion();
404
405 projects.put(projectId, reactorProject);
406 }
407
408
409 Collection<Artifact> artifacts = mvnProject.getArtifacts();
410
411 Collection<Artifact> dependencyArtifacts = new LinkedHashSet<>();
412
413 for (Artifact artifact : artifacts) {
414
415 artifact.isSnapshot();
416
417 String projectId = artifact.getGroupId() + ':' + artifact.getArtifactId() + ':' + artifact.getBaseVersion();
418
419 if (!projects.containsKey(projectId)) {
420 dependencyArtifacts.add(artifact);
421 }
422 }
423
424
425 try {
426
427 for (Artifact artifact : dependencyArtifacts) {
428 copyArtifact(artifact);
429 }
430
431
432 for (String projectId : dependencyProjects) {
433 MavenProject dependencyProject = projects.get(projectId);
434 if (dependencyProject == null) {
435 getLog().warn("skip dependencyProject null for projectId=" + projectId);
436 continue;
437 }
438 installProjectArtifacts(dependencyProject);
439 installProjectParents(dependencyProject);
440 }
441 } catch (Exception e) {
442 throw new MojoExecutionException("Failed to install project dependencies: " + mvnProject, e);
443 }
444 }
445
446 protected void collectAllProjectReferences(MavenProject project, Collection<String> dependencyProjects) {
447 for (MavenProject reactorProject : project.getProjectReferences().values()) {
448 String projectId = reactorProject.getGroupId()
449 + ':'
450 + reactorProject.getArtifactId()
451 + ':'
452 + reactorProject.getVersion();
453 if (dependencyProjects.add(projectId)) {
454 collectAllProjectReferences(reactorProject, dependencyProjects);
455 }
456 }
457 }
458
459 private void copyArtifact(Artifact artifact) throws MojoExecutionException {
460 copyPoms(artifact);
461
462 Artifact depArtifact = artifactFactory.createArtifactWithClassifier(
463 artifact.getGroupId(),
464 artifact.getArtifactId(),
465 artifact.getBaseVersion(),
466 artifact.getType(),
467 artifact.getClassifier());
468
469 File artifactFile = artifact.getFile();
470
471 copyArtifact(artifactFile, depArtifact);
472 }
473
474 private void copyPoms(Artifact artifact) throws MojoExecutionException {
475 Artifact pomArtifact = artifactFactory.createProjectArtifact(
476 artifact.getGroupId(), artifact.getArtifactId(), artifact.getBaseVersion());
477
478 File pomFile = new File(localRepository.getBasedir(), localRepository.pathOf(pomArtifact));
479
480 if (pomFile.isFile()) {
481 copyArtifact(pomFile, pomArtifact);
482 copyParentPoms(pomFile);
483 }
484 }
485
486
487
488
489
490
491
492 private void copyParentPoms(File pomFile) throws MojoExecutionException {
493 Model model = PomUtils.loadPom(pomFile);
494 Parent parent = model.getParent();
495 if (parent != null) {
496 copyParentPoms(parent.getGroupId(), parent.getArtifactId(), parent.getVersion());
497 }
498 }
499
500
501
502
503
504
505
506
507
508 private void copyParentPoms(String groupId, String artifactId, String version) throws MojoExecutionException {
509 Artifact pomArtifact = artifactFactory.createProjectArtifact(groupId, artifactId, version);
510
511 if (installedArtifacts.contains(pomArtifact.getId()) || copiedArtifacts.contains(pomArtifact.getId())) {
512 getLog().debug("Not re-installing " + pomArtifact);
513 return;
514 }
515
516 File pomFile = new File(localRepository.getBasedir(), localRepository.pathOf(pomArtifact));
517 if (pomFile.isFile()) {
518 copyArtifact(pomFile, pomArtifact);
519 copyParentPoms(pomFile);
520 }
521 }
522
523 private void installExtraArtifacts(String[] extraArtifacts) throws MojoExecutionException {
524 if (extraArtifacts == null) {
525 return;
526 }
527
528 for (String extraArtifact : extraArtifacts) {
529 String[] gav = extraArtifact.split(":");
530 if (gav.length < 3 || gav.length > 5) {
531 throw new MojoExecutionException("Invalid artifact " + extraArtifact);
532 }
533
534 String groupId = gav[0];
535 String artifactId = gav[1];
536 String version = gav[2];
537
538 String type = "jar";
539 if (gav.length > 3) {
540 type = gav[3];
541 }
542
543 String classifier = null;
544 if (gav.length == 5) {
545 classifier = gav[4];
546 }
547
548 DefaultDependableCoordinate coordinate = new DefaultDependableCoordinate();
549 try {
550 coordinate.setGroupId(groupId);
551 coordinate.setArtifactId(artifactId);
552 coordinate.setVersion(version);
553 coordinate.setType(type);
554 coordinate.setClassifier(classifier);
555
556 if (!localRepository.getBasedir().equals(localRepositoryPath.getPath()) && useLocalRepository) {
557 String previousId = localRepository.getId();
558 try {
559
560 ProjectBuildingRequest projectBuildingRequest = repositoryManager.setLocalRepositoryBasedir(
561 session.getProjectBuildingRequest(), localRepositoryPath);
562 projectBuildingRequest.setRemoteRepositories(Collections.singletonList(localRepository));
563 resolver.resolveDependencies(
564 projectBuildingRequest,
565 coordinate,
566 new PatternExclusionsFilter(Collections.emptyList()));
567 } finally {
568 localRepository.setId(previousId);
569 }
570 } else {
571 resolver.resolveDependencies(
572 projectBuildingRequest, coordinate, new PatternExclusionsFilter(Collections.emptyList()));
573 }
574 } catch (DependencyResolverException e) {
575 throw new MojoExecutionException("Unable to resolve dependencies for: " + coordinate, e);
576 }
577 }
578 }
579 }