1 11 12 package org.eclipse.core.internal.model; 13 14 import java.util.*; 15 import org.eclipse.core.internal.runtime.InternalPlatform; 16 import org.eclipse.core.internal.runtime.Messages; 17 import org.eclipse.core.runtime.*; 18 import org.eclipse.core.runtime.model.*; 19 import org.eclipse.osgi.util.NLS; 20 21 public class RegistryResolver { 22 23 private Map idmap; 24 private PluginRegistryModel reg; 25 private MultiStatus status; 26 private boolean trimPlugins = true; 27 private boolean crossLink = true; 28 29 private boolean DEBUG_RESOLVE = false; 30 private static final String OPTION_DEBUG_RESOLVE = "org.eclipse.core.runtime/registry/debug/resolve"; 32 private class Constraint { 38 private PluginDescriptorModel parent; 39 private PluginPrerequisiteModel prq; 40 private PluginVersionIdentifier ver; 41 private byte type = PluginPrerequisiteModel.PREREQ_MATCH_UNSPECIFIED; 42 private ConstraintsEntry cEntry = null; 43 44 private Constraint(PluginDescriptorModel parent, PluginPrerequisiteModel prq) { 45 this.parent = parent; 46 this.prq = prq; 47 if (prq != null) { 48 ver = RegistryResolver.this.getVersionIdentifier(prq); 49 type = prq.getMatchByte(); 50 if ((ver != null) && (type == PluginPrerequisiteModel.PREREQ_MATCH_UNSPECIFIED)) 51 type = PluginPrerequisiteModel.PREREQ_MATCH_COMPATIBLE; 52 } 53 } 54 55 private int getMatchType() { 56 return type; 57 } 58 59 private ConstraintsEntry getConstraintsEntry() { 60 return cEntry; 61 } 62 63 private void setConstraintsEntry(ConstraintsEntry entry) { 64 cEntry = entry; 65 } 66 67 private PluginDescriptorModel getParent() { 68 return parent; 69 } 70 71 private PluginPrerequisiteModel getPrerequisite() { 72 return prq; 73 } 74 75 private PluginVersionIdentifier getVersionIdentifier() { 76 return ver; 77 } 78 79 public String toString() { 80 if (prq == null) 81 return "(null)"; String s = parent.toString() + "->" + prq.getPlugin(); switch (prq.getMatchByte()) { 84 case PluginPrerequisiteModel.PREREQ_MATCH_UNSPECIFIED : 85 s += "(any)"; break; 87 case PluginPrerequisiteModel.PREREQ_MATCH_PERFECT : 88 s += IModel.PLUGIN_REQUIRES_MATCH_PERFECT; 89 break; 90 case PluginPrerequisiteModel.PREREQ_MATCH_EQUIVALENT : 91 s += IModel.PLUGIN_REQUIRES_MATCH_EQUIVALENT; 92 break; 93 case PluginPrerequisiteModel.PREREQ_MATCH_COMPATIBLE : 94 s += IModel.PLUGIN_REQUIRES_MATCH_COMPATIBLE; 95 break; 96 case PluginPrerequisiteModel.PREREQ_MATCH_GREATER_OR_EQUAL : 97 s += IModel.PLUGIN_REQUIRES_MATCH_GREATER_OR_EQUAL; 98 break; 99 } 100 return s; 101 } 102 } 103 104 private class ConstraintsEntry { 114 private IndexEntry parent; 115 private List constraintList = new LinkedList(); 116 private PluginDescriptorModel lastResolved = null; 122 private boolean isResolved = false; 123 private PluginDescriptorModel bestMatch = null; 124 private boolean bestMatchEnabled = false; 125 126 private ConstraintsEntry(IndexEntry parent) { 127 this.parent = parent; 130 } 131 132 private int constraintCount() { 133 return constraintList.size(); 136 } 137 138 private PluginDescriptorModel addConstraint(Constraint c) { 139 constraintList.add(c); 147 c.setConstraintsEntry(this); 148 List constrained = getMatchingDescriptors(); 151 if (constrained.size() <= 0) { 152 constraintList.remove(c); 154 c.setConstraintsEntry(null); 155 return null; 156 } else { 157 PluginDescriptorModel match = (PluginDescriptorModel) constrained.get(0); 160 if (!match.equals(lastResolved)) { 161 lastResolved = match; 162 isResolved = false; 163 } 164 return match; 165 } 166 } 167 168 private void removeConstraint(Constraint c) { 169 if (DEBUG_RESOLVE) 170 debug("removing constraint " + c.toString()); constraintList.remove(c); 172 c.setConstraintsEntry(null); 173 lastResolved = null; 174 isResolved = false; 175 } 176 177 private void removeConstraintFor(PluginPrerequisiteModel prereq) { 178 List remove = new ArrayList(); 179 for (Iterator list = constraintList.iterator(); list.hasNext();) { 180 Constraint c = (Constraint) list.next(); 181 if (c.getPrerequisite() == prereq) 182 remove.add(c); 183 } 184 for (Iterator list = remove.iterator(); list.hasNext();) 185 removeConstraint((Constraint) list.next()); 186 } 187 188 private PluginDescriptorModel getMatchingDescriptor() { 189 List constrained = getMatchingDescriptors(); 193 if (constrained.size() <= 0) 194 return null; 195 else 196 return (PluginDescriptorModel) constrained.get(0); 197 } 198 199 private List getMatchingDescriptors() { 200 204 List constrained = new LinkedList(); 206 207 for (Iterator list = parent.versions().iterator(); list.hasNext();) { 208 PluginDescriptorModel pd = (PluginDescriptorModel) list.next(); 212 if (pd.getEnabled()) 213 constrained.add(pd); 214 } 215 218 for (Iterator list = constraintList.iterator(); list.hasNext();) { 219 223 Constraint c = (Constraint) list.next(); 225 if (c.getMatchType() == PluginPrerequisiteModel.PREREQ_MATCH_UNSPECIFIED) 226 continue; 227 for (Iterator list2 = parent.versions().iterator(); list2.hasNext();) { 228 PluginDescriptorModel pd = (PluginDescriptorModel) list2.next(); 229 if (!pd.getEnabled()) 230 continue; 232 switch (c.getMatchType()) { 233 case PluginPrerequisiteModel.PREREQ_MATCH_PERFECT : 234 if (!getVersionIdentifier(pd).isPerfect(c.getVersionIdentifier())) 235 constrained.remove(pd); 236 break; 237 case PluginPrerequisiteModel.PREREQ_MATCH_EQUIVALENT : 238 if (!getVersionIdentifier(pd).isEquivalentTo(c.getVersionIdentifier())) 239 constrained.remove(pd); 240 break; 241 case PluginPrerequisiteModel.PREREQ_MATCH_COMPATIBLE : 242 if (!getVersionIdentifier(pd).isCompatibleWith(c.getVersionIdentifier())) 243 constrained.remove(pd); 244 break; 245 case PluginPrerequisiteModel.PREREQ_MATCH_GREATER_OR_EQUAL : 246 if (!getVersionIdentifier(pd).isGreaterOrEqualTo(c.getVersionIdentifier())) 247 constrained.remove(pd); 248 break; 249 } 250 } 251 } 252 253 256 return constrained; 257 } 258 259 private void preresolve(List roots) { 260 266 if (constraintList.size() <= 0) { 267 if (roots.contains(parent.getId())) { 270 bestMatch = (PluginDescriptorModel) parent.versions().get(0); 271 if (bestMatch == null) { 272 if (DEBUG_RESOLVE) 273 debug("*ERROR* no resolved descriptor for " + parent.getId()); } else 275 bestMatchEnabled = bestMatch.getEnabled(); 276 } 277 } else { 278 bestMatch = getMatchingDescriptor(); 283 if (bestMatch == null) { 284 if (DEBUG_RESOLVE) 285 debug("*ERROR* no resolved descriptor for " + parent.getId()); } else 287 bestMatchEnabled = true; 288 } 289 } 290 291 private void resolve() { 292 if (bestMatch != null) { 299 bestMatch.setEnabled(bestMatchEnabled); 305 if (bestMatchEnabled) { 306 if (DEBUG_RESOLVE) 307 debug("configured " + bestMatch.toString()); if (constraintList.size() > 0) { 309 for (int i = 0; i < constraintList.size(); i++) { 310 PluginPrerequisiteModel prq = (PluginPrerequisiteModel) ((Constraint) constraintList.get(i)).getPrerequisite(); 313 prq.setResolvedVersion(getVersionIdentifier(bestMatch).toString()); 314 } 315 } 316 } 317 } 318 } 319 320 private boolean isResolved() { 321 return this.isResolved; 322 } 323 324 private void isResolved(boolean isResolved) { 325 this.isResolved = isResolved; 326 } 327 } 328 329 private class IndexEntry { 338 private String id; 339 private List verList = new LinkedList(); 340 private List concurrentList = new ArrayList(); 341 342 private IndexEntry(String id) { 343 this.id = id; 344 concurrentList.add(new ConstraintsEntry(this)); 346 } 347 348 private String getId() { 349 return id; 350 } 351 352 private ConstraintsEntry getConstraintsEntryFor(Constraint c) { 353 ConstraintsEntry ce = c.getConstraintsEntry(); 356 if (ce != null) 357 return ce; 358 ce = (ConstraintsEntry) concurrentList.get(0); 359 if (c.getPrerequisite() == null) 360 c.setConstraintsEntry(ce); 361 return ce; 362 } 363 364 private PluginDescriptorModel addConstraint(Constraint c) { 365 int concurrentCount = concurrentList.size(); 366 367 for (Iterator list = concurrentList.iterator(); list.hasNext();) { 369 ConstraintsEntry cie = (ConstraintsEntry) list.next(); 370 PluginDescriptorModel pd = cie.addConstraint(c); 371 if (pd != null) { 375 376 if (concurrentCount <= 1) 378 return pd; 379 380 if (allowConcurrencyFor(pd)) 382 return pd; 383 else { 384 cie.removeConstraint(c); return null; 386 } 387 } 388 } 389 390 398 ConstraintsEntry cie; 400 PluginDescriptorModel pd; 401 402 if (concurrentList.size() == 1) { 403 cie = (ConstraintsEntry) concurrentList.get(0); 405 pd = cie.getMatchingDescriptor(); 406 if (!allowConcurrencyFor(pd)) 407 return null; 408 } 409 410 cie = new ConstraintsEntry(this); 411 pd = cie.addConstraint(c); 412 if (pd == null) { 413 cie.removeConstraint(c); return null; 415 } 416 if (!allowConcurrencyFor(pd)) { 417 cie.removeConstraint(c); return null; 419 } 420 if (DEBUG_RESOLVE) 421 debug("creating new constraints list in " + id + " for " + c.toString()); concurrentList.add(cie); 423 return pd; 424 } 425 426 private boolean allowConcurrencyFor(PluginDescriptorModel pd) { 427 if (pd == null) 428 return false; 429 if (pd.getDeclaredExtensions() != null && pd.getDeclaredExtensions().length > 0) 430 return false; 431 if (pd.getDeclaredExtensionPoints() != null && pd.getDeclaredExtensionPoints().length > 0) 432 return false; 433 return true; 434 } 435 436 private void removeConstraintFor(PluginPrerequisiteModel prereq) { 437 for (Iterator list = concurrentList.iterator(); list.hasNext();) 438 ((ConstraintsEntry) list.next()).removeConstraintFor(prereq); 439 } 440 441 private PluginDescriptorModel getMatchingDescriptorFor(Constraint c) { 442 ConstraintsEntry cie = getConstraintsEntryFor(c); 443 return cie.getMatchingDescriptor(); 444 } 445 446 private void disableAllDescriptors() { 447 for (Iterator list = verList.iterator(); list.hasNext();) { 448 PluginDescriptorModel pd = (PluginDescriptorModel) list.next(); 449 pd.setEnabled(false); 450 } 451 } 452 453 private void resolveDependencies(List roots) { 454 for (Iterator list = concurrentList.iterator(); list.hasNext();) 458 ((ConstraintsEntry) list.next()).preresolve(roots); 459 disableAllDescriptors(); 461 for (Iterator list = concurrentList.iterator(); list.hasNext();) 465 ((ConstraintsEntry) list.next()).resolve(); 466 } 467 468 471 private boolean isRoot() { 472 if (concurrentList.size() != 1) 473 return false; 474 ConstraintsEntry constraintsEntry = (ConstraintsEntry) concurrentList.get(0); 475 return constraintsEntry.constraintCount() == 0; 476 } 477 478 private List versions() { 479 return verList; 480 } 481 482 private boolean isResolvedFor(Constraint c) { 483 ConstraintsEntry cie = getConstraintsEntryFor(c); 484 return cie.isResolved(); 485 } 486 487 private void isResolvedFor(Constraint c, boolean value) { 488 ConstraintsEntry cie = getConstraintsEntryFor(c); 489 cie.isResolved(value); 490 } 491 492 } 493 494 private class Cookie { 496 private boolean ok = true; 497 private List changes = new ArrayList(); 499 private Cookie() { 500 } 501 502 private boolean addChange(Constraint c) { 503 PluginPrerequisiteModel prereq = c.getPrerequisite(); 507 for (Iterator list = changes.iterator(); list.hasNext();) 508 if (prereq == ((Constraint) list.next()).getPrerequisite()) 509 return false; 511 changes.add(c); 512 return true; 513 } 514 515 private List getChanges() { 516 return changes; 517 } 518 519 private boolean isOk() { 520 return ok; 521 } 522 523 private void isOk(boolean value) { 524 ok = value; 525 } 526 } 527 528 public RegistryResolver() { 529 String debug = Platform.getDebugOption(OPTION_DEBUG_RESOLVE); 530 DEBUG_RESOLVE = debug == null ? false : (debug.equalsIgnoreCase("true") ? true : false); } 532 533 private void add(PluginDescriptorModel pd) { 534 535 String key = pd.getId(); 536 List verList; 537 IndexEntry ix = (IndexEntry) idmap.get(key); 538 539 if (ix == null) { 541 ix = new IndexEntry(key); 542 idmap.put(key, ix); 543 } 544 545 verList = ix.versions(); 547 int i = 0; 548 for (i = 0; i < verList.size(); i++) { 549 PluginDescriptorModel element = (PluginDescriptorModel) verList.get(i); 550 if (getVersionIdentifier(pd).equals(getVersionIdentifier(element))) 551 return; if (getVersionIdentifier(pd).isGreaterThan(getVersionIdentifier(element))) 553 break; 554 } 555 verList.add(i, pd); 556 } 557 558 private void addExtensions(ExtensionModel[] extensions, PluginDescriptorModel plugin) { 559 int extLength = extensions.length; 561 for (int i = 0; i < extLength; i++) { 562 extensions[i].setParentPluginDescriptor(plugin); 563 } 564 ExtensionModel[] list = plugin.getDeclaredExtensions(); 565 int listLength = (list == null ? 0 : list.length); 566 ExtensionModel[] result = null; 567 if (list == null) 568 result = new ExtensionModel[extLength]; 569 else { 570 result = new ExtensionModel[list.length + extLength]; 571 System.arraycopy(list, 0, result, 0, list.length); 572 } 573 System.arraycopy(extensions, 0, result, listLength, extLength); 574 plugin.setDeclaredExtensions(result); 575 } 576 577 private void addExtensionPoints(ExtensionPointModel[] extensionPoints, PluginDescriptorModel plugin) { 578 int extPtLength = extensionPoints.length; 580 for (int i = 0; i < extPtLength; i++) { 581 extensionPoints[i].setParentPluginDescriptor(plugin); 582 } 583 ExtensionPointModel[] list = plugin.getDeclaredExtensionPoints(); 584 int listLength = (list == null ? 0 : list.length); 585 ExtensionPointModel[] result = null; 586 if (list == null) 587 result = new ExtensionPointModel[extPtLength]; 588 else { 589 result = new ExtensionPointModel[list.length + extPtLength]; 590 System.arraycopy(list, 0, result, 0, list.length); 591 } 592 System.arraycopy(extensionPoints, 0, result, listLength, extPtLength); 593 plugin.setDeclaredExtensionPoints(result); 594 } 595 596 private void addLibraries(LibraryModel[] libraries, PluginDescriptorModel plugin) { 597 int libLength = libraries.length; 599 LibraryModel[] list = plugin.getRuntime(); 600 LibraryModel[] result = null; 601 int listLength = (list == null ? 0 : list.length); 602 if (list == null) 603 result = new LibraryModel[libLength]; 604 else { 605 result = new LibraryModel[list.length + libLength]; 606 System.arraycopy(list, 0, result, 0, list.length); 607 } 608 System.arraycopy(libraries, 0, result, listLength, libLength); 609 plugin.setRuntime(result); 610 } 611 612 private void addPrerequisites(PluginPrerequisiteModel[] prerequisites, PluginDescriptorModel plugin) { 613 int reqLength = prerequisites.length; 615 PluginPrerequisiteModel[] list = plugin.getRequires(); 616 PluginPrerequisiteModel[] result = null; 617 int listLength = (list == null ? 0 : list.length); 618 if (list == null) 619 result = new PluginPrerequisiteModel[reqLength]; 620 else { 621 result = new PluginPrerequisiteModel[list.length + reqLength]; 622 System.arraycopy(list, 0, result, 0, list.length); 623 } 624 System.arraycopy(prerequisites, 0, result, listLength, reqLength); 625 plugin.setRequires(result); 626 } 627 628 private void debug(String s) { 629 System.out.println("Registry Resolve: " + s); } 631 632 private void error(String message) { 633 Status error = new Status(IStatus.WARNING, Platform.PI_RUNTIME, Platform.PARSE_PROBLEM, message, null); 634 status.add(error); 635 if (InternalPlatform.DEBUG && DEBUG_RESOLVE) 636 System.out.println(error.toString()); 637 } 638 639 private void information(String message) { 640 if (InternalPlatform.DEBUG && DEBUG_RESOLVE) 641 System.out.println(message); 642 } 643 644 public IExtensionPoint getExtensionPoint(PluginDescriptorModel plugin, String extensionPointId) { 645 if (extensionPointId == null) 646 return null; 647 ExtensionPointModel[] list = plugin.getDeclaredExtensionPoints(); 648 if (list == null) 649 return null; 650 for (int i = 0; i < list.length; i++) { 651 if (extensionPointId.equals(list[i].getId())) 652 return (IExtensionPoint) list[i]; 653 } 654 return null; 655 } 656 657 private PluginVersionIdentifier getVersionIdentifier(PluginModel model) { 658 try { 659 return new PluginVersionIdentifier(model.getVersion()); 660 } catch (RuntimeException e) { 661 if (this.DEBUG_RESOLVE) 663 e.printStackTrace(System.out); 665 return new PluginVersionIdentifier(0, 0, 0); 670 } 671 } 672 673 private PluginVersionIdentifier getVersionIdentifier(PluginPrerequisiteModel prereq) { 674 String version = prereq.getVersion(); 675 return version == null ? null : new PluginVersionIdentifier(version); 676 } 677 678 private boolean fragmentHasPrerequisites(PluginFragmentModel fragment) { 679 PluginPrerequisiteModel[] requires = fragment.getRequires(); 680 if (requires == null || requires.length == 0) 681 return true; 682 for (int i = 0; i < requires.length; i++) { 683 if (idmap.get(requires[i].getPlugin()) == null) { 688 error(NLS.bind(Messages.parse_badPrereqOnFrag, fragment.getName(), requires[i].getPlugin())); 690 return false; 691 } 692 } 693 return true; 694 } 695 696 private void linkFragments() { 697 700 PluginFragmentModel[] fragments = reg.getFragments(); 701 for (int i = 0; i < fragments.length; i++) { 702 PluginFragmentModel fragment = fragments[i]; 703 if (!requiredFragment(fragment)) { 704 String id, name; 707 if ((id = fragment.getId()) != null) 708 error(NLS.bind(Messages.parse_fragmentMissingAttr, id)); 709 else if ((name = fragment.getName()) != null) 710 error(NLS.bind(Messages.parse_fragmentMissingAttr, name)); 711 else 712 error(Messages.parse_fragmentMissingIdName); 713 continue; 714 } 715 if (!fragmentHasPrerequisites(fragment)) { 716 continue; 719 } 720 721 PluginDescriptorModel plugin = null; 724 IndexEntry ix = (IndexEntry) idmap.get(fragment.getPluginId()); 725 byte matchType = fragment.getMatch(); 726 if (ix != null) { 727 for (Iterator list = ix.versions().iterator(); list.hasNext() && plugin == null;) { 728 PluginDescriptorModel pd = (PluginDescriptorModel) list.next(); 729 if (pd.getEnabled()) { 730 switch (matchType) { 732 case PluginFragmentModel.FRAGMENT_MATCH_PERFECT : 733 if (getVersionIdentifier(pd).isPerfect(new PluginVersionIdentifier(fragment.getPluginVersion()))) 734 plugin = pd; 735 break; 736 case PluginFragmentModel.FRAGMENT_MATCH_EQUIVALENT : 737 if (getVersionIdentifier(pd).isEquivalentTo(new PluginVersionIdentifier(fragment.getPluginVersion()))) 738 plugin = pd; 739 break; 740 case PluginFragmentModel.FRAGMENT_MATCH_COMPATIBLE : 741 case PluginFragmentModel.FRAGMENT_MATCH_UNSPECIFIED : 742 if (getVersionIdentifier(pd).isCompatibleWith(new PluginVersionIdentifier(fragment.getPluginVersion()))) 743 plugin = pd; 744 break; 745 case PluginFragmentModel.FRAGMENT_MATCH_GREATER_OR_EQUAL : 746 if (getVersionIdentifier(pd).isGreaterOrEqualTo(new PluginVersionIdentifier(fragment.getPluginVersion()))) 747 plugin = pd; 748 break; 749 } 750 } 751 } 752 } 753 754 if (plugin == null) { 755 error(NLS.bind(Messages.parse_missingFragmentPd, fragment.getPluginId(), fragment.getId())); 757 continue; 758 } 759 760 PluginFragmentModel[] list = plugin.getFragments(); 762 PluginFragmentModel[] newList; 763 if (list == null) { 764 newList = new PluginFragmentModel[1]; 765 newList[0] = fragment; 766 } else { 767 newList = new PluginFragmentModel[list.length + 1]; 768 System.arraycopy(list, 0, newList, 0, list.length); 769 newList[list.length] = fragment; 770 } 771 plugin.setFragments(newList); 772 } 773 } 774 775 private void removeConstraintFor(PluginPrerequisiteModel prereq) { 776 777 String id = prereq.getPlugin(); 778 IndexEntry ix = (IndexEntry) idmap.get(id); 779 if (ix == null) { 780 if (DEBUG_RESOLVE) 781 debug("unable to locate index entry for " + id); return; 783 } 784 ix.removeConstraintFor(prereq); 785 } 786 787 private void resolve() { 788 789 PluginDescriptorModel[] pluginList = reg.getPlugins(); 792 idmap = new HashMap(); 793 for (int i = 0; i < pluginList.length; i++) { 794 if (!requiredPluginDescriptor(pluginList[i])) { 799 pluginList[i].setEnabled(false); 800 String id, name; 801 if ((id = pluginList[i].getId()) != null) 802 error(NLS.bind(Messages.parse_pluginMissingAttr, id)); 803 else if ((name = pluginList[i].getName()) != null) 804 error(NLS.bind(Messages.parse_pluginMissingAttr, name)); 805 else 806 error(Messages.parse_pluginMissingIdName); 807 continue; 808 } 809 add(pluginList[i]); 810 } 811 linkFragments(); 815 for (int i = 0; i < pluginList.length; i++) { 819 if (pluginList[i].getFragments() != null) { 820 resolvePluginFragments(pluginList[i]); 823 } 824 } 825 826 List roots = resolveRootDescriptors(); 828 829 if (roots.size() == 0) { 830 PluginDescriptorModel[] plugins = reg.getPlugins(); 835 for (int i = 0; i < plugins.length; i++) { 836 plugins[i].setEnabled(false); 837 } 838 resolvePluginRegistry(); 839 idmap = null; 840 reg = null; 841 error(Messages.plugin_unableToResolve); 842 return; 843 } 844 845 849 for (Set orphans, rootsSet = new HashSet(roots); !rootsSet.isEmpty(); rootsSet = orphans) { 852 orphans = new HashSet(); 853 for (Iterator rootsIter = rootsSet.iterator(); rootsIter.hasNext();) { 855 String rootID = (String ) rootsIter.next(); 856 resolveNode(rootID, null, null, null, orphans); 857 } 861 for (Iterator orphansIter = orphans.iterator(); orphansIter.hasNext();) { 863 IndexEntry orphan = (IndexEntry) idmap.get(orphansIter.next()); 864 if (orphan.isRoot()) { 871 if (DEBUG_RESOLVE) 872 debug("orphan " + orphan.getId()); roots.add(orphan.getId()); 874 } else 875 orphansIter.remove(); 876 } 877 } 878 879 Iterator plugins = idmap.entrySet().iterator(); 881 while (plugins.hasNext()) { 882 IndexEntry ix = (IndexEntry) ((Map.Entry) plugins.next()).getValue(); 883 ix.resolveDependencies(roots); 887 } 888 889 resolvePluginRegistry(); 892 893 idmap = null; 895 reg = null; 896 } 897 898 public IStatus resolve(PluginRegistryModel registry) { 899 903 status = new MultiStatus(Platform.PI_RUNTIME, IStatus.OK, "", null); 905 if (registry.isResolved()) 906 return status; 908 909 reg = registry; 910 resolve(); 911 registry.markResolved(); 912 return status; 913 } 914 915 private void resolveExtension(ExtensionModel ext) { 916 917 String target = ext.getExtensionPoint(); 918 int ix = target.lastIndexOf("."); String pluginId = target.substring(0, ix); 920 String extPtId = target.substring(ix + 1); 921 String message; 922 923 PluginDescriptorModel plugin = (PluginDescriptorModel) reg.getPlugin(pluginId); 924 if (plugin == null) { 925 message = NLS.bind(Messages.parse_extPointUnknown, target, ext.getParentPluginDescriptor().getId()); 926 error(message); 927 return; 928 } 929 if (!plugin.getEnabled()) { 930 message = NLS.bind(Messages.parse_extPointDisabled, target, ext.getParentPluginDescriptor().getId()); 931 error(message); 932 return; 933 } 934 935 ExtensionPointModel extPt = (ExtensionPointModel) getExtensionPoint(plugin, extPtId); 936 if (extPt == null) { 937 message = NLS.bind(Messages.parse_extPointUnknown, target, ext.getParentPluginDescriptor().getId()); 938 error(message); 939 return; 940 } 941 942 ExtensionModel[] oldValues = extPt.getDeclaredExtensions(); 943 ExtensionModel[] newValues = null; 944 if (oldValues == null) 945 newValues = new ExtensionModel[1]; 946 else { 947 newValues = new ExtensionModel[oldValues.length + 1]; 948 System.arraycopy(oldValues, 0, newValues, 0, oldValues.length); 949 } 950 newValues[newValues.length - 1] = ext; 951 extPt.setDeclaredExtensions(newValues); 952 } 953 954 private Cookie resolveNode(String child, PluginDescriptorModel parent, PluginPrerequisiteModel prq, Cookie cookie, Set orphans) { 955 959 if (DEBUG_RESOLVE) 960 debug("PUSH> " + child); 962 if (cookie == null) 963 cookie = new Cookie(); 964 965 IndexEntry ix = (IndexEntry) idmap.get(child); 967 if (ix == null) { 970 if (prq.getOptional() && parent != null && child != null) 975 return cookie; 976 if (parent != null) 977 error(NLS.bind(Messages.parse_prereqDisabled, parent.getId(), child)); 978 if (DEBUG_RESOLVE) 979 debug("<POP " + child + " not found"); cookie.isOk(false); 981 return cookie; 982 } 983 984 Constraint currentConstraint = new Constraint(parent, prq); 986 PluginDescriptorModel childPd = null; 988 if (parent != null) { 989 childPd = ix.addConstraint(currentConstraint); 990 if (childPd == null) { 991 if (prq.getOptional()) { 992 orphans.add(ix.getId()); 995 information(NLS.bind(Messages.parse_unsatisfiedOptPrereq, parent.getId(), child)); 996 return cookie; 997 } else { 998 String message = NLS.bind(Messages.parse_unsatisfiedPrereq, parent.getId(), child); 1000 error(message); 1001 if (DEBUG_RESOLVE) 1002 debug("<POP " + child + " unable to satisfy constraint"); cookie.isOk(false); 1004 return cookie; 1005 } 1006 } else if (!cookie.addChange(currentConstraint)) { 1007 if (prq.getOptional()) { 1008 information(NLS.bind(Messages.parse_prereqOptLoop, parent.getId(), child)); 1011 return cookie; 1012 } else { 1013 String message = NLS.bind(Messages.parse_prereqLoop, parent.getId(), child); 1014 error(message); 1015 if (DEBUG_RESOLVE) 1016 debug("<POP " + child + " prerequisite loop"); cookie.isOk(false); 1018 return cookie; 1019 } 1020 } 1021 } else { 1022 childPd = ix.getMatchingDescriptorFor(currentConstraint); 1025 if (childPd == null) { 1026 if (DEBUG_RESOLVE) 1027 debug("<POP " + child + " not found (missing descriptor entry)"); cookie.isOk(false); 1029 return cookie; 1030 } 1031 } 1032 1033 if (ix.isResolvedFor(currentConstraint)) { 1035 if (DEBUG_RESOLVE) 1036 debug("<POP " + child + " already resolved"); return cookie; 1038 } 1039 1040 PluginPrerequisiteModel[] prereqs = childPd.getRequires(); 1042 PluginPrerequisiteModel prereq; 1043 prereqs = prereqs == null ? new PluginPrerequisiteModel[0] : prereqs; 1044 for (int i = 0; cookie.isOk() && i < prereqs.length; i++) { 1045 prereq = (PluginPrerequisiteModel) prereqs[i]; 1046 cookie = resolveNode(prereq.getPlugin(), childPd, prereq, cookie, orphans); 1047 } 1048 1049 if (!cookie.isOk()) { 1051 Constraint cookieConstraint; 1052 for (Iterator change = cookie.getChanges().iterator(); change.hasNext();) { 1053 cookieConstraint = (Constraint) change.next(); 1054 prereq = cookieConstraint.getPrerequisite(); 1055 if (childPd == cookieConstraint.getParent()) { 1056 if (!orphans.contains(prereq.getPlugin()) && (idmap.get(prereq.getPlugin()) != null)) 1058 orphans.add(prereq.getPlugin()); 1059 } 1060 removeConstraintFor(prereq); 1061 } 1062 for (int i = 0; i < prereqs.length; i++) { 1065 if (!orphans.contains(prereqs[i].getPlugin()) && (idmap.get(prereqs[i].getPlugin()) != null)) 1066 orphans.add(prereqs[i].getPlugin()); 1067 } 1068 if (parent != null) 1069 error(NLS.bind(Messages.parse_prereqDisabled, parent.getId(), child)); 1070 childPd.setEnabled(false); 1071 if (DEBUG_RESOLVE) 1072 debug("<POP " + child + " failed to resolve subtree"); return cookie; 1074 } else { 1075 ix.isResolvedFor(currentConstraint, true); 1077 if (DEBUG_RESOLVE) 1078 debug("<POP " + child + " " + getVersionIdentifier(childPd)); return cookie; 1080 } 1081 } 1082 1083 private void resolvePluginDescriptor(PluginDescriptorModel pd) { 1084 ExtensionModel[] list = pd.getDeclaredExtensions(); 1085 if (list == null || list.length == 0 || !pd.getEnabled()) 1086 return; 1088 for (int i = 0; i < list.length; i++) 1089 resolveExtension((ExtensionModel) list[i]); 1090 } 1091 1092 private void resolvePluginFragment(PluginFragmentModel fragment, PluginDescriptorModel plugin) { 1093 ExtensionModel[] extensions = fragment.getDeclaredExtensions(); 1094 if (extensions != null) 1095 addExtensions(extensions, plugin); 1097 1098 ExtensionPointModel[] points = fragment.getDeclaredExtensionPoints(); 1099 if (points != null) 1100 addExtensionPoints(points, plugin); 1102 1103 LibraryModel[] libraries = fragment.getRuntime(); 1104 if (libraries != null) 1105 addLibraries(libraries, plugin); 1107 1108 PluginPrerequisiteModel[] prerequisites = fragment.getRequires(); 1109 if (prerequisites != null) 1110 addPrerequisites(prerequisites, plugin); 1112 } 1113 1114 private void resolvePluginFragments(PluginDescriptorModel plugin) { 1115 1123 1124 boolean dirty = false; 1127 1128 PluginFragmentModel[] fragmentList = plugin.getFragments(); 1129 HashMap latestFragments = new HashMap(30); 1130 for (int i = 0; i < fragmentList.length; i++) { 1131 String fragmentId = fragmentList[i].getId(); 1132 PluginFragmentModel latestVersion = (PluginFragmentModel) latestFragments.get(fragmentId); 1133 if (latestVersion == null) { 1134 latestFragments.put(fragmentId, fragmentList[i]); 1136 } else { 1137 dirty = true; 1138 if (getVersionIdentifier(fragmentList[i]).equals(getVersionIdentifier(latestVersion))) 1139 error(NLS.bind(Messages.parse_duplicateFragment, fragmentId, fragmentList[i].getVersion())); 1141 if (getVersionIdentifier(fragmentList[i]).isGreaterThan(getVersionIdentifier(latestVersion))) { 1142 latestFragments.put(fragmentId, fragmentList[i]); 1143 } 1144 } 1145 } 1146 1147 1150 Set latestOnly = new HashSet(); 1152 for (Iterator list = latestFragments.values().iterator(); list.hasNext();) { 1153 PluginFragmentModel latestFragment = (PluginFragmentModel) list.next(); 1154 if (dirty) 1155 latestOnly.add(latestFragment); 1156 int numLibraries = latestFragment.getRuntime() == null ? 0 : latestFragment.getRuntime().length; 1157 resolvePluginFragment(latestFragment, plugin); 1158 if (numLibraries != 0) { 1161 LibraryModel[] libraries = plugin.getRuntime(); 1163 Set libNames = new HashSet(); 1166 int setSize = libNames.size(); 1167 for (int i = 0; i < libraries.length; i++) { 1168 libNames.add(libraries[i].getName()); 1169 if (libNames.size() == setSize) { 1170 String [] bindings = {latestFragment.getId(), plugin.getId(), libraries[i].getName()}; 1173 error(NLS.bind(Messages.parse_duplicateLib, bindings)); 1174 } else { 1175 setSize = libNames.size(); 1176 } 1177 } 1178 } 1179 } 1180 if (dirty) 1184 plugin.setFragments((PluginFragmentModel[]) latestOnly.toArray(new PluginFragmentModel[latestOnly.size()])); 1185 1186 } 1187 1188 private void resolvePluginRegistry() { 1189 if (trimPlugins) 1191 trimRegistry(); 1192 1193 if (crossLink) { 1195 PluginDescriptorModel[] plugins = reg.getPlugins(); 1197 for (int i = 0; i < plugins.length; i++) 1198 resolvePluginDescriptor(plugins[i]); 1199 } 1200 } 1201 1202 private boolean requiredPluginDescriptor(PluginDescriptorModel plugin) { 1203 boolean retValue = true; 1204 retValue = plugin.getName() != null && plugin.getId() != null && plugin.getVersion() != null; 1205 if (!retValue) 1206 return retValue; 1207 1208 PluginPrerequisiteModel[] requiresList = plugin.getRequires(); 1209 ExtensionModel[] extensions = plugin.getDeclaredExtensions(); 1210 ExtensionPointModel[] extensionPoints = plugin.getDeclaredExtensionPoints(); 1211 LibraryModel[] libraryList = plugin.getRuntime(); 1212 PluginFragmentModel[] fragments = plugin.getFragments(); 1213 1214 if (requiresList != null) { 1215 for (int i = 0; i < requiresList.length && retValue; i++) { 1216 retValue = retValue && requiredPrerequisite(requiresList[i]); 1217 } 1218 } 1219 if (extensions != null) { 1220 for (int i = 0; i < extensions.length && retValue; i++) { 1221 retValue = retValue && requiredExtension(extensions[i]); 1222 } 1223 } 1224 if (extensionPoints != null) { 1225 for (int i = 0; i < extensionPoints.length && retValue; i++) { 1226 retValue = retValue && requiredExtensionPoint(extensionPoints[i]); 1227 } 1228 } 1229 if (libraryList != null) { 1230 for (int i = 0; i < libraryList.length && retValue; i++) { 1231 retValue = retValue && requiredLibrary(libraryList[i]); 1232 } 1233 } 1234 if (fragments != null) { 1235 for (int i = 0; i < fragments.length && retValue; i++) { 1236 retValue = retValue && requiredFragment(fragments[i]); 1237 } 1238 } 1239 1240 return retValue; 1241 } 1242 1243 private boolean requiredPrerequisite(PluginPrerequisiteModel prerequisite) { 1244 return ((prerequisite.getPlugin() != null)); 1245 } 1246 1247 private boolean requiredExtension(ExtensionModel extension) { 1248 return (extension.getExtensionPoint() != null); 1249 } 1250 1251 private boolean requiredExtensionPoint(ExtensionPointModel extensionPoint) { 1252 return ((extensionPoint.getName() != null) && (extensionPoint.getId() != null)); 1253 } 1254 1255 private boolean requiredLibrary(LibraryModel library) { 1256 return (library.getName() != null); 1257 } 1258 1259 private boolean requiredFragment(PluginFragmentModel fragment) { 1260 return ((fragment.getName() != null) && (fragment.getId() != null) && (fragment.getPlugin() != null) && (fragment.getPluginVersion() != null) && (fragment.getVersion() != null)); 1261 } 1262 1263 private List resolveRootDescriptors() { 1264 1265 1268 List ids = new ArrayList(); 1270 ids.addAll(idmap.keySet()); 1271 1272 1276 Iterator p = idmap.entrySet().iterator(); 1278 while (p.hasNext()) { 1279 IndexEntry ix = (IndexEntry) ((Map.Entry) p.next()).getValue(); 1280 if (ix != null) { 1281 List list = ix.versions(); 1282 int ixSize = list.size(); 1283 if (ixSize > 0) { 1284 for (int i = 0; i < ixSize; i++) { 1286 PluginDescriptorModel pd = (PluginDescriptorModel) list.get(i); 1287 PluginPrerequisiteModel[] prereqs = pd.getRequires(); 1288 for (int j = 0; prereqs != null && j < prereqs.length; j++) { 1289 ids.remove(prereqs[j].getPlugin()); 1290 } 1291 } 1292 } 1293 } 1294 } 1295 1296 if (ids.size() > 0) { 1297 String id; 1299 p = ids.iterator(); 1300 while (p.hasNext()) { 1301 id = (String ) p.next(); 1302 IndexEntry ix = (IndexEntry) idmap.get(id); 1303 if (ix != null) { 1304 List list = ix.versions(); 1305 for (int i = 0; i < list.size(); i++) { 1306 PluginDescriptorModel pd = (PluginDescriptorModel) list.get(i); 1307 if (i == 0) { 1308 if (DEBUG_RESOLVE) 1311 debug("root " + pd); } else { 1313 if (DEBUG_RESOLVE) 1316 debug(" " + pd + " disabled"); pd.setEnabled(false); 1318 } 1319 } 1320 } 1321 } 1322 } else { 1323 if (DEBUG_RESOLVE) 1324 debug("NO ROOTS"); } 1326 1327 return ids; 1328 } 1329 1330 1334 public void setCrossLink(boolean value) { 1335 crossLink = value; 1336 } 1337 1338 1342 public void setTrimPlugins(boolean value) { 1343 trimPlugins = value; 1344 } 1345 1346 private void trimRegistry() { 1347 PluginDescriptorModel[] list = reg.getPlugins(); 1348 for (int i = 0; i < list.length; i++) { 1349 PluginDescriptorModel pd = (PluginDescriptorModel) list[i]; 1350 if (!pd.getEnabled()) { 1351 if (DEBUG_RESOLVE) 1352 debug("removing " + pd.toString()); reg.removePlugin(pd.getId(), pd.getVersion()); 1354 } 1355 } 1356 } 1357} 1358 | Popular Tags |