1 package org.apache.maven.repository.metadata;
2
3 /*
4 * Licensed to the Apache Software Foundation (ASF) under one
5 * or more contributor license agreements. See the NOTICE file
6 * distributed with this work for additional information
7 * regarding copyright ownership. The ASF licenses this file
8 * to you under the Apache License, Version 2.0 (the
9 * "License"); you may not use this file except in compliance
10 * with the License. You may obtain a copy of the License at
11 *
12 * http://www.apache.org/licenses/LICENSE-2.0
13 *
14 * Unless required by applicable law or agreed to in writing,
15 * software distributed under the License is distributed on an
16 * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
17 * KIND, either express or implied. See the License for the
18 * specific language governing permissions and limitations
19 * under the License.
20 */
21
22 import java.util.ArrayList;
23 import java.util.Arrays;
24 import java.util.Comparator;
25 import java.util.List;
26
27 import org.apache.maven.artifact.ArtifactScopeEnum;
28 import org.codehaus.plexus.component.annotations.Component;
29 import org.codehaus.plexus.component.annotations.Requirement;
30
31 /**
32 * default implementation of the metadata classpath transformer
33 *
34 * @author <a href="oleg@codehaus.org">Oleg Gusakov</a>
35 *
36 */
37 @Component( role = ClasspathTransformation.class )
38 public class DefaultClasspathTransformation
39 implements ClasspathTransformation
40 {
41 @Requirement
42 GraphConflictResolver conflictResolver;
43
44 //----------------------------------------------------------------------------------------------------
45 public ClasspathContainer transform( MetadataGraph dirtyGraph, ArtifactScopeEnum scope, boolean resolve )
46 throws MetadataGraphTransformationException
47 {
48 try
49 {
50 if ( dirtyGraph == null || dirtyGraph.isEmpty() )
51 {
52 return null;
53 }
54
55 MetadataGraph cleanGraph = conflictResolver.resolveConflicts( dirtyGraph, scope );
56
57 if ( cleanGraph == null || cleanGraph.isEmpty() )
58 {
59 return null;
60 }
61
62 ClasspathContainer cpc = new ClasspathContainer( scope );
63 if ( cleanGraph.isEmptyEdges() )
64 {
65 // single entry in the classpath, populated from itself
66 ArtifactMetadata amd = cleanGraph.getEntry().getMd();
67 cpc.add( amd );
68 }
69 else
70 {
71 ClasspathGraphVisitor v = new ClasspathGraphVisitor( cleanGraph, cpc );
72 MetadataGraphVertex entry = cleanGraph.getEntry();
73 // entry point
74 v.visit( entry );
75 }
76
77 return cpc;
78 }
79 catch ( GraphConflictResolutionException e )
80 {
81 throw new MetadataGraphTransformationException( e );
82 }
83 }
84
85 //===================================================================================================
86 /**
87 * Helper class to traverse graph. Required to make the containing method thread-safe
88 * and yet use class level data to lessen stack usage in recursion
89 */
90 private class ClasspathGraphVisitor
91 {
92 MetadataGraph graph;
93
94 ClasspathContainer cpc;
95
96 List<MetadataGraphVertex> visited;
97
98 // -----------------------------------------------------------------------
99 protected ClasspathGraphVisitor( MetadataGraph cleanGraph, ClasspathContainer cpc )
100 {
101 this.cpc = cpc;
102 this.graph = cleanGraph;
103
104 visited = new ArrayList<>( cleanGraph.getVertices().size() );
105 }
106
107 // -----------------------------------------------------------------------
108 protected void visit( MetadataGraphVertex node ) // , String version, String artifactUri )
109 {
110 ArtifactMetadata md = node.getMd();
111 if ( visited.contains( node ) )
112 {
113 return;
114 }
115
116 cpc.add( md );
117 //
118 // TreeSet<MetadataGraphEdge> deps = new TreeSet<MetadataGraphEdge>(
119 // new Comparator<MetadataGraphEdge>()
120 // {
121 // public int compare( MetadataGraphEdge e1
122 // , MetadataGraphEdge e2
123 // )
124 // {
125 // if( e1.getDepth() == e2.getDepth() )
126 // {
127 // if( e2.getPomOrder() == e1.getPomOrder() )
128 // return e1.getTarget().toString().compareTo(e2.getTarget().toString() );
129 //
130 // return e2.getPomOrder() - e1.getPomOrder();
131 // }
132 //
133 // return e2.getDepth() - e1.getDepth();
134 // }
135 // }
136 // );
137
138 List<MetadataGraphEdge> exits = graph.getExcidentEdges( node );
139
140 if ( exits != null && exits.size() > 0 )
141 {
142 MetadataGraphEdge[] sortedExits = exits.toArray( new MetadataGraphEdge[0] );
143 Arrays.sort( sortedExits
144 ,
145 new Comparator<MetadataGraphEdge>()
146 {
147 public int compare( MetadataGraphEdge e1
148 , MetadataGraphEdge e2
149 )
150 {
151 if ( e1.getDepth() == e2.getDepth() )
152 {
153 if ( e2.getPomOrder() == e1.getPomOrder() )
154 {
155 return e1.getTarget().toString().compareTo( e2.getTarget().toString() );
156 }
157 return e2.getPomOrder() - e1.getPomOrder();
158 }
159
160 return e2.getDepth() - e1.getDepth();
161 }
162 }
163 );
164
165 for ( MetadataGraphEdge e : sortedExits )
166 {
167 MetadataGraphVertex targetNode = e.getTarget();
168 targetNode.getMd().setArtifactScope( e.getScope() );
169 targetNode.getMd().setWhy( e.getSource().getMd().toString() );
170 visit( targetNode );
171 }
172 }
173
174 }
175 //-----------------------------------------------------------------------
176 //-----------------------------------------------------------------------
177 }
178 //----------------------------------------------------------------------------------------------------
179 //----------------------------------------------------------------------------------------------------
180 }
181
182
183