incubator-ivy-commits mailing list archives

Site index · List index
Message view « Date » · « Thread »
Top « Date » · « Thread »
From xav...@apache.org
Subject svn commit: r502534 [2/2] - in /incubator/ivy/core/trunk: src/java/org/apache/ivy/ant/ src/java/org/apache/ivy/core/module/descriptor/ src/java/org/apache/ivy/core/module/id/ src/java/org/apache/ivy/core/report/ src/java/org/apache/ivy/core/resolve/ sr...
Date Fri, 02 Feb 2007 08:42:22 GMT
Added: incubator/ivy/core/trunk/src/java/org/apache/ivy/core/resolve/IvyNodeEviction.java
URL: http://svn.apache.org/viewvc/incubator/ivy/core/trunk/src/java/org/apache/ivy/core/resolve/IvyNodeEviction.java?view=auto&rev=502534
==============================================================================
--- incubator/ivy/core/trunk/src/java/org/apache/ivy/core/resolve/IvyNodeEviction.java (added)
+++ incubator/ivy/core/trunk/src/java/org/apache/ivy/core/resolve/IvyNodeEviction.java Fri Feb  2 00:42:21 2007
@@ -0,0 +1,295 @@
+/*
+ *  Licensed to the Apache Software Foundation (ASF) under one or more
+ *  contributor license agreements.  See the NOTICE file distributed with
+ *  this work for additional information regarding copyright ownership.
+ *  The ASF licenses this file to You under the Apache License, Version 2.0
+ *  (the "License"); you may not use this file except in compliance with
+ *  the License.  You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ *  Unless required by applicable law or agreed to in writing, software
+ *  distributed under the License is distributed on an "AS IS" BASIS,
+ *  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ *  See the License for the specific language governing permissions and
+ *  limitations under the License.
+ *
+ */
+package org.apache.ivy.core.resolve;
+
+import java.util.Collection;
+import java.util.HashMap;
+import java.util.HashSet;
+import java.util.Iterator;
+import java.util.Map;
+import java.util.Set;
+
+import org.apache.ivy.core.module.id.ModuleId;
+import org.apache.ivy.plugins.conflict.ConflictManager;
+
+public class IvyNodeEviction {
+    public static class EvictionData {
+        private IvyNode _parent; // can be null in case of transitive eviction
+        private ConflictManager _conflictManager; // can be null in case of transitive eviction
+        private Collection _selected; // Collection(IvyNode); can be null in case of transitive eviction
+        private String _rootModuleConf;
+
+        public EvictionData(String rootModuleConf, IvyNode parent, ConflictManager conflictManager, Collection selected) {
+            _rootModuleConf = rootModuleConf;
+            _parent = parent;
+            _conflictManager = conflictManager;
+            _selected = selected;
+            for (Iterator iter = selected.iterator(); iter.hasNext();) {
+				Object o = (Object) iter.next();
+				if (! (o instanceof IvyNode)) {
+					throw new IllegalArgumentException("selected nodes must be instance of IvyNode. Found: "+o.getClass().getName());
+				}
+			}
+        }
+        
+        public String toString() {
+            if (_selected != null) {
+                return _selected + " in "+ _parent+" ("+_conflictManager+") ["+_rootModuleConf+"]";
+            } else {
+                return "transitively ["+_rootModuleConf+"]";
+            }
+        }
+
+        public ConflictManager getConflictManager() {
+            return _conflictManager;
+        }
+        
+
+        public IvyNode getParent() {
+            return _parent;
+        }
+
+        public Collection getSelected() {
+            return _selected;
+        }
+        
+
+        public String getRootModuleConf() {
+            return _rootModuleConf;
+        }
+    }
+
+    private static final class ModuleIdConf {
+        private ModuleId _moduleId;
+        private String _conf;
+
+        public ModuleIdConf(ModuleId mid, String conf) {
+            _moduleId = mid;
+            _conf = conf;
+        }
+
+        public final String getConf() {
+            return _conf;
+        }
+        
+        public final ModuleId getModuleId() {
+            return _moduleId;
+        }
+        public boolean equals(Object obj) {
+            if (!(obj instanceof ModuleIdConf)) {
+                return false;
+            }
+            return getModuleId().equals(((ModuleIdConf)obj).getModuleId()) 
+                && getConf().equals(((ModuleIdConf)obj).getConf());
+        }
+        public int hashCode() {
+            int hash = 33;
+            hash += getModuleId().hashCode() * 17;
+            hash += getConf().hashCode() * 17;
+            return hash;
+        }
+    }
+    
+    private IvyNode _node;
+
+    private Map _selectedDeps = new HashMap(); // Map (ModuleIdConf -> Set(Node)) // map indicating for each dependency which node has been selected
+
+    private Map _evictedDeps = new HashMap(); // Map (ModuleIdConf -> Set(Node)) // map indicating for each dependency which node has been evicted
+    private Map _evictedRevs = new HashMap(); // Map (ModuleIdConf -> Set(ModuleRevisionId)) // map indicating for each dependency which revision has been evicted
+    
+    private Map _evicted = new HashMap(); // Map (root module conf -> EvictionData) // indicates if the node is evicted in each root module conf
+    
+    public IvyNodeEviction(IvyNode node) {
+		_node = node;
+	}
+    
+	public Collection getResolvedNodes(ModuleId mid, String rootModuleConf) {
+        Collection resolved = (Collection)_selectedDeps.get(new ModuleIdConf(mid, rootModuleConf));
+        Set ret = new HashSet();
+        if (resolved != null) {
+            for (Iterator iter = resolved.iterator(); iter.hasNext();) {
+                IvyNode node = (IvyNode)iter.next();
+                ret.add(node.getRealNode());
+            }
+        }
+        return ret;
+    }
+    public Collection getResolvedRevisions(ModuleId mid, String rootModuleConf) {
+    	Collection resolved = (Collection)_selectedDeps.get(new ModuleIdConf(mid, rootModuleConf));
+    	if (resolved == null) {
+    		return new HashSet();
+    	} else {
+    		Collection resolvedRevs = new HashSet();
+    		for (Iterator iter = resolved.iterator(); iter.hasNext();) {
+    			IvyNode node = (IvyNode)iter.next();
+    			resolvedRevs.add(node.getId());
+    			resolvedRevs.add(node.getResolvedId());
+    		}
+    		return resolvedRevs;
+    	}
+    }
+
+    public void setResolvedNodes(ModuleId moduleId, String rootModuleConf, Collection resolved) {
+        ModuleIdConf moduleIdConf = new ModuleIdConf(moduleId, rootModuleConf);
+        _selectedDeps.put(moduleIdConf, new HashSet(resolved));
+    }
+    
+    public Collection getEvictedNodes(ModuleId mid, String rootModuleConf) {
+        Collection resolved = (Collection)_evictedDeps.get(new ModuleIdConf(mid, rootModuleConf));
+        Set ret = new HashSet();
+        if (resolved != null) {
+            for (Iterator iter = resolved.iterator(); iter.hasNext();) {
+                IvyNode node = (IvyNode)iter.next();
+                ret.add(node.getRealNode());
+            }
+        }
+        return ret;
+    }
+    public Collection getEvictedRevisions(ModuleId mid, String rootModuleConf) {
+        Collection evicted = (Collection)_evictedRevs.get(new ModuleIdConf(mid, rootModuleConf));
+        if (evicted == null) {
+            return new HashSet();
+        } else {
+            return new HashSet(evicted);
+        }
+    }
+
+    public void setEvictedNodes(ModuleId moduleId, String rootModuleConf, Collection evicted) {
+        ModuleIdConf moduleIdConf = new ModuleIdConf(moduleId, rootModuleConf);
+        _evictedDeps.put(moduleIdConf, new HashSet(evicted));
+        Collection evictedRevs = new HashSet();
+        for (Iterator iter = evicted.iterator(); iter.hasNext();) {
+            IvyNode node = (IvyNode)iter.next();
+            evictedRevs.add(node.getId());
+            evictedRevs.add(node.getResolvedId());
+        }
+        _evictedRevs.put(moduleIdConf, evictedRevs);
+    }
+    
+
+    public boolean isEvicted(String rootModuleConf) {
+        cleanEvicted();
+        IvyNode root = _node.getRoot();
+        return root != _node && !root.getResolvedRevisions(_node.getId().getModuleId(), rootModuleConf).contains(_node.getResolvedId());
+    }
+
+    public boolean isCompletelyEvicted() {
+        cleanEvicted();
+        if (_node.isRoot()) {
+        	return false;
+        }
+        String[] rootModuleConfigurations = _node.getRootModuleConfigurations();
+		for (int i = 0; i < rootModuleConfigurations.length; i++) {
+			if (!isEvicted(rootModuleConfigurations[i])) {
+				return false;
+			}
+		}
+        return true;
+    }
+    
+    private void cleanEvicted() {
+        // check if it was evicted by a node that we are now the real node for
+        for (Iterator iter = _evicted.keySet().iterator(); iter.hasNext();) {
+            String rootModuleConf = (String)iter.next();
+            EvictionData ed = (EvictionData)_evicted.get(rootModuleConf);
+            Collection sel = ed.getSelected();
+            if (sel != null) {
+                for (Iterator iterator = sel.iterator(); iterator.hasNext();) {
+                    IvyNode n = (IvyNode)iterator.next();
+                    if (n.getRealNode().equals(this)) {
+                        // yes, we are the real node for a selected one !
+                        // we are no more evicted in this conf !
+                        iter.remove();                    
+                    }
+                }
+            }
+        }
+    }
+
+    public void markEvicted(String rootModuleConf, IvyNode node, ConflictManager conflictManager, Collection resolved) {
+        EvictionData evictionData = new EvictionData(rootModuleConf, node, conflictManager, resolved);
+        markEvicted(evictionData);
+    }
+
+    public void markEvicted(EvictionData evictionData) {
+        _evicted.put(evictionData.getRootModuleConf(), evictionData);
+    }
+    
+    public EvictionData getEvictedData(String rootModuleConf) {
+        cleanEvicted();
+        return (EvictionData)_evicted.get(rootModuleConf);
+    }
+    public String[] getEvictedConfs() {
+        cleanEvicted();
+        return (String[])_evicted.keySet().toArray(new String[_evicted.keySet().size()]);
+    }
+
+    /**
+     * Returns null if this node has only be evicted transitively, or the the colletion of selected nodes
+     * if it has been evicted by other selected nodes
+     * @return
+     */
+    public Collection getAllEvictingNodes() {
+        Collection allEvictingNodes = null;
+        for (Iterator iter = _evicted.values().iterator(); iter.hasNext();) {
+            EvictionData ed = (EvictionData)iter.next();
+            Collection selected = ed.getSelected();
+            if (selected != null) {
+                if (allEvictingNodes == null) {
+                    allEvictingNodes = new HashSet();
+                }
+                allEvictingNodes.addAll(selected);
+            }
+        }        
+        return allEvictingNodes;
+    }    
+
+    public Collection getAllEvictingConflictManagers() {
+        Collection ret = new HashSet();
+        for (Iterator iter = _evicted.values().iterator(); iter.hasNext();) {
+            EvictionData ed = (EvictionData)iter.next();
+            ret.add(ed.getConflictManager());
+        }        
+        return ret;
+    }    
+
+
+    /**
+     * Returns the eviction data for this node if it has been previously evicted in the root,
+     * null otherwise (if it hasn't been evicted in root) for the 
+     * given rootModuleConf.
+     * Note that this method only works if conflict resolution has already be done in all the ancestors.
+     * 
+     * @param rootModuleConf
+     * @param ancestor
+     * @return
+     */
+    public EvictionData getEvictionDataInRoot(String rootModuleConf, IvyNode ancestor) {
+        Collection selectedNodes = _node.getRoot().getResolvedNodes(_node.getModuleId(), rootModuleConf);
+        for (Iterator iter = selectedNodes.iterator(); iter.hasNext();) {
+            IvyNode node = (IvyNode)iter.next();
+            if (node.getResolvedId().equals(_node.getResolvedId())) {
+                // the node is part of the selected ones for the root: no eviction data to return
+                return null;
+            }
+        }
+        // we didn't find this mrid in the selected ones for the root: it has been previously evicted
+        return new EvictionData(rootModuleConf, ancestor, _node.getRoot().getConflictManager(_node.getModuleId()), selectedNodes);
+    }
+
+}

Modified: incubator/ivy/core/trunk/src/java/org/apache/ivy/core/resolve/ResolveData.java
URL: http://svn.apache.org/viewvc/incubator/ivy/core/trunk/src/java/org/apache/ivy/core/resolve/ResolveData.java?view=diff&rev=502534&r1=502533&r2=502534
==============================================================================
--- incubator/ivy/core/trunk/src/java/org/apache/ivy/core/resolve/ResolveData.java (original)
+++ incubator/ivy/core/trunk/src/java/org/apache/ivy/core/resolve/ResolveData.java Fri Feb  2 00:42:21 2007
@@ -18,8 +18,11 @@
 package org.apache.ivy.core.resolve;
 
 import java.io.File;
+import java.util.ArrayList;
+import java.util.Collection;
 import java.util.Date;
-import java.util.HashMap;
+import java.util.Iterator;
+import java.util.LinkedHashMap;
 import java.util.Map;
 
 import org.apache.ivy.core.cache.CacheManager;
@@ -30,7 +33,7 @@
 
 
 public class ResolveData {
-    private Map _nodes; // shared map of all nodes: Map (ModuleRevisionId -> IvyNode)
+    private Map _visitData; // shared map of all visit data: Map (ModuleRevisionId -> VisitData)
     private Date _date;
     private boolean _validate;
     private boolean _transitive;
@@ -39,11 +42,11 @@
 	private ResolveEngine _engine;
 
     public ResolveData(ResolveData data, boolean validate) {
-        this(data._engine, data._cacheManager, data._date, data._report, validate, data._transitive, data._nodes);
+        this(data._engine, data._cacheManager, data._date, data._report, validate, data._transitive, data._visitData);
     }
 
     public ResolveData(ResolveEngine engine, File cache, Date date, ConfigurationResolveReport report, boolean validate) {
-        this(engine, cache, date, report, validate, new HashMap());
+        this(engine, cache, date, report, validate, true, new LinkedHashMap());
     }
 
     public ResolveData(ResolveEngine engine, File cache, Date date, ConfigurationResolveReport report, boolean validate, Map nodes) {
@@ -52,25 +55,34 @@
     public ResolveData(ResolveEngine engine, File cache, Date date, ConfigurationResolveReport report, boolean validate, boolean transitive, Map nodes) {
     	this(engine, new CacheManager(engine.getSettings(), cache), date, report, validate, transitive, nodes);
     }
-    public ResolveData(ResolveEngine engine, CacheManager cacheManager, Date date, ConfigurationResolveReport report, boolean validate, boolean transitive, Map nodes) {
+
+    public ResolveData(ResolveEngine engine, File cache, Date date, ConfigurationResolveReport report, boolean validate, boolean transitive) {
+		this(engine, cache, date, report, validate, transitive, new LinkedHashMap());
+	}
+    public ResolveData(ResolveEngine engine, CacheManager cacheManager, Date date, ConfigurationResolveReport report, boolean validate, boolean transitive, Map visitData) {
     	_engine = engine;
         _date = date;
         _report = report;
         _validate = validate;
         _transitive = transitive;
-        _nodes = nodes;
+        _visitData = visitData;
         _cacheManager = cacheManager;
     }
 
     
 
-    public Date getDate() {
+	public Date getDate() {
         return _date;
     }
     
 
-    public Map getNodes() {
-        return _nodes;
+    /**
+     * Returns the Map of visit data.
+     * Map (ModuleRevisionId -> VisitData)
+     * @return
+     */
+    public Map getVisitDataMap() {
+        return _visitData;
     }
     
 
@@ -84,17 +96,66 @@
     }
 
     public IvyNode getNode(ModuleRevisionId mrid) {
-        return (IvyNode)_nodes.get(mrid);
+        VisitData visitData = getVisitData(mrid);
+		return visitData == null ? null : visitData.getNode();
     }
-
-    public void register(IvyNode node) {
-        _nodes.put(node.getId(), node);
+    
+    public Collection getNodes() {
+    	Collection nodes = new ArrayList();
+    	for (Iterator iter = _visitData.values().iterator(); iter.hasNext();) {
+			VisitData vdata = (VisitData) iter.next();
+			nodes.add(vdata.getNode());
+		}
+    	return nodes;
+    }
+    
+    public Collection getNodeIds() {
+    	return _visitData.keySet();
+    }
+    
+    public VisitData getVisitData(ModuleRevisionId mrid) {
+    	return (VisitData) _visitData.get(mrid);
     }
 
-    public void register(ModuleRevisionId id, IvyNode node) {
-        _nodes.put(id, node);
+    public void register(VisitNode node) {
+    	register(node.getId(), node);
     }
 
+    public void register(ModuleRevisionId mrid, VisitNode node) {
+		VisitData visitData = getVisitData(mrid);
+    	if (visitData == null) {
+    		visitData = new VisitData(node.getNode());
+    		visitData.addVisitNode(node);
+    		_visitData.put(mrid, visitData);
+    	} else {
+    		visitData.setNode(node.getNode());
+    		visitData.addVisitNode(node);
+    	}
+    }
+
+    /**
+     * Updates the visit data currently associated with the given mrid
+     * with the given node and the visit nodes of the old visitData
+     * for the given rootModuleConf
+     * @param mrid the module revision id for which the update should be done
+     * @param node the IvyNode to associate with the visit data to update
+     * @param rootModuleConf the root module configuration in which the update is made
+     */
+    void replaceNode(ModuleRevisionId mrid, IvyNode node, String rootModuleConf) {
+		VisitData visitData = getVisitData(mrid);
+    	if (visitData == null) {
+    		throw new IllegalArgumentException("impossible to replace node for id "+mrid+". No registered node found.");
+    	}
+    	VisitData keptVisitData = getVisitData(node.getId());
+    	if (keptVisitData == null) {
+    		throw new IllegalArgumentException("impossible to replace node with "+node+". No registered node found for "+node.getId()+".");
+    	}
+    	// replace visit data in Map (discards old one)
+    	_visitData.put(mrid, keptVisitData);
+    	// update visit data with discarde visit nodes
+    	keptVisitData.addVisitNodes(rootModuleConf, visitData.getVisitNodes(rootModuleConf));
+    }
+    
     public void setReport(ConfigurationResolveReport report) {
         _report = report;
     }

Modified: incubator/ivy/core/trunk/src/java/org/apache/ivy/core/resolve/ResolveEngine.java
URL: http://svn.apache.org/viewvc/incubator/ivy/core/trunk/src/java/org/apache/ivy/core/resolve/ResolveEngine.java?view=diff&rev=502534&r1=502533&r2=502534
==============================================================================
--- incubator/ivy/core/trunk/src/java/org/apache/ivy/core/resolve/ResolveEngine.java (original)
+++ incubator/ivy/core/trunk/src/java/org/apache/ivy/core/resolve/ResolveEngine.java Fri Feb  2 00:42:21 2007
@@ -29,11 +29,9 @@
 import java.util.Date;
 import java.util.HashSet;
 import java.util.Iterator;
-import java.util.LinkedHashMap;
 import java.util.LinkedHashSet;
 import java.util.List;
 import java.util.ListIterator;
-import java.util.Map;
 import java.util.Properties;
 import java.util.Set;
 
@@ -56,9 +54,10 @@
 import org.apache.ivy.core.report.DownloadReport;
 import org.apache.ivy.core.report.DownloadStatus;
 import org.apache.ivy.core.report.ResolveReport;
-import org.apache.ivy.core.resolve.IvyNode.EvictionData;
+import org.apache.ivy.core.resolve.IvyNodeEviction.EvictionData;
 import org.apache.ivy.core.settings.IvySettings;
 import org.apache.ivy.core.sort.SortEngine;
+import org.apache.ivy.plugins.conflict.ConflictManager;
 import org.apache.ivy.plugins.parser.ModuleDescriptorParser;
 import org.apache.ivy.plugins.parser.ModuleDescriptorParserRegistry;
 import org.apache.ivy.plugins.repository.url.URLResource;
@@ -300,7 +299,8 @@
         	checkInterrupted();
             //download artifacts required in all asked configurations
             if (!dependencies[i].isCompletelyEvicted() && !dependencies[i].hasProblem()) {
-                DependencyResolver resolver = dependencies[i].getModuleRevision().getArtifactResolver();
+                DependencyResolver resolver = dependencies[i].getModuleRevision()
+                													.getArtifactResolver();
                 Artifact[] selectedArtifacts = dependencies[i].getSelectedArtifacts(artifactFilter);
                 DownloadReport dReport = resolver.download(selectedArtifacts, new DownloadOptions(_settings, cacheManager, _eventManager, useOrigin));
                 ArtifactDownloadReport[] adrs = dReport.getArtifactsReports();
@@ -399,9 +399,8 @@
             confs = md.getConfigurationsNames();
         }
         
-        Map dependenciesMap = new LinkedHashMap();
         Date reportDate = new Date();
-        ResolveData data = new ResolveData(this, cache, date, null, validate, transitive, dependenciesMap);
+        ResolveData data = new ResolveData(this, cache, date, null, validate, transitive);
         IvyNode rootNode = new IvyNode(data, md);
         
         for (int i = 0; i < confs.length; i++) {
@@ -424,18 +423,24 @@
                 data.setReport(confReport); 
                 
                 // update the root module conf we are about to fetch
-                rootNode.setRootModuleConf(confs[i]); 
-                rootNode.setRequestedConf(confs[i]);
+                VisitNode root = new VisitNode(data, rootNode, null, confs[i], null);
+                root.setRequestedConf(confs[i]);
                 rootNode.updateConfsToFetch(Collections.singleton(confs[i]));
                 
                 // go fetch !
-                fetchDependencies(rootNode, confs[i], false);
+                fetchDependencies(root, confs[i], false);
+                
+                // clean data
+                for (Iterator iter = data.getNodes().iterator(); iter.hasNext();) {
+                    IvyNode dep = (IvyNode) iter.next();
+                    dep.clean();
+                }                
             }
         }
         
         // prune and reverse sort fectched dependencies 
-        Collection dependencies = new LinkedHashSet(dependenciesMap.size()); // use a Set to avoids duplicates
-        for (Iterator iter = dependenciesMap.values().iterator(); iter.hasNext();) {
+        Collection dependencies = new LinkedHashSet(data.getNodes().size()); // use a Set to avoids duplicates
+        for (Iterator iter = data.getNodes().iterator(); iter.hasNext();) {
             IvyNode dep = (IvyNode) iter.next();
             if (dep != null) {
                 dependencies.add(dep);
@@ -453,7 +458,7 @@
             IvyNode node = (IvyNode)iter.next();
             if (!node.isCompletelyEvicted()) {
                 for (int i = 0; i < confs.length; i++) {
-                    IvyNode.Caller[] callers = node.getCallers(confs[i]);
+                    IvyNodeCallers.Caller[] callers = node.getCallers(confs[i]);
                     if (_settings.debugConflictResolution()) {
                         Message.debug("checking if "+node.getId()+" is transitively evicted in "+confs[i]);
                     }
@@ -464,9 +469,9 @@
                             allEvicted = false;
                             break;                            
                         } else {
-                            IvyNode callerNode = (IvyNode)dependenciesMap.get(callers[j].getModuleRevisionId());
+                            IvyNode callerNode = data.getNode(callers[j].getModuleRevisionId());
                             if (callerNode == null) {
-                                Message.warn("ivy internal error: no node found for "+callers[j].getModuleRevisionId()+": looked in "+dependenciesMap.keySet()+" and root module id was "+md.getModuleRevisionId());
+                                Message.warn("ivy internal error: no node found for "+callers[j].getModuleRevisionId()+": looked in "+data.getNodeIds()+" and root module id was "+md.getModuleRevisionId());
                             } else if (!callerNode.isEvicted(confs[i])) {
                                 allEvicted = false;
                                 break;
@@ -495,19 +500,17 @@
 
     
     
-    private void fetchDependencies(IvyNode node, String conf, boolean shouldBePublic) {
+    private void fetchDependencies(VisitNode node, String conf, boolean shouldBePublic) {
     	checkInterrupted();
         long start = System.currentTimeMillis();
         if (_settings.debugConflictResolution()) {
             Message.debug(node.getId()+" => resolving dependencies in "+conf);
         }
-        resolveConflict(node, node.getParent());
+        resolveConflict(node);
         
         if (node.loadData(conf, shouldBePublic)) {
-            node = node.getRealNode(true); // if data loading discarded the node, get the real one
-            
-            resolveConflict(node, node.getParent());
-            if (!node.isEvicted(node.getRootModuleConf())) {
+            resolveConflict(node);
+            if (!node.isEvicted()) {
                 String[] confs = node.getRealConfs(conf);
                 for (int i = 0; i < confs.length; i++) {
                     doFetchDependencies(node, confs[i]);
@@ -516,20 +519,26 @@
         } else if (!node.hasProblem()) {
             // the node has not been loaded but hasn't problem: it was already loaded 
             // => we just have to update its dependencies data
-            if (!node.isEvicted(node.getRootModuleConf())) {
+            if (!node.isEvicted()) {
                 String[] confs = node.getRealConfs(conf);
                 for (int i = 0; i < confs.length; i++) {
                     doFetchDependencies(node, confs[i]);
                 }
             }
         }
-        if (node.isEvicted(node.getRootModuleConf())) {
+        if (node.isEvicted()) {
             // update selected nodes with confs asked in evicted one
-            IvyNode.EvictionData ed = node.getEvictedData(node.getRootModuleConf());
+            EvictionData ed = node.getEvictedData();
             if (ed.getSelected() != null) {
             	for (Iterator iter = ed.getSelected().iterator(); iter.hasNext();) {
             		IvyNode selected = (IvyNode)iter.next();
-            		fetchDependencies(selected, conf, true);
+            		if (!selected.isLoaded()) {
+            			// the node is not yet loaded, we can simply update its set of configurations to fetch
+            			selected.updateConfsToFetch(Collections.singleton(conf));
+            		} else {
+            			// the node has already been loaded, we must fetch its dependencies in the required conf 
+            			fetchDependencies(node.gotoNode(selected), conf, true);
+            		}
             	}
             }
         }
@@ -538,7 +547,7 @@
         }
     }
 
-    private void doFetchDependencies(IvyNode node, String conf) {
+    private void doFetchDependencies(VisitNode node, String conf) {
         Configuration c = node.getConfiguration(conf);
         if (c == null) {
             Message.warn("configuration not found '"+conf+"' in "+node.getResolvedId()+": ignoring");
@@ -566,13 +575,12 @@
         }
         
         // now we can actually resolve this configuration dependencies
-        DependencyDescriptor dd = node.getDependencyDescriptor(node.getParent());
-        if (!isDependenciesFetched(node, conf) && (dd == null || node.isTransitive())) {
-            Collection dependencies = node.getDependencies(conf, true);
+        DependencyDescriptor dd = node.getDependencyDescriptor();
+        if (!isDependenciesFetched(node.getNode(), conf) && (dd == null || node.isTransitive())) {
+            Collection dependencies = node.getDependencies(conf);
             for (Iterator iter = dependencies.iterator(); iter.hasNext();) {
-                IvyNode dep = (IvyNode)iter.next();
-                dep = dep.getRealNode(); // the node may have been resolved to another real one while resolving other deps
-                node.traverse(conf, dep); // dependency traversal data may have been changed while resolving other deps, we update it
+                VisitNode dep = (VisitNode)iter.next();
+                dep.useRealNode(); // the node may have been resolved to another real one while resolving other deps
                 if (dep.isCircular()) {
                     continue;
                 }
@@ -615,30 +623,31 @@
         return false;
     }    
 
-    private void resolveConflict(IvyNode node, IvyNode parent) {
-        resolveConflict(node, parent, Collections.EMPTY_SET);
+    private void resolveConflict(VisitNode node) {
+        resolveConflict(node, node.getParent(), Collections.EMPTY_SET);
     }
-    private void resolveConflict(IvyNode node, IvyNode parent, Collection toevict) {
-        if (parent == null || node == parent) {
+    private void resolveConflict(VisitNode node, VisitNode ancestor, Collection toevict) {
+        if (ancestor == null || node == ancestor) {
             return;
         }
         // check if job is not already done
-        if (checkConflictSolved(node, parent)) {
+        if (checkConflictSolved(node, ancestor)) {
             return;
         }
         
         // compute conflicts
-        Collection resolvedNodes = new HashSet(parent.getResolvedNodes(node.getModuleId(), node.getRootModuleConf()));
-        Collection conflicts = computeConflicts(node, parent, toevict, resolvedNodes);
+        Collection resolvedNodes = new HashSet(ancestor.getNode().getResolvedNodes(node.getModuleId(), node.getRootModuleConf()));
+        Collection conflicts = computeConflicts(node, ancestor, toevict, resolvedNodes);
         if (_settings.debugConflictResolution()) {
-            Message.debug("found conflicting revisions for "+node+" in "+parent+": "+conflicts);
+            Message.debug("found conflicting revisions for "+node+" in "+ancestor+": "+conflicts);
         }
         
-        Collection resolved = parent.getConflictManager(node.getModuleId()).resolveConflicts(parent, conflicts);
+        ConflictManager conflictManager = ancestor.getNode().getConflictManager(node.getModuleId());
+		Collection resolved = conflictManager.resolveConflicts(ancestor.getNode(), conflicts);
         if (_settings.debugConflictResolution()) {
-            Message.debug("selected revisions for "+node+" in "+parent+": "+resolved);
+            Message.debug("selected revisions for "+node+" in "+ancestor+": "+resolved);
         }
-        if (resolved.contains(node)) {
+        if (resolved.contains(node.getNode())) {
             // node has been selected for the current parent
             
             // handle previously selected nodes that are now evicted by this new node
@@ -647,7 +656,7 @@
             
             for (Iterator iter = toevict.iterator(); iter.hasNext();) {
                 IvyNode te = (IvyNode)iter.next();
-                te.markEvicted(node.getRootModuleConf(), parent, parent.getConflictManager(node.getModuleId()), resolved);
+                te.markEvicted(node.getRootModuleConf(), ancestor.getNode(), conflictManager, resolved);
                 
                 if (_settings.debugConflictResolution()) {
                     Message.debug("evicting "+te+" by "+te.getEvictedData(node.getRootModuleConf()));
@@ -657,46 +666,46 @@
             // it's very important to update resolved and evicted nodes BEFORE recompute parent call
             // to allow it to recompute its resolved collection with correct data
             // if necessary            
-            parent.setResolvedNodes(node.getModuleId(), node.getRootModuleConf(), resolved); 
+            ancestor.getNode().setResolvedNodes(node.getModuleId(), node.getRootModuleConf(), resolved); 
 
-            Collection evicted = new HashSet(parent.getEvictedNodes(node.getModuleId(), node.getRootModuleConf()));
+            Collection evicted = new HashSet(ancestor.getNode().getEvictedNodes(node.getModuleId(), node.getRootModuleConf()));
             evicted.removeAll(resolved);
             evicted.addAll(toevict);
-            parent.setEvictedNodes(node.getModuleId(), node.getRootModuleConf(), evicted);
+            ancestor.getNode().setEvictedNodes(node.getModuleId(), node.getRootModuleConf(), evicted);
             
-            resolveConflict(node, parent.getParent(), toevict);
+            resolveConflict(node, ancestor.getParent(), toevict);
         } else {
             // node has been evicted for the current parent
             if (resolved.isEmpty()) {
                 if (_settings.debugConflictResolution()) {
-                    Message.verbose("conflict manager '"+parent.getConflictManager(node.getModuleId())+"' evicted all revisions among "+conflicts);
+                    Message.verbose("conflict manager '"+conflictManager+"' evicted all revisions among "+conflicts);
                 }
             }
             
             
             // it's time to update parent resolved and evicted with what was found 
             
-            Collection evicted = new HashSet(parent.getEvictedNodes(node.getModuleId(), node.getRootModuleConf()));
+            Collection evicted = new HashSet(ancestor.getNode().getEvictedNodes(node.getModuleId(), node.getRootModuleConf()));
             toevict.removeAll(resolved);
             evicted.removeAll(resolved);
             evicted.addAll(toevict);
-            evicted.add(node);
-            parent.setEvictedNodes(node.getModuleId(), node.getRootModuleConf(), evicted);
+            evicted.add(node.getNode());
+            ancestor.getNode().setEvictedNodes(node.getModuleId(), node.getRootModuleConf(), evicted);
 
             
-            node.markEvicted(node.getRootModuleConf(), parent, parent.getConflictManager(node.getModuleId()), resolved);
+            node.markEvicted(ancestor, conflictManager, resolved);
             if (_settings.debugConflictResolution()) {
-                Message.debug("evicting "+node+" by "+node.getEvictedData(node.getRootModuleConf()));
+                Message.debug("evicting "+node+" by "+node.getEvictedData());
             }
 
             // if resolved changed we have to go up in the graph
-            Collection prevResolved = parent.getResolvedNodes(node.getModuleId(), node.getRootModuleConf());
+            Collection prevResolved = ancestor.getNode().getResolvedNodes(node.getModuleId(), node.getRootModuleConf());
             if (!prevResolved.equals(resolved)) {                
-                parent.setResolvedNodes(node.getModuleId(), node.getRootModuleConf(), resolved);
+                ancestor.getNode().setResolvedNodes(node.getModuleId(), node.getRootModuleConf(), resolved);
                 for (Iterator iter = resolved.iterator(); iter.hasNext();) {
                     IvyNode sel = (IvyNode)iter.next();
                     if (!prevResolved.contains(sel)) {
-                        resolveConflict(sel, parent.getParent(), toevict);
+                        resolveConflict(node.gotoNode(sel), ancestor.getParent(), toevict);
                     }
                 }
             }
@@ -704,23 +713,25 @@
         }
     }
 
-    private Collection computeConflicts(IvyNode node, IvyNode parent, Collection toevict, Collection resolvedNodes) {
+    private Collection computeConflicts(VisitNode node, VisitNode ancestor, Collection toevict, Collection resolvedNodes) {
         Collection conflicts = new HashSet();
+        conflicts.add(node.getNode());
         if (resolvedNodes.removeAll(toevict)) {
             // parent.resolved(node.mid) is not up to date:
             // recompute resolved from all sub nodes
-            conflicts.add(node);
-            Collection deps = parent.getDependencies(parent.getRequiredConfigurations());
+            Collection deps = ancestor.getNode().getDependencies(node.getRootModuleConf(), ancestor.getRequiredConfigurations());
             for (Iterator iter = deps.iterator(); iter.hasNext();) {
                 IvyNode dep = (IvyNode)iter.next();
+                if (dep.getModuleId().equals(node.getModuleId())) {
+                	conflicts.add(dep);
+                }
                 conflicts.addAll(dep.getResolvedNodes(node.getModuleId(), node.getRootModuleConf()));
             }
-        } else if (resolvedNodes.isEmpty() && node.getParent() != parent) {
-            conflicts.add(node);
-            DependencyDescriptor[] dds = parent.getDescriptor().getDependencies();
+        } else if (resolvedNodes.isEmpty() && node.getParent() != ancestor) {
+            DependencyDescriptor[] dds = ancestor.getDescriptor().getDependencies();
             for (int i = 0; i < dds.length; i++) {
                 if (dds[i].getDependencyId().equals(node.getModuleId())) {
-                    IvyNode n = node.findNode(dds[i].getDependencyRevisionId());
+                    IvyNode n = node.getNode().findNode(dds[i].getDependencyRevisionId());
                     if (n != null) {
                         conflicts.add(n);
                         break;
@@ -728,20 +739,19 @@
                 }
             }
         } else {
-            conflicts.add(node);
             conflicts.addAll(resolvedNodes);
         }
         return conflicts;
     }
 
-    private boolean checkConflictSolved(IvyNode node, IvyNode parent) {
-        if (parent.getResolvedRevisions(node.getModuleId(), node.getRootModuleConf()).contains(node.getResolvedId())) {
+    private boolean checkConflictSolved(VisitNode node, VisitNode ancestor) {
+        if (ancestor.getResolvedRevisions(node.getModuleId()).contains(node.getResolvedId())) {
             // resolve conflict has already be done with node with the same id
             // => job already done, we just have to check if the node wasn't previously evicted in root ancestor
             if (_settings.debugConflictResolution()) {
-                Message.debug("conflict resolution already done for "+node+" in "+parent);
+                Message.debug("conflict resolution already done for "+node+" in "+ancestor);
             }
-            EvictionData evictionData = node.getEvictionDataInRoot(node.getRootModuleConf(), parent);
+            EvictionData evictionData = node.getEvictionDataInRoot(node.getRootModuleConf(), ancestor);
             if (evictionData != null) {
                 // node has been previously evicted in an ancestor: we mark it as evicted
                 if (_settings.debugConflictResolution()) {
@@ -754,11 +764,11 @@
                 }
             }
             return true;
-        } else if (parent.getEvictedRevisions(node.getModuleId(), node.getRootModuleConf()).contains(node.getResolvedId())) {
+        } else if (ancestor.getEvictedRevisions(node.getModuleId()).contains(node.getResolvedId())) {
             // resolve conflict has already be done with node with the same id
             // => job already done, we just have to check if the node wasn't previously selected in root ancestor
             if (_settings.debugConflictResolution()) {
-                Message.debug("conflict resolution already done for "+node+" in "+parent);
+                Message.debug("conflict resolution already done for "+node+" in "+ancestor);
             }
             return true;
         }

Added: incubator/ivy/core/trunk/src/java/org/apache/ivy/core/resolve/VisitData.java
URL: http://svn.apache.org/viewvc/incubator/ivy/core/trunk/src/java/org/apache/ivy/core/resolve/VisitData.java?view=auto&rev=502534
==============================================================================
--- incubator/ivy/core/trunk/src/java/org/apache/ivy/core/resolve/VisitData.java (added)
+++ incubator/ivy/core/trunk/src/java/org/apache/ivy/core/resolve/VisitData.java Fri Feb  2 00:42:21 2007
@@ -0,0 +1,77 @@
+/*
+ *  Licensed to the Apache Software Foundation (ASF) under one or more
+ *  contributor license agreements.  See the NOTICE file distributed with
+ *  this work for additional information regarding copyright ownership.
+ *  The ASF licenses this file to You under the Apache License, Version 2.0
+ *  (the "License"); you may not use this file except in compliance with
+ *  the License.  You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ *  Unless required by applicable law or agreed to in writing, software
+ *  distributed under the License is distributed on an "AS IS" BASIS,
+ *  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ *  See the License for the specific language governing permissions and
+ *  limitations under the License.
+ *
+ */
+package org.apache.ivy.core.resolve;
+
+import java.util.ArrayList;
+import java.util.HashMap;
+import java.util.List;
+import java.util.Map;
+
+/**
+ * This class is used to store data related to one node of the dependency graph visit.
+ * 
+ * It stores both an {@link IvyNode} and related {@link VisitNode} objects.
+ * 
+ * Indeed, during the visit of the graph, the algorithm can visit the same node
+ * from several parents, thus requiring several VisitNode.
+ * 
+ * @author Xavier Hanin
+ *
+ */
+public class VisitData {
+	/**
+	 * A node in the graph of module dependencies resolution
+	 */
+	private IvyNode _node;
+	/**
+	 * The associated visit nodes, per rootModuleConf
+	 * Note that the value is a List, because a node can be visited from
+	 * several parents during the resolution process
+	 */
+	private Map _visitNodes = new HashMap(); // Map (String rootModuleConf -> List(VisitNode))
+
+	public VisitData(IvyNode node) {
+		_node = node;
+	}
+	
+	public void addVisitNode(VisitNode node) {
+		String rootModuleConf = node.getRootModuleConf();
+		getVisitNodes(rootModuleConf).add(node);
+	}
+
+	public List getVisitNodes(String rootModuleConf) {
+		List visits = (List) _visitNodes.get(rootModuleConf);
+		if (visits == null) {
+			visits = new ArrayList();
+			_visitNodes.put(rootModuleConf, visits);
+		}
+		return visits;
+	}
+	
+	public IvyNode getNode() {
+		return _node;
+	}
+
+	public void setNode(IvyNode node) {
+		_node = node;
+	}
+
+	public void addVisitNodes(String rootModuleConf, List visitNodes) {
+		getVisitNodes(rootModuleConf).addAll(visitNodes);
+	}
+}

Added: incubator/ivy/core/trunk/src/java/org/apache/ivy/core/resolve/VisitNode.java
URL: http://svn.apache.org/viewvc/incubator/ivy/core/trunk/src/java/org/apache/ivy/core/resolve/VisitNode.java?view=auto&rev=502534
==============================================================================
--- incubator/ivy/core/trunk/src/java/org/apache/ivy/core/resolve/VisitNode.java (added)
+++ incubator/ivy/core/trunk/src/java/org/apache/ivy/core/resolve/VisitNode.java Fri Feb  2 00:42:21 2007
@@ -0,0 +1,447 @@
+/*
+ *  Licensed to the Apache Software Foundation (ASF) under one or more
+ *  contributor license agreements.  See the NOTICE file distributed with
+ *  this work for additional information regarding copyright ownership.
+ *  The ASF licenses this file to You under the Apache License, Version 2.0
+ *  (the "License"); you may not use this file except in compliance with
+ *  the License.  You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ *  Unless required by applicable law or agreed to in writing, software
+ *  distributed under the License is distributed on an "AS IS" BASIS,
+ *  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ *  See the License for the specific language governing permissions and
+ *  limitations under the License.
+ *
+ */
+package org.apache.ivy.core.resolve;
+
+import java.util.ArrayList;
+import java.util.Collection;
+import java.util.Collections;
+import java.util.HashSet;
+import java.util.Iterator;
+import java.util.LinkedHashSet;
+
+import org.apache.ivy.core.IvyContext;
+import org.apache.ivy.core.module.descriptor.Configuration;
+import org.apache.ivy.core.module.descriptor.DependencyDescriptor;
+import org.apache.ivy.core.module.descriptor.ModuleDescriptor;
+import org.apache.ivy.core.module.id.ModuleId;
+import org.apache.ivy.core.module.id.ModuleRevisionId;
+import org.apache.ivy.core.resolve.IvyNodeEviction.EvictionData;
+import org.apache.ivy.plugins.conflict.ConflictManager;
+
+/**
+ * A visit node is an object used to represent one visit from one parent on 
+ * an {@link IvyNode} of the dependency graph.
+ * 
+ * During dependency resolution, the {@link ResolveEngine} visits nodes of the 
+ * depency graph following the dependencies, thus the same node can be visited
+ * several times, if it is requested from several module.
+ * 
+ * In this case you will have one VisitNode per parent and per root module 
+ * configuration.
+ * 
+ * Thus VisitNode stores data specific to the visit:
+ * <ul>
+ * <li>parent</li> the node from which the visit is occuring
+ * <li>parentConf</li> the configuration of the parent in which this node is visited
+ * <li>rootModuleConf</li> the configuration of the root module which is currently resolved
+ * </ul>
+ * 
+ * @author Xavier Hanin
+ */
+public class VisitNode {
+	/**
+	 * The node which is currently visited 
+	 */
+	private IvyNode _node;
+    /** 
+     * Represents the current parent of the node during ivy visit
+     * of dependency graph.
+     */
+    private VisitNode _parent = null;
+    /**
+     * The root node of the current visit
+     * It is null until it is required, see getRoot
+     */
+    private VisitNode _root = null;
+    /**
+     * Direct path from root to this node. 
+     * Note that the colleciton is ordered but is not a list implementation 
+     * This collection is null until it is required, see getPath
+     */
+    private Collection _path = null; // Collection(VisitNode)
+    
+    
+    /**
+     * The configuration of the parent module in the current visit 
+     */
+    private String _parentConf = null;
+    /**
+     * The configuration requested by the parent
+     * Note that this is the actual conf requested by the parent, not 
+     * a configuration extended by the requested conf which actually 
+     * trigger the node visit
+     */
+    private String _requestedConf; 
+    /**
+     * The root configuration which is currently visited
+     */
+    private String _rootModuleConf;
+    
+    /**
+     * Shared ResolveData instance, which can be used
+     * to get info on the current resolve process
+     */
+    private ResolveData _data;
+
+    
+    public VisitNode(ResolveData data, IvyNode node, VisitNode parent, String rootModuleConf, String parentConf) {
+    	_data = data;
+    	_node = node;
+    	_parent = parent;
+    	_rootModuleConf = rootModuleConf;
+    	_parentConf = parentConf;
+
+        // we do not register if this is a root module (root == no parent)
+        init(data, _parent != null);
+    }
+
+    private void init(ResolveData data, boolean register) {
+        _data = data;
+        if (register) {
+            _data.register(this);
+        }
+    }
+    
+    
+	public IvyNode getNode() {
+		return _node;
+	}
+
+	/**
+     * @return Returns the configuration requested by the parent
+     */
+    public String getRequestedConf() {
+        return _requestedConf;
+    }
+    
+    public void setRequestedConf(String requestedConf) {
+        _requestedConf = requestedConf;
+    }
+    
+
+    public VisitNode getParent() {
+        return _parent;
+    }    
+
+    public VisitNode getRoot() {
+        if (_root == null) {
+            _root = computeRoot();
+        }
+        return _root;
+    }
+
+    public Collection getPath() {
+        if (_path == null) {
+            _path = computePath();
+        }
+        return _path;
+    }
+
+    private Collection computePath() {
+        if (_parent != null) {
+            Collection p = new LinkedHashSet(_parent.getPath());
+            p.add(this);
+            return p;
+        } else {
+            return Collections.singletonList(this);
+        }
+    }
+
+    private VisitNode computeRoot() {
+        if (_node.isRoot()) {
+            return this;
+        } else if (_parent != null) {
+            return _parent.getRoot();
+        } else {
+            return null;
+        }
+    }
+
+    public String getParentConf() {
+        return _parentConf;
+    }
+
+    public void setParentConf(String parentConf) {
+        _parentConf = parentConf;
+    }
+
+    public String getRootModuleConf() {
+        return _rootModuleConf;
+    }
+
+    public static VisitNode getRoot(VisitNode parent) {
+    	VisitNode root = parent;
+        Collection path = new HashSet();
+        path.add(root);
+        while (root.getParent() != null && !root.getNode().isRoot()) {
+            if (path.contains(root.getParent())) {
+                return root;
+            }
+            root = root.getParent();
+            path.add(root);
+        }
+        return root;
+    }
+    
+
+    /**
+     * Returns true if the current dependency descriptor is transitive
+     * and the parent configuration is transitive.  Otherwise returns false.
+     * @param node curent node
+     * @return true if current node is transitive and the parent configuration is
+     * transitive.
+     */
+    public boolean isTransitive() {
+        return (_data.isTransitive() &&
+        		_node.getDependencyDescriptor(getParentNode()).isTransitive() &&
+                isParentConfTransitive() );
+    }
+
+    /**
+     * Checks if the current node's parent configuration is transitive.
+     * @param node current node
+     * @return true if the node's parent configuration is transitive
+     */
+    protected boolean isParentConfTransitive() {
+        String conf = getParent().getRequestedConf();
+        if (conf==null) {
+            return true;
+        }
+        Configuration parentConf = getParentNode().getConfiguration(conf);
+        return parentConf.isTransitive();
+
+    }
+
+    /**
+     * Returns the 'real' node currently visited.
+     * 'Real' means that if we are visiting a node created originally with only a version
+     * constraint, and if this version constraint has been resolved to an existing node
+     * in the graph, we will return the existing node, and not the one originally used
+     * which is about to be discarded, since it's not possible to have in the graph
+     * two nodes for the same ModuleRevisionId
+     * @return the 'real' node currently visited.
+     */
+    public IvyNode getRealNode() {
+        IvyNode node = _node.getRealNode();
+        if (node != null) {
+            return node;
+        } else {
+            return _node;
+        }
+    }
+
+    /**
+     * Ask to the current visited node to use a real node only, if one exist. 
+     * See getRealNode for details about what a 'real' node is.
+     */
+    public void useRealNode() {
+        IvyNode node = _data.getNode(_node.getId());
+        if (node != null && node != _node) {
+        	_node = node;
+        }
+    }
+
+    public boolean loadData(String conf, boolean shouldBePublic) {
+        boolean loaded = _node.loadData(_rootModuleConf, getParentNode(), _parentConf, conf, shouldBePublic);
+        if (loaded) {
+	        useRealNode();
+	
+	        // if the revision was a dynamic one (which has now be resolved)
+	        // we now register this node on the resolved id
+	        if (_data.getSettings().getVersionMatcher().isDynamic(getId())) {
+	            _data.register(_node.getResolvedId(), this);
+	        }
+        }
+
+        return loaded;
+    }
+
+    public Collection getDependencies(String conf) {
+    	Collection deps = _node.getDependencies(_rootModuleConf, conf, _requestedConf);
+    	Collection ret = new ArrayList(deps.size());
+    	for (Iterator iter = deps.iterator(); iter.hasNext();) {
+			IvyNode depNode = (IvyNode) iter.next();
+			ret.add(traverseChild(conf, depNode));
+		}
+    	return ret;
+    }
+    
+    /**
+     * Returns a VisitNode for the given node.
+     * The given node must be a representation of the same module 
+     * (usually in another revision) as the one visited by this node.
+     * 
+     * The given node must also have been already visited.
+     * 
+     * @param node the node to visit
+     * @return a VisitNode for the given node
+     */
+	VisitNode gotoNode(IvyNode node) {
+		if (!getModuleId().equals(node.getModuleId())) {
+			throw new IllegalArgumentException("you can't use gotoNode for a node which does not represent the same Module as the one represented by this node.\nCurrent node module id="+getModuleId()+" Given node module id="+node.getModuleId());
+		}
+		VisitData visitData = _data.getVisitData(node.getId());
+		if (visitData == null) {
+			throw new IllegalArgumentException("you can't use gotoNode with a node which has not been visited yet.\nGiven node id="+node.getId());
+		}
+		for (Iterator iter = visitData.getVisitNodes(_rootModuleConf).iterator(); iter.hasNext();) {
+			VisitNode vnode = (VisitNode) iter.next();
+			if ((_parent == null && vnode.getParent() == null) || 
+					(_parent != null && _parent.getId().equals(vnode.getParent().getId()))) {
+				return vnode;
+			}
+		}
+		// the node has not yet been visited from the current parent, we create a new visit node
+		return traverse(_parent, _parentConf, node);
+	}
+
+	private VisitNode traverseChild(String parentConf, IvyNode child) {
+		VisitNode parent = this;
+		return traverse(parent, parentConf, child);
+	}
+
+	private VisitNode traverse(VisitNode parent, String parentConf, IvyNode node) {
+		if (getPath().contains(node)) {
+			IvyContext.getContext().getCircularDependencyStrategy()
+				.handleCircularDependency(toMrids(getPath(), node.getId()));
+			// we do not use the new parent, but the first one, to always be able to go up to the root
+//			parent = getVisitNode(depNode).getParent(); 
+		}
+		return new VisitNode(_data, node, parent, _rootModuleConf, parentConf);
+	}
+
+	private ModuleRevisionId[] toMrids(Collection path, ModuleRevisionId last) {
+    	ModuleRevisionId[] ret = new ModuleRevisionId[path.size()+1];
+    	int i=0;
+    	for (Iterator iter = path.iterator(); iter.hasNext(); i++) {
+    		VisitNode node = (VisitNode) iter.next();
+			ret[i] = node.getNode().getId();
+		}
+    	ret[ret.length-1] = last;
+		return ret;
+	}
+
+	public ModuleRevisionId getResolvedId() {
+		return _node.getResolvedId();
+	}
+
+	public void updateConfsToFetch(Collection confs) {
+		_node.updateConfsToFetch(confs);
+	}
+
+	public ModuleRevisionId getId() {
+		return _node.getId();
+	}
+
+	public boolean isEvicted() {
+		return _node.isEvicted(_rootModuleConf);
+	}
+
+	public String[] getRealConfs(String conf) {
+		return _node.getRealConfs(conf);
+	}
+
+	public boolean hasProblem() {
+		return _node.hasProblem();
+	}
+
+	public Configuration getConfiguration(String conf) {
+		return _node.getConfiguration(conf);
+	}
+
+	public EvictionData getEvictedData() {
+		return _node.getEvictedData(_rootModuleConf);
+	}
+
+	public DependencyDescriptor getDependencyDescriptor() {
+		return _node.getDependencyDescriptor(getParentNode());
+	}
+
+	private IvyNode getParentNode() {
+		return _parent==null?null:_parent.getNode();
+	}
+
+	public boolean isCircular() {
+		return _node.isCircular();
+	}
+
+	public String[] getConfsToFetch() {
+		return _node.getConfsToFetch();
+	}
+
+	public String[] getRequiredConfigurations(VisitNode in, String inConf) {
+		return _node.getRequiredConfigurations(in.getNode(), inConf);
+	}
+
+	public ModuleId getModuleId() {
+		return _node.getModuleId();
+	}
+
+	public Collection getResolvedRevisions(ModuleId mid) {
+		return _node.getResolvedRevisions(mid, _rootModuleConf);
+	}
+
+	public void markEvicted(EvictionData evictionData) {
+		_node.markEvicted(evictionData);
+	}
+
+	public String[] getRequiredConfigurations() {
+		return _node.getRequiredConfigurations();
+	}
+
+	/**
+	 * Marks the current node as evicted by the the given selected IvyNodes, 
+	 * in the given parent and root module configuration, with the given
+	 * {@link ConflictManager}
+	 * 
+	 * @param parent the VisitNode in which eviction has been made
+	 * @param conflictManager the conflict manager responsible for the eviction
+	 * @param selected a Collection of {@link IvyNode} which have been selected 
+	 */
+	public void markEvicted(VisitNode parent, ConflictManager conflictManager, Collection selected) {
+		_node.markEvicted(_rootModuleConf, parent.getNode(), conflictManager, selected);
+	}
+
+	public ModuleDescriptor getDescriptor() {
+		return _node.getDescriptor();
+	}
+
+	public EvictionData getEvictionDataInRoot(String rootModuleConf, VisitNode ancestor) {
+		return _node.getEvictionDataInRoot(rootModuleConf, ancestor.getNode());
+	}
+
+	public Collection getEvictedRevisions(ModuleId moduleId) {
+		return _node.getEvictedRevisions(moduleId, _rootModuleConf);
+	}
+
+
+//    public void setRootModuleConf(String rootModuleConf) {
+//        if (_rootModuleConf != null && !_rootModuleConf.equals(rootModuleConf)) {
+//            _confsToFetch.clear(); // we change of root module conf => we discard all confs to fetch
+//        }
+//        if (rootModuleConf != null && rootModuleConf.equals(_rootModuleConf)) {
+//            _selectedDeps.put(new ModuleIdConf(_id.getModuleId(), rootModuleConf), Collections.singleton(this));
+//        }
+//        _rootModuleConf = rootModuleConf;
+//    }
+
+	public String toString() {
+		return _node.toString();
+	}
+
+}

Modified: incubator/ivy/core/trunk/src/java/org/apache/ivy/plugins/conflict/LatestConflictManager.java
URL: http://svn.apache.org/viewvc/incubator/ivy/core/trunk/src/java/org/apache/ivy/plugins/conflict/LatestConflictManager.java?view=diff&rev=502534&r1=502533&r2=502534
==============================================================================
--- incubator/ivy/core/trunk/src/java/org/apache/ivy/plugins/conflict/LatestConflictManager.java (original)
+++ incubator/ivy/core/trunk/src/java/org/apache/ivy/plugins/conflict/LatestConflictManager.java Fri Feb  2 00:42:21 2007
@@ -75,7 +75,8 @@
         for (Iterator iter = conflicts.iterator(); iter.hasNext();) {
             IvyNode node = (IvyNode)iter.next();
             DependencyDescriptor dd = node.getDependencyDescriptor(parent);
-            if (dd != null && dd.isForce() && parent.getResolvedId().equals(dd.getParentRevisionId())) {
+            if (dd != null && dd.isForce() 
+            		&& parent.getResolvedId().equals(dd.getParentRevisionId())) {
                 return Collections.singleton(node);
             }
         }

Modified: incubator/ivy/core/trunk/src/java/org/apache/ivy/plugins/conflict/RegexpConflictManager.java
URL: http://svn.apache.org/viewvc/incubator/ivy/core/trunk/src/java/org/apache/ivy/plugins/conflict/RegexpConflictManager.java?view=diff&rev=502534&r1=502533&r2=502534
==============================================================================
--- incubator/ivy/core/trunk/src/java/org/apache/ivy/plugins/conflict/RegexpConflictManager.java (original)
+++ incubator/ivy/core/trunk/src/java/org/apache/ivy/plugins/conflict/RegexpConflictManager.java Fri Feb  2 00:42:21 2007
@@ -17,6 +17,7 @@
  */
 package org.apache.ivy.plugins.conflict;
 
+import java.util.Arrays;
 import java.util.Collection;
 import java.util.Collections;
 import java.util.Iterator;
@@ -78,9 +79,9 @@
 
 			if (lastNode != null && !matchEquals(node, lastNode)) {
 				String msg = lastNode + ":" + getMatch(lastNode)
-						+ " (needed by " + lastNode.getParent()
+						+ " (needed by " + Arrays.asList(lastNode.getAllCallers())
 						+ ") conflicts with " + node + ":" + getMatch(node)
-						+ " (needed by " + node.getParent() + ")";
+						+ " (needed by " + Arrays.asList(node.getAllCallers()) + ")";
 				Message.error(msg);
 				Message.sumupProblems();
 				throw new StrictConflictException(msg);

Modified: incubator/ivy/core/trunk/src/java/org/apache/ivy/plugins/conflict/StrictConflictManager.java
URL: http://svn.apache.org/viewvc/incubator/ivy/core/trunk/src/java/org/apache/ivy/plugins/conflict/StrictConflictManager.java?view=diff&rev=502534&r1=502533&r2=502534
==============================================================================
--- incubator/ivy/core/trunk/src/java/org/apache/ivy/plugins/conflict/StrictConflictManager.java (original)
+++ incubator/ivy/core/trunk/src/java/org/apache/ivy/plugins/conflict/StrictConflictManager.java Fri Feb  2 00:42:21 2007
@@ -17,6 +17,7 @@
  */
 package org.apache.ivy.plugins.conflict;
 
+import java.util.Arrays;
 import java.util.Collection;
 import java.util.Collections;
 import java.util.Iterator;
@@ -40,7 +41,7 @@
             IvyNode node = (IvyNode)iter.next();
 
             if (lastNode != null && !lastNode.equals(node)) {
-                String msg = lastNode + " (needed by " + lastNode.getParent() + ") conflicts with " + node + " (needed by " + node.getParent() + ")";
+                String msg = lastNode + " (needed by " + Arrays.asList(lastNode.getAllCallers()) + ") conflicts with " + node + " (needed by " + Arrays.asList(node.getAllCallers()) + ")";
                 Message.error(msg);
                 Message.sumupProblems();
                 throw new StrictConflictException(msg);

Modified: incubator/ivy/core/trunk/src/java/org/apache/ivy/plugins/report/LogReportOutputter.java
URL: http://svn.apache.org/viewvc/incubator/ivy/core/trunk/src/java/org/apache/ivy/plugins/report/LogReportOutputter.java?view=diff&rev=502534&r1=502533&r2=502534
==============================================================================
--- incubator/ivy/core/trunk/src/java/org/apache/ivy/plugins/report/LogReportOutputter.java (original)
+++ incubator/ivy/core/trunk/src/java/org/apache/ivy/plugins/report/LogReportOutputter.java Fri Feb  2 00:42:21 2007
@@ -25,6 +25,7 @@
 import org.apache.ivy.core.report.ConfigurationResolveReport;
 import org.apache.ivy.core.report.ResolveReport;
 import org.apache.ivy.core.resolve.IvyNode;
+import org.apache.ivy.core.resolve.IvyNodeEviction.EvictionData;
 import org.apache.ivy.util.Message;
 
 
@@ -53,8 +54,8 @@
                 }
                 String[] confs = evicted[i].getEvictedConfs();
                 for (int j = 0; j < confs.length; j++) {
-                    IvyNode.EvictionData evictedData = evicted[i].getEvictedData(confs[j]);
-                    Message.verbose("\t  in "+evictedData.getNode()+" with "+evictedData.getConflictManager());
+                    EvictionData evictedData = evicted[i].getEvictedData(confs[j]);
+                    Message.verbose("\t  in "+evictedData.getParent()+" with "+evictedData.getConflictManager());
                 }
             }
         }
@@ -96,7 +97,7 @@
             Message.warn("\t::::::::::::::::::::::::::::::::::::::::::::::");
         }
         for (int i = 0; i < unresolved.length; i++) {
-            Message.warn("\t:: "+unresolved[i]+": "+unresolved[i].getProblem().getMessage());
+            Message.warn("\t:: "+unresolved[i]+": "+unresolved[i].getProblemMessage());
         }
         if (unresolved.length > 0) {
             Message.warn("\t::::::::::::::::::::::::::::::::::::::::::::::\n");

Modified: incubator/ivy/core/trunk/src/java/org/apache/ivy/plugins/report/XmlReportOutputter.java
URL: http://svn.apache.org/viewvc/incubator/ivy/core/trunk/src/java/org/apache/ivy/plugins/report/XmlReportOutputter.java?view=diff&rev=502534&r1=502533&r2=502534
==============================================================================
--- incubator/ivy/core/trunk/src/java/org/apache/ivy/plugins/report/XmlReportOutputter.java (original)
+++ incubator/ivy/core/trunk/src/java/org/apache/ivy/plugins/report/XmlReportOutputter.java Fri Feb  2 00:42:21 2007
@@ -39,6 +39,8 @@
 import org.apache.ivy.core.report.ConfigurationResolveReport;
 import org.apache.ivy.core.report.ResolveReport;
 import org.apache.ivy.core.resolve.IvyNode;
+import org.apache.ivy.core.resolve.IvyNodeCallers.Caller;
+import org.apache.ivy.core.resolve.IvyNodeEviction.EvictionData;
 import org.apache.ivy.util.FileUtil;
 import org.apache.ivy.util.Message;
 import org.apache.ivy.util.StringUtils;
@@ -128,7 +130,7 @@
                         " artresolver=\"").append(dep.getModuleRevision().getArtifactResolver().getName()).append("\"");
                 }
                 if (dep.isEvicted(report.getConfiguration())) {
-                    IvyNode.EvictionData ed = dep.getEvictedData(report.getConfiguration());
+                    EvictionData ed = dep.getEvictedData(report.getConfiguration());
                     if (ed.getConflictManager() != null) {
                         details.append(" evicted=\"").append(ed.getConflictManager()).append("\"");
                     } else {
@@ -169,7 +171,7 @@
                     }
                 }
                 if (dep.isEvicted(report.getConfiguration())) {
-                    IvyNode.EvictionData ed = dep.getEvictedData(report.getConfiguration());
+                    EvictionData ed = dep.getEvictedData(report.getConfiguration());
                     Collection selected = ed.getSelected();
                     if (selected != null) {
                         for (Iterator it3 = selected.iterator(); it3.hasNext();) {
@@ -178,7 +180,7 @@
                         }
                     }
                 }
-                IvyNode.Caller[] callers = dep.getCallers(report.getConfiguration());
+                Caller[] callers = dep.getCallers(report.getConfiguration());
 				for (int i = 0; i < callers.length; i++) {
 					StringBuffer callerDetails = new StringBuffer();
 					Map callerExtraAttributes = callers[i].getDependencyDescriptor().getExtraAttributes();

Modified: incubator/ivy/core/trunk/src/java/org/apache/ivy/plugins/version/VersionRangeMatcher.java
URL: http://svn.apache.org/viewvc/incubator/ivy/core/trunk/src/java/org/apache/ivy/plugins/version/VersionRangeMatcher.java?view=diff&rev=502534&r1=502533&r2=502534
==============================================================================
--- incubator/ivy/core/trunk/src/java/org/apache/ivy/plugins/version/VersionRangeMatcher.java (original)
+++ incubator/ivy/core/trunk/src/java/org/apache/ivy/plugins/version/VersionRangeMatcher.java Fri Feb  2 00:42:21 2007
@@ -127,7 +127,8 @@
 	}
 
 	public boolean isDynamic(ModuleRevisionId askedMrid) {
-		return ALL_RANGE.matcher(askedMrid.getRevision()).matches();
+		String revision = askedMrid.getRevision();
+		return ALL_RANGE.matcher(revision).matches();
 	}
 
 	public boolean accept(ModuleRevisionId askedMrid, ModuleRevisionId foundMrid) {

Modified: incubator/ivy/core/trunk/test/java/org/apache/ivy/plugins/conflict/RegexpConflictManagerTest.java
URL: http://svn.apache.org/viewvc/incubator/ivy/core/trunk/test/java/org/apache/ivy/plugins/conflict/RegexpConflictManagerTest.java?view=diff&rev=502534&r1=502533&r2=502534
==============================================================================
--- incubator/ivy/core/trunk/test/java/org/apache/ivy/plugins/conflict/RegexpConflictManagerTest.java (original)
+++ incubator/ivy/core/trunk/test/java/org/apache/ivy/plugins/conflict/RegexpConflictManagerTest.java Fri Feb  2 00:42:21 2007
@@ -66,9 +66,12 @@
         catch ( StrictConflictException e )
         {
             // this is expected
-            assertTrue(e.getMessage().indexOf("[ org1 | mod1.2 | 2.0.0 ]:2.0 (needed by [ apache | resolve-noconflict | 1.0 ])")!=-1);
-            assertTrue(e.getMessage().indexOf("conflicts with")!=-1);
-            assertTrue(e.getMessage().indexOf("[ org1 | mod1.2 | 2.1.0 ]:2.1 (needed by [ apache | resolve-noconflict | 1.0 ])")!=-1);
+            assertTrue("bad exception message: "+e.getMessage(), 
+            		e.getMessage().indexOf("[ org1 | mod1.2 | 2.0.0 ]:2.0 (needed by [[ apache | resolve-noconflict | 1.0 ]])")!=-1);
+            assertTrue("bad exception message: "+e.getMessage(), 
+            		e.getMessage().indexOf("conflicts with")!=-1);
+            assertTrue("bad exception message: "+e.getMessage(), 
+            		e.getMessage().indexOf("[ org1 | mod1.2 | 2.1.0 ]:2.1 (needed by [[ apache | resolve-noconflict | 1.0 ]])")!=-1);
         }
     }
 }

Modified: incubator/ivy/core/trunk/test/java/org/apache/ivy/plugins/parser/xml/XmlModuleDescriptorParserTest.java
URL: http://svn.apache.org/viewvc/incubator/ivy/core/trunk/test/java/org/apache/ivy/plugins/parser/xml/XmlModuleDescriptorParserTest.java?view=diff&rev=502534&r1=502533&r2=502534
==============================================================================
--- incubator/ivy/core/trunk/test/java/org/apache/ivy/plugins/parser/xml/XmlModuleDescriptorParserTest.java (original)
+++ incubator/ivy/core/trunk/test/java/org/apache/ivy/plugins/parser/xml/XmlModuleDescriptorParserTest.java Fri Feb  2 00:42:21 2007
@@ -24,6 +24,7 @@
 import java.util.GregorianCalendar;
 import java.util.HashSet;
 
+import org.apache.ivy.Ivy;
 import org.apache.ivy.core.module.descriptor.Artifact;
 import org.apache.ivy.core.module.descriptor.Configuration;
 import org.apache.ivy.core.module.descriptor.DependencyDescriptor;
@@ -52,7 +53,7 @@
         assertNotNull(md);
         assertEquals("myorg", md.getModuleRevisionId().getOrganisation());
         assertEquals("mymodule", md.getModuleRevisionId().getName());
-        assertEquals(null, md.getModuleRevisionId().getRevision());
+        assertEquals(Ivy.getWorkingRevision(), md.getModuleRevisionId().getRevision());
         assertEquals("integration", md.getStatus());
         
         assertNotNull(md.getConfigurations());
@@ -346,7 +347,7 @@
         assertNotNull(md);
         assertEquals("myorg", md.getModuleRevisionId().getOrganisation());
         assertEquals("mymodule", md.getModuleRevisionId().getName());
-        assertEquals(null, md.getModuleRevisionId().getRevision());
+        assertEquals(Ivy.getWorkingRevision(), md.getModuleRevisionId().getRevision());
         assertEquals("integration", md.getStatus());
         
         assertNotNull(md.getConfigurations());

Modified: incubator/ivy/core/trunk/test/java/org/apache/ivy/plugins/parser/xml/XmlModuleDescriptorWriterTest.java
URL: http://svn.apache.org/viewvc/incubator/ivy/core/trunk/test/java/org/apache/ivy/plugins/parser/xml/XmlModuleDescriptorWriterTest.java?view=diff&rev=502534&r1=502533&r2=502534
==============================================================================
--- incubator/ivy/core/trunk/test/java/org/apache/ivy/plugins/parser/xml/XmlModuleDescriptorWriterTest.java (original)
+++ incubator/ivy/core/trunk/test/java/org/apache/ivy/plugins/parser/xml/XmlModuleDescriptorWriterTest.java Fri Feb  2 00:42:21 2007
@@ -28,6 +28,7 @@
 
 import org.apache.ivy.core.module.descriptor.DefaultModuleDescriptor;
 import org.apache.ivy.core.module.descriptor.ModuleDescriptor;
+import org.apache.ivy.core.module.id.ModuleRevisionId;
 import org.apache.ivy.core.settings.IvySettings;
 import org.apache.ivy.util.FileUtil;
 
@@ -37,6 +38,7 @@
     public void testSimple() throws Exception {
         DefaultModuleDescriptor md = (DefaultModuleDescriptor)XmlModuleDescriptorParser.getInstance().parseDescriptor(new IvySettings(), XmlModuleDescriptorWriterTest.class.getResource("test-simple.xml"), true);
         md.setResolvedPublicationDate(new GregorianCalendar(2005, 4, 1, 11, 0, 0).getTime());
+        md.setResolvedModuleRevisionId(new ModuleRevisionId(md.getModuleRevisionId().getModuleId(), "NONE"));
         XmlModuleDescriptorWriter.write(md, _dest);
         
         assertTrue(_dest.exists());

Modified: incubator/ivy/core/trunk/test/java/org/apache/ivy/plugins/parser/xml/test-write-simple.xml
URL: http://svn.apache.org/viewvc/incubator/ivy/core/trunk/test/java/org/apache/ivy/plugins/parser/xml/test-write-simple.xml?view=diff&rev=502534&r1=502533&r2=502534
==============================================================================
--- incubator/ivy/core/trunk/test/java/org/apache/ivy/plugins/parser/xml/test-write-simple.xml (original)
+++ incubator/ivy/core/trunk/test/java/org/apache/ivy/plugins/parser/xml/test-write-simple.xml Fri Feb  2 00:42:21 2007
@@ -2,6 +2,7 @@
 <ivy-module version="1.0">
 	<info organisation="myorg"
 		module="mymodule"
+		revision="NONE"
 		status="integration"
 		publication="20050501110000"
 	/>

Modified: incubator/ivy/core/trunk/test/repositories/circular/ivy.xml
URL: http://svn.apache.org/viewvc/incubator/ivy/core/trunk/test/repositories/circular/ivy.xml?view=diff&rev=502534&r1=502533&r2=502534
==============================================================================
--- incubator/ivy/core/trunk/test/repositories/circular/ivy.xml (original)
+++ incubator/ivy/core/trunk/test/repositories/circular/ivy.xml Fri Feb  2 00:42:21 2007
@@ -1,6 +1,7 @@
 <ivy-module version="1.0">
 	<info organisation="org8"
 	       module="mod8.5"
+	       revision="NONE"
 	/>
 	<configurations>
 		<conf name="compile"/>



Mime
View raw message