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