KickJava   Java API By Example, From Geeks To Geeks.

Java > Open Source Codes > org > eclipse > core > internal > registry > ExtensionRegistry


1 /*******************************************************************************
2  * Copyright (c) 2000, 2007 IBM Corporation and others.
3  * All rights reserved. This program and the accompanying materials
4  * are made available under the terms of the Eclipse Public License v1.0
5  * which accompanies this distribution, and is available at
6  * http://www.eclipse.org/legal/epl-v10.html
7  *
8  * Contributors:
9  * IBM Corporation - initial API and implementation
10  * Danail Nachev - exception handling for registry listeners (bug 188369)
11  *******************************************************************************/

12 package org.eclipse.core.internal.registry;
13
14 import java.io.*;
15 import java.lang.reflect.Array JavaDoc;
16 import java.util.*;
17 import javax.xml.parsers.ParserConfigurationException JavaDoc;
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 JavaDoc;
25 import org.xml.sax.SAXException JavaDoc;
26
27 /**
28  * An implementation for the extension registry API.
29  */

30 public class ExtensionRegistry implements IExtensionRegistry {
31
32     protected class ListenerInfo {
33         public String JavaDoc filter;
34         public IRegistryChangeListener listener;
35
36         public ListenerInfo(IRegistryChangeListener listener, String JavaDoc filter) {
37             this.listener = listener;
38             this.filter = filter;
39         }
40
41         /**
42          * Used by ListenerList to ensure uniqueness.
43          */

44         public boolean equals(Object JavaDoc another) {
45             return another instanceof ListenerInfo && ((ListenerInfo) another).listener == this.listener;
46         }
47     }
48
49     // used to enforce concurrent access policy for readers/writers
50
private ReadWriteMonitor access = new ReadWriteMonitor();
51
52     // deltas not broadcasted yet. Deltas are kept organized by the namespace name (objects with the same namespace are grouped together)
53
private transient Map deltas = new HashMap(11);
54
55     //storage manager associated with the registry cache
56
protected StorageManager cacheStorageManager;
57
58     // all registry change listeners
59
private transient ListenerList listeners = new ListenerList();
60
61     private RegistryObjectManager registryObjects = null;
62
63     // set to "true" if registry was able to use cache to populate it's content.
64
// if "false", content is empty and might need to be filled in
65
protected boolean isRegistryFilledFromCache = false;
66
67     // Table reader associated with this extension registry
68
protected TableReader theTableReader = new TableReader(this);
69
70     private Object JavaDoc masterToken; // use to get full control of the registry; objects created as "static"
71
private Object JavaDoc userToken; // use to modify non-persisted registry elements
72

73     protected RegistryStrategy strategy; // overridable portions of the registry functionality
74

75     private RegistryTimestamp aggregatedTimestamp = new RegistryTimestamp(); // tracks current contents of the registry
76

77     public RegistryObjectManager getObjectManager() {
78         return registryObjects;
79     }
80
81     /**
82      * Sets new cache file manager. If existing file manager was owned by the registry,
83      * closes it.
84      *
85      * @param newFileManager - new cache file manager
86      * @param registryOwnsManager - true: life cycle of the file manager is controlled by the registry
87      */

88     protected void setFileManager(File cacheBase, boolean isCacheReadOnly) {
89         if (cacheStorageManager != null)
90             cacheStorageManager.close(); // close existing file manager first
91

92         if (cacheBase != null) {
93             cacheStorageManager = new StorageManager(cacheBase, isCacheReadOnly ? "none" : null, isCacheReadOnly); //$NON-NLS-1$
94
try {
95                 cacheStorageManager.open(!isCacheReadOnly);
96             } catch (IOException e) {
97                 // Ignore the exception. The registry will be rebuilt from source.
98
}
99         }
100     }
101
102     /**
103      * Adds and resolves all extensions and extension points provided by the
104      * plug-in.
105      * <p>
106      * A corresponding IRegistryChangeEvent will be broadcast to all listeners
107      * interested on changes in the given plug-in.
108      * </p>
109      */

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     /* Utility method to help with array concatenations */
121     static Object JavaDoc concatArrays(Object JavaDoc a, Object JavaDoc b) {
122         Object JavaDoc[] result = (Object JavaDoc[]) 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 JavaDoc addExtension(int extension) {
129         Extension addedExtension = (Extension) registryObjects.getObject(extension, RegistryObjectManager.EXTENSION);
130         String JavaDoc extensionPointToAddTo = addedExtension.getExtensionPointIdentifier();
131         ExtensionPoint extPoint = registryObjects.getExtensionPointObject(extensionPointToAddTo);
132         //orphan extension
133
if (extPoint == null) {
134             registryObjects.addOrphan(extensionPointToAddTo, extension);
135             return null;
136         }
137         // otherwise, link them
138
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     /**
148      * Looks for existing orphan extensions to connect to the given extension
149      * point. If none is found, there is nothing to do. Otherwise, link them.
150      */

151     private String JavaDoc 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         // now add and resolve extensions and extension points
162
Set affectedNamespaces = new HashSet();
163         int[] extPoints = element.getExtensionPoints();
164         for (int i = 0; i < extPoints.length; i++) {
165             String JavaDoc 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 JavaDoc 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         // this is just a convenience API - no need to do any sync'ing here
180
addRegistryChangeListener(listener, null);
181     }
182
183     public void addRegistryChangeListener(IRegistryChangeListener listener, String JavaDoc 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 JavaDoc) iter.next()).setObjectManager(manager);
200         }
201     }
202
203     private void basicRemove(String JavaDoc contributorId) {
204         // ignore anonymous namespaces
205
Set affectedNamespaces = removeExtensionsAndExtensionPoints(contributorId);
206         Map associatedObjects = registryObjects.getAssociatedObjects(contributorId);
207         registryObjects.removeObjects(associatedObjects);
208         registryObjects.addNavigableObjects(associatedObjects); // put the complete set of navigable objects
209
setObjectManagers(affectedNamespaces, registryObjects.createDelegatingObjectManager(associatedObjects));
210
211         registryObjects.removeContribution(contributorId);
212         registryObjects.removeContributor(contributorId);
213     }
214
215     // allow other objects in the registry to use the same lock
216
void enterRead() {
217         access.enterRead();
218     }
219
220     // allow other objects in the registry to use the same lock
221
void exitRead() {
222         access.exitRead();
223     }
224
225     /**
226      * Broadcasts (asynchronously) the event to all interested parties.
227      */

228     private void fireRegistryChangeEvent() {
229         // if there is nothing to say, just bail out
230
if (deltas.isEmpty() || listeners.isEmpty())
231             return;
232         // for thread safety, create tmp collections
233
Object JavaDoc[] tmpListeners = listeners.getListeners();
234         Map tmpDeltas = new HashMap(this.deltas);
235         // the deltas have been saved for notification - we can clear them now
236
deltas.clear();
237         // do the notification asynchronously
238
strategy.scheduleChangeEvent(tmpListeners, tmpDeltas, this);
239     }
240
241     /*
242      * (non-Javadoc)
243      * @see org.eclipse.core.runtime.IExtensionRegistry#getConfigurationElementsFor(java.lang.String)
244      */

245     public IConfigurationElement[] getConfigurationElementsFor(String JavaDoc extensionPointId) {
246         // this is just a convenience API - no need to do any sync'ing here
247
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     /*
254      * (non-Javadoc)
255      * @see org.eclipse.core.runtime.IExtensionRegistry#getConfigurationElementsFor(java.lang.String, java.lang.String)
256      */

257     public IConfigurationElement[] getConfigurationElementsFor(String JavaDoc pluginId, String JavaDoc extensionPointSimpleId) {
258         // this is just a convenience API - no need to do any sync'ing here
259
IExtensionPoint extPoint = this.getExtensionPoint(pluginId, extensionPointSimpleId);
260         if (extPoint == null)
261             return new IConfigurationElement[0];
262         return extPoint.getConfigurationElements();
263     }
264
265     /*
266      * (non-Javadoc)
267      * @see org.eclipse.core.runtime.IExtensionRegistry#getConfigurationElementsFor(java.lang.String, java.lang.String, java.lang.String)
268      */

269     public IConfigurationElement[] getConfigurationElementsFor(String JavaDoc pluginId, String JavaDoc extensionPointName, String JavaDoc extensionId) {
270         // this is just a convenience API - no need to do any sync'ing here
271
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 JavaDoc namespace) {
278         // is there a delta for the plug-in?
279
RegistryDelta existingDelta = (RegistryDelta) deltas.get(namespace);
280         if (existingDelta != null)
281             return existingDelta;
282
283         //if not, create one
284
RegistryDelta delta = new RegistryDelta();
285         deltas.put(namespace, delta);
286         return delta;
287     }
288
289     /*
290      * (non-Javadoc)
291      * @see org.eclipse.core.runtime.IExtensionRegistry#getExtension(java.lang.String)
292      */

293     public IExtension getExtension(String JavaDoc extensionId) {
294         if (extensionId == null)
295             return null;
296         int lastdot = extensionId.lastIndexOf('.');
297         if (lastdot == -1)
298             return null;
299         String JavaDoc 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     /*
311      * (non-Javadoc)
312      * @see org.eclipse.core.runtime.IExtensionRegistry#getExtension(java.lang.String, java.lang.String)
313      */

314     public IExtension getExtension(String JavaDoc extensionPointId, String JavaDoc extensionId) {
315         // this is just a convenience API - no need to do any sync'ing here
316
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     /*
323      * (non-Javadoc)
324      * @see org.eclipse.core.runtime.IExtensionRegistry#getExtension(java.lang.String, java.lang.String, java.lang.String)
325      */

326     public IExtension getExtension(String JavaDoc pluginId, String JavaDoc extensionPointName, String JavaDoc extensionId) {
327         // this is just a convenience API - no need to do any sync'ing here
328
IExtensionPoint extPoint = getExtensionPoint(pluginId, extensionPointName);
329         if (extPoint != null)
330             return extPoint.getExtension(extensionId);
331         return null;
332     }
333
334     /*
335      * (non-Javadoc)
336      * @see org.eclipse.core.runtime.IExtensionRegistry#getExtensionPoint(java.lang.String)
337      */

338     public IExtensionPoint getExtensionPoint(String JavaDoc xptUniqueId) {
339         return registryObjects.getExtensionPointHandle(xptUniqueId);
340     }
341
342     /*
343      * (non-Javadoc)
344      * @see org.eclipse.core.runtime.IExtensionRegistry#getExtensionPoint(java.lang.String, java.lang.String)
345      */

346     public IExtensionPoint getExtensionPoint(String JavaDoc elementName, String JavaDoc xpt) {
347         access.enterRead();
348         try {
349             return registryObjects.getExtensionPointHandle(elementName + '.' + xpt);
350         } finally {
351             access.exitRead();
352         }
353     }
354
355     /*
356      * (non-Javadoc)
357      * @see org.eclipse.core.runtime.IExtensionRegistry#getExtensionPoints()
358      */

359     public IExtensionPoint[] getExtensionPoints() {
360         access.enterRead();
361         try {
362             return registryObjects.getExtensionPointsHandles();
363         } finally {
364             access.exitRead();
365         }
366     }
367
368     /*
369      * (non-Javadoc)
370      * @see org.eclipse.core.runtime.IExtensionRegistry#getExtensionPoints(java.lang.String)
371      */

372     public IExtensionPoint[] getExtensionPoints(String JavaDoc namespaceName) {
373         access.enterRead();
374         try {
375             return registryObjects.getExtensionPointsFromNamespace(namespaceName);
376         } finally {
377             access.exitRead();
378         }
379     }
380
381     /*
382      * (non-Javadoc)
383      * @see org.eclipse.core.runtime.IExtensionRegistry#getExtensions(java.lang.String)
384      */

385     public IExtension[] getExtensions(String JavaDoc namespaceName) {
386         access.enterRead();
387         try {
388             return registryObjects.getExtensionsFromNamespace(namespaceName);
389         } finally {
390             access.exitRead();
391         }
392     }
393
394     /*
395      * (non-Javadoc)
396      * @see org.eclipse.core.runtime.IExtensionRegistry#getNamespaces()
397      */

398     public String JavaDoc[] getNamespaces() {
399         access.enterRead();
400         try {
401             KeyedElement[] namespaceElements = registryObjects.getNamespacesIndex().elements();
402             String JavaDoc[] namespaceNames = new String JavaDoc[namespaceElements.length];
403             for (int i = 0; i < namespaceElements.length; i++) {
404                 namespaceNames[i] = (String JavaDoc) ((RegistryIndexElement) namespaceElements[i]).getKey();
405             }
406             return namespaceNames;
407         } finally {
408             access.exitRead();
409         }
410     }
411
412     public boolean hasContribution(String JavaDoc 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     /*
427      * Records an extension addition/removal.
428      */

429     private String JavaDoc recordChange(ExtensionPoint extPoint, int extension, int kind) {
430         // avoid computing deltas when there are no listeners
431
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     /*
442      * Records a set of extension additions/removals.
443      */

444     private String JavaDoc 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 JavaDoc removedContributorId, long timestamp) {
461         remove(removedContributorId);
462         if (timestamp != 0)
463             aggregatedTimestamp.remove(timestamp);
464     }
465
466     /**
467      * Unresolves and removes all extensions and extension points provided by
468      * the plug-in.
469      * <p>
470      * A corresponding IRegistryChangeEvent will be broadcast to all listeners
471      * interested on changes in the given plug-in.
472      * </p>
473      */

474     public void remove(String JavaDoc removedContributorId) {
475         access.enterWrite();
476         try {
477             basicRemove(removedContributorId);
478             fireRegistryChangeEvent();
479         } finally {
480             access.exitWrite();
481         }
482     }
483
484     //Return the affected namespace
485
private String JavaDoc removeExtension(int extensionId) {
486         Extension extension = (Extension) registryObjects.getObject(extensionId, RegistryObjectManager.EXTENSION);
487         registryObjects.removeExtensionFromNamespaceIndex(extensionId, extension.getNamespaceIdentifier());
488         String JavaDoc xptName = extension.getExtensionPointIdentifier();
489         ExtensionPoint extPoint = registryObjects.getExtensionPointObject(xptName);
490         if (extPoint == null) {
491             registryObjects.removeOrphan(xptName, extensionId);
492             return null;
493         }
494         // otherwise, unlink the extension from the extension point
495
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 JavaDoc 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         //Remove the extension point from the registry object
518
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 JavaDoc contributorId) {
524         Set affectedNamespaces = new HashSet();
525         int[] extensions = registryObjects.getExtensionsFrom(contributorId);
526         for (int i = 0; i < extensions.length; i++) {
527             String JavaDoc namespace = this.removeExtension(extensions[i]);
528             if (namespace != null)
529                 affectedNamespaces.add(namespace);
530         }
531
532         // remove extension points
533
int[] extPoints = registryObjects.getExtensionPointsFrom(contributorId);
534         for (int i = 0; i < extPoints.length; i++) {
535             String JavaDoc 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 JavaDoc masterToken, Object JavaDoc 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             // Try to read the registry from the cache first. If that fails, create a new registry
560
long start = 0;
561             if (debug())
562                 start = System.currentTimeMillis();
563
564             //The cache is made of several files, find the real names of these other files. If all files are found, try to initialize the objectManager
565
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                     // The registry will be rebuilt from the xml files. Make sure to clear anything filled
580
// from cache so that we won't have partially filled items.
581
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                 // set cache storage manager to a first writable location
589
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)); //$NON-NLS-1$
599

600             if (debug()) {
601                 if (!isRegistryFilledFromCache)
602                     System.out.println("Reloading registry from manifest files..."); //$NON-NLS-1$
603
else
604                     System.out.println("Using registry cache..."); //$NON-NLS-1$
605
}
606         }
607
608         if (debugEvents())
609             addRegistryChangeListener(new IRegistryChangeListener() {
610                 public void registryChanged(IRegistryChangeEvent event) {
611                     System.out.println(event);
612                 }
613             });
614
615         // Do extra start processing if specified in the registry strategy
616
strategy.onStart(this);
617     }
618
619     /**
620      * Stops the registry. Registry has to be stopped to properly
621      * close cache and dispose of listeners.
622      * @param key - key token for this registry
623      */

624     public void stop(Object JavaDoc key) {
625         // If the registry creator specified a key token, check that the key mathches it
626
// (it is assumed that registry owner keeps the key to prevent unautorized accesss).
627
if (masterToken != null && masterToken != key) {
628             throw new IllegalArgumentException JavaDoc("Unauthorized access to the ExtensionRegistry.stop() method. Check if proper access token is supplied."); //$NON-NLS-1$
629
}
630
631         // Do extra stop processing if specified in the registry strategy
632
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()); //$NON-NLS-1$
663
mainFile = File.createTempFile(TableReader.MAIN, ".new", cacheStorageManager.getBase()); //$NON-NLS-1$
664
extraFile = File.createTempFile(TableReader.EXTRA, ".new", cacheStorageManager.getBase()); //$NON-NLS-1$
665
contributionsFile = File.createTempFile(TableReader.CONTRIBUTIONS, ".new", cacheStorageManager.getBase()); //$NON-NLS-1$
666
contributorsFile = File.createTempFile(TableReader.CONTRIBUTORS, ".new", cacheStorageManager.getBase()); //$NON-NLS-1$
667
namespacesFile = File.createTempFile(TableReader.NAMESPACES, ".new", cacheStorageManager.getBase()); //$NON-NLS-1$
668
orphansFile = File.createTempFile(TableReader.ORPHANS, ".new", cacheStorageManager.getBase()); //$NON-NLS-1$
669
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; //Ignore the exception since we can recompute the cache
679
}
680         try {
681             long timestamp;
682             // A bit of backward compatibility: if registry was modified, but timestamp was not,
683
// it means that the new timestamp tracking mechanism was not used. In this case
684
// explicitly obtain timestamps for all contributions. Note that this logic
685
// maintains a problem described in the bug 104267 for contributions that
686
// don't use the timestamp tracking mechanism.
687
if (aggregatedTimestamp.isModifed())
688                 timestamp = aggregatedTimestamp.getContentsTimestamp(); // use timestamp tracking
689
else
690                 timestamp = strategy.getContributionsTimestamp(); // use legacy approach
691

692             if (theTableWriter.saveCache(registryObjects, timestamp))
693                 cacheStorageManager.update(new String JavaDoc[] {TableReader.TABLE, TableReader.MAIN, TableReader.EXTRA, TableReader.CONTRIBUTIONS, TableReader.CONTRIBUTORS, TableReader.NAMESPACES, TableReader.ORPHANS}, new String JavaDoc[] {tableFile.getName(), mainFile.getName(), extraFile.getName(), contributionsFile.getName(), contributorsFile.getName(), namespacesFile.getName(), orphansFile.getName()});
694         } catch (IOException e) {
695             //Ignore the exception since we can recompute the cache
696
}
697         theTableReader.close();
698         cacheStorageManager.close();
699     }
700
701     /*
702      * Clear the registry cache files from the file manager so on next start-up we recompute it.
703      */

704     public void clearRegistryCache() {
705         String JavaDoc[] keys = new String JavaDoc[] {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     /////////////////////////////////////////////////////////////////////////////////////////////////
716
// Registry Object Factory
717
// The factory produces contributions, extension points, extensions, and configuration elements
718
// to be stored in the extension registry.
719
protected RegistryObjectFactory theRegistryObjectFactory = null;
720
721     // Override to provide domain-specific elements to be stored in the extension registry
722
protected void setElementFactory() {
723         theRegistryObjectFactory = new RegistryObjectFactory(this);
724     }
725
726     // Lazy initialization.
727
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 JavaDoc translate(String JavaDoc 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     // Find the first location that contains a cache table file and set file manager to it.
762
protected boolean checkCache() {
763         for (int index = 0; index < strategy.getLocationsLength(); index++) {
764             File possibleCacheLocation = strategy.getStorage(index);
765             if (possibleCacheLocation == null)
766                 break; // bail out on the first null
767
setFileManager(possibleCacheLocation, strategy.isCacheReadOnly(index));
768             if (cacheStorageManager != null) {
769                 // check this new location:
770
File cacheFile = null;
771                 try {
772                     cacheFile = cacheStorageManager.lookup(TableReader.getTestFileName(), false);
773                 } catch (IOException e) {
774                     //Ignore the exception. The registry will be rebuilt from the xml files.
775
}
776                 if (cacheFile != null && cacheFile.isFile())
777                     return true; // found the appropriate location
778
}
779         }
780         return false;
781     }
782
783     public boolean filledFromCache() {
784         return isRegistryFilledFromCache;
785     }
786
787     public Object JavaDoc createExecutableExtension(RegistryContributor defaultContributor, String JavaDoc className, String JavaDoc requestedContributorName) throws CoreException {
788         return strategy.createExecutableExtension(defaultContributor, className, requestedContributorName);
789     }
790
791     //////////////////////////////////////////////////////////////////////////////////////////
792
// Registry change events processing
793

794     public IStatus processChangeEvent(Object JavaDoc[] 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 JavaDoc {
803                         ((IRegistryChangeListener) listenerInfo.listener).registryChanged(new RegistryChangeEvent(deltas, listenerInfo.filter));
804                     }
805
806                     public void handleException(Throwable JavaDoc 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; // registry event loop
818
private final List queue = new LinkedList(); // stores registry events info
819

820     // Registry events notifications are done on a separate thread in a sequential manner
821
// (first in - first processed)
822
public void scheduleChangeEvent(Object JavaDoc[] 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     // The pair of values we store in the event queue
835
private class QueueElement {
836         Object JavaDoc[] listenerInfos;
837         Map deltas;
838
839         QueueElement(Object JavaDoc[] infos, Map deltas) {
840             this.deltas = deltas;
841             listenerInfos = infos;
842         }
843     }
844
845     private class RegistryEventThread extends Thread JavaDoc {
846         private ExtensionRegistry registry;
847
848         public RegistryEventThread(ExtensionRegistry registry) {
849             super("Extension Registry Event Dispatcher"); //$NON-NLS-1$
850
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 JavaDoc 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     /**
881      * Access check for add/remove operations:
882      * - Master key allows all operations
883      * - User key allows modifications of non-persisted elements
884      *
885      * @param key key to the registry supplied by the user
886      * @param persist true if operation affects persisted elements
887      * @return true is the key grants read/write access to the registry
888      */

889     private boolean checkReadWriteAccess(Object JavaDoc 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 JavaDoc contributionName, ResourceBundle translationBundle, Object JavaDoc 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 JavaDoc contributionName, ResourceBundle translationBundle, Object JavaDoc key) {
905         if (!checkReadWriteAccess(key, persist))
906             throw new IllegalArgumentException JavaDoc("Unauthorized access to the ExtensionRegistry.addContribution() method. Check if proper access token is supplied."); //$NON-NLS-1$
907
if (contributionName == null)
908             contributionName = ""; //$NON-NLS-1$
909

910         RegistryContributor internalContributor = (RegistryContributor) contributor;
911         registryObjects.addContributor(internalContributor); // only adds a contributor if it is not already present
912

913         String JavaDoc ownerName = internalContributor.getActualName();
914         String JavaDoc 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 JavaDoc(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 JavaDoc e) {
928             logError(ownerName, contributionName, e);
929             return false;
930         } catch (SAXException JavaDoc 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                 // nothing to do
941
}
942         }
943         add(contribution); // the add() method does synchronization
944
return true;
945     }
946
947     private void logError(String JavaDoc owner, String JavaDoc contributionName, Exception JavaDoc e) {
948         String JavaDoc message = NLS.bind(RegistryMessages.parse_failedParsingManifest, owner + "/" + contributionName); //$NON-NLS-1$
949
log(new Status(IStatus.ERROR, RegistryMessages.OWNER_NAME, 0, message, e));
950     }
951
952     /**
953      * Adds an extension point to the extension registry.
954      * <p>
955      * If the registry is not modifiable, this method is an access controlled method.
956      * Proper token should be passed as an argument for non-modifiable registries.
957      * </p>
958      * @param identifier Id of the extension point. If non-qualified names is supplied,
959      * it will be converted internally into a fully qualified name
960      * @param contributor the contributor of this extension point
961      * @param persist indicates if contribution should be stored in the registry cache. If false,
962      * contribution is not persisted in the registry cache and is lost on Eclipse restart
963      * @param label display string for the extension point
964      * @param schemaReference reference to the extension point schema. The schema reference
965      * is a URL path relative to the plug-in installation URL. May be null
966      * @param token the key used to check permissions. Two registry keys are set in the registry
967      * constructor {@link RegistryFactory#createRegistry(org.eclipse.core.runtime.spi.RegistryStrategy, Object, Object)}:
968      * master token and a user token. Master token allows all operations; user token
969      * allows non-persisted registry elements to be modified.
970      * @return <code>true</code> if successful, <code>false</code> if a problem was encountered
971      * @throws IllegalArgumentException if incorrect token is passed in
972      */

973     public boolean addExtensionPoint(String JavaDoc identifier, IContributor contributor, boolean persist, String JavaDoc label, String JavaDoc schemaReference, Object JavaDoc token) throws IllegalArgumentException JavaDoc {
974         if (!checkReadWriteAccess(token, persist))
975             throw new IllegalArgumentException JavaDoc("Unauthorized access to the ExtensionRegistry.addExtensionPoint() method. Check if proper access token is supplied."); //$NON-NLS-1$
976

977         RegistryContributor internalContributor = (RegistryContributor) contributor;
978         registryObjects.addContributor(internalContributor); // only adds a contributor if it is not already present
979
String JavaDoc contributorId = internalContributor.getActualId();
980
981         // Extension point Id might not be null
982
if (identifier == null) {
983             String JavaDoc 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 = ""; //$NON-NLS-1$
988

989         // addition wraps in a contribution
990
Contribution contribution = getElementFactory().createContribution(contributorId, persist);
991         ExtensionPoint currentExtPoint = getElementFactory().createExtensionPoint(persist);
992
993         String JavaDoc uniqueId;
994         String JavaDoc 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 JavaDoc labelNLS = translate(label, null);
1006        currentExtPoint.setLabel(labelNLS);
1007        currentExtPoint.setSchema(schemaReference);
1008
1009        if (!getObjectManager().addExtensionPoint(currentExtPoint, true)) {
1010            if (debug()) {
1011                String JavaDoc 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        // array format: {Number of extension points, Number of extensions, Extension Id}
1020
int[] contributionChildren = new int[3];
1021        // Put the extension points into this namespace
1022
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    /**
1033     * Adds an extension to the extension registry.
1034     * <p>
1035     * If the registry is not modifiable, this method is an access controlled method.
1036     * Proper token should be passed as an argument for non-modifiable registries.
1037     * </p>
1038     * @see org.eclipse.core.internal.registry.spi.ConfigurationElementDescription
1039     *
1040     * @param identifier Id of the extension. If non-qualified name is supplied,
1041     * it will be converted internally into a fully qualified name
1042     * @param contributor the contributor of this extension
1043     * @param persist indicates if contribution should be stored in the registry cache. If false,
1044     * contribution is not persisted in the registry cache and is lost on Eclipse restart
1045     * @param label display string for this extension
1046     * @param extensionPointId Id of the point being extended. If non-qualified
1047     * name is supplied, it is assumed to have the same contributorId as this extension
1048     * @param configurationElements contents of the extension
1049     * @param token the key used to check permissions. Two registry keys are set in the registry
1050     * constructor {@link RegistryFactory#createRegistry(org.eclipse.core.runtime.spi.RegistryStrategy, Object, Object)}:
1051     * master token and a user token. Master token allows all operations; user token
1052     * allows non-persisted registry elements to be modified.
1053     * @return <code>true</code> if successful, <code>false</code> if a problem was encountered
1054     * @throws IllegalArgumentException if incorrect token is passed in
1055     */

1056    public boolean addExtension(String JavaDoc identifier, IContributor contributor, boolean persist, String JavaDoc label, String JavaDoc extensionPointId, ConfigurationElementDescription configurationElements, Object JavaDoc token) throws IllegalArgumentException JavaDoc {
1057        if (!checkReadWriteAccess(token, persist))
1058            throw new IllegalArgumentException JavaDoc("Unauthorized access to the ExtensionRegistry.addExtensionPoint() method. Check if proper access token is supplied."); //$NON-NLS-1$
1059
// prepare namespace information
1060
RegistryContributor internalContributor = (RegistryContributor) contributor;
1061        registryObjects.addContributor(internalContributor); // only adds a contributor if it is not already present
1062
String JavaDoc contributorId = internalContributor.getActualId();
1063
1064        // addition wraps in a contribution
1065
Contribution contribution = getElementFactory().createContribution(contributorId, persist);
1066        Extension currentExtension = getElementFactory().createExtension(persist);
1067
1068        String JavaDoc simpleId;
1069        String JavaDoc 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 JavaDoc extensionLabelNLS = translate(label, null);
1082        currentExtension.setLabel(extensionLabelNLS);
1083
1084        String JavaDoc targetExtensionPointId;
1085        if (extensionPointId.indexOf('.') == -1) // No dots -> namespace name added at the start
1086
targetExtensionPointId = contribution.getDefaultNamespace() + '.' + extensionPointId;
1087        else
1088            targetExtensionPointId = extensionPointId;
1089        currentExtension.setExtensionPointIdentifier(targetExtensionPointId);
1090
1091        // if we have an Id specified, check for duplicates. Only issue warning if duplicate found
1092
// as it might still work fine - depending on the access pattern.
1093
if (simpleId != null && debug()) {
1094            String JavaDoc uniqueId = namespaceName + '.' + simpleId;
1095            IExtension existingExtension = getExtension(uniqueId);
1096            if (existingExtension != null) {
1097                String JavaDoc currentSupplier = contribution.getDefaultNamespace();
1098                String JavaDoc existingSupplier = existingExtension.getContributor().getName();
1099                String JavaDoc msg = NLS.bind(RegistryMessages.parse_duplicateExtension, new String JavaDoc[] {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    // Fill in the actual content of this extension
1123
private void createExtensionData(String JavaDoc 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 JavaDoc[] properties = new String JavaDoc[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 JavaDoc value = description.getValue();
1142        if (value != null)
1143            currentConfigurationElement.setValue(value);
1144
1145        getObjectManager().add(currentConfigurationElement, true);
1146
1147        // process children
1148
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 JavaDoc token) throws IllegalArgumentException JavaDoc {
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 JavaDoc token) throws IllegalArgumentException JavaDoc {
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 JavaDoc token) {
1180        if (!checkReadWriteAccess(token, registryObject.shouldPersist()))
1181            throw new IllegalArgumentException JavaDoc("Unauthorized access to the ExtensionRegistry.removeExtension() method. Check if proper access token is supplied."); //$NON-NLS-1$
1182
int id = registryObject.getObjectId();
1183
1184        access.enterWrite();
1185        try {
1186            String JavaDoc 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 JavaDoc(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    /**
1207     * <strong>EXPERIMENTAL</strong>. This method has been added as part of a work in progress.
1208     * There is a guarantee neither that this API will work nor that it will remain the same.
1209     * Please do not use this method without consulting with the Equinox team.
1210     */

1211    public Object JavaDoc getTemporaryUserToken() {
1212        return userToken;
1213    }
1214
1215}
1216
Popular Tags