1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19 package org.apache.maven.internal.impl.model;
20
21 import java.util.Collection;
22 import java.util.HashSet;
23 import java.util.Iterator;
24 import java.util.LinkedHashMap;
25 import java.util.List;
26 import java.util.Map;
27 import java.util.Objects;
28 import java.util.Set;
29
30 import org.apache.maven.api.di.Named;
31 import org.apache.maven.api.di.Singleton;
32 import org.apache.maven.api.model.Dependency;
33 import org.apache.maven.api.model.DependencyManagement;
34 import org.apache.maven.api.model.Exclusion;
35 import org.apache.maven.api.model.InputLocation;
36 import org.apache.maven.api.model.InputSource;
37 import org.apache.maven.api.model.Model;
38 import org.apache.maven.api.services.BuilderProblem.Severity;
39 import org.apache.maven.api.services.ModelBuilderRequest;
40 import org.apache.maven.api.services.ModelProblem.Version;
41 import org.apache.maven.api.services.ModelProblemCollector;
42 import org.apache.maven.api.services.model.DependencyManagementImporter;
43
44
45
46
47
48 @Named
49 @Singleton
50 public class DefaultDependencyManagementImporter implements DependencyManagementImporter {
51
52 @Override
53 public Model importManagement(
54 Model target,
55 List<? extends DependencyManagement> sources,
56 ModelBuilderRequest request,
57 ModelProblemCollector problems) {
58 if (sources != null && !sources.isEmpty()) {
59 Map<String, Dependency> dependencies = new LinkedHashMap<>();
60
61 DependencyManagement depMgmt = target.getDependencyManagement();
62
63 if (depMgmt != null) {
64 for (Dependency dependency : depMgmt.getDependencies()) {
65 dependencies.put(dependency.getManagementKey(), dependency);
66 }
67 } else {
68 depMgmt = DependencyManagement.newInstance();
69 }
70
71 Set<String> directDependencies = new HashSet<>(dependencies.keySet());
72
73 for (DependencyManagement source : sources) {
74 for (Dependency dependency : source.getDependencies()) {
75 String key = dependency.getManagementKey();
76 Dependency present = dependencies.putIfAbsent(key, dependency);
77 if (present != null && !equals(dependency, present) && !directDependencies.contains(key)) {
78
79 problems.add(
80 Severity.WARNING,
81 Version.V40,
82 "Ignored POM import for: " + toString(dependency) + " as already imported "
83 + toString(present) + ". Add the conflicting managed dependency directly "
84 + "to the dependencyManagement section of the POM.");
85 }
86 if (present == null && request.isLocationTracking()) {
87 Dependency updatedDependency = updateWithImportedFrom(dependency, source);
88 dependencies.put(key, updatedDependency);
89 }
90 }
91 }
92
93 return target.withDependencyManagement(depMgmt.withDependencies(dependencies.values()));
94 }
95 return target;
96 }
97
98 private String toString(Dependency dependency) {
99 StringBuilder stringBuilder = new StringBuilder();
100 stringBuilder
101 .append(dependency.getGroupId())
102 .append(":")
103 .append(dependency.getArtifactId())
104 .append(":")
105 .append(dependency.getType());
106 if (dependency.getClassifier() != null && !dependency.getClassifier().isEmpty()) {
107 stringBuilder.append(":").append(dependency.getClassifier());
108 }
109 stringBuilder
110 .append(":")
111 .append(dependency.getVersion())
112 .append("@")
113 .append(dependency.getScope() == null ? "compile" : dependency.getScope());
114 if (dependency.isOptional()) {
115 stringBuilder.append("[optional]");
116 }
117 if (!dependency.getExclusions().isEmpty()) {
118 stringBuilder.append("[").append(dependency.getExclusions().size()).append(" exclusions]");
119 }
120 return stringBuilder.toString();
121 }
122
123 private boolean equals(Dependency d1, Dependency d2) {
124 return Objects.equals(d1.getGroupId(), d2.getGroupId())
125 && Objects.equals(d1.getArtifactId(), d2.getArtifactId())
126 && Objects.equals(d1.getVersion(), d2.getVersion())
127 && Objects.equals(d1.getType(), d2.getType())
128 && Objects.equals(d1.getClassifier(), d2.getClassifier())
129 && Objects.equals(d1.getScope(), d2.getScope())
130 && Objects.equals(d1.getSystemPath(), d2.getSystemPath())
131 && Objects.equals(d1.getOptional(), d2.getOptional())
132 && equals(d1.getExclusions(), d2.getExclusions());
133 }
134
135 private boolean equals(Collection<Exclusion> ce1, Collection<Exclusion> ce2) {
136 if (ce1.size() == ce2.size()) {
137 Iterator<Exclusion> i1 = ce1.iterator();
138 Iterator<Exclusion> i2 = ce2.iterator();
139 while (i1.hasNext() && i2.hasNext()) {
140 if (!equals(i1.next(), i2.next())) {
141 return false;
142 }
143 }
144 return !i1.hasNext() && !i2.hasNext();
145 }
146 return false;
147 }
148
149 private boolean equals(Exclusion e1, Exclusion e2) {
150 return Objects.equals(e1.getGroupId(), e2.getGroupId())
151 && Objects.equals(e1.getArtifactId(), e2.getArtifactId());
152 }
153
154 static Dependency updateWithImportedFrom(Dependency dependency, DependencyManagement bom) {
155
156 InputLocation dependencyLocation = dependency.getLocation("");
157 InputLocation bomLocation = bom.getLocation("");
158
159 if (dependencyLocation == null || bomLocation == null) {
160 return dependency;
161 }
162
163 InputSource dependencySource = dependencyLocation.getSource();
164 InputSource bomSource = bomLocation.getSource();
165
166
167 if (dependencySource == null
168 || bomSource == null
169 || Objects.equals(dependencySource.getModelId(), bomSource.getModelId())) {
170 return Dependency.newBuilder(dependency, true)
171 .importedFrom(bomLocation)
172 .build();
173 }
174
175 while (dependencySource.getImportedFrom() != null) {
176 InputLocation importedFrom = dependencySource.getImportedFrom();
177
178
179 if (Objects.equals(importedFrom.getSource().getModelId(), bomSource.getModelId())) {
180 return dependency;
181 }
182
183 dependencySource = importedFrom.getSource();
184 }
185
186
187
188 return Dependency.newBuilder(dependency, true)
189 .importedFrom(new InputLocation(bomLocation))
190 .build();
191 }
192 }