View Javadoc
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[exits.size()] );
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