1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19 package org.apache.maven.plugin.ide;
20
21 import java.io.File;
22 import java.io.IOException;
23 import java.util.ArrayList;
24 import java.util.Collections;
25 import java.util.HashMap;
26 import java.util.HashSet;
27 import java.util.Iterator;
28 import java.util.List;
29 import java.util.Map;
30 import java.util.Set;
31 import java.util.TreeSet;
32 import java.util.jar.Attributes;
33 import java.util.jar.JarFile;
34 import java.util.jar.Manifest;
35 import java.util.zip.ZipFile;
36
37 import org.apache.maven.artifact.Artifact;
38 import org.apache.maven.artifact.factory.ArtifactFactory;
39 import org.apache.maven.artifact.metadata.ArtifactMetadataSource;
40 import org.apache.maven.artifact.repository.ArtifactRepository;
41 import org.apache.maven.artifact.resolver.ArtifactCollector;
42 import org.apache.maven.artifact.resolver.ArtifactNotFoundException;
43 import org.apache.maven.artifact.resolver.ArtifactResolutionException;
44 import org.apache.maven.artifact.resolver.ArtifactResolutionResult;
45 import org.apache.maven.artifact.resolver.ArtifactResolver;
46 import org.apache.maven.artifact.resolver.DebugResolutionListener;
47 import org.apache.maven.artifact.resolver.ResolutionNode;
48 import org.apache.maven.artifact.resolver.WarningResolutionListener;
49 import org.apache.maven.artifact.resolver.filter.ArtifactFilter;
50 import org.apache.maven.artifact.resolver.filter.ExcludesArtifactFilter;
51 import org.apache.maven.artifact.versioning.ArtifactVersion;
52 import org.apache.maven.artifact.versioning.InvalidVersionSpecificationException;
53 import org.apache.maven.artifact.versioning.VersionRange;
54 import org.apache.maven.execution.RuntimeInformation;
55 import org.apache.maven.model.Dependency;
56 import org.apache.maven.model.DependencyManagement;
57 import org.apache.maven.model.Exclusion;
58 import org.apache.maven.plugin.AbstractMojo;
59 import org.apache.maven.plugin.MojoExecutionException;
60 import org.apache.maven.plugin.MojoFailureException;
61 import org.apache.maven.plugin.eclipse.Constants;
62 import org.apache.maven.plugin.eclipse.Messages;
63 import org.apache.maven.project.MavenProject;
64 import org.codehaus.plexus.logging.LogEnabled;
65 import org.codehaus.plexus.logging.Logger;
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84 public abstract class AbstractIdeSupportMojo
85 extends AbstractMojo
86 implements LogEnabled
87 {
88
89
90
91
92
93
94
95
96 protected MavenProject project;
97
98
99
100
101
102
103
104 protected MavenProject executedProject;
105
106
107
108
109
110
111 protected String packaging;
112
113
114
115
116
117
118
119
120 protected ArtifactFactory artifactFactory;
121
122
123
124
125
126
127
128
129 protected ArtifactResolver artifactResolver;
130
131
132
133
134
135
136
137
138 protected ArtifactCollector artifactCollector;
139
140
141
142
143 protected ArtifactMetadataSource artifactMetadataSource;
144
145
146
147
148
149
150 private RuntimeInformation runtimeInformation;
151
152
153
154
155
156
157
158
159 protected List remoteArtifactRepositories;
160
161
162
163
164
165
166
167
168 protected ArtifactRepository localRepository;
169
170
171
172
173
174
175
176
177 protected List reactorProjects;
178
179
180
181
182
183
184 private boolean skip;
185
186
187
188
189
190
191
192
193
194
195 protected boolean downloadSources;
196
197
198
199
200
201
202
203
204
205
206 protected boolean downloadJavadocs;
207
208
209
210
211
212
213
214
215
216 protected boolean forceRecheck;
217
218
219
220
221 protected Logger logger;
222
223
224
225
226
227
228 public ArtifactMetadataSource getArtifactMetadataSource()
229 {
230 return artifactMetadataSource;
231 }
232
233
234
235
236
237
238 public void setArtifactMetadataSource( ArtifactMetadataSource artifactMetadataSource )
239 {
240 this.artifactMetadataSource = artifactMetadataSource;
241 }
242
243
244
245
246
247
248 public MavenProject getProject()
249 {
250 return project;
251 }
252
253
254
255
256
257
258 public void setProject( MavenProject project )
259 {
260 this.project = project;
261 }
262
263
264
265
266
267
268 public List getReactorProjects()
269 {
270 return reactorProjects;
271 }
272
273
274
275
276
277
278 public void setReactorProjects( List reactorProjects )
279 {
280 this.reactorProjects = reactorProjects;
281 }
282
283
284
285
286
287
288 public List getRemoteArtifactRepositories()
289 {
290 return remoteArtifactRepositories;
291 }
292
293
294
295
296
297
298 public void setRemoteArtifactRepositories( List remoteArtifactRepositories )
299 {
300 this.remoteArtifactRepositories = remoteArtifactRepositories;
301 }
302
303
304
305
306
307
308 public ArtifactFactory getArtifactFactory()
309 {
310 return artifactFactory;
311 }
312
313
314
315
316
317
318 public void setArtifactFactory( ArtifactFactory artifactFactory )
319 {
320 this.artifactFactory = artifactFactory;
321 }
322
323
324
325
326
327
328 public ArtifactResolver getArtifactResolver()
329 {
330 return artifactResolver;
331 }
332
333
334
335
336
337
338 public void setArtifactResolver( ArtifactResolver artifactResolver )
339 {
340 this.artifactResolver = artifactResolver;
341 }
342
343
344
345
346
347
348 public MavenProject getExecutedProject()
349 {
350 return executedProject;
351 }
352
353
354
355
356
357
358 public void setExecutedProject( MavenProject executedProject )
359 {
360 this.executedProject = executedProject;
361 }
362
363
364
365
366
367
368 public ArtifactRepository getLocalRepository()
369 {
370 return localRepository;
371 }
372
373
374
375
376
377
378 public void setLocalRepository( ArtifactRepository localRepository )
379 {
380 this.localRepository = localRepository;
381 }
382
383
384
385
386
387
388 public boolean getDownloadJavadocs()
389 {
390 return downloadJavadocs;
391 }
392
393
394
395
396
397
398 public void setDownloadJavadocs( boolean downloadJavadoc )
399 {
400 downloadJavadocs = downloadJavadoc;
401 }
402
403
404
405
406
407
408 public boolean getDownloadSources()
409 {
410 return downloadSources;
411 }
412
413
414
415
416
417
418 public void setDownloadSources( boolean downloadSources )
419 {
420 this.downloadSources = downloadSources;
421 }
422
423 protected void setResolveDependencies( boolean resolveDependencies )
424 {
425 this.resolveDependencies = resolveDependencies;
426 }
427
428 protected boolean isResolveDependencies()
429 {
430 return resolveDependencies;
431 }
432
433
434
435
436
437
438
439 protected abstract boolean getUseProjectReferences();
440
441
442
443
444
445
446
447 protected abstract boolean setup()
448 throws MojoExecutionException;
449
450
451
452
453
454
455
456 protected abstract void writeConfiguration( IdeDependency[] deps )
457 throws MojoExecutionException;
458
459
460
461
462 private List missingSourceDependencies = new ArrayList();
463
464
465
466
467
468 private List missingJavadocDependencies = new ArrayList();
469
470
471
472
473 private IdeDependency[] ideDeps;
474
475
476
477
478
479 private boolean resolveDependencies = true;
480
481
482
483
484 public void enableLogging( Logger logger )
485 {
486 this.logger = logger;
487 }
488
489
490
491
492 public final void execute()
493 throws MojoExecutionException, MojoFailureException
494 {
495 if ( skip )
496 {
497 return;
498 }
499
500 boolean processProject = setup();
501 if ( !processProject )
502 {
503 return;
504 }
505
506
507 IdeDependency[] deps = doDependencyResolution();
508
509 resolveSourceAndJavadocArtifacts( deps );
510
511 writeConfiguration( deps );
512
513 reportMissingArtifacts();
514
515 }
516
517
518
519
520
521
522
523
524
525 protected IdeDependency[] doDependencyResolution()
526 throws MojoExecutionException
527 {
528 if ( ideDeps == null )
529 {
530 if ( resolveDependencies )
531 {
532 MavenProject project = getProject();
533 ArtifactRepository localRepo = getLocalRepository();
534
535 List deps = getProject().getDependencies();
536
537
538 List dependencies = new ArrayList();
539
540 if ( deps != null )
541 {
542 Map managedVersions =
543 createManagedVersionMap( getArtifactFactory(), project.getId(),
544 project.getDependencyManagement() );
545
546 ArtifactResolutionResult artifactResolutionResult = null;
547
548 try
549 {
550
551 List listeners = new ArrayList();
552
553 if ( logger.isDebugEnabled() )
554 {
555 listeners.add( new DebugResolutionListener( logger ) );
556 }
557
558 listeners.add( new WarningResolutionListener( logger ) );
559
560 artifactResolutionResult =
561 artifactCollector.collect( getProjectArtifacts(), project.getArtifact(), managedVersions,
562 localRepo, project.getRemoteArtifactRepositories(),
563 getArtifactMetadataSource(), null, listeners );
564 }
565 catch ( ArtifactResolutionException e )
566 {
567 getLog().debug( e.getMessage(), e );
568 getLog().error(
569 Messages.getString( "AbstractIdeSupportMojo.artifactresolution", new Object[] {
570 e.getGroupId(), e.getArtifactId(), e.getVersion(),
571 e.getMessage() } ) );
572
573
574
575
576
577 return new IdeDependency[0];
578 }
579
580
581 Set emittedReactorProjectId = new HashSet();
582
583 for ( Iterator i = artifactResolutionResult.getArtifactResolutionNodes().iterator(); i.hasNext(); )
584 {
585
586 ResolutionNode node = (ResolutionNode) i.next();
587 int dependencyDepth = node.getDepth();
588 Artifact art = node.getArtifact();
589
590 if ( hasToResolveJar( art ) )
591 {
592 try
593 {
594 artifactResolver.resolve( art, node.getRemoteRepositories(), localRepository );
595 }
596 catch ( ArtifactNotFoundException e )
597 {
598 getLog().debug( e.getMessage(), e );
599 getLog().warn(
600 Messages.getString( "AbstractIdeSupportMojo.artifactdownload", new Object[] {
601 e.getGroupId(), e.getArtifactId(), e.getVersion(),
602 e.getMessage() } ) );
603 }
604 catch ( ArtifactResolutionException e )
605 {
606 getLog().debug( e.getMessage(), e );
607 getLog().warn(
608 Messages.getString( "AbstractIdeSupportMojo.artifactresolution", new Object[] {
609 e.getGroupId(), e.getArtifactId(), e.getVersion(),
610 e.getMessage() } ) );
611 }
612 }
613
614 boolean includeArtifact = true;
615 if ( getExcludes() != null )
616 {
617 String artifactFullId = art.getGroupId() + ":" + art.getArtifactId();
618 if ( getExcludes().contains( artifactFullId ) )
619 {
620 getLog().info( "excluded: " + artifactFullId );
621 includeArtifact = false;
622 }
623 }
624
625 if ( includeArtifact
626 && ( !( getUseProjectReferences() && isAvailableAsAReactorProject( art ) ) || emittedReactorProjectId.add( art.getGroupId()
627 + '-' + art.getArtifactId() ) ) )
628 {
629
630
631
632
633
634
635
636
637
638
639
640
641
642
643 boolean isOsgiBundle = false;
644 String osgiSymbolicName = null;
645 if ( art.getFile() != null )
646 {
647 JarFile jarFile = null;
648 try
649 {
650 jarFile = new JarFile( art.getFile(), false, ZipFile.OPEN_READ );
651
652 Manifest manifest = jarFile.getManifest();
653 if ( manifest != null )
654 {
655 osgiSymbolicName =
656 manifest.getMainAttributes().getValue(
657 new Attributes.Name(
658 "Bundle-SymbolicName" ) );
659 }
660 }
661 catch ( IOException e )
662 {
663 getLog().info( "Unable to read jar manifest from " + art.getFile() );
664 }
665 finally
666 {
667 if ( jarFile != null )
668 {
669 try
670 {
671 jarFile.close();
672 }
673 catch ( IOException e )
674 {
675
676 }
677 }
678 }
679 }
680
681 isOsgiBundle = osgiSymbolicName != null;
682
683 IdeDependency dep =
684 new IdeDependency( art.getGroupId(), art.getArtifactId(), art.getVersion(),
685 art.getClassifier(), useProjectReference( art ),
686 Artifact.SCOPE_TEST.equals( art.getScope() ),
687 Artifact.SCOPE_SYSTEM.equals( art.getScope() ),
688 Artifact.SCOPE_PROVIDED.equals( art.getScope() ),
689 art.getArtifactHandler().isAddedToClasspath(), art.getFile(),
690 art.getType(), isOsgiBundle, osgiSymbolicName, dependencyDepth,
691 getProjectNameForArifact( art ) );
692
693 if ( !dependencies.contains( dep ) )
694 {
695 dependencies.add( dep );
696 }
697 }
698
699 }
700
701
702
703
704 }
705
706 ideDeps = (IdeDependency[]) dependencies.toArray( new IdeDependency[dependencies.size()] );
707 }
708 else
709 {
710 ideDeps = new IdeDependency[0];
711 }
712 }
713
714 return ideDeps;
715 }
716
717
718
719
720
721
722
723 abstract public String getProjectNameForArifact( Artifact artifact );
724
725
726
727
728
729
730
731
732 private Set getProjectArtifacts()
733 throws MojoExecutionException
734 {
735
736 Set artifacts = new TreeSet();
737
738 for ( Iterator dependencies = getProject().getDependencies().iterator(); dependencies.hasNext(); )
739 {
740 Dependency dependency = (Dependency) dependencies.next();
741
742 String groupId = dependency.getGroupId();
743 String artifactId = dependency.getArtifactId();
744 VersionRange versionRange;
745 try
746 {
747 versionRange = VersionRange.createFromVersionSpec( dependency.getVersion() );
748 }
749 catch ( InvalidVersionSpecificationException e )
750 {
751 throw new MojoExecutionException(
752 Messages.getString(
753 "AbstractIdeSupportMojo.unabletoparseversion", new Object[] {
754 dependency.getArtifactId(),
755 dependency.getVersion(),
756 dependency.getManagementKey(), e.getMessage() } ),
757 e );
758 }
759
760 String type = dependency.getType();
761 if ( type == null )
762 {
763 type = Constants.PROJECT_PACKAGING_JAR;
764 }
765 String classifier = dependency.getClassifier();
766 boolean optional = dependency.isOptional();
767 String scope = dependency.getScope();
768 if ( scope == null )
769 {
770 scope = Artifact.SCOPE_COMPILE;
771 }
772
773 Artifact art =
774 getArtifactFactory().createDependencyArtifact( groupId, artifactId, versionRange, type, classifier,
775 scope, optional );
776
777 if ( scope.equalsIgnoreCase( Artifact.SCOPE_SYSTEM ) )
778 {
779 art.setFile( new File( dependency.getSystemPath() ) );
780 }
781
782 List exclusions = new ArrayList();
783 for ( Iterator j = dependency.getExclusions().iterator(); j.hasNext(); )
784 {
785 Exclusion e = (Exclusion) j.next();
786 exclusions.add( e.getGroupId() + ":" + e.getArtifactId() );
787 }
788
789 ArtifactFilter newFilter = new ExcludesArtifactFilter( exclusions );
790
791 art.setDependencyFilter( newFilter );
792
793 artifacts.add( art );
794 }
795
796 return artifacts;
797 }
798
799
800
801
802
803
804
805 protected boolean isAvailableAsAReactorProject( Artifact artifact )
806 {
807 return getReactorProject( artifact ) != null;
808 }
809
810
811
812
813
814
815
816 protected MavenProject getReactorProject( Artifact artifact ) {
817 if ( reactorProjects != null )
818 {
819 for ( Iterator iter = reactorProjects.iterator(); iter.hasNext(); )
820 {
821 MavenProject reactorProject = (MavenProject) iter.next();
822
823 if ( reactorProject.getGroupId().equals( artifact.getGroupId() )
824 && reactorProject.getArtifactId().equals( artifact.getArtifactId() ) )
825 {
826 if ( reactorProject.getVersion().equals( artifact.getVersion() ) )
827 {
828 return reactorProject;
829 }
830 else
831 {
832 getLog().info(
833 "Artifact "
834 + artifact.getId()
835 + " already available as a reactor project, but with different version. Expected: "
836 + artifact.getVersion() + ", found: " + reactorProject.getVersion() );
837 }
838 }
839 }
840 }
841 return null;
842 }
843
844
845
846
847 protected IdeDependency[] getWorkspaceArtefacts()
848 {
849 return new IdeDependency[0];
850 }
851
852 private Map createManagedVersionMap( ArtifactFactory artifactFactory, String projectId,
853 DependencyManagement dependencyManagement )
854 throws MojoExecutionException
855 {
856 Map map;
857 if ( dependencyManagement != null && dependencyManagement.getDependencies() != null )
858 {
859 map = new HashMap();
860 for ( Iterator i = dependencyManagement.getDependencies().iterator(); i.hasNext(); )
861 {
862 Dependency d = (Dependency) i.next();
863
864 try
865 {
866 VersionRange versionRange = VersionRange.createFromVersionSpec( d.getVersion() );
867 Artifact artifact =
868 artifactFactory.createDependencyArtifact( d.getGroupId(), d.getArtifactId(), versionRange,
869 d.getType(), d.getClassifier(), d.getScope(),
870 d.isOptional() );
871 map.put( d.getManagementKey(), artifact );
872 }
873 catch ( InvalidVersionSpecificationException e )
874 {
875 throw new MojoExecutionException( Messages.getString( "AbstractIdeSupportMojo.unabletoparseversion", new Object[] {
876 projectId, d.getVersion(),
877 d.getManagementKey(), e.getMessage() } ),
878 e );
879 }
880 }
881 }
882 else
883 {
884 map = Collections.EMPTY_MAP;
885 }
886 return map;
887 }
888
889
890
891
892
893
894
895
896
897 private void resolveSourceAndJavadocArtifacts( IdeDependency[] deps )
898 {
899 final List missingSources =
900 resolveDependenciesWithClassifier( deps, "sources", getDownloadSources() );
901 missingSourceDependencies.addAll( missingSources );
902
903 final List missingJavadocs =
904 resolveDependenciesWithClassifier( deps, "javadoc", getDownloadJavadocs() );
905 missingJavadocDependencies.addAll( missingJavadocs );
906 }
907
908
909
910
911
912
913
914
915
916
917 private List resolveDependenciesWithClassifier( IdeDependency[] deps, String inClassifier,
918 boolean includeRemoteRepositories )
919 {
920 List missingClassifierDependencies = new ArrayList();
921
922
923
924 List remoteRepos = includeRemoteRepositories ? getRemoteArtifactRepositories() : Collections.EMPTY_LIST;
925
926 for ( int j = 0; j < deps.length; j++ )
927 {
928 IdeDependency dependency = deps[j];
929
930 if ( dependency.isReferencedProject() || dependency.isSystemScoped() )
931 {
932
933 continue;
934 }
935
936 if ( getLog().isDebugEnabled() )
937 {
938 getLog().debug(
939 "Searching for sources for " + dependency.getId() + ":" + dependency.getClassifier()
940 + " at " + dependency.getId() + ":" + inClassifier );
941 }
942
943 Artifact baseArtifact =
944 artifactFactory.createArtifactWithClassifier( dependency.getGroupId(), dependency.getArtifactId(),
945 dependency.getVersion(), dependency.getType(),
946 dependency.getClassifier() );
947 baseArtifact =
948 IdeUtils.resolveArtifact( artifactResolver, baseArtifact, remoteRepos, localRepository, getLog() );
949 if (!baseArtifact.isResolved()) {
950
951 continue;
952 }
953
954 Artifact artifact =
955 IdeUtils.createArtifactWithClassifier( dependency.getGroupId(), dependency.getArtifactId(),
956 dependency.getVersion(), dependency.getClassifier(),
957 inClassifier, artifactFactory );
958 File notAvailableMarkerFile = IdeUtils.getNotAvailableMarkerFile( localRepository, artifact );
959
960 if (forceRecheck && notAvailableMarkerFile.exists()) {
961 if (!notAvailableMarkerFile.delete()) {
962 getLog().warn( Messages.getString( "AbstractIdeSupportMojo.unabletodeletenotavailablemarkerfile", notAvailableMarkerFile ) );
963 }
964 }
965
966 if ( !notAvailableMarkerFile.exists() )
967 {
968 artifact =
969 IdeUtils.resolveArtifact( artifactResolver, artifact, remoteRepos, localRepository, getLog() );
970 if ( artifact.isResolved() )
971 {
972 if ( "sources".equals( inClassifier ) )
973 {
974 dependency.setSourceAttachment( artifact.getFile() );
975 }
976 else if ( "javadoc".equals( inClassifier ) )
977 {
978 dependency.setJavadocAttachment( artifact.getFile() );
979 }
980 }
981 else
982 {
983 if ( includeRemoteRepositories )
984 {
985 try
986 {
987 notAvailableMarkerFile.createNewFile();
988 getLog().debug( Messages.getString( "AbstractIdeSupportMojo.creatednotavailablemarkerfile", notAvailableMarkerFile ) );
989 }
990 catch ( IOException e )
991 {
992 getLog().warn( Messages.getString( "AbstractIdeSupportMojo.failedtocreatenotavailablemarkerfile",
993 notAvailableMarkerFile ) );
994 }
995 }
996
997
998
999 missingClassifierDependencies.add( dependency );
1000 }
1001 }
1002 }
1003
1004
1005
1006 return missingClassifierDependencies;
1007
1008 }
1009
1010
1011
1012
1013 private void reportMissingArtifacts()
1014 {
1015 StringBuffer msg = new StringBuffer();
1016
1017 if ( !missingSourceDependencies.isEmpty() )
1018 {
1019 if ( getDownloadSources() )
1020 {
1021 msg.append( Messages.getString( "AbstractIdeSupportMojo.sourcesnotavailable" ) );
1022 }
1023 else
1024 {
1025 msg.append( Messages.getString( "AbstractIdeSupportMojo.sourcesnotdownloaded" ) );
1026 }
1027
1028 for ( Iterator it = missingSourceDependencies.iterator(); it.hasNext(); )
1029 {
1030 IdeDependency art = (IdeDependency) it.next();
1031 msg.append( Messages.getString( "AbstractIdeSupportMojo.sourcesmissingitem", art.getId() ) );
1032 }
1033 msg.append( "\n" );
1034 }
1035
1036 if ( !missingJavadocDependencies.isEmpty() )
1037 {
1038 if ( getDownloadJavadocs() )
1039 {
1040 msg.append( Messages.getString( "AbstractIdeSupportMojo.javadocnotavailable" ) );
1041 }
1042 else
1043 {
1044 msg.append( Messages.getString( "AbstractIdeSupportMojo.javadocnotdownloaded" ) );
1045 }
1046
1047 for ( Iterator it = missingJavadocDependencies.iterator(); it.hasNext(); )
1048 {
1049 IdeDependency art = (IdeDependency) it.next();
1050 msg.append( Messages.getString( "AbstractIdeSupportMojo.javadocmissingitem", art.getId() ) );
1051 }
1052 msg.append( "\n" );
1053 }
1054 getLog().info( msg );
1055 }
1056
1057
1058
1059
1060
1061 public abstract List getExcludes();
1062
1063
1064
1065
1066
1067
1068
1069 protected boolean hasToResolveJar( Artifact art )
1070 {
1071 return !( getUseProjectReferences() && isAvailableAsAReactorProject( art ) );
1072 }
1073
1074
1075
1076
1077
1078
1079
1080 protected boolean useProjectReference( Artifact art )
1081 {
1082 return getUseProjectReferences() && isAvailableAsAReactorProject( art );
1083 }
1084
1085
1086
1087
1088
1089
1090
1091
1092 protected boolean isMavenVersion( String version )
1093 {
1094 try
1095 {
1096 VersionRange versionRange = VersionRange.createFromVersionSpec( version );
1097 ArtifactVersion mavenVersion = runtimeInformation.getApplicationVersion();
1098 return versionRange.containsVersion( mavenVersion );
1099 }
1100 catch ( InvalidVersionSpecificationException e )
1101 {
1102 throw new IllegalArgumentException( e.getMessage() );
1103 }
1104 }
1105
1106 }