1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19 package org.apache.maven.repository.metadata;
20
21 import java.util.ArrayList;
22 import java.util.List;
23 import java.util.TreeSet;
24
25 import org.apache.maven.artifact.ArtifactScopeEnum;
26 import org.codehaus.plexus.component.annotations.Component;
27 import org.codehaus.plexus.component.annotations.Requirement;
28
29
30
31
32
33
34 @Component(role = GraphConflictResolver.class)
35 public class DefaultGraphConflictResolver implements GraphConflictResolver {
36
37
38
39 @Requirement(role = GraphConflictResolutionPolicy.class)
40 protected GraphConflictResolutionPolicy policy;
41
42
43
44 public MetadataGraph resolveConflicts(MetadataGraph graph, ArtifactScopeEnum scope)
45 throws GraphConflictResolutionException {
46 if (policy == null) {
47 throw new GraphConflictResolutionException("no GraphConflictResolutionPolicy injected");
48 }
49
50 if (graph == null) {
51 return null;
52 }
53
54 final MetadataGraphVertex entry = graph.getEntry();
55 if (entry == null) {
56 return null;
57 }
58
59 if (graph.isEmpty()) {
60 throw new GraphConflictResolutionException("graph with an entry, but not vertices do not exist");
61 }
62
63 if (graph.isEmptyEdges()) {
64 return null;
65 }
66
67 final TreeSet<MetadataGraphVertex> vertices = graph.getVertices();
68
69 try {
70
71 if (vertices.size() == 1) {
72 return new MetadataGraph(entry);
73 }
74
75 final ArtifactScopeEnum requestedScope = ArtifactScopeEnum.checkScope(scope);
76
77 MetadataGraph res = new MetadataGraph(vertices.size());
78 res.setVersionedVertices(false);
79 res.setScopedVertices(false);
80
81 MetadataGraphVertex resEntry = res.addVertex(entry.getMd());
82 res.setEntry(resEntry);
83
84 res.setScope(requestedScope);
85
86 for (MetadataGraphVertex v : vertices) {
87 final List<MetadataGraphEdge> ins = graph.getIncidentEdges(v);
88 final MetadataGraphEdge edge = cleanEdges(v, ins, requestedScope);
89
90 if (edge == null) {
91 if (entry.equals(v)) {
92
93 res.getEntry().getMd().setWhy("This is a graph entry point. No links.");
94 } else {
95
96
97
98
99
100 }
101 } else {
102
103
104 ArtifactMetadata md = v.getMd();
105 ArtifactMetadata newMd = new ArtifactMetadata(
106 md.getGroupId(),
107 md.getArtifactId(),
108 edge.getVersion(),
109 md.getType(),
110 md.getScopeAsEnum(),
111 md.getClassifier(),
112 edge.getArtifactUri(),
113 edge.getSource() == null
114 ? ""
115 : edge.getSource().getMd().toString(),
116 edge.isResolved(),
117 edge.getTarget() == null
118 ? null
119 : edge.getTarget().getMd().getError());
120 MetadataGraphVertex newV = res.addVertex(newMd);
121 MetadataGraphVertex sourceV = res.addVertex(edge.getSource().getMd());
122
123 res.addEdge(sourceV, newV, edge);
124 }
125 }
126
127
128
129
130 return findLinkedSubgraph(res);
131 } catch (MetadataResolutionException e) {
132 throw new GraphConflictResolutionException(e);
133 }
134 }
135
136
137 private MetadataGraph findLinkedSubgraph(MetadataGraph g) {
138 if (g.getVertices().size() == 1) {
139 return g;
140 }
141
142 List<MetadataGraphVertex> visited = new ArrayList<>(g.getVertices().size());
143 visit(g.getEntry(), visited, g);
144
145 List<MetadataGraphVertex> dropList = new ArrayList<>(g.getVertices().size());
146
147
148 for (MetadataGraphVertex v : g.getVertices()) {
149 if (!visited.contains(v)) {
150 dropList.add(v);
151 }
152 }
153
154 if (dropList.size() < 1) {
155 return g;
156 }
157
158
159 TreeSet<MetadataGraphVertex> vertices = g.getVertices();
160 for (MetadataGraphVertex v : dropList) {
161 vertices.remove(v);
162 }
163
164 return g;
165 }
166
167
168 private void visit(MetadataGraphVertex from, List<MetadataGraphVertex> visited, MetadataGraph graph) {
169 if (visited.contains(from)) {
170 return;
171 }
172
173 visited.add(from);
174
175 List<MetadataGraphEdge> exitList = graph.getExcidentEdges(from);
176
177 if (exitList != null && exitList.size() > 0) {
178 for (MetadataGraphEdge e : graph.getExcidentEdges(from)) {
179 visit(e.getTarget(), visited, graph);
180 }
181 }
182 }
183
184
185 private MetadataGraphEdge cleanEdges(
186 MetadataGraphVertex v, List<MetadataGraphEdge> edges, ArtifactScopeEnum scope) {
187 if (edges == null || edges.isEmpty()) {
188 return null;
189 }
190
191 if (edges.size() == 1) {
192 MetadataGraphEdge e = edges.get(0);
193 if (scope.encloses(e.getScope())) {
194 return e;
195 }
196
197 return null;
198 }
199
200 MetadataGraphEdge res = null;
201
202 for (MetadataGraphEdge e : edges) {
203 if (!scope.encloses(e.getScope())) {
204 continue;
205 }
206
207 if (res == null) {
208 res = e;
209 } else {
210 res = policy.apply(e, res);
211 }
212 }
213
214 return res;
215 }
216
217
218 }