1 package org.apache.maven.archiva.dependency.graph.tasks;
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
12 * http://www.apache.org/licenses/LICENSE-2.0
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
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;
34 import java.util.HashMap;
35 import java.util.Iterator;
36 import java.util.List;
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.
45 public class DependencyManagementApplier
47 implements DependencyGraphVisitor
49 private DependencyManagementStack depStack = new DependencyManagementStack();
51 private DependencyGraphBuilder builder;
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.
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.
61 private Map nodeVersionChanges = new HashMap();
63 private int nodesAdded = 0;
65 public void discoverGraph( DependencyGraph graph )
67 super.discoverGraph( graph );
68 nodeVersionChanges.clear();
73 public void discoverNode( DependencyGraphNode node )
75 super.discoverNode( node );
77 depStack.push( node );
79 List edgesFrom = graph.getEdgesFrom( node );
80 Iterator it = edgesFrom.iterator();
81 while ( it.hasNext() )
83 DependencyGraphEdge edge = (DependencyGraphEdge) it.next();
84 Rules rules = depStack.getRules( edge );
88 // No rules for edge, skip it.
92 DependencyGraphNode subnode = graph.getNode( edge.getNodeTo() );
94 /* There are 3 steps to processing the DependencyManagement. */
96 /* 1) Add exclusions to node ________________________________________________ */
97 node.getExcludes().addAll( rules.exclusions );
99 /* 2) Track version changes to node _________________________________________ */
101 // This is the version as specified by the rules.
102 String specifiedVersion = rules.artifact.getVersion();
104 // This is the version as being tracked by the nodeVersionChanges map.
105 String trackedVersion = (String) nodeVersionChanges.get( edge.getNodeTo() );
107 // This is the version of the subnode.
108 String nodeVersion = subnode.getArtifact().getVersion();
110 // This is the actual version as determined by tracked and subnode
111 String actualVersion = StringUtils.defaultString( trackedVersion, nodeVersion );
113 // If the specified version changes the actual version ...
114 if ( !StringUtils.equals( specifiedVersion, actualVersion ) )
116 // ... save this new value to be track ( for processing in #finishedGraph )
117 nodeVersionChanges.put( edge.getNodeTo(), specifiedVersion );
120 /* 3) Update scope to edge __________________________________________________ */
122 if ( StringUtils.isNotBlank( rules.scope ) )
124 edge.setScope( rules.scope );
129 public void finishNode( DependencyGraphNode node )
131 super.finishNode( node );
136 public void finishGraph( DependencyGraph graph )
138 super.finishGraph( graph );
140 Iterator it = this.nodeVersionChanges.keySet().iterator();
141 while ( it.hasNext() )
143 ArtifactReference ref = (ArtifactReference) it.next();
144 String toVersion = (String) this.nodeVersionChanges.get( ref );
146 collapseVersions( graph, ref, ref.getVersion(), toVersion );
151 * Collapses Versions of nodes.
153 * Takes two nodes, with differing versions.
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)
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
164 private void collapseVersions( DependencyGraph graph, ArtifactReference fromRef, String fromVersion,
167 if ( StringUtils.equals( fromVersion, toVersion ) )
169 // No point in doing anything. nothing has changed.
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() );
180 DependencyGraphNode nodeFROM = graph.getNode( fromRef );
181 DependencyGraphNode nodeTO = graph.getNode( toRef );
183 if ( nodeTO == null )
185 // new node doesn't exist in graph (yet)
186 nodeTO = new DependencyGraphNode( toRef );
187 nodeTO.setResolved( false );
189 graph.addNode( nodeTO );
191 VersionedReference projectRef = new VersionedReference();
192 projectRef.setGroupId( toRef.getGroupId() );
193 projectRef.setArtifactId( toRef.getArtifactId() );
194 projectRef.setVersion( toRef.getVersion() );
196 builder.resolveNode( graph, nodeTO, projectRef );
200 DependencyGraphUtils.collapseNodes( graph, nodeFROM, nodeTO );
203 public DependencyGraphBuilder getBuilder()
208 public void setBuilder( DependencyGraphBuilder builder )
210 this.builder = builder;
213 public boolean hasCreatedNodes()
215 return ( nodesAdded > 0 );