1 6 package fr.jayasoft.ivy; 7 8 import java.util.ArrayList ; 9 import java.util.Arrays ; 10 import java.util.Collection ; 11 import java.util.Collections ; 12 import java.util.HashMap ; 13 import java.util.HashSet ; 14 import java.util.Iterator ; 15 import java.util.LinkedHashSet ; 16 import java.util.LinkedList ; 17 import java.util.List ; 18 import java.util.Map ; 19 import java.util.Set ; 20 import java.util.Stack ; 21 import java.util.regex.Matcher ; 22 import java.util.regex.Pattern ; 23 24 import fr.jayasoft.ivy.event.resolve.EndResolveDependencyEvent; 25 import fr.jayasoft.ivy.event.resolve.StartResolveDependencyEvent; 26 import fr.jayasoft.ivy.filter.Filter; 27 import fr.jayasoft.ivy.filter.FilterHelper; 28 import fr.jayasoft.ivy.matcher.MatcherHelper; 29 import fr.jayasoft.ivy.util.Message; 30 31 public class IvyNode { 32 private static final Pattern FALLBACK_CONF_PATTERN = Pattern.compile("(.+)\\((.*)\\)"); 33 34 public static class EvictionData { 35 private IvyNode _node; private ConflictManager _conflictManager; private Collection _selected; private String _rootModuleConf; 39 40 public EvictionData(String rootModuleConf, IvyNode node, ConflictManager conflictManager, Collection selected) { 41 _rootModuleConf = rootModuleConf; 42 _node = node; 43 _conflictManager = conflictManager; 44 _selected = selected; 45 } 46 47 public String toString() { 48 if (_selected != null) { 49 return _selected + " in "+ _node+" ("+_conflictManager+") ["+_rootModuleConf+"]"; 50 } else { 51 return "transitively ["+_rootModuleConf+"]"; 52 } 53 } 54 55 public ConflictManager getConflictManager() { 56 return _conflictManager; 57 } 58 59 60 public IvyNode getNode() { 61 return _node; 62 } 63 64 public Collection getSelected() { 65 return _selected; 66 } 67 68 69 public String getRootModuleConf() { 70 return _rootModuleConf; 71 } 72 73 74 } 75 76 public class Caller { 77 private ModuleDescriptor _md; 78 private ModuleRevisionId _mrid; 79 private Map _confs = new HashMap (); private DependencyDescriptor _dd; 81 private boolean _callerCanExclude; 82 83 public Caller(ModuleDescriptor md, ModuleRevisionId mrid, DependencyDescriptor dd, boolean callerCanExclude) { 84 _md = md; 85 _mrid = mrid; 86 _dd = dd; 87 _callerCanExclude = callerCanExclude; 88 } 89 public void addConfiguration(String callerConf, String [] dependencyConfs) { 90 String [] prevDepConfs = (String [])_confs.get(callerConf); 91 if (prevDepConfs != null) { 92 Set newDepConfs = new HashSet (Arrays.asList(prevDepConfs)); 93 newDepConfs.addAll(Arrays.asList(dependencyConfs)); 94 _confs.put(callerConf, (String [])newDepConfs.toArray(new String [newDepConfs.size()])); 95 } else { 96 _confs.put(callerConf, dependencyConfs); 97 } 98 } 99 public String [] getCallerConfigurations() { 100 return (String [])_confs.keySet().toArray(new String [_confs.keySet().size()]); 101 } 102 public ModuleRevisionId getModuleRevisionId() { 103 return _mrid; 104 } 105 public boolean equals(Object obj) { 106 if (! (obj instanceof Caller)) { 107 return false; 108 } 109 Caller other = (Caller)obj; 110 return other._confs.equals(_confs) 111 && _mrid.equals(other._mrid); 112 } 113 public int hashCode() { 114 int hash = 31; 115 hash = hash * 13 + _confs.hashCode(); 116 hash = hash * 13 + _mrid.hashCode(); 117 return hash; 118 } 119 public String toString() { 120 return _mrid.toString(); 121 } 122 public ModuleRevisionId getAskedDependencyId() { 123 return _dd.getDependencyRevisionId(); 124 } 125 public ModuleDescriptor getModuleDescriptor() { 126 return _md; 127 } 128 public boolean canExclude() { 129 return _callerCanExclude || _dd.canExclude(); 130 } 131 public DependencyDescriptor getDependencyDescriptor() { 132 return _dd; 133 } 134 } 135 private static final class NodeConf { 136 private IvyNode _node; 137 private String _conf; 138 139 public NodeConf(IvyNode node, String conf) { 140 _node = node; 141 _conf = conf; 142 } 143 144 public final String getConf() { 145 return _conf; 146 } 147 148 public final IvyNode getNode() { 149 return _node; 150 } 151 public boolean equals(Object obj) { 152 if (!(obj instanceof NodeConf)) { 153 return false; 154 } 155 return getNode().equals(((NodeConf)obj).getNode()) 156 && getConf().equals(((NodeConf)obj).getConf()); 157 } 158 public int hashCode() { 159 int hash = 33; 160 hash += getNode().hashCode() * 17; 161 hash += getConf().hashCode() * 17; 162 return hash; 163 } 164 } 165 166 private static final class ModuleIdConf { 167 private ModuleId _moduleId; 168 private String _conf; 169 170 public ModuleIdConf(ModuleId mid, String conf) { 171 _moduleId = mid; 172 _conf = conf; 173 } 174 175 public final String getConf() { 176 return _conf; 177 } 178 179 public final ModuleId getModuleId() { 180 return _moduleId; 181 } 182 public boolean equals(Object obj) { 183 if (!(obj instanceof ModuleIdConf)) { 184 return false; 185 } 186 return getModuleId().equals(((ModuleIdConf)obj).getModuleId()) 187 && getConf().equals(((ModuleIdConf)obj).getConf()); 188 } 189 public int hashCode() { 190 int hash = 33; 191 hash += getModuleId().hashCode() * 17; 192 hash += getConf().hashCode() * 17; 193 return hash; 194 } 195 } 196 197 private ModuleRevisionId _id; 199 205 private IvyNode _parent = null; 206 private IvyNode _root = null; 207 private Collection _path = null; private String _parentConf = null; 209 private String _rootModuleConf; 210 211 private Map _selectedDeps = new HashMap (); 213 private Map _evictedDeps = new HashMap (); private Map _evictedRevs = new HashMap (); 216 private Map _evicted = new HashMap (); 218 private Map _callersByRootConf = new HashMap (); 220 221 private Map _rootModuleConfs = new HashMap (); 225 226 private Map _dependencyArtifactsIncludes = new HashMap (); 228 229 private ResolveData _data; 231 232 private Collection _confsToFetch = new HashSet (); 233 private Collection _fetchedConfigurations = new HashSet (); 234 235 private Map _dds = new HashMap (); 238 private ModuleDescriptor _md; 240 241 private ResolvedModuleRevision _module; 242 243 private Exception _problem = null; 244 245 private boolean _downloaded = false; 246 private boolean _searched = false; 247 248 249 private Map _requiredConfs = new HashMap (); 251 private boolean _isRoot = false; 252 253 256 private Map _allCallers = new HashMap (); 258 private boolean _isCircular = false; 259 260 private Collection _loadedRootModuleConfs = new HashSet (); 261 262 private Map _requestedConf = new HashMap (); 266 267 public IvyNode(ResolveData data, IvyNode parent, DependencyDescriptor dd) { 268 _id = dd.getDependencyRevisionId(); 269 _dds.put(parent, dd); 270 _isRoot = false; 271 272 init(data, true); 273 } 274 275 public IvyNode(ResolveData data, ModuleDescriptor md) { 276 _id = md.getModuleRevisionId(); 277 _md = md; 278 _isRoot = true; 279 _root = this; 280 281 init(data, false); 284 } 285 286 private void init(ResolveData data, boolean register) { 287 _data = data; 288 if (register) { 289 _data.register(this); 290 } 291 } 292 293 public ConflictManager getConflictManager(ModuleId mid) { 294 if (_md == null) { 295 throw new IllegalStateException ("impossible to get conflict manager when data has not been loaded"); 296 } 297 ConflictManager cm = _md.getConflictManager(mid); 298 return cm == null ? _data.getIvy().getDefaultConflictManager() : cm; 299 } 300 301 public Collection getResolvedNodes(ModuleId mid, String rootModuleConf) { 302 Collection resolved = (Collection )_selectedDeps.get(new ModuleIdConf(mid, rootModuleConf)); 303 Set ret = new HashSet (); 304 if (resolved != null) { 305 for (Iterator iter = resolved.iterator(); iter.hasNext();) { 306 IvyNode node = (IvyNode)iter.next(); 307 ret.add(node.getRealNode()); 308 } 309 } 310 return ret; 311 } 312 public Collection getResolvedRevisions(ModuleId mid, String rootModuleConf) { 313 Collection resolved = (Collection )_selectedDeps.get(new ModuleIdConf(mid, rootModuleConf)); 314 if (resolved == null) { 315 return new HashSet (); 316 } else { 317 Collection resolvedRevs = new HashSet (); 318 for (Iterator iter = resolved.iterator(); iter.hasNext();) { 319 IvyNode node = (IvyNode)iter.next(); 320 resolvedRevs.add(node.getId()); 321 resolvedRevs.add(node.getResolvedId()); 322 } 323 return resolvedRevs; 324 } 325 } 326 327 public void setResolvedNodes(ModuleId moduleId, String rootModuleConf, Collection resolved) { 328 ModuleIdConf moduleIdConf = new ModuleIdConf(moduleId, rootModuleConf); 329 _selectedDeps.put(moduleIdConf, new HashSet (resolved)); 330 } 331 332 public Collection getEvictedNodes(ModuleId mid, String rootModuleConf) { 333 Collection resolved = (Collection )_evictedDeps.get(new ModuleIdConf(mid, rootModuleConf)); 334 Set ret = new HashSet (); 335 if (resolved != null) { 336 for (Iterator iter = resolved.iterator(); iter.hasNext();) { 337 IvyNode node = (IvyNode)iter.next(); 338 ret.add(node.getRealNode()); 339 } 340 } 341 return ret; 342 } 343 public Collection getEvictedRevisions(ModuleId mid, String rootModuleConf) { 344 Collection evicted = (Collection )_evictedRevs.get(new ModuleIdConf(mid, rootModuleConf)); 345 if (evicted == null) { 346 return new HashSet (); 347 } else { 348 return new HashSet (evicted); 349 } 350 } 351 352 public void setEvictedNodes(ModuleId moduleId, String rootModuleConf, Collection evicted) { 353 ModuleIdConf moduleIdConf = new ModuleIdConf(moduleId, rootModuleConf); 354 _evictedDeps.put(moduleIdConf, new HashSet (evicted)); 355 Collection evictedRevs = new HashSet (); 356 for (Iterator iter = evicted.iterator(); iter.hasNext();) { 357 IvyNode node = (IvyNode)iter.next(); 358 evictedRevs.add(node.getId()); 359 evictedRevs.add(node.getResolvedId()); 360 } 361 _evictedRevs.put(moduleIdConf, evictedRevs); 362 } 363 364 365 public boolean isEvicted(String rootModuleConf) { 366 cleanEvicted(); 367 return getRoot() != this && !getRoot().getResolvedRevisions(getId().getModuleId(), rootModuleConf).contains(getResolvedId()); 368 } 369 370 public boolean isCompletelyEvicted() { 371 cleanEvicted(); 372 if (getRoot() == this) { 373 return false; 374 } 375 for (Iterator iter = _rootModuleConfs.keySet().iterator(); iter.hasNext();) { 376 String conf = (String ) iter.next(); 377 if (!isEvicted(conf)) { 378 return false; 379 } 380 } 381 return true; 382 } 383 384 private void cleanEvicted() { 385 for (Iterator iter = _evicted.keySet().iterator(); iter.hasNext();) { 387 String rootModuleConf = (String )iter.next(); 388 EvictionData ed = (EvictionData)_evicted.get(rootModuleConf); 389 Collection sel = ed.getSelected(); 390 if (sel != null) { 391 for (Iterator iterator = sel.iterator(); iterator.hasNext();) { 392 IvyNode n = (IvyNode)iterator.next(); 393 if (n.getRealNode().equals(this)) { 394 iter.remove(); 397 } 398 } 399 } 400 } 401 } 402 403 public void markEvicted(String rootModuleConf, IvyNode node, ConflictManager conflictManager, Collection resolved) { 404 EvictionData evictionData = new EvictionData(rootModuleConf, node, conflictManager, resolved); 405 markEvicted(evictionData); 406 } 407 408 public void markEvicted(EvictionData evictionData) { 409 _evicted.put(evictionData.getRootModuleConf(), evictionData); 410 if (!_rootModuleConfs.keySet().contains(evictionData.getRootModuleConf())) { 411 _rootModuleConfs.put(evictionData.getRootModuleConf(), null); 412 } 413 414 if (evictionData.getSelected() != null) { 416 for (Iterator iter = evictionData.getSelected().iterator(); iter.hasNext();) { 417 IvyNode selected = (IvyNode)iter.next(); 418 selected.updateDataFrom(this, evictionData.getRootModuleConf()); 419 } 420 } 421 } 422 423 private void updateDataFrom(IvyNode node, String rootModuleConf) { 424 Map nodecallers = (Map )node._callersByRootConf.get(rootModuleConf); 426 if (nodecallers != null) { 427 Map thiscallers = (Map )_callersByRootConf.get(rootModuleConf); 428 if (thiscallers == null) { 429 thiscallers = new HashMap (); 430 _callersByRootConf.put(rootModuleConf, thiscallers); 431 } 432 for (Iterator iter = nodecallers.values().iterator(); iter.hasNext();) { 433 Caller caller = (Caller)iter.next(); 434 if (!thiscallers.containsKey(caller.getModuleRevisionId())) { 435 thiscallers.put(caller.getModuleRevisionId(), caller); 436 } 437 } 438 } 439 440 updateMapOfSet(node._requiredConfs, _requiredConfs); 442 443 updateMapOfSetForKey(node._rootModuleConfs, _rootModuleConfs, rootModuleConf); 445 446 updateMapOfSetForKey(node._dependencyArtifactsIncludes, _dependencyArtifactsIncludes, rootModuleConf); 448 449 updateConfsToFetch(node._fetchedConfigurations); 451 updateConfsToFetch(node._confsToFetch); 452 } 453 454 private void updateMapOfSet(Map from, Map to) { 455 for (Iterator iter = from.keySet().iterator(); iter.hasNext();) { 456 Object key = iter.next(); 457 updateMapOfSetForKey(from, to, key); 458 } 459 } 460 461 private void updateMapOfSetForKey(Map from, Map to, Object key) { 462 Set set = (Set )from.get(key); 463 if (set != null) { 464 Set toupdate = (Set )to.get(key); 465 if (toupdate != null) { 466 toupdate.addAll(set); 467 } else { 468 to.put(key, new HashSet (set)); 469 } 470 } 471 } 472 473 public EvictionData getEvictedData(String rootModuleConf) { 474 cleanEvicted(); 475 return (EvictionData)_evicted.get(rootModuleConf); 476 } 477 public String [] getEvictedConfs() { 478 cleanEvicted(); 479 return (String [])_evicted.keySet().toArray(new String [_evicted.keySet().size()]); 480 } 481 482 487 public Collection getAllEvictingNodes() { 488 Collection allEvictingNodes = null; 489 for (Iterator iter = _evicted.values().iterator(); iter.hasNext();) { 490 EvictionData ed = (EvictionData)iter.next(); 491 Collection selected = ed.getSelected(); 492 if (selected != null) { 493 if (allEvictingNodes == null) { 494 allEvictingNodes = new HashSet (); 495 } 496 allEvictingNodes.addAll(selected); 497 } 498 } 499 return allEvictingNodes; 500 } 501 502 public Collection getAllEvictingConflictManagers() { 503 Collection ret = new HashSet (); 504 for (Iterator iter = _evicted.values().iterator(); iter.hasNext();) { 505 EvictionData ed = (EvictionData)iter.next(); 506 ret.add(ed.getConflictManager()); 507 } 508 return ret; 509 } 510 511 512 public IvyNode getParent() { 513 return _parent; 514 } 515 516 public void setParent(IvyNode parent) { 517 _parent = parent; 518 _root = null; 519 _path = null; 520 } 521 522 public IvyNode getRoot() { 523 if (_root == null) { 524 _root = computeRoot(); 525 } 526 return _root; 527 } 528 529 public Collection getPath() { 530 if (_path == null) { 531 _path = computePath(); 532 } 533 return _path; 534 } 535 536 private Collection computePath() { 537 if (_parent != null) { 538 Collection p = new LinkedHashSet (_parent.getPath()); 539 p.add(this); 540 return p; 541 } else { 542 return Collections.singletonList(this); 543 } 544 } 545 546 private IvyNode computeRoot() { 547 if (isRoot()) { 548 return this; 549 } else if (_parent != null) { 550 return _parent.getRoot(); 551 } else { 552 return null; 553 } 554 } 566 567 public String getParentConf() { 568 return _parentConf; 569 } 570 571 public void setParentConf(String parentConf) { 572 _parentConf = parentConf; 573 } 574 575 576 public boolean hasConfigurationsToLoad() { 577 return !_confsToFetch.isEmpty(); 578 } 579 580 588 public boolean loadData(String conf, boolean shouldBePublic) { 589 boolean loaded = false; 590 if (!isEvicted(_rootModuleConf) && (hasConfigurationsToLoad() || !isRootModuleConfLoaded()) && !hasProblem()) { 591 markRootModuleConfLoaded(); 592 if (_md == null) { 593 DependencyResolver resolver = _data.getIvy().getResolver(getModuleId()); 594 if (resolver == null) { 595 Message.error("no resolver found for "+getModuleId()+": check your configuration"); 596 _problem = new RuntimeException ("no resolver found for "+getModuleId()+": check your configuration"); 597 _data.getReport().addDependency(this); 598 return false; 599 } 600 try { 601 Message.debug("\tusing "+resolver+" to resolve "+getId()); 602 DependencyDescriptor dependencyDescriptor = getDependencyDescriptor(getParent()); 603 _data.getIvy().fireIvyEvent(new StartResolveDependencyEvent(_data.getIvy(), resolver, dependencyDescriptor)); 604 _module = resolver.getDependency(dependencyDescriptor, _data); 605 _data.getIvy().fireIvyEvent(new EndResolveDependencyEvent(_data.getIvy(), resolver, dependencyDescriptor, _module)); 606 if (_module != null) { 607 _data.getIvy().saveResolver(_data.getCache(), _module.getDescriptor(), _module.getResolver().getName()); 608 _data.getIvy().saveArtResolver(_data.getCache(), _module.getDescriptor(), _module.getArtifactResolver().getName()); 609 if (_data.getIvy().logModuleWhenFound()) { 610 Message.info("\tfound "+_module.getId()+" in "+_module.getResolver().getName()); 611 } else { 612 Message.verbose("\tfound "+_module.getId()+" in "+_module.getResolver().getName()); 613 } 614 615 if (_data.getIvy().getVersionMatcher().isDynamic(getId())) { 616 if (_data.getIvy().getVersionMatcher().isDynamic(_module.getId())) { 618 Message.error("impossible to resolve dynamic revision for "+getId()+": check your configuration and make sure revision is part of your pattern"); 619 _problem = new RuntimeException ("impossible to resolve dynamic revision"); 620 _data.getReport().addDependency(this); 621 return false; 622 } 623 IvyNode resolved = _data.getNode(_module.getId()); 624 if (resolved != null) { 625 _md = _module.getDescriptor(); if (!handleConfiguration(loaded, conf, shouldBePublic)) { 629 return false; 630 } 631 632 if (resolved._md == null) { 633 resolved._md = _md; 634 } 635 if (resolved._module == null) { 636 resolved._module = _module; 637 } 638 resolved._downloaded |= _module.isDownloaded(); 639 resolved._searched |= _module.isSearched(); 640 resolved._dds.putAll(_dds); 641 resolved.updateDataFrom(this, _rootModuleConf); 642 resolved.loadData(conf, shouldBePublic); 643 DependencyDescriptor dd = dependencyDescriptor; 644 if (dd != null) { 645 resolved.addDependencyArtifactsIncludes(_rootModuleConf, dd.getDependencyArtifactsIncludes(getParentConf())); 646 } 647 _data.register(getId(), resolved); 649 if (_data.getIvy().logResolvedRevision()) { 650 Message.info("\t["+_module.getId().getRevision()+"] "+getId()); 651 } else { 652 Message.verbose("\t["+_module.getId().getRevision()+"] "+getId()); 653 } 654 655 return true; 656 } 657 } 658 _downloaded = _module.isDownloaded(); 659 _searched = _module.isSearched(); 660 } else { 661 Message.warn("\tmodule not found: "+getId()); 662 resolver.reportFailure(); 663 _problem = new RuntimeException ("not found"); 664 } 665 } catch (Exception e) { 666 _problem = e; 667 } 668 669 if (_module == null) { 671 _data.getReport().addDependency(this); 672 return false; 673 } else { 674 loaded = true; 675 if (_data.getIvy().getVersionMatcher().isDynamic(getId())) { 676 if (_data.getIvy().logResolvedRevision()) { 677 Message.info("\t["+_module.getId().getRevision()+"] "+getId()); 678 } else { 679 Message.verbose("\t["+_module.getId().getRevision()+"] "+getId()); 680 } 681 } 682 _md = _module.getDescriptor(); 683 if (_data.getIvy().getVersionMatcher().isDynamic(getId())) { 686 _data.register(_module.getId(), this); 687 } 688 _confsToFetch.remove("*"); 689 updateConfsToFetch(Arrays.asList(resolveSpecialConfigurations(getRequiredConfigurations(getParent(), getParentConf()), this))); 690 } 691 } else { 692 loaded = true; 693 } 694 } 695 if (hasProblem()) { 696 _data.getReport().addDependency(this); 697 return handleConfiguration(loaded, conf, shouldBePublic) && loaded; 698 } 699 if (!handleConfiguration(loaded, conf, shouldBePublic)) { 700 return false; 701 } 702 DependencyDescriptor dd = getDependencyDescriptor(getParent()); 703 if (dd != null) { 704 addDependencyArtifactsIncludes(_rootModuleConf, dd.getDependencyArtifactsIncludes(getParentConf())); 705 } 706 return loaded; 707 708 } 709 710 private boolean markRootModuleConfLoaded() { 711 return _loadedRootModuleConfs.add(_rootModuleConf); 712 } 713 714 private boolean isRootModuleConfLoaded() { 715 return _loadedRootModuleConfs.contains(_rootModuleConf); 716 } 717 718 private boolean handleConfiguration(boolean loaded, String conf, boolean shouldBePublic) { 719 if (_md != null) { 720 String [] confs = getRealConfs(conf); 721 for (int i = 0; i < confs.length; i++) { 722 Configuration c = _md.getConfiguration(confs[i]); 723 if (c == null) { 724 _confsToFetch.remove(conf); 725 if (!conf.equals(confs[i])) { 726 _problem = new RuntimeException ("configuration(s) not found in "+this+": "+conf+". Missing configuration: "+confs[i]+". It was required from "+getParent()+" "+getParentConf()); 727 } else { 728 _problem = new RuntimeException ("configuration(s) not found in "+this+": "+confs[i]+". It was required from "+getParent()+" "+getParentConf()); 729 } 730 _data.getReport().addDependency(this); 731 return false; 732 } else if (shouldBePublic && !isRoot() && c.getVisibility() != Configuration.Visibility.PUBLIC) { 733 _confsToFetch.remove(conf); 734 _problem = new RuntimeException ("configuration not public in "+this+": "+c+". It was required from "+getParent()+" "+getParentConf()); 735 _data.getReport().addDependency(this); 736 return false; 737 } 738 if (loaded) { 739 _fetchedConfigurations.add(conf); 740 _confsToFetch.removeAll(Arrays.asList(confs)); 741 _confsToFetch.remove(conf); 742 } 743 addRootModuleConfigurations(_rootModuleConf, confs); 744 } 745 } 746 return true; 747 } 748 749 private String getDefaultConf(String conf) { 750 Matcher m = FALLBACK_CONF_PATTERN.matcher(conf); 751 if (m.matches()) { 752 return m.group(2); 753 } else { 754 return conf; 755 } 756 } 757 758 private String getMainConf(String conf) { 759 Matcher m = FALLBACK_CONF_PATTERN.matcher(conf); 760 if (m.matches()) { 761 return m.group(1); 762 } else { 763 return null; 764 } 765 } 766 767 private boolean isRoot() { 768 return _isRoot ; 769 } 770 771 public IvyNode getRealNode() { 772 return getRealNode(false); 773 } 774 775 776 public IvyNode getRealNode(boolean traverse) { 777 IvyNode node = _data.getNode(getId()); 778 if (node != null) { 779 if (traverse) { 780 node.setParent(getParent()); 781 node.setParentConf(getParentConf()); 782 node.setRootModuleConf(getRootModuleConf()); 783 node.setRequestedConf(getRequestedConf()); 784 node._data = _data; 785 } 786 return node; 787 } else { 788 return this; 789 } 790 } 791 792 public Collection getDependencies(String [] confs) { 793 if (_md == null) { 794 throw new IllegalStateException ("impossible to get dependencies when data has not been loaded"); 795 } 796 if (Arrays.asList(confs).contains("*")) { 797 confs = _md.getConfigurationsNames(); 798 } 799 Collection deps = new HashSet (); 800 for (int i = 0; i < confs.length; i++) { 801 deps.addAll(getDependencies(confs[i], false)); 802 } 803 return deps; 804 } 805 806 public Collection getDependencies(String conf, boolean traverse) { 807 if (_md == null) { 808 throw new IllegalStateException ("impossible to get dependencies when data has not been loaded"); 809 } 810 DependencyDescriptor[] dds = _md.getDependencies(); 811 Collection dependencies = new LinkedHashSet (); for (int i = 0; i < dds.length; i++) { 813 DependencyDescriptor dd = dds[i]; 814 String [] dependencyConfigurations = dd.getDependencyConfigurations(conf, getRequestedConf()); 815 if (dependencyConfigurations.length == 0) { 816 continue; 819 } 820 if (isDependencyModuleExcluded(dd.getDependencyRevisionId(), conf)) { 821 Message.verbose("excluding "+dd.getDependencyRevisionId()+" in "+conf); 823 continue; 824 } 825 IvyNode depNode = _data.getNode(dd.getDependencyRevisionId()); 826 if (depNode == null) { 827 depNode = new IvyNode(_data, this, dd); 828 } else { 829 depNode.addDependencyDescriptor(this, dd); 830 if (depNode.hasProblem()) { 831 } 834 835 } 836 Collection confs = Arrays.asList(resolveSpecialConfigurations(dependencyConfigurations, depNode)); 837 depNode.updateConfsToFetch(confs); 838 depNode.setRequiredConfs(this, conf, confs); 839 840 depNode.addCaller(_rootModuleConf, this, conf, dependencyConfigurations, dd); 841 dependencies.add(depNode); 842 if (traverse) { 843 traverse(conf, depNode); 844 } 845 } 846 return dependencies; 847 } 848 849 public void traverse(String conf, IvyNode depNode) { 850 if (getPath().contains(depNode)) { 851 IvyContext.getContext().getCircularDependencyStrategy().handleCircularDependency(toMrids(getPath(), depNode)); 852 } else { 853 depNode.setParent(this); 854 } 855 depNode.setParentConf(conf); 856 depNode.setRootModuleConf(getRootModuleConf()); 857 depNode._data = _data; 858 } 859 860 private ModuleRevisionId[] toMrids(Collection path, IvyNode depNode) { 861 ModuleRevisionId[] ret = new ModuleRevisionId[path.size()+1]; 862 int i=0; 863 for (Iterator iter = path.iterator(); iter.hasNext(); i++) { 864 IvyNode node = (IvyNode) iter.next(); 865 ret[i] = node.getId(); 866 } 867 ret[ret.length-1] = depNode.getId(); 868 return ret; 869 } 870 871 874 public final String getRequestedConf() { 875 return (String ) _requestedConf.get(getRootModuleConf()); 876 } 877 878 public final void setRequestedConf(String requestedConf) { 879 _requestedConf.put(getRootModuleConf(), requestedConf); 880 } 881 882 private void addDependencyDescriptor(IvyNode parent, DependencyDescriptor dd) { 883 _dds.put(parent, dd); 884 } 885 886 private boolean isDependencyModuleExcluded(ModuleRevisionId dependencyRevisionId, String conf) { 887 return doesCallersExclude(getRootModuleConf(), DefaultArtifact.newIvyArtifact(dependencyRevisionId, null)); 888 } 889 890 public ModuleRevisionId getId() { 891 return _id; 892 } 893 894 public void updateConfsToFetch(Collection confs) { 895 _confsToFetch.addAll(confs); 896 _confsToFetch.removeAll(_fetchedConfigurations); 897 } 898 899 public ModuleId getModuleId() { 900 return _id.getModuleId(); 901 } 902 903 906 private String [] resolveSpecialConfigurations(String [] dependencyConfigurations, IvyNode node) { 907 if (dependencyConfigurations.length == 1 908 && dependencyConfigurations[0].startsWith("*") 909 && node != null 910 && node.isLoaded()) { 911 String conf = dependencyConfigurations[0]; 912 if ("*".equals(conf)) { 913 return node.getDescriptor().getPublicConfigurationsNames(); 914 } 915 List exclusions = Arrays.asList(conf.substring(2).split("\\!")); 917 918 List ret = new ArrayList (Arrays.asList(node.getDescriptor().getPublicConfigurationsNames())); 919 ret.removeAll(exclusions); 920 921 return (String [])ret.toArray(new String [ret.size()]); 922 } 923 return dependencyConfigurations; 924 } 925 926 public boolean isLoaded() { 927 return _md != null; 928 } 929 930 public ModuleDescriptor getDescriptor() { 931 return _md; 932 } 933 934 939 public String [] getRequiredConfigurations(IvyNode in, String inConf) { 940 Collection req = (Collection )_requiredConfs.get(new NodeConf(in, inConf)); 941 return req == null?new String [0]:(String [])req.toArray(new String [req.size()]); 942 } 943 944 948 public String [] getRequiredConfigurations() { 949 Collection required = new ArrayList (_confsToFetch.size() + _fetchedConfigurations.size()); 950 required.addAll(_fetchedConfigurations); 951 required.addAll(_confsToFetch); 952 return (String [])required.toArray(new String [required.size()]); 953 } 954 955 private void setRequiredConfs(IvyNode parent, String parentConf, Collection confs) { 956 _requiredConfs.put(new NodeConf(parent, parentConf), new HashSet (confs)); 957 } 958 959 public Configuration getConfiguration(String conf) { 960 if (_md == null) { 961 throw new IllegalStateException ("impossible to get configuration when data has not been loaded"); 962 } 963 String defaultConf = getDefaultConf(conf); 964 conf = getMainConf(conf); 965 Configuration configuration = _md.getConfiguration(conf); 966 if (configuration == null) { 967 configuration = _md.getConfiguration(defaultConf); 968 } 969 return configuration; 970 } 971 972 public ResolvedModuleRevision getModuleRevision() { 973 return _module; 974 } 975 976 977 985 public void addCaller(String rootModuleConf, IvyNode node, String callerConf, String [] dependencyConfs, DependencyDescriptor dd) { 986 ModuleDescriptor md = node.getDescriptor(); 987 ModuleRevisionId mrid = node.getId(); 988 if (mrid.getModuleId().equals(getId().getModuleId())) { 989 throw new IllegalArgumentException ("a module is not authorized to depend on itself: "+getId()); 990 } 991 Map callers = (Map )_callersByRootConf.get(rootModuleConf); 992 if (callers == null) { 993 callers = new HashMap (); 994 _callersByRootConf.put(rootModuleConf, callers); 995 } 996 Caller caller = (Caller)callers.get(mrid); 997 if (caller == null) { 998 caller = new Caller(md, mrid, dd, node.canExclude(rootModuleConf)); 999 callers.put(mrid, caller); 1000 } 1001 caller.addConfiguration(callerConf, dependencyConfs); 1002 1003 IvyNode parent = node.getRealNode(); 1004 for (Iterator iter = parent._allCallers.keySet().iterator(); iter.hasNext();) { 1005 ModuleId mid = (ModuleId) iter.next(); 1006 _allCallers.put(mid, parent); 1007 } 1008 _allCallers.put(mrid.getModuleId(), node); 1009 _isCircular = _allCallers.keySet().contains(getId().getModuleId()); 1010 if (_isCircular) { 1011 IvyContext.getContext().getCircularDependencyStrategy().handleCircularDependency( 1012 toMrids(findPath(getId().getModuleId()), this)); 1013 } 1014 } 1015 1016 1022 private Collection findPath(ModuleId from) { 1023 return findPath(from, this, new LinkedList ()); 1024 } 1025 1026 private Collection findPath(ModuleId from, IvyNode node, List path) { 1027 IvyNode parent = (IvyNode) node._allCallers.get(from); 1028 if (parent == null) { 1029 throw new IllegalArgumentException ("no path from "+from+" to "+getId()+" found"); 1030 } 1031 if (path.contains(parent)) { 1032 path.add(0, parent); 1033 Message.verbose("circular dependency found while looking for the path for another one: was looking for "+from+" as a caller of "+path.get(path.size()-1)); 1034 return path; 1035 } 1036 path.add(0, parent); 1037 if (parent.getId().getModuleId().equals(from)) { 1038 return path; 1039 } 1040 return findPath(from, parent, path); 1041 } 1042 1043 private boolean canExclude(String rootModuleConf) { 1044 DependencyDescriptor dd = getDependencyDescriptor(getParent()); 1045 if (dd != null && dd.canExclude()) { 1046 return true; 1047 } 1048 Caller[] callers = getCallers(rootModuleConf); 1049 for (int i = 0; i < callers.length; i++) { 1050 if (callers[i].canExclude()) { 1051 return true; 1052 } 1053 } 1054 return false; 1055 } 1056 1057 public Caller[] getCallers(String rootModuleConf) { 1058 Map callers = (Map )_callersByRootConf.get(rootModuleConf); 1059 if (callers == null) { 1060 return new Caller[0]; 1061 } 1062 return (Caller[])callers.values().toArray(new Caller[callers.values().size()]); 1063 } 1064 1065 public Caller[] getAllCallers() { 1066 Set all = new HashSet (); 1067 for (Iterator iter = _callersByRootConf.values().iterator(); iter.hasNext();) { 1068 Map callers = (Map )iter.next(); 1069 all.addAll(callers.values()); 1070 } 1071 return (Caller[])all.toArray(new Caller[all.size()]); 1072 } 1073 1074 public String toString() { 1075 return getResolvedId().toString(); 1076 } 1077 1078 public boolean equals(Object obj) { 1079 if (! (obj instanceof IvyNode)) { 1080 return false; 1081 } 1082 IvyNode node = (IvyNode)obj; 1083 return node.getId().equals(getId()); 1084 } 1085 1086 public int hashCode() { 1087 return getId().hashCode(); 1088 } 1089 1090 1096 public String [] getConfigurations(String rootModuleConf) { 1097 Set depConfs = (Set ) _rootModuleConfs.get(rootModuleConf); 1098 if (depConfs == null) { 1099 return new String [0]; 1100 } 1101 return (String []) depConfs.toArray(new String [depConfs.size()]); 1102 } 1103 1104 public void discardConf(String conf) { 1105 discardConf(_rootModuleConf, conf); 1106 } 1107 1108 public void discardConf(String rootModuleConf, String conf) { 1109 Set depConfs = (Set ) _rootModuleConfs.get(rootModuleConf); 1110 if (depConfs == null) { 1111 depConfs = new HashSet (); 1112 _rootModuleConfs.put(rootModuleConf, depConfs); 1113 } 1114 if (_md != null) { 1115 Configuration c = _md.getConfiguration(conf); 1117 if (conf != null) { 1118 String [] exts = c.getExtends(); 1119 for (int i = 0; i < exts.length; i++) { 1120 discardConf(rootModuleConf, exts[i]); } 1122 depConfs.remove(c.getName()); 1123 } else { 1124 Message.warn("unknown configuration in "+getId()+": "+conf); 1125 } 1126 } else { 1127 depConfs.remove(conf); 1128 } 1129 } 1130 1131 private void addRootModuleConfigurations(String rootModuleConf, String [] dependencyConfs) { 1132 Set depConfs = (Set ) _rootModuleConfs.get(rootModuleConf); 1133 if (depConfs == null) { 1134 depConfs = new HashSet (); 1135 _rootModuleConfs.put(rootModuleConf, depConfs); 1136 } 1137 if (_md != null) { 1138 for (int i = 0; i < dependencyConfs.length; i++) { 1140 Configuration conf = _md.getConfiguration(dependencyConfs[i]); 1141 if (conf != null) { 1142 String [] exts = conf.getExtends(); 1143 addRootModuleConfigurations(rootModuleConf, exts); depConfs.add(conf.getName()); 1145 } else { 1146 Message.warn("unknown configuration in "+getId()+": "+dependencyConfs[i]); 1147 } 1148 } 1149 } else { 1150 for (int i = 0; i < dependencyConfs.length; i++) { 1151 depConfs.add(dependencyConfs[i]); 1152 } 1153 } 1154 } 1155 1156 1160 public String [] getRootModuleConfigurations() { 1161 return (String [])_rootModuleConfs.keySet().toArray(new String [_rootModuleConfs.size()]); 1162 } 1163 1164 1169 public Artifact[] getAllArtifacts() { 1170 Set ret = new HashSet (); 1171 for (Iterator it = _rootModuleConfs.keySet().iterator(); it.hasNext();) { 1172 String rootModuleConf = (String )it.next(); 1173 ret.addAll(Arrays.asList(getArtifacts(rootModuleConf))); 1174 } 1175 return (Artifact[])ret.toArray(new Artifact[ret.size()]); 1176 } 1177 1178 1184 public Artifact[] getSelectedArtifacts(Filter artifactFilter) { 1185 Collection ret = new HashSet (); 1186 for (Iterator it = _rootModuleConfs.keySet().iterator(); it.hasNext();) { 1187 String rootModuleConf = (String )it.next(); 1188 if (!isEvicted(rootModuleConf)) { 1189 ret.addAll(Arrays.asList(getArtifacts(rootModuleConf))); 1190 } 1191 } 1192 ret = FilterHelper.filter(ret, artifactFilter); 1193 return (Artifact[])ret.toArray(new Artifact[ret.size()]); 1194 } 1195 1196 1202 public Artifact[] getArtifacts(String rootModuleConf) { 1203 Set confs = (Set ) _rootModuleConfs.get(rootModuleConf); 1206 if (confs == null) { 1207 return new Artifact[0]; 1209 } 1210 1211 Set artifacts = new HashSet (); 1213 Set includes = (Set )_dependencyArtifactsIncludes.get(rootModuleConf); 1215 1216 if (_md.isDefault() && includes != null && !includes.isEmpty()) { 1217 for (Iterator it = includes.iterator(); it.hasNext();) { 1223 DependencyArtifactDescriptor dad = (DependencyArtifactDescriptor)it.next(); 1224 artifacts.add(new MDArtifact(_md, dad.getName(), dad.getType(), dad.getExt(), dad.getUrl(), null)); 1225 } 1226 } else { 1227 if (includes == null || includes.isEmpty()) { 1228 for (Iterator iter = confs.iterator(); iter.hasNext();) { 1230 String conf = (String ) iter.next(); 1231 artifacts.addAll(Arrays.asList(_md.getArtifacts(conf))); 1232 } 1233 } else { 1234 1236 Map allArtifacts = new HashMap (); 1239 for (Iterator iter = confs.iterator(); iter.hasNext();) { 1240 String conf = (String ) iter.next(); 1241 Artifact[] arts = _md.getArtifacts(conf); 1242 for (int i = 0; i < arts.length; i++) { 1243 allArtifacts.put(arts[i].getId().getArtifactId(), arts[i]); 1244 } 1245 } 1246 1247 for (Iterator it = includes.iterator(); it.hasNext();) { 1249 DependencyArtifactDescriptor dad = (DependencyArtifactDescriptor)it.next(); 1250 Collection arts = findArtifactsMatching(dad, allArtifacts); 1251 if (arts.isEmpty()) { 1252 Message.error("a required artifact is not listed by module descriptor: "+dad.getId()); 1253 it.remove(); 1255 } else { 1256 Message.debug(this+" in "+rootModuleConf+": including "+arts); 1257 artifacts.addAll(arts); 1258 } 1259 } 1260 } 1261 } 1262 1263 for (Iterator iter = artifacts.iterator(); iter.hasNext();) { 1265 Artifact artifact = (Artifact)iter.next(); 1266 boolean excluded = doesCallersExclude(rootModuleConf, artifact); 1267 if (excluded) { 1268 Message.debug(this+" in "+rootModuleConf+": excluding "+artifact); 1269 iter.remove(); 1270 } 1271 } 1272 return (Artifact[]) artifacts.toArray(new Artifact[artifacts.size()]); 1273 } 1274 1275 1281 private boolean doesCallersExclude(String rootModuleConf, Artifact artifact) { 1282 return doesCallersExclude(rootModuleConf, artifact, new Stack ()); 1283 } 1284 private boolean doesCallersExclude(String rootModuleConf, Artifact artifact, Stack callersStack) { 1285 if (callersStack.contains(getId())) { 1286 return false; 1287 } 1288 callersStack.push(getId()); 1289 try { 1290 Caller[] callers = getCallers(rootModuleConf); 1291 if (callers.length == 0) { 1292 return false; 1293 } 1294 Collection callersNodes = new ArrayList (); 1295 for (int i = 0; i < callers.length; i++) { 1296 if (!callers[i].canExclude()) { 1297 return false; 1298 } 1299 ModuleDescriptor md = callers[i].getModuleDescriptor(); 1300 if (!doesExclude(md, rootModuleConf, callers[i].getCallerConfigurations(), this, callers[i].getDependencyDescriptor(), artifact, callersStack)) { 1301 return false; 1302 } 1303 } 1304 return true; 1305 } finally { 1306 callersStack.pop(); 1307 } 1308 } 1309 1310 private boolean doesExclude(ModuleDescriptor md, String rootModuleConf, String [] moduleConfs, IvyNode dependency, DependencyDescriptor dd, Artifact artifact, Stack callersStack) { 1311 if (dd != null) { 1313 if (dd.doesExclude(moduleConfs, artifact.getId().getArtifactId())) { 1314 return true; 1315 } 1316 } 1317 IvyNode c = _data.getNode(md.getModuleRevisionId()); 1319 if (c != null) { 1320 return c.doesCallersExclude(rootModuleConf, artifact, callersStack); 1321 } else { 1322 return false; 1323 } 1324 } 1325 1326 private static DependencyDescriptor getDependencyDescriptor(ModuleDescriptor md, IvyNode dependency) { 1327 if (md != null) { 1328 DependencyDescriptor[] dds = md.getDependencies(); 1329 for (int i = 0; i < dds.length; i++) { 1330 if (dds[i].getDependencyId().equals(dependency.getModuleId())) { 1331 return dds[i]; 1332 } 1333 } 1334 } 1335 return null; 1336 } 1337 1338 private static Collection findArtifactsMatching(DependencyArtifactDescriptor dad, Map allArtifacts) { 1339 Collection ret = new ArrayList (); 1340 for (Iterator iter = allArtifacts.keySet().iterator(); iter.hasNext();) { 1341 ArtifactId aid = (ArtifactId)iter.next(); 1342 if (MatcherHelper.matches(dad.getMatcher(), dad.getId(), aid)) { 1343 ret.add(allArtifacts.get(aid)); 1344 } 1345 } 1346 return ret; 1347 } 1348 1349 private void addDependencyArtifactsIncludes(String rootModuleConf, DependencyArtifactDescriptor[] dependencyArtifacts) { 1350 addDependencyArtifacts(rootModuleConf, dependencyArtifacts, _dependencyArtifactsIncludes); 1351 } 1352 1353 private void addDependencyArtifacts(String rootModuleConf, DependencyArtifactDescriptor[] dependencyArtifacts, Map artifactsMap) { 1354 Set depArtifacts = (Set ) artifactsMap.get(rootModuleConf); 1355 if (depArtifacts == null) { 1356 depArtifacts = new HashSet (); 1357 artifactsMap.put(rootModuleConf, depArtifacts); 1358 } 1359 depArtifacts.addAll(Arrays.asList(dependencyArtifacts)); 1360 } 1361 1362 public long getPublication() { 1363 if (_module != null) { 1364 return _module.getPublicationDate().getTime(); 1365 } 1366 return 0; 1367 } 1368 1369 public DependencyDescriptor getDependencyDescriptor(IvyNode parent) { 1370 return (DependencyDescriptor)_dds.get(parent); 1371 } 1372 1373 public boolean hasProblem() { 1374 return _problem != null; 1375 } 1376 1377 public ModuleRevisionId getResolvedId() { 1378 if (_md != null && _md.getResolvedModuleRevisionId().getRevision() != null) { 1379 return _md.getResolvedModuleRevisionId(); 1380 } else if (_module != null) { 1381 return _module.getId(); 1382 } else { 1383 return getId(); 1384 } 1385 } 1386 1387 public Exception getProblem() { 1388 return _problem; 1389 } 1390 1391 public boolean isDownloaded() { 1392 return _downloaded; 1393 } 1394 1395 public boolean isSearched() { 1396 return _searched; 1397 } 1398 1399 public String getRootModuleConf() { 1400 return _rootModuleConf; 1401 } 1402 1403 1404 public void setRootModuleConf(String rootModuleConf) { 1405 if (_rootModuleConf != null && !_rootModuleConf.equals(rootModuleConf)) { 1406 _confsToFetch.clear(); } 1408 if (rootModuleConf != null && rootModuleConf.equals(_rootModuleConf)) { 1409 _selectedDeps.put(new ModuleIdConf(_id.getModuleId(), rootModuleConf), Collections.singleton(this)); 1410 } 1411 _rootModuleConf = rootModuleConf; 1412 } 1413 1414 public String [] getConfsToFetch() { 1415 return (String [])_confsToFetch.toArray(new String [_confsToFetch.size()]); 1416 } 1417 1418 1422 public boolean isCircular() { 1423 return _isCircular; 1424 } 1425 1426 public boolean isFetched(String conf) { 1427 return _fetchedConfigurations.contains(conf); 1428 } 1429 1430 1440 public EvictionData getEvictionDataInRoot(String rootModuleConf, IvyNode parent) { 1441 IvyNode root = parent.getRoot(); 1442 Collection selectedNodes = root.getResolvedNodes(getModuleId(), rootModuleConf); 1443 for (Iterator iter = selectedNodes.iterator(); iter.hasNext();) { 1444 IvyNode node = (IvyNode)iter.next(); 1445 if (node.getResolvedId().equals(getResolvedId())) { 1446 return null; 1448 } 1449 } 1450 return new EvictionData(rootModuleConf, parent, root.getConflictManager(getModuleId()), selectedNodes); 1452 } 1453 1454 public static IvyNode getRoot(IvyNode parent) { 1455 IvyNode root = parent; 1456 Collection path = new HashSet (); 1457 path.add(root); 1458 while (root.getParent() != null && !root.isRoot()) { 1459 if (path.contains(root.getParent())) { 1460 return root; 1461 } 1462 root = root.getParent(); 1463 path.add(root); 1464 } 1465 return root; 1466 } 1467 1468 public IvyNode findNode(ModuleRevisionId mrid) { 1469 return _data.getNode(mrid); 1470 } 1471 1472 public String [] getRealConfs(String conf) { 1473 if (_md == null) { 1474 return new String [] {conf}; 1475 } 1476 String defaultConf = getDefaultConf(conf); 1477 conf = getMainConf(conf); 1478 if (_md.getConfiguration(conf) == null) { 1479 if ("".equals(defaultConf)) { 1480 return new String [0]; 1481 } 1482 conf = defaultConf; 1483 } 1484 if (conf.startsWith("*")) { 1485 return resolveSpecialConfigurations(new String [] {conf}, this); 1486 } else if (conf.indexOf(',') != -1) { 1487 String [] confs = conf.split(","); 1488 for (int i = 0; i < confs.length; i++) { 1489 confs[i] = confs[i].trim(); 1490 } 1491 } 1492 return new String [] {conf}; 1493 1494 } 1495 1496 1503 protected boolean isTransitive() { 1504 return (_data.isTransitive() && 1505 getDependencyDescriptor(getParent()).isTransitive() && 1506 isParentConfTransitive() ); 1507 } 1508 1509 1514 protected boolean isParentConfTransitive() { 1515 String conf = getParent().getRequestedConf(); 1516 if (conf==null) { 1517 return true; 1518 } 1519 Configuration parentConf = getParent().getConfiguration(conf); 1520 return parentConf.isTransitive(); 1521 1522 } 1523 1524 public ResolveData getResolveData() { 1525 return _data; 1526 } 1527 1528} 1529 | Popular Tags |