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