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