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.List;
24  import java.util.TreeSet;
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 conflict resolver.Implements closer newer first policy by default, but could be configured via plexus
32   *
33   * @author <a href="mailto:oleg@codehaus.org">Oleg Gusakov</a>
34   * @version $Id: DefaultGraphConflictResolver.java 958295 2010-06-26 23:16:18Z hboutemy $
35   */
36  @Component( role = GraphConflictResolver.class )
37  public class DefaultGraphConflictResolver
38      implements GraphConflictResolver
39  {
40      /**
41       * artifact, closer to the entry point, is selected
42       */
43      @Requirement( role = GraphConflictResolutionPolicy.class )
44      protected GraphConflictResolutionPolicy policy;
45  
46      // -------------------------------------------------------------------------------------
47      // -------------------------------------------------------------------------------------
48      public MetadataGraph resolveConflicts( MetadataGraph graph, ArtifactScopeEnum scope )
49          throws GraphConflictResolutionException
50      {
51          if ( policy == null )
52          {
53              throw new GraphConflictResolutionException( "no GraphConflictResolutionPolicy injected" );
54          }
55  
56          if ( graph == null )
57          {
58              return null;
59          }
60  
61          final MetadataGraphVertex entry = graph.getEntry();
62          if ( entry == null )
63          {
64              return null;
65          }
66  
67          if ( graph.isEmpty() )
68          {
69              throw new GraphConflictResolutionException( "graph with an entry, but not vertices do not exist" );
70          }
71  
72          if ( graph.isEmptyEdges() )
73          {
74              return null; // no edges - nothing to worry about
75          }
76  
77          final TreeSet<MetadataGraphVertex> vertices = graph.getVertices();
78  
79          try
80          {
81              // edge case - single vertex graph
82              if ( vertices.size() == 1 )
83              {
84                  return new MetadataGraph( entry );
85              }
86  
87              final ArtifactScopeEnum requestedScope = ArtifactScopeEnum.checkScope( scope );
88  
89              MetadataGraph res = new MetadataGraph( vertices.size() );
90              res.setVersionedVertices( false );
91              res.setScopedVertices( false );
92  
93              MetadataGraphVertex resEntry = res.addVertex( entry.getMd() );
94              res.setEntry( resEntry );
95  
96              res.setScope( requestedScope );
97  
98              for ( MetadataGraphVertex v : vertices )
99              {
100                 final List<MetadataGraphEdge> ins = graph.getIncidentEdges( v );
101                 final MetadataGraphEdge edge = cleanEdges( v, ins, requestedScope );
102 
103                 if ( edge == null )
104                 { // no edges - don't need this vertex any more
105                     if ( entry.equals( v ) )
106                     { // unless it's an entry point.
107                         // currently processing the entry point - it should not have any entry incident edges
108                         res.getEntry().getMd().setWhy( "This is a graph entry point. No links." );
109                     }
110                     else
111                     {
112                         // System.out.println("--->"+v.getMd().toDomainString()
113                         // +" has been terminated on this entry set\n-------------------\n"
114                         // +ins
115                         // +"\n-------------------\n"
116                         // );
117                     }
118                 }
119                 else
120                 {
121                     // System.out.println("+++>"+v.getMd().toDomainString()+" still has "+edge.toString() );
122                     // fill in domain md with actual version data
123                     ArtifactMetadata md = v.getMd();
124                     ArtifactMetadata newMd =
125                         new ArtifactMetadata( md.getGroupId(), md.getArtifactId(), edge.getVersion(), md.getType(),
126                                               md.getScopeAsEnum(), md.getClassifier(), edge.getArtifactUri(),
127                                               edge.getSource() == null ? "" : edge.getSource().getMd().toString(),
128                                               edge.isResolved(), edge.getTarget() == null ? null
129                                                               : edge.getTarget().getMd().getError() );
130                     MetadataGraphVertex newV = res.addVertex( newMd );
131                     MetadataGraphVertex sourceV = res.addVertex( edge.getSource().getMd() );
132 
133                     res.addEdge( sourceV, newV, edge );
134                 }
135             }
136             MetadataGraph linkedRes = findLinkedSubgraph( res );
137             // System.err.println("Original graph("+graph.getVertices().size()+"):\n"+graph.toString());
138             // System.err.println("Cleaned("+requestedScope+") graph("+res.getVertices().size()+"):\n"+res.toString());
139             // System.err.println("Linked("+requestedScope+")
140             // subgraph("+linkedRes.getVertices().size()+"):\n"+linkedRes.toString());
141             return linkedRes;
142         }
143         catch ( MetadataResolutionException e )
144         {
145             throw new GraphConflictResolutionException( e );
146         }
147     }
148 
149     // -------------------------------------------------------------------------------------
150     private MetadataGraph findLinkedSubgraph( MetadataGraph g )
151     {
152         if ( g.getVertices().size() == 1 )
153         {
154             return g;
155         }
156 
157         List<MetadataGraphVertex> visited = new ArrayList<MetadataGraphVertex>( g.getVertices().size() );
158         visit( g.getEntry(), visited, g );
159 
160         List<MetadataGraphVertex> dropList = new ArrayList<MetadataGraphVertex>( g.getVertices().size() );
161 
162         // collect drop list
163         for ( MetadataGraphVertex v : g.getVertices() )
164         {
165             if ( !visited.contains( v ) )
166             {
167                 dropList.add( v );
168             }
169         }
170 
171         if ( dropList.size() < 1 )
172         {
173             return g;
174         }
175 
176         // now - drop vertices
177         TreeSet<MetadataGraphVertex> vertices = g.getVertices();
178         for ( MetadataGraphVertex v : dropList )
179         {
180             vertices.remove( v );
181         }
182 
183         return g;
184     }
185 
186     // -------------------------------------------------------------------------------------
187     private void visit( MetadataGraphVertex from, List<MetadataGraphVertex> visited, MetadataGraph graph )
188     {
189         if ( visited.contains( from ) )
190         {
191             return;
192         }
193 
194         visited.add( from );
195 
196         List<MetadataGraphEdge> exitList = graph.getExcidentEdges( from );
197         // String s = "|---> "+from.getMd().toString()+" - "+(exitList == null ? -1 : exitList.size()) + " exit links";
198         if ( exitList != null && exitList.size() > 0 )
199         {
200             for ( MetadataGraphEdge e : graph.getExcidentEdges( from ) )
201             {
202                 visit( e.getTarget(), visited, graph );
203             }
204         }
205     }
206 
207     // -------------------------------------------------------------------------------------
208     private MetadataGraphEdge cleanEdges( MetadataGraphVertex v, List<MetadataGraphEdge> edges,
209                                           ArtifactScopeEnum scope )
210     {
211         if ( edges == null || edges.isEmpty() )
212         {
213             return null;
214         }
215 
216         if ( edges.size() == 1 )
217         {
218             MetadataGraphEdge e = edges.get( 0 );
219             if ( scope.encloses( e.getScope() ) )
220             {
221                 return e;
222             }
223 
224             return null;
225         }
226 
227         MetadataGraphEdge res = null;
228 
229         for ( MetadataGraphEdge e : edges )
230         {
231             if ( !scope.encloses( e.getScope() ) )
232             {
233                 continue;
234             }
235 
236             if ( res == null )
237             {
238                 res = e;
239             }
240             else
241             {
242                 res = policy.apply( e, res );
243             }
244         }
245 
246         return res;
247     }
248     // -------------------------------------------------------------------------------------
249     // -------------------------------------------------------------------------------------
250 }