1 12 package org.eclipse.core.internal.registry; 13 14 import java.io.*; 15 import java.lang.reflect.Array ; 16 import java.util.*; 17 import javax.xml.parsers.ParserConfigurationException ; 18 import org.eclipse.core.internal.registry.spi.ConfigurationElementDescription; 19 import org.eclipse.core.internal.registry.spi.ConfigurationElementAttribute; 20 import org.eclipse.core.runtime.*; 21 import org.eclipse.core.runtime.spi.*; 22 import org.eclipse.osgi.storagemanager.StorageManager; 23 import org.eclipse.osgi.util.NLS; 24 import org.xml.sax.InputSource ; 25 import org.xml.sax.SAXException ; 26 27 30 public class ExtensionRegistry implements IExtensionRegistry { 31 32 protected class ListenerInfo { 33 public String filter; 34 public IRegistryChangeListener listener; 35 36 public ListenerInfo(IRegistryChangeListener listener, String filter) { 37 this.listener = listener; 38 this.filter = filter; 39 } 40 41 44 public boolean equals(Object another) { 45 return another instanceof ListenerInfo && ((ListenerInfo) another).listener == this.listener; 46 } 47 } 48 49 private ReadWriteMonitor access = new ReadWriteMonitor(); 51 52 private transient Map deltas = new HashMap(11); 54 55 protected StorageManager cacheStorageManager; 57 58 private transient ListenerList listeners = new ListenerList(); 60 61 private RegistryObjectManager registryObjects = null; 62 63 protected boolean isRegistryFilledFromCache = false; 66 67 protected TableReader theTableReader = new TableReader(this); 69 70 private Object masterToken; private Object userToken; 73 protected RegistryStrategy strategy; 75 private RegistryTimestamp aggregatedTimestamp = new RegistryTimestamp(); 77 public RegistryObjectManager getObjectManager() { 78 return registryObjects; 79 } 80 81 88 protected void setFileManager(File cacheBase, boolean isCacheReadOnly) { 89 if (cacheStorageManager != null) 90 cacheStorageManager.close(); 92 if (cacheBase != null) { 93 cacheStorageManager = new StorageManager(cacheBase, isCacheReadOnly ? "none" : null, isCacheReadOnly); try { 95 cacheStorageManager.open(!isCacheReadOnly); 96 } catch (IOException e) { 97 } 99 } 100 } 101 102 110 private void add(Contribution element) { 111 access.enterWrite(); 112 try { 113 basicAdd(element, true); 114 fireRegistryChangeEvent(); 115 } finally { 116 access.exitWrite(); 117 } 118 } 119 120 121 static Object concatArrays(Object a, Object b) { 122 Object [] result = (Object []) Array.newInstance(a.getClass().getComponentType(), Array.getLength(a) + Array.getLength(b)); 123 System.arraycopy(a, 0, result, 0, Array.getLength(a)); 124 System.arraycopy(b, 0, result, Array.getLength(a), Array.getLength(b)); 125 return result; 126 } 127 128 private String addExtension(int extension) { 129 Extension addedExtension = (Extension) registryObjects.getObject(extension, RegistryObjectManager.EXTENSION); 130 String extensionPointToAddTo = addedExtension.getExtensionPointIdentifier(); 131 ExtensionPoint extPoint = registryObjects.getExtensionPointObject(extensionPointToAddTo); 132 if (extPoint == null) { 134 registryObjects.addOrphan(extensionPointToAddTo, extension); 135 return null; 136 } 137 int[] newExtensions; 139 int[] existingExtensions = extPoint.getRawChildren(); 140 newExtensions = new int[existingExtensions.length + 1]; 141 System.arraycopy(existingExtensions, 0, newExtensions, 0, existingExtensions.length); 142 newExtensions[newExtensions.length - 1] = extension; 143 link(extPoint, newExtensions); 144 return recordChange(extPoint, extension, IExtensionDelta.ADDED); 145 } 146 147 151 private String addExtensionPoint(int extPoint) { 152 ExtensionPoint extensionPoint = (ExtensionPoint) registryObjects.getObject(extPoint, RegistryObjectManager.EXTENSION_POINT); 153 int[] orphans = registryObjects.removeOrphans(extensionPoint.getUniqueIdentifier()); 154 if (orphans == null) 155 return null; 156 link(extensionPoint, orphans); 157 return recordChange(extensionPoint, orphans, IExtensionDelta.ADDED); 158 } 159 160 private Set addExtensionsAndExtensionPoints(Contribution element) { 161 Set affectedNamespaces = new HashSet(); 163 int[] extPoints = element.getExtensionPoints(); 164 for (int i = 0; i < extPoints.length; i++) { 165 String namespace = this.addExtensionPoint(extPoints[i]); 166 if (namespace != null) 167 affectedNamespaces.add(namespace); 168 } 169 int[] extensions = element.getExtensions(); 170 for (int i = 0; i < extensions.length; i++) { 171 String namespace = this.addExtension(extensions[i]); 172 if (namespace != null) 173 affectedNamespaces.add(namespace); 174 } 175 return affectedNamespaces; 176 } 177 178 public void addRegistryChangeListener(IRegistryChangeListener listener) { 179 addRegistryChangeListener(listener, null); 181 } 182 183 public void addRegistryChangeListener(IRegistryChangeListener listener, String filter) { 184 synchronized (listeners) { 185 listeners.add(new ListenerInfo(listener, filter)); 186 } 187 } 188 189 private void basicAdd(Contribution element, boolean link) { 190 registryObjects.addContribution(element); 191 if (!link) 192 return; 193 Set affectedNamespaces = addExtensionsAndExtensionPoints(element); 194 setObjectManagers(affectedNamespaces, registryObjects.createDelegatingObjectManager(registryObjects.getAssociatedObjects(element.getContributorId()))); 195 } 196 197 private void setObjectManagers(Set affectedNamespaces, IObjectManager manager) { 198 for (Iterator iter = affectedNamespaces.iterator(); iter.hasNext();) { 199 getDelta((String ) iter.next()).setObjectManager(manager); 200 } 201 } 202 203 private void basicRemove(String contributorId) { 204 Set affectedNamespaces = removeExtensionsAndExtensionPoints(contributorId); 206 Map associatedObjects = registryObjects.getAssociatedObjects(contributorId); 207 registryObjects.removeObjects(associatedObjects); 208 registryObjects.addNavigableObjects(associatedObjects); setObjectManagers(affectedNamespaces, registryObjects.createDelegatingObjectManager(associatedObjects)); 210 211 registryObjects.removeContribution(contributorId); 212 registryObjects.removeContributor(contributorId); 213 } 214 215 void enterRead() { 217 access.enterRead(); 218 } 219 220 void exitRead() { 222 access.exitRead(); 223 } 224 225 228 private void fireRegistryChangeEvent() { 229 if (deltas.isEmpty() || listeners.isEmpty()) 231 return; 232 Object [] tmpListeners = listeners.getListeners(); 234 Map tmpDeltas = new HashMap(this.deltas); 235 deltas.clear(); 237 strategy.scheduleChangeEvent(tmpListeners, tmpDeltas, this); 239 } 240 241 245 public IConfigurationElement[] getConfigurationElementsFor(String extensionPointId) { 246 int lastdot = extensionPointId.lastIndexOf('.'); 248 if (lastdot == -1) 249 return new IConfigurationElement[0]; 250 return getConfigurationElementsFor(extensionPointId.substring(0, lastdot), extensionPointId.substring(lastdot + 1)); 251 } 252 253 257 public IConfigurationElement[] getConfigurationElementsFor(String pluginId, String extensionPointSimpleId) { 258 IExtensionPoint extPoint = this.getExtensionPoint(pluginId, extensionPointSimpleId); 260 if (extPoint == null) 261 return new IConfigurationElement[0]; 262 return extPoint.getConfigurationElements(); 263 } 264 265 269 public IConfigurationElement[] getConfigurationElementsFor(String pluginId, String extensionPointName, String extensionId) { 270 IExtension extension = this.getExtension(pluginId, extensionPointName, extensionId); 272 if (extension == null) 273 return new IConfigurationElement[0]; 274 return extension.getConfigurationElements(); 275 } 276 277 private RegistryDelta getDelta(String namespace) { 278 RegistryDelta existingDelta = (RegistryDelta) deltas.get(namespace); 280 if (existingDelta != null) 281 return existingDelta; 282 283 RegistryDelta delta = new RegistryDelta(); 285 deltas.put(namespace, delta); 286 return delta; 287 } 288 289 293 public IExtension getExtension(String extensionId) { 294 if (extensionId == null) 295 return null; 296 int lastdot = extensionId.lastIndexOf('.'); 297 if (lastdot == -1) 298 return null; 299 String namespace = extensionId.substring(0, lastdot); 300 301 ExtensionHandle[] extensions = registryObjects.getExtensionsFromNamespace(namespace); 302 for (int i = 0; i < extensions.length; i++) { 303 ExtensionHandle suspect = extensions[i]; 304 if (extensionId.equals(suspect.getUniqueIdentifier())) 305 return suspect; 306 } 307 return null; 308 } 309 310 314 public IExtension getExtension(String extensionPointId, String extensionId) { 315 int lastdot = extensionPointId.lastIndexOf('.'); 317 if (lastdot == -1) 318 return null; 319 return getExtension(extensionPointId.substring(0, lastdot), extensionPointId.substring(lastdot + 1), extensionId); 320 } 321 322 326 public IExtension getExtension(String pluginId, String extensionPointName, String extensionId) { 327 IExtensionPoint extPoint = getExtensionPoint(pluginId, extensionPointName); 329 if (extPoint != null) 330 return extPoint.getExtension(extensionId); 331 return null; 332 } 333 334 338 public IExtensionPoint getExtensionPoint(String xptUniqueId) { 339 return registryObjects.getExtensionPointHandle(xptUniqueId); 340 } 341 342 346 public IExtensionPoint getExtensionPoint(String elementName, String xpt) { 347 access.enterRead(); 348 try { 349 return registryObjects.getExtensionPointHandle(elementName + '.' + xpt); 350 } finally { 351 access.exitRead(); 352 } 353 } 354 355 359 public IExtensionPoint[] getExtensionPoints() { 360 access.enterRead(); 361 try { 362 return registryObjects.getExtensionPointsHandles(); 363 } finally { 364 access.exitRead(); 365 } 366 } 367 368 372 public IExtensionPoint[] getExtensionPoints(String namespaceName) { 373 access.enterRead(); 374 try { 375 return registryObjects.getExtensionPointsFromNamespace(namespaceName); 376 } finally { 377 access.exitRead(); 378 } 379 } 380 381 385 public IExtension[] getExtensions(String namespaceName) { 386 access.enterRead(); 387 try { 388 return registryObjects.getExtensionsFromNamespace(namespaceName); 389 } finally { 390 access.exitRead(); 391 } 392 } 393 394 398 public String [] getNamespaces() { 399 access.enterRead(); 400 try { 401 KeyedElement[] namespaceElements = registryObjects.getNamespacesIndex().elements(); 402 String [] namespaceNames = new String [namespaceElements.length]; 403 for (int i = 0; i < namespaceElements.length; i++) { 404 namespaceNames[i] = (String ) ((RegistryIndexElement) namespaceElements[i]).getKey(); 405 } 406 return namespaceNames; 407 } finally { 408 access.exitRead(); 409 } 410 } 411 412 public boolean hasContribution(String name) { 413 access.enterRead(); 414 try { 415 return registryObjects.hasContribution(name); 416 } finally { 417 access.exitRead(); 418 } 419 } 420 421 private void link(ExtensionPoint extPoint, int[] extensions) { 422 extPoint.setRawChildren(extensions); 423 registryObjects.add(extPoint, true); 424 } 425 426 429 private String recordChange(ExtensionPoint extPoint, int extension, int kind) { 430 if (listeners.isEmpty()) 432 return null; 433 ExtensionDelta extensionDelta = new ExtensionDelta(); 434 extensionDelta.setExtension(extension); 435 extensionDelta.setExtensionPoint(extPoint.getObjectId()); 436 extensionDelta.setKind(kind); 437 getDelta(extPoint.getNamespace()).addExtensionDelta(extensionDelta); 438 return extPoint.getNamespace(); 439 } 440 441 444 private String recordChange(ExtensionPoint extPoint, int[] extensions, int kind) { 445 if (listeners.isEmpty()) 446 return null; 447 if (extensions == null || extensions.length == 0) 448 return null; 449 RegistryDelta pluginDelta = getDelta(extPoint.getNamespace()); 450 for (int i = 0; i < extensions.length; i++) { 451 ExtensionDelta extensionDelta = new ExtensionDelta(); 452 extensionDelta.setExtension(extensions[i]); 453 extensionDelta.setExtensionPoint(extPoint.getObjectId()); 454 extensionDelta.setKind(kind); 455 pluginDelta.addExtensionDelta(extensionDelta); 456 } 457 return extPoint.getNamespace(); 458 } 459 460 public void remove(String removedContributorId, long timestamp) { 461 remove(removedContributorId); 462 if (timestamp != 0) 463 aggregatedTimestamp.remove(timestamp); 464 } 465 466 474 public void remove(String removedContributorId) { 475 access.enterWrite(); 476 try { 477 basicRemove(removedContributorId); 478 fireRegistryChangeEvent(); 479 } finally { 480 access.exitWrite(); 481 } 482 } 483 484 private String removeExtension(int extensionId) { 486 Extension extension = (Extension) registryObjects.getObject(extensionId, RegistryObjectManager.EXTENSION); 487 registryObjects.removeExtensionFromNamespaceIndex(extensionId, extension.getNamespaceIdentifier()); 488 String xptName = extension.getExtensionPointIdentifier(); 489 ExtensionPoint extPoint = registryObjects.getExtensionPointObject(xptName); 490 if (extPoint == null) { 491 registryObjects.removeOrphan(xptName, extensionId); 492 return null; 493 } 494 int[] existingExtensions = extPoint.getRawChildren(); 496 int[] newExtensions = RegistryObjectManager.EMPTY_INT_ARRAY; 497 if (existingExtensions.length > 1) { 498 if (existingExtensions.length == 1) 499 newExtensions = RegistryObjectManager.EMPTY_INT_ARRAY; 500 501 newExtensions = new int[existingExtensions.length - 1]; 502 for (int i = 0, j = 0; i < existingExtensions.length; i++) 503 if (existingExtensions[i] != extension.getObjectId()) 504 newExtensions[j++] = existingExtensions[i]; 505 } 506 link(extPoint, newExtensions); 507 return recordChange(extPoint, extension.getObjectId(), IExtensionDelta.REMOVED); 508 } 509 510 private String removeExtensionPoint(int extPoint) { 511 ExtensionPoint extensionPoint = (ExtensionPoint) registryObjects.getObject(extPoint, RegistryObjectManager.EXTENSION_POINT); 512 registryObjects.removeExtensionPointFromNamespaceIndex(extPoint, extensionPoint.getNamespace()); 513 int[] existingExtensions = extensionPoint.getRawChildren(); 514 if (existingExtensions == null || existingExtensions.length == 0) { 515 return null; 516 } 517 registryObjects.addOrphans(extensionPoint.getUniqueIdentifier(), existingExtensions); 519 link(extensionPoint, RegistryObjectManager.EMPTY_INT_ARRAY); 520 return recordChange(extensionPoint, existingExtensions, IExtensionDelta.REMOVED); 521 } 522 523 private Set removeExtensionsAndExtensionPoints(String contributorId) { 524 Set affectedNamespaces = new HashSet(); 525 int[] extensions = registryObjects.getExtensionsFrom(contributorId); 526 for (int i = 0; i < extensions.length; i++) { 527 String namespace = this.removeExtension(extensions[i]); 528 if (namespace != null) 529 affectedNamespaces.add(namespace); 530 } 531 532 int[] extPoints = registryObjects.getExtensionPointsFrom(contributorId); 534 for (int i = 0; i < extPoints.length; i++) { 535 String namespace = this.removeExtensionPoint(extPoints[i]); 536 if (namespace != null) 537 affectedNamespaces.add(namespace); 538 } 539 return affectedNamespaces; 540 } 541 542 public void removeRegistryChangeListener(IRegistryChangeListener listener) { 543 synchronized (listeners) { 544 listeners.remove(new ListenerInfo(listener, null)); 545 } 546 } 547 548 public ExtensionRegistry(RegistryStrategy registryStrategy, Object masterToken, Object userToken) { 549 if (registryStrategy != null) 550 strategy = registryStrategy; 551 else 552 strategy = new RegistryStrategy(null, null); 553 554 this.masterToken = masterToken; 555 this.userToken = userToken; 556 registryObjects = new RegistryObjectManager(this); 557 558 if (strategy.cacheUse()) { 559 long start = 0; 561 if (debug()) 562 start = System.currentTimeMillis(); 563 564 if (checkCache()) { 566 try { 567 theTableReader.setTableFile(cacheStorageManager.lookup(TableReader.TABLE, false)); 568 theTableReader.setExtraDataFile(cacheStorageManager.lookup(TableReader.EXTRA, false)); 569 theTableReader.setMainDataFile(cacheStorageManager.lookup(TableReader.MAIN, false)); 570 theTableReader.setContributionsFile(cacheStorageManager.lookup(TableReader.CONTRIBUTIONS, false)); 571 theTableReader.setContributorsFile(cacheStorageManager.lookup(TableReader.CONTRIBUTORS, false)); 572 theTableReader.setNamespacesFile(cacheStorageManager.lookup(TableReader.NAMESPACES, false)); 573 theTableReader.setOrphansFile(cacheStorageManager.lookup(TableReader.ORPHANS, false)); 574 long timestamp = strategy.getContributionsTimestamp(); 575 isRegistryFilledFromCache = registryObjects.init(timestamp); 576 if (isRegistryFilledFromCache) 577 aggregatedTimestamp.set(timestamp); 578 } catch (IOException e) { 579 isRegistryFilledFromCache = false; 582 clearRegistryCache(); 583 log(new Status(IStatus.ERROR, RegistryMessages.OWNER_NAME, 0, RegistryMessages.registry_bad_cache, e)); 584 } 585 } 586 587 if (!isRegistryFilledFromCache) { 588 for (int index = 0; index < strategy.getLocationsLength(); index++) { 590 if (!strategy.isCacheReadOnly(index)) { 591 setFileManager(strategy.getStorage(index), false); 592 break; 593 } 594 } 595 } 596 597 if (debug() && isRegistryFilledFromCache) 598 System.out.println("Reading registry cache: " + (System.currentTimeMillis() - start)); 600 if (debug()) { 601 if (!isRegistryFilledFromCache) 602 System.out.println("Reloading registry from manifest files..."); else 604 System.out.println("Using registry cache..."); } 606 } 607 608 if (debugEvents()) 609 addRegistryChangeListener(new IRegistryChangeListener() { 610 public void registryChanged(IRegistryChangeEvent event) { 611 System.out.println(event); 612 } 613 }); 614 615 strategy.onStart(this); 617 } 618 619 624 public void stop(Object key) { 625 if (masterToken != null && masterToken != key) { 628 throw new IllegalArgumentException ("Unauthorized access to the ExtensionRegistry.stop() method. Check if proper access token is supplied."); } 630 631 strategy.onStop(this); 633 634 stopChangeEventScheduler(); 635 636 if (cacheStorageManager == null) 637 return; 638 639 if (!registryObjects.isDirty() || cacheStorageManager.isReadOnly()) { 640 cacheStorageManager.close(); 641 return; 642 } 643 644 File tableFile = null; 645 File mainFile = null; 646 File extraFile = null; 647 File contributionsFile = null; 648 File contributorsFile = null; 649 File namespacesFile = null; 650 File orphansFile = null; 651 652 TableWriter theTableWriter = new TableWriter(this); 653 654 try { 655 cacheStorageManager.lookup(TableReader.TABLE, true); 656 cacheStorageManager.lookup(TableReader.MAIN, true); 657 cacheStorageManager.lookup(TableReader.EXTRA, true); 658 cacheStorageManager.lookup(TableReader.CONTRIBUTIONS, true); 659 cacheStorageManager.lookup(TableReader.CONTRIBUTORS, true); 660 cacheStorageManager.lookup(TableReader.NAMESPACES, true); 661 cacheStorageManager.lookup(TableReader.ORPHANS, true); 662 tableFile = File.createTempFile(TableReader.TABLE, ".new", cacheStorageManager.getBase()); mainFile = File.createTempFile(TableReader.MAIN, ".new", cacheStorageManager.getBase()); extraFile = File.createTempFile(TableReader.EXTRA, ".new", cacheStorageManager.getBase()); contributionsFile = File.createTempFile(TableReader.CONTRIBUTIONS, ".new", cacheStorageManager.getBase()); contributorsFile = File.createTempFile(TableReader.CONTRIBUTORS, ".new", cacheStorageManager.getBase()); namespacesFile = File.createTempFile(TableReader.NAMESPACES, ".new", cacheStorageManager.getBase()); orphansFile = File.createTempFile(TableReader.ORPHANS, ".new", cacheStorageManager.getBase()); theTableWriter.setTableFile(tableFile); 670 theTableWriter.setExtraDataFile(extraFile); 671 theTableWriter.setMainDataFile(mainFile); 672 theTableWriter.setContributionsFile(contributionsFile); 673 theTableWriter.setContributorsFile(contributorsFile); 674 theTableWriter.setNamespacesFile(namespacesFile); 675 theTableWriter.setOrphansFile(orphansFile); 676 } catch (IOException e) { 677 cacheStorageManager.close(); 678 return; } 680 try { 681 long timestamp; 682 if (aggregatedTimestamp.isModifed()) 688 timestamp = aggregatedTimestamp.getContentsTimestamp(); else 690 timestamp = strategy.getContributionsTimestamp(); 692 if (theTableWriter.saveCache(registryObjects, timestamp)) 693 cacheStorageManager.update(new String [] {TableReader.TABLE, TableReader.MAIN, TableReader.EXTRA, TableReader.CONTRIBUTIONS, TableReader.CONTRIBUTORS, TableReader.NAMESPACES, TableReader.ORPHANS}, new String [] {tableFile.getName(), mainFile.getName(), extraFile.getName(), contributionsFile.getName(), contributorsFile.getName(), namespacesFile.getName(), orphansFile.getName()}); 694 } catch (IOException e) { 695 } 697 theTableReader.close(); 698 cacheStorageManager.close(); 699 } 700 701 704 public void clearRegistryCache() { 705 String [] keys = new String [] {TableReader.TABLE, TableReader.MAIN, TableReader.EXTRA, TableReader.CONTRIBUTIONS, TableReader.ORPHANS}; 706 for (int i = 0; i < keys.length; i++) 707 try { 708 cacheStorageManager.remove(keys[i]); 709 } catch (IOException e) { 710 log(new Status(IStatus.ERROR, RegistryMessages.OWNER_NAME, IStatus.ERROR, RegistryMessages.meta_registryCacheReadProblems, e)); 711 } 712 aggregatedTimestamp.reset(); 713 } 714 715 protected RegistryObjectFactory theRegistryObjectFactory = null; 720 721 protected void setElementFactory() { 723 theRegistryObjectFactory = new RegistryObjectFactory(this); 724 } 725 726 public RegistryObjectFactory getElementFactory() { 728 if (theRegistryObjectFactory == null) 729 setElementFactory(); 730 return theRegistryObjectFactory; 731 } 732 733 TableReader getTableReader() { 734 return theTableReader; 735 } 736 737 public void log(IStatus status) { 738 strategy.log(status); 739 } 740 741 public String translate(String key, ResourceBundle resources) { 742 return strategy.translate(key, resources); 743 } 744 745 public boolean debug() { 746 return strategy.debug(); 747 } 748 749 public boolean debugEvents() { 750 return strategy.debugRegistryEvents(); 751 } 752 753 public boolean useLazyCacheLoading() { 754 return strategy.cacheLazyLoading(); 755 } 756 757 public long computeState() { 758 return strategy.getContainerTimestamp(); 759 } 760 761 protected boolean checkCache() { 763 for (int index = 0; index < strategy.getLocationsLength(); index++) { 764 File possibleCacheLocation = strategy.getStorage(index); 765 if (possibleCacheLocation == null) 766 break; setFileManager(possibleCacheLocation, strategy.isCacheReadOnly(index)); 768 if (cacheStorageManager != null) { 769 File cacheFile = null; 771 try { 772 cacheFile = cacheStorageManager.lookup(TableReader.getTestFileName(), false); 773 } catch (IOException e) { 774 } 776 if (cacheFile != null && cacheFile.isFile()) 777 return true; } 779 } 780 return false; 781 } 782 783 public boolean filledFromCache() { 784 return isRegistryFilledFromCache; 785 } 786 787 public Object createExecutableExtension(RegistryContributor defaultContributor, String className, String requestedContributorName) throws CoreException { 788 return strategy.createExecutableExtension(defaultContributor, className, requestedContributorName); 789 } 790 791 794 public IStatus processChangeEvent(Object [] listenerInfos, final Map deltas) { 795 final MultiStatus result = new MultiStatus(RegistryMessages.OWNER_NAME, IStatus.OK, RegistryMessages.plugin_eventListenerError, null); 796 for (int i = 0; i < listenerInfos.length; i++) { 797 final ListenerInfo listenerInfo = (ListenerInfo) listenerInfos[i]; 798 if (listenerInfo.filter != null && !deltas.containsKey(listenerInfo.filter)) 799 continue; 800 if (listenerInfo.listener instanceof IRegistryChangeListener) 801 SafeRunner.run(new ISafeRunnable() { 802 public void run() throws Exception { 803 ((IRegistryChangeListener) listenerInfo.listener).registryChanged(new RegistryChangeEvent(deltas, listenerInfo.filter)); 804 } 805 806 public void handleException(Throwable exception) { 807 result.add(new Status(IStatus.ERROR, RegistryMessages.OWNER_NAME, RegistryMessages.plugin_eventListenerError, exception)); 808 } 809 }); 810 } 811 for (Iterator iter = deltas.values().iterator(); iter.hasNext();) { 812 ((RegistryDelta) iter.next()).getObjectManager().close(); 813 } 814 return result; 815 } 816 817 private RegistryEventThread eventThread = null; private final List queue = new LinkedList(); 820 public void scheduleChangeEvent(Object [] listenerInfos, Map deltas) { 823 QueueElement newElement = new QueueElement(listenerInfos, deltas); 824 if (eventThread == null) { 825 eventThread = new RegistryEventThread(this); 826 eventThread.start(); 827 } 828 synchronized (queue) { 829 queue.add(newElement); 830 queue.notify(); 831 } 832 } 833 834 private class QueueElement { 836 Object [] listenerInfos; 837 Map deltas; 838 839 QueueElement(Object [] infos, Map deltas) { 840 this.deltas = deltas; 841 listenerInfos = infos; 842 } 843 } 844 845 private class RegistryEventThread extends Thread { 846 private ExtensionRegistry registry; 847 848 public RegistryEventThread(ExtensionRegistry registry) { 849 super("Extension Registry Event Dispatcher"); setDaemon(true); 851 this.registry = registry; 852 } 853 854 public void run() { 855 while (true) { 856 QueueElement element; 857 synchronized (queue) { 858 try { 859 while (queue.isEmpty()) 860 queue.wait(); 861 } catch (InterruptedException e) { 862 return; 863 } 864 element = (QueueElement) queue.remove(0); 865 } 866 registry.processChangeEvent(element.listenerInfos, element.deltas); 867 } 868 } 869 } 870 871 protected void stopChangeEventScheduler() { 872 if (eventThread != null) { 873 synchronized (queue) { 874 eventThread.interrupt(); 875 eventThread = null; 876 } 877 } 878 } 879 880 889 private boolean checkReadWriteAccess(Object key, boolean persist) { 890 if (masterToken == key) 891 return true; 892 if (userToken == key && !persist) 893 return true; 894 return false; 895 } 896 897 public boolean addContribution(InputStream is, IContributor contributor, boolean persist, String contributionName, ResourceBundle translationBundle, Object key, long timestamp) { 898 boolean result = addContribution(is, contributor, persist, contributionName, translationBundle, key); 899 if (timestamp != 0) 900 aggregatedTimestamp.add(timestamp); 901 return result; 902 } 903 904 public boolean addContribution(InputStream is, IContributor contributor, boolean persist, String contributionName, ResourceBundle translationBundle, Object key) { 905 if (!checkReadWriteAccess(key, persist)) 906 throw new IllegalArgumentException ("Unauthorized access to the ExtensionRegistry.addContribution() method. Check if proper access token is supplied."); if (contributionName == null) 908 contributionName = ""; 910 RegistryContributor internalContributor = (RegistryContributor) contributor; 911 registryObjects.addContributor(internalContributor); 913 String ownerName = internalContributor.getActualName(); 914 String message = NLS.bind(RegistryMessages.parse_problems, ownerName); 915 MultiStatus problems = new MultiStatus(RegistryMessages.OWNER_NAME, ExtensionsParser.PARSE_PROBLEM, message, null); 916 ExtensionsParser parser = new ExtensionsParser(problems, this); 917 Contribution contribution = getElementFactory().createContribution(internalContributor.getActualId(), persist); 918 919 try { 920 parser.parseManifest(strategy.getXMLParser(), new InputSource (is), contributionName, getObjectManager(), contribution, translationBundle); 921 int status = problems.getSeverity(); 922 if (status != IStatus.OK) { 923 log(problems); 924 if (status == IStatus.ERROR || status == IStatus.CANCEL) 925 return false; 926 } 927 } catch (ParserConfigurationException e) { 928 logError(ownerName, contributionName, e); 929 return false; 930 } catch (SAXException e) { 931 logError(ownerName, contributionName, e); 932 return false; 933 } catch (IOException e) { 934 logError(ownerName, contributionName, e); 935 return false; 936 } finally { 937 try { 938 is.close(); 939 } catch (IOException ioe) { 940 } 942 } 943 add(contribution); return true; 945 } 946 947 private void logError(String owner, String contributionName, Exception e) { 948 String message = NLS.bind(RegistryMessages.parse_failedParsingManifest, owner + "/" + contributionName); log(new Status(IStatus.ERROR, RegistryMessages.OWNER_NAME, 0, message, e)); 950 } 951 952 973 public boolean addExtensionPoint(String identifier, IContributor contributor, boolean persist, String label, String schemaReference, Object token) throws IllegalArgumentException { 974 if (!checkReadWriteAccess(token, persist)) 975 throw new IllegalArgumentException ("Unauthorized access to the ExtensionRegistry.addExtensionPoint() method. Check if proper access token is supplied."); 977 RegistryContributor internalContributor = (RegistryContributor) contributor; 978 registryObjects.addContributor(internalContributor); String contributorId = internalContributor.getActualId(); 980 981 if (identifier == null) { 983 String message = NLS.bind(RegistryMessages.create_failedExtensionPoint, label); 984 log(new Status(IStatus.ERROR, RegistryMessages.OWNER_NAME, 0, message, null)); 985 } 986 if (schemaReference == null) 987 schemaReference = ""; 989 Contribution contribution = getElementFactory().createContribution(contributorId, persist); 991 ExtensionPoint currentExtPoint = getElementFactory().createExtensionPoint(persist); 992 993 String uniqueId; 994 String namespaceName; 995 int simpleIdStart = identifier.lastIndexOf('.'); 996 if (simpleIdStart == -1) { 997 namespaceName = contribution.getDefaultNamespace(); 998 uniqueId = namespaceName + '.' + identifier; 999 } else { 1000 namespaceName = identifier.substring(0, simpleIdStart); 1001 uniqueId = identifier; 1002 } 1003 currentExtPoint.setUniqueIdentifier(uniqueId); 1004 currentExtPoint.setNamespace(namespaceName); 1005 String labelNLS = translate(label, null); 1006 currentExtPoint.setLabel(labelNLS); 1007 currentExtPoint.setSchema(schemaReference); 1008 1009 if (!getObjectManager().addExtensionPoint(currentExtPoint, true)) { 1010 if (debug()) { 1011 String msg = NLS.bind(RegistryMessages.parse_duplicateExtensionPoint, uniqueId, contribution.getDefaultNamespace()); 1012 log(new Status(IStatus.ERROR, RegistryMessages.OWNER_NAME, 0, msg, null)); 1013 } 1014 return false; 1015 } 1016 1017 currentExtPoint.setContributorId(contributorId); 1018 1019 int[] contributionChildren = new int[3]; 1021 contributionChildren[Contribution.EXTENSION_POINT] = 1; 1023 contributionChildren[Contribution.EXTENSION] = 0; 1024 contributionChildren[Contribution.EXTENSION + 1] = currentExtPoint.getObjectId(); 1025 1026 contribution.setRawChildren(contributionChildren); 1027 1028 add(contribution); 1029 return true; 1030 } 1031 1032 1056 public boolean addExtension(String identifier, IContributor contributor, boolean persist, String label, String extensionPointId, ConfigurationElementDescription configurationElements, Object token) throws IllegalArgumentException { 1057 if (!checkReadWriteAccess(token, persist)) 1058 throw new IllegalArgumentException ("Unauthorized access to the ExtensionRegistry.addExtensionPoint() method. Check if proper access token is supplied."); RegistryContributor internalContributor = (RegistryContributor) contributor; 1061 registryObjects.addContributor(internalContributor); String contributorId = internalContributor.getActualId(); 1063 1064 Contribution contribution = getElementFactory().createContribution(contributorId, persist); 1066 Extension currentExtension = getElementFactory().createExtension(persist); 1067 1068 String simpleId; 1069 String namespaceName; 1070 int simpleIdStart = identifier.lastIndexOf('.'); 1071 if (simpleIdStart != -1) { 1072 simpleId = identifier.substring(simpleIdStart + 1); 1073 namespaceName = identifier.substring(0, simpleIdStart); 1074 } else { 1075 simpleId = identifier; 1076 namespaceName = contribution.getDefaultNamespace(); 1077 } 1078 currentExtension.setSimpleIdentifier(simpleId); 1079 currentExtension.setNamespaceIdentifier(namespaceName); 1080 1081 String extensionLabelNLS = translate(label, null); 1082 currentExtension.setLabel(extensionLabelNLS); 1083 1084 String targetExtensionPointId; 1085 if (extensionPointId.indexOf('.') == -1) targetExtensionPointId = contribution.getDefaultNamespace() + '.' + extensionPointId; 1087 else 1088 targetExtensionPointId = extensionPointId; 1089 currentExtension.setExtensionPointIdentifier(targetExtensionPointId); 1090 1091 if (simpleId != null && debug()) { 1094 String uniqueId = namespaceName + '.' + simpleId; 1095 IExtension existingExtension = getExtension(uniqueId); 1096 if (existingExtension != null) { 1097 String currentSupplier = contribution.getDefaultNamespace(); 1098 String existingSupplier = existingExtension.getContributor().getName(); 1099 String msg = NLS.bind(RegistryMessages.parse_duplicateExtension, new String [] {currentSupplier, existingSupplier, uniqueId}); 1100 log(new Status(IStatus.WARNING, RegistryMessages.OWNER_NAME, 0, msg, null)); 1101 return false; 1102 } 1103 } 1104 1105 getObjectManager().add(currentExtension, true); 1106 1107 createExtensionData(contributorId, configurationElements, currentExtension, persist); 1108 1109 currentExtension.setContributorId(contributorId); 1110 1111 int[] contributionChildren = new int[3]; 1112 1113 contributionChildren[Contribution.EXTENSION_POINT] = 0; 1114 contributionChildren[Contribution.EXTENSION] = 1; 1115 contributionChildren[Contribution.EXTENSION + 1] = currentExtension.getObjectId(); 1116 contribution.setRawChildren(contributionChildren); 1117 1118 add(contribution); 1119 return true; 1120 } 1121 1122 private void createExtensionData(String contributorId, ConfigurationElementDescription description, RegistryObject parent, boolean persist) { 1124 ConfigurationElement currentConfigurationElement = getElementFactory().createConfigurationElement(persist); 1125 currentConfigurationElement.setContributorId(contributorId); 1126 currentConfigurationElement.setName(description.getName()); 1127 1128 ConfigurationElementAttribute[] descriptionProperties = description.getAttributes(); 1129 1130 if (descriptionProperties != null && descriptionProperties.length != 0) { 1131 int len = descriptionProperties.length; 1132 String [] properties = new String [len * 2]; 1133 for (int i = 0; i < len; i++) { 1134 properties[i * 2] = descriptionProperties[i].getName(); 1135 properties[i * 2 + 1] = translate(descriptionProperties[i].getValue(), null); 1136 } 1137 currentConfigurationElement.setProperties(properties); 1138 } else 1139 currentConfigurationElement.setProperties(RegistryObjectManager.EMPTY_STRING_ARRAY); 1140 1141 String value = description.getValue(); 1142 if (value != null) 1143 currentConfigurationElement.setValue(value); 1144 1145 getObjectManager().add(currentConfigurationElement, true); 1146 1147 ConfigurationElementDescription[] children = description.getChildren(); 1149 if (children != null) { 1150 for (int i = 0; i < children.length; i++) { 1151 createExtensionData(contributorId, children[i], currentConfigurationElement, persist); 1152 } 1153 } 1154 1155 int[] oldValues = parent.getRawChildren(); 1156 int size = oldValues.length; 1157 int[] newValues = new int[size + 1]; 1158 for (int i = 0; i < size; i++) { 1159 newValues[i] = oldValues[i]; 1160 } 1161 newValues[size] = currentConfigurationElement.getObjectId(); 1162 parent.setRawChildren(newValues); 1163 currentConfigurationElement.setParentId(parent.getObjectId()); 1164 currentConfigurationElement.setParentType(parent instanceof ConfigurationElement ? RegistryObjectManager.CONFIGURATION_ELEMENT : RegistryObjectManager.EXTENSION); 1165 } 1166 1167 public boolean removeExtension(IExtension extension, Object token) throws IllegalArgumentException { 1168 if (!(extension instanceof ExtensionHandle)) 1169 return false; 1170 return removeObject(((ExtensionHandle) extension).getObject(), false, token); 1171 } 1172 1173 public boolean removeExtensionPoint(IExtensionPoint extensionPoint, Object token) throws IllegalArgumentException { 1174 if (!(extensionPoint instanceof ExtensionPointHandle)) 1175 return false; 1176 return removeObject(((ExtensionPointHandle) extensionPoint).getObject(), true, token); 1177 } 1178 1179 private boolean removeObject(RegistryObject registryObject, boolean isExtensionPoint, Object token) { 1180 if (!checkReadWriteAccess(token, registryObject.shouldPersist())) 1181 throw new IllegalArgumentException ("Unauthorized access to the ExtensionRegistry.removeExtension() method. Check if proper access token is supplied."); int id = registryObject.getObjectId(); 1183 1184 access.enterWrite(); 1185 try { 1186 String namespace; 1187 if (isExtensionPoint) 1188 namespace = removeExtensionPoint(id); 1189 else 1190 namespace = removeExtension(id); 1191 1192 Map removed = new HashMap(1); 1193 removed.put(new Integer (id), registryObject); 1194 registryObjects.removeObjects(removed); 1195 registryObjects.addNavigableObjects(removed); 1196 getDelta(namespace).setObjectManager(registryObjects.createDelegatingObjectManager(removed)); 1197 1198 registryObjects.unlinkChildFromContributions(id); 1199 fireRegistryChangeEvent(); 1200 } finally { 1201 access.exitWrite(); 1202 } 1203 return true; 1204 } 1205 1206 1211 public Object getTemporaryUserToken() { 1212 return userToken; 1213 } 1214 1215} 1216 | Popular Tags |