View Javadoc
1   /*
2    * Licensed to the Apache Software Foundation (ASF) under one
3    * or more contributor license agreements.  See the NOTICE file
4    * distributed with this work for additional information
5    * regarding copyright ownership.  The ASF licenses this file
6    * to you under the Apache License, Version 2.0 (the
7    * "License"); you may not use this file except in compliance
8    * with the License.  You may obtain a copy of the License at
9    *
10   *   http://www.apache.org/licenses/LICENSE-2.0
11   *
12   * Unless required by applicable law or agreed to in writing,
13   * software distributed under the License is distributed on an
14   * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
15   * KIND, either express or implied.  See the License for the
16   * specific language governing permissions and limitations
17   * under the License.
18   */
19  package org.apache.maven.repository.metadata;
20  
21  import javax.inject.Inject;
22  import javax.inject.Named;
23  import javax.inject.Singleton;
24  
25  import java.util.ArrayList;
26  import java.util.List;
27  import java.util.TreeSet;
28  
29  import org.apache.maven.artifact.ArtifactScopeEnum;
30  
31  /**
32   * Default conflict resolver.Implements closer newer first policy by default, but could be configured via plexus
33   *
34   */
35  @Named
36  @Singleton
37  @Deprecated
38  public class DefaultGraphConflictResolver implements GraphConflictResolver {
39      /**
40       * artifact, closer to the entry point, is selected
41       */
42      @Inject
43      protected GraphConflictResolutionPolicy policy;
44  
45      // -------------------------------------------------------------------------------------
46      // -------------------------------------------------------------------------------------
47      public MetadataGraph resolveConflicts(MetadataGraph graph, ArtifactScopeEnum scope)
48              throws GraphConflictResolutionException {
49          if (policy == null) {
50              throw new GraphConflictResolutionException("no GraphConflictResolutionPolicy injected");
51          }
52  
53          if (graph == null) {
54              return null;
55          }
56  
57          final MetadataGraphVertex entry = graph.getEntry();
58          if (entry == null) {
59              return null;
60          }
61  
62          if (graph.isEmpty()) {
63              throw new GraphConflictResolutionException("graph with an entry, but not vertices do not exist");
64          }
65  
66          if (graph.isEmptyEdges()) {
67              return null; // no edges - nothing to worry about
68          }
69  
70          final TreeSet<MetadataGraphVertex> vertices = graph.getVertices();
71  
72          try {
73              // edge case - single vertex graph
74              if (vertices.size() == 1) {
75                  return new MetadataGraph(entry);
76              }
77  
78              final ArtifactScopeEnum requestedScope = ArtifactScopeEnum.checkScope(scope);
79  
80              MetadataGraph res = new MetadataGraph(vertices.size());
81              res.setVersionedVertices(false);
82              res.setScopedVertices(false);
83  
84              MetadataGraphVertex resEntry = res.addVertex(entry.getMd());
85              res.setEntry(resEntry);
86  
87              res.setScope(requestedScope);
88  
89              for (MetadataGraphVertex v : vertices) {
90                  final List<MetadataGraphEdge> ins = graph.getIncidentEdges(v);
91                  final MetadataGraphEdge edge = cleanEdges(v, ins, requestedScope);
92  
93                  if (edge == null) { // no edges - don't need this vertex anymore
94                      if (entry.equals(v)) { // unless it's an entry point.
95                          // currently processing the entry point - it should not have any entry incident edges
96                          res.getEntry().getMd().setWhy("This is a graph entry point. No links.");
97                      } else {
98                          // System.out.println("--->"+v.getMd().toDomainString()
99                          // +" has been terminated on this entry set\n-------------------\n"
100                         // +ins
101                         // +"\n-------------------\n"
102                         // );
103                     }
104                 } else {
105                     // System.out.println("+++>"+v.getMd().toDomainString()+" still has "+edge.toString() );
106                     // fill in domain md with actual version data
107                     ArtifactMetadata md = v.getMd();
108                     ArtifactMetadata newMd = new ArtifactMetadata(
109                             md.getGroupId(),
110                             md.getArtifactId(),
111                             edge.getVersion(),
112                             md.getType(),
113                             md.getScopeAsEnum(),
114                             md.getClassifier(),
115                             edge.getArtifactUri(),
116                             edge.getSource() == null
117                                     ? ""
118                                     : edge.getSource().getMd().toString(),
119                             edge.isResolved(),
120                             edge.getTarget() == null
121                                     ? null
122                                     : edge.getTarget().getMd().getError());
123                     MetadataGraphVertex newV = res.addVertex(newMd);
124                     MetadataGraphVertex sourceV = res.addVertex(edge.getSource().getMd());
125 
126                     res.addEdge(sourceV, newV, edge);
127                 }
128             }
129             // System.err.println("Original graph("+graph.getVertices().size()+"):\n"+graph.toString());
130             // System.err.println("Cleaned("+requestedScope+") graph("+res.getVertices().size()+"):\n"+res.toString());
131             // System.err.println("Linked("+requestedScope+")
132             // subgraph("+linkedRes.getVertices().size()+"):\n"+linkedRes.toString());
133             return findLinkedSubgraph(res);
134         } catch (MetadataResolutionException e) {
135             throw new GraphConflictResolutionException(e);
136         }
137     }
138 
139     // -------------------------------------------------------------------------------------
140     private MetadataGraph findLinkedSubgraph(MetadataGraph g) {
141         if (g.getVertices().size() == 1) {
142             return g;
143         }
144 
145         List<MetadataGraphVertex> visited = new ArrayList<>(g.getVertices().size());
146         visit(g.getEntry(), visited, g);
147 
148         List<MetadataGraphVertex> dropList = new ArrayList<>(g.getVertices().size());
149 
150         // collect drop list
151         for (MetadataGraphVertex v : g.getVertices()) {
152             if (!visited.contains(v)) {
153                 dropList.add(v);
154             }
155         }
156 
157         if (dropList.size() < 1) {
158             return g;
159         }
160 
161         // now - drop vertices
162         TreeSet<MetadataGraphVertex> vertices = g.getVertices();
163         for (MetadataGraphVertex v : dropList) {
164             vertices.remove(v);
165         }
166 
167         return g;
168     }
169 
170     // -------------------------------------------------------------------------------------
171     private void visit(MetadataGraphVertex from, List<MetadataGraphVertex> visited, MetadataGraph graph) {
172         if (visited.contains(from)) {
173             return;
174         }
175 
176         visited.add(from);
177 
178         List<MetadataGraphEdge> exitList = graph.getExcidentEdges(from);
179         // String s = "|---> "+from.getMd().toString()+" - "+(exitList == null ? -1 : exitList.size()) + " exit links";
180         if (exitList != null && exitList.size() > 0) {
181             for (MetadataGraphEdge e : graph.getExcidentEdges(from)) {
182                 visit(e.getTarget(), visited, graph);
183             }
184         }
185     }
186 
187     // -------------------------------------------------------------------------------------
188     private MetadataGraphEdge cleanEdges(
189             MetadataGraphVertex v, List<MetadataGraphEdge> edges, ArtifactScopeEnum scope) {
190         if (edges == null || edges.isEmpty()) {
191             return null;
192         }
193 
194         if (edges.size() == 1) {
195             MetadataGraphEdge e = edges.get(0);
196             if (scope.encloses(e.getScope())) {
197                 return e;
198             }
199 
200             return null;
201         }
202 
203         MetadataGraphEdge res = null;
204 
205         for (MetadataGraphEdge e : edges) {
206             if (!scope.encloses(e.getScope())) {
207                 continue;
208             }
209 
210             if (res == null) {
211                 res = e;
212             } else {
213                 res = policy.apply(e, res);
214             }
215         }
216 
217         return res;
218     }
219     // -------------------------------------------------------------------------------------
220     // -------------------------------------------------------------------------------------
221 }