]> source.dussan.org Git - archiva.git/blob
35bc3aa0bce6e4680cb8d1c37327992733ba72cd
[archiva.git] /
1 package org.apache.maven.archiva.dependency.graph.tasks;
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 org.apache.commons.lang.StringUtils;
23 import org.apache.maven.archiva.dependency.graph.DependencyGraph;
24 import org.apache.maven.archiva.dependency.graph.DependencyGraphBuilder;
25 import org.apache.maven.archiva.dependency.graph.DependencyGraphEdge;
26 import org.apache.maven.archiva.dependency.graph.DependencyGraphNode;
27 import org.apache.maven.archiva.dependency.graph.DependencyGraphUtils;
28 import org.apache.maven.archiva.dependency.graph.tasks.DependencyManagementStack.Rules;
29 import org.apache.maven.archiva.dependency.graph.walk.BaseVisitor;
30 import org.apache.maven.archiva.dependency.graph.walk.DependencyGraphVisitor;
31 import org.apache.maven.archiva.model.ArtifactReference;
32 import org.apache.maven.archiva.model.VersionedReference;
33
34 import java.util.HashMap;
35 import java.util.Iterator;
36 import java.util.List;
37 import java.util.Map;
38
39 /**
40  * Takes a stack of DependencyManagement objects and applies them to the node in question.
41  * This merely sets the version / scope / and exclusions on the nodes, as defined by DependencyManagement.
42  * 
43  * @version $Id$
44  */
45 public class DependencyManagementApplier
46     extends BaseVisitor
47     implements DependencyGraphVisitor
48 {
49     private DependencyManagementStack depStack = new DependencyManagementStack();
50
51     private DependencyGraphBuilder builder;
52
53     /**
54      * Map of changes to node versions (that will likely cause a reorganization of
55      * the graph), this is tracked until the walk is complete, at which point the
56      * changes are applied to the graph.
57      * 
58      * Performing graph changes of this scope during a walk of graph is hazardous,
59      * as you will be moving nodes around, mergeing nodes, dropping edges, etc.
60      */
61     private Map nodeVersionChanges = new HashMap();
62
63     private int nodesAdded = 0;
64
65     public void discoverGraph( DependencyGraph graph )
66     {
67         super.discoverGraph( graph );
68         nodeVersionChanges.clear();
69         depStack.reset();
70         nodesAdded = 0;
71     }
72
73     public void discoverNode( DependencyGraphNode node )
74     {
75         super.discoverNode( node );
76
77         depStack.push( node );
78
79         List edgesFrom = graph.getEdgesFrom( node );
80         Iterator it = edgesFrom.iterator();
81         while ( it.hasNext() )
82         {
83             DependencyGraphEdge edge = (DependencyGraphEdge) it.next();
84             Rules rules = depStack.getRules( edge );
85
86             if ( rules == null )
87             {
88                 // No rules for edge, skip it.
89                 continue;
90             }
91
92             DependencyGraphNode subnode = graph.getNode( edge.getNodeTo() );
93
94             /* There are 3 steps to processing the DependencyManagement. */
95
96             /* 1) Add exclusions to node ________________________________________________ */
97             node.getExcludes().addAll( rules.exclusions );
98
99             /* 2) Track version changes to node _________________________________________ */
100
101             // This is the version as specified by the rules.
102             String specifiedVersion = rules.artifact.getVersion();
103
104             // This is the version as being tracked by the nodeVersionChanges map.
105             String trackedVersion = (String) nodeVersionChanges.get( edge.getNodeTo() );
106
107             // This is the version of the subnode. 
108             String nodeVersion = subnode.getArtifact().getVersion();
109
110             // This is the actual version as determined by tracked and subnode
111             String actualVersion = StringUtils.defaultString( trackedVersion, nodeVersion );
112
113             // If the specified version changes the actual version ...
114             if ( !StringUtils.equals( specifiedVersion, actualVersion ) )
115             {
116                 // ... save this new value to be track ( for processing in #finishedGraph )
117                 nodeVersionChanges.put( edge.getNodeTo(), specifiedVersion );
118             }
119
120             /* 3) Update scope to edge __________________________________________________ */
121
122             if ( StringUtils.isNotBlank( rules.scope ) )
123             {
124                 edge.setScope( rules.scope );
125             }
126         }
127     }
128
129     public void finishNode( DependencyGraphNode node )
130     {
131         super.finishNode( node );
132
133         depStack.pop();
134     }
135
136     public void finishGraph( DependencyGraph graph )
137     {
138         super.finishGraph( graph );
139
140         Iterator it = this.nodeVersionChanges.keySet().iterator();
141         while ( it.hasNext() )
142         {
143             ArtifactReference ref = (ArtifactReference) it.next();
144             String toVersion = (String) this.nodeVersionChanges.get( ref );
145
146             collapseVersions( graph, ref, ref.getVersion(), toVersion );
147         }
148     }
149
150     /**
151      * Collapses Versions of nodes.
152      * 
153      * Takes two nodes, with differing versions.
154      * 
155      * 1) Removes the FROM edges connected to the FROM node
156      * 2) Moves the TO edges connected to the FROM node to the TO node.
157      * 3) Removes the FROM node (which is now orphaned)  
158      *  
159      * @param graph the graph to perform operation on
160      * @param fromRef the artifact reference of the FROM node.
161      * @param fromVersion the version of the FROM node
162      * @param toVersion the version of the TO node
163      */
164     private void collapseVersions( DependencyGraph graph, ArtifactReference fromRef, String fromVersion,
165                                    String toVersion )
166     {
167         if ( StringUtils.equals( fromVersion, toVersion ) )
168         {
169             // No point in doing anything.  nothing has changed.
170             return;
171         }
172
173         ArtifactReference toRef = new ArtifactReference();
174         toRef.setGroupId( fromRef.getGroupId() );
175         toRef.setArtifactId( fromRef.getArtifactId() );
176         toRef.setVersion( toVersion );
177         toRef.setClassifier( fromRef.getClassifier() );
178         toRef.setType( fromRef.getType() );
179
180         DependencyGraphNode nodeFROM = graph.getNode( fromRef );
181         DependencyGraphNode nodeTO = graph.getNode( toRef );
182
183         if ( nodeTO == null )
184         {
185             // new node doesn't exist in graph (yet)
186             nodeTO = new DependencyGraphNode( toRef );
187             nodeTO.setResolved( false );
188
189             graph.addNode( nodeTO );
190
191             VersionedReference projectRef = new VersionedReference();
192             projectRef.setGroupId( toRef.getGroupId() );
193             projectRef.setArtifactId( toRef.getArtifactId() );
194             projectRef.setVersion( toRef.getVersion() );
195
196             builder.resolveNode( graph, nodeTO, projectRef );
197             nodesAdded++;
198         }
199
200         DependencyGraphUtils.collapseNodes( graph, nodeFROM, nodeTO );
201     }
202
203     public DependencyGraphBuilder getBuilder()
204     {
205         return builder;
206     }
207
208     public void setBuilder( DependencyGraphBuilder builder )
209     {
210         this.builder = builder;
211     }
212
213     public boolean hasCreatedNodes()
214     {
215         return ( nodesAdded > 0 );
216     }
217 }