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