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