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.Arrays;
27 import java.util.List;
28
29 import org.apache.maven.artifact.ArtifactScopeEnum;
30
31 /**
32 * default implementation of the metadata classpath transformer
33 *
34 *
35 */
36 @Named
37 @Singleton
38 @Deprecated
39 public class DefaultClasspathTransformation implements ClasspathTransformation {
40 @Inject
41 GraphConflictResolver conflictResolver;
42
43 // ----------------------------------------------------------------------------------------------------
44 public ClasspathContainer transform(MetadataGraph dirtyGraph, ArtifactScopeEnum scope, boolean resolve)
45 throws MetadataGraphTransformationException {
46 try {
47 if (dirtyGraph == null || dirtyGraph.isEmpty()) {
48 return null;
49 }
50
51 MetadataGraph cleanGraph = conflictResolver.resolveConflicts(dirtyGraph, scope);
52
53 if (cleanGraph == null || cleanGraph.isEmpty()) {
54 return null;
55 }
56
57 ClasspathContainer cpc = new ClasspathContainer(scope);
58 if (cleanGraph.isEmptyEdges()) {
59 // single entry in the classpath, populated from itself
60 ArtifactMetadata amd = cleanGraph.getEntry().getMd();
61 cpc.add(amd);
62 } else {
63 ClasspathGraphVisitor v = new ClasspathGraphVisitor(cleanGraph, cpc);
64 MetadataGraphVertex entry = cleanGraph.getEntry();
65 // entry point
66 v.visit(entry);
67 }
68
69 return cpc;
70 } catch (GraphConflictResolutionException e) {
71 throw new MetadataGraphTransformationException(e);
72 }
73 }
74
75 // ===================================================================================================
76 /**
77 * Helper class to traverse graph. Required to make the containing method thread-safe
78 * and yet use class level data to lessen stack usage in recursion
79 */
80 private class ClasspathGraphVisitor {
81 MetadataGraph graph;
82
83 ClasspathContainer cpc;
84
85 List<MetadataGraphVertex> visited;
86
87 // -----------------------------------------------------------------------
88 protected ClasspathGraphVisitor(MetadataGraph cleanGraph, ClasspathContainer cpc) {
89 this.cpc = cpc;
90 this.graph = cleanGraph;
91
92 visited = new ArrayList<>(cleanGraph.getVertices().size());
93 }
94
95 // -----------------------------------------------------------------------
96 protected void visit(MetadataGraphVertex node) // , String version, String artifactUri )
97 {
98 ArtifactMetadata md = node.getMd();
99 if (visited.contains(node)) {
100 return;
101 }
102
103 cpc.add(md);
104 //
105 // TreeSet<MetadataGraphEdge> deps = new TreeSet<MetadataGraphEdge>(
106 // new Comparator<MetadataGraphEdge>()
107 // {
108 // public int compare( MetadataGraphEdge e1
109 // , MetadataGraphEdge e2
110 // )
111 // {
112 // if( e1.getDepth() == e2.getDepth() )
113 // {
114 // if( e2.getPomOrder() == e1.getPomOrder() )
115 // return
116 // e1.getTarget().toString().compareTo(e2.getTarget().toString() );
117 //
118 // return e2.getPomOrder() - e1.getPomOrder();
119 // }
120 //
121 // return e2.getDepth() - e1.getDepth();
122 // }
123 // }
124 // );
125
126 List<MetadataGraphEdge> exits = graph.getExcidentEdges(node);
127
128 if (exits != null && exits.size() > 0) {
129 MetadataGraphEdge[] sortedExits = exits.toArray(new MetadataGraphEdge[0]);
130 Arrays.sort(sortedExits, (e1, e2) -> {
131 if (e1.getDepth() == e2.getDepth()) {
132 if (e2.getPomOrder() == e1.getPomOrder()) {
133 return e1.getTarget()
134 .toString()
135 .compareTo(e2.getTarget().toString());
136 }
137 return e2.getPomOrder() - e1.getPomOrder();
138 }
139 return e2.getDepth() - e1.getDepth();
140 });
141
142 for (MetadataGraphEdge e : sortedExits) {
143 MetadataGraphVertex targetNode = e.getTarget();
144 targetNode.getMd().setArtifactScope(e.getScope());
145 targetNode.getMd().setWhy(e.getSource().getMd().toString());
146 visit(targetNode);
147 }
148 }
149 }
150 // -----------------------------------------------------------------------
151 // -----------------------------------------------------------------------
152 }
153 // ----------------------------------------------------------------------------------------------------
154 // ----------------------------------------------------------------------------------------------------
155 }