blob: 55bad67432666950fbd1ddb8e68436c450816df1 [file] [log] [blame]
/*
* Licensed to the Apache Software Foundation (ASF) under one
* or more contributor license agreements. See the NOTICE file
* distributed with this work for additional information
* regarding copyright ownership. The ASF licenses this file
* to you under the Apache License, Version 2.0 (the
* "License"); you may not use this file except in compliance
* with the License. You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing,
* software distributed under the License is distributed on an
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
* KIND, either express or implied. See the License for the
* specific language governing permissions and limitations
* under the License.
*/
package org.apache.maven.repository.metadata;
import javax.inject.Inject;
import javax.inject.Named;
import javax.inject.Singleton;
import java.util.ArrayList;
import java.util.List;
import java.util.TreeSet;
import org.apache.maven.artifact.ArtifactScopeEnum;
/**
* Default conflict resolver.Implements closer newer first policy by default, but could be configured via plexus
*
*/
@Named
@Singleton
@Deprecated
public class DefaultGraphConflictResolver implements GraphConflictResolver {
/**
* artifact, closer to the entry point, is selected
*/
@Inject
protected GraphConflictResolutionPolicy policy;
// -------------------------------------------------------------------------------------
// -------------------------------------------------------------------------------------
public MetadataGraph resolveConflicts(MetadataGraph graph, ArtifactScopeEnum scope)
throws GraphConflictResolutionException {
if (policy == null) {
throw new GraphConflictResolutionException("no GraphConflictResolutionPolicy injected");
}
if (graph == null) {
return null;
}
final MetadataGraphVertex entry = graph.getEntry();
if (entry == null) {
return null;
}
if (graph.isEmpty()) {
throw new GraphConflictResolutionException("graph with an entry, but not vertices do not exist");
}
if (graph.isEmptyEdges()) {
return null; // no edges - nothing to worry about
}
final TreeSet<MetadataGraphVertex> vertices = graph.getVertices();
try {
// edge case - single vertex graph
if (vertices.size() == 1) {
return new MetadataGraph(entry);
}
final ArtifactScopeEnum requestedScope = ArtifactScopeEnum.checkScope(scope);
MetadataGraph res = new MetadataGraph(vertices.size());
res.setVersionedVertices(false);
res.setScopedVertices(false);
MetadataGraphVertex resEntry = res.addVertex(entry.getMd());
res.setEntry(resEntry);
res.setScope(requestedScope);
for (MetadataGraphVertex v : vertices) {
final List<MetadataGraphEdge> ins = graph.getIncidentEdges(v);
final MetadataGraphEdge edge = cleanEdges(v, ins, requestedScope);
if (edge == null) { // no edges - don't need this vertex anymore
if (entry.equals(v)) { // unless it's an entry point.
// currently processing the entry point - it should not have any entry incident edges
res.getEntry().getMd().setWhy("This is a graph entry point. No links.");
} else {
// System.out.println("--->"+v.getMd().toDomainString()
// +" has been terminated on this entry set\n-------------------\n"
// +ins
// +"\n-------------------\n"
// );
}
} else {
// System.out.println("+++>"+v.getMd().toDomainString()+" still has "+edge.toString() );
// fill in domain md with actual version data
ArtifactMetadata md = v.getMd();
ArtifactMetadata newMd = new ArtifactMetadata(
md.getGroupId(),
md.getArtifactId(),
edge.getVersion(),
md.getType(),
md.getScopeAsEnum(),
md.getClassifier(),
edge.getArtifactUri(),
edge.getSource() == null
? ""
: edge.getSource().getMd().toString(),
edge.isResolved(),
edge.getTarget() == null
? null
: edge.getTarget().getMd().getError());
MetadataGraphVertex newV = res.addVertex(newMd);
MetadataGraphVertex sourceV = res.addVertex(edge.getSource().getMd());
res.addEdge(sourceV, newV, edge);
}
}
// System.err.println("Original graph("+graph.getVertices().size()+"):\n"+graph.toString());
// System.err.println("Cleaned("+requestedScope+") graph("+res.getVertices().size()+"):\n"+res.toString());
// System.err.println("Linked("+requestedScope+")
// subgraph("+linkedRes.getVertices().size()+"):\n"+linkedRes.toString());
return findLinkedSubgraph(res);
} catch (MetadataResolutionException e) {
throw new GraphConflictResolutionException(e);
}
}
// -------------------------------------------------------------------------------------
private MetadataGraph findLinkedSubgraph(MetadataGraph g) {
if (g.getVertices().size() == 1) {
return g;
}
List<MetadataGraphVertex> visited = new ArrayList<>(g.getVertices().size());
visit(g.getEntry(), visited, g);
List<MetadataGraphVertex> dropList = new ArrayList<>(g.getVertices().size());
// collect drop list
for (MetadataGraphVertex v : g.getVertices()) {
if (!visited.contains(v)) {
dropList.add(v);
}
}
if (dropList.size() < 1) {
return g;
}
// now - drop vertices
TreeSet<MetadataGraphVertex> vertices = g.getVertices();
for (MetadataGraphVertex v : dropList) {
vertices.remove(v);
}
return g;
}
// -------------------------------------------------------------------------------------
private void visit(MetadataGraphVertex from, List<MetadataGraphVertex> visited, MetadataGraph graph) {
if (visited.contains(from)) {
return;
}
visited.add(from);
List<MetadataGraphEdge> exitList = graph.getExcidentEdges(from);
// String s = "|---> "+from.getMd().toString()+" - "+(exitList == null ? -1 : exitList.size()) + " exit links";
if (exitList != null && exitList.size() > 0) {
for (MetadataGraphEdge e : graph.getExcidentEdges(from)) {
visit(e.getTarget(), visited, graph);
}
}
}
// -------------------------------------------------------------------------------------
private MetadataGraphEdge cleanEdges(
MetadataGraphVertex v, List<MetadataGraphEdge> edges, ArtifactScopeEnum scope) {
if (edges == null || edges.isEmpty()) {
return null;
}
if (edges.size() == 1) {
MetadataGraphEdge e = edges.get(0);
if (scope.encloses(e.getScope())) {
return e;
}
return null;
}
MetadataGraphEdge res = null;
for (MetadataGraphEdge e : edges) {
if (!scope.encloses(e.getScope())) {
continue;
}
if (res == null) {
res = e;
} else {
res = policy.apply(e, res);
}
}
return res;
}
// -------------------------------------------------------------------------------------
// -------------------------------------------------------------------------------------
}