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