KickJava   Java API By Example, From Geeks To Geeks.

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


1 /*******************************************************************************
2  * Copyright (c) 2004, 2006 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  *******************************************************************************/

11 package org.eclipse.core.internal.registry;
12
13 import java.lang.ref.SoftReference JavaDoc;
14 import java.util.*;
15 import org.eclipse.core.runtime.InvalidRegistryObjectException;
16 import org.eclipse.core.runtime.spi.RegistryContributor;
17
18 /**
19  * This class manage all the object from the registry but does not deal with their dependencies.
20  * It serves the objects which are either directly obtained from memory or read from a cache.
21  * It also returns handles for objects.
22  */

23 public class RegistryObjectManager implements IObjectManager {
24     //Constants used to get the objects and their handles
25
static public final byte CONFIGURATION_ELEMENT = 1;
26     static public final byte EXTENSION = 2;
27     static public final byte EXTENSION_POINT = 3;
28     static public final byte THIRDLEVEL_CONFIGURATION_ELEMENT = 4;
29
30     static final int CACHE_INITIAL_SIZE = 512; //This value has been picked because it is the minimal size required to startup an RCP app. (FYI, eclipse requires 3 growths).
31
static final float DEFAULT_LOADFACTOR = 0.75f; //This is the default factor used in reference map.
32

33     static final int[] EMPTY_INT_ARRAY = new int[0];
34     static final String JavaDoc[] EMPTY_STRING_ARRAY = new String JavaDoc[0];
35
36     static int UNKNOWN = -1;
37
38     // key: extensionPointName, value: object id
39
private HashtableOfStringAndInt extensionPoints; //This is loaded on startup. Then entries can be added when loading a new plugin from the xml.
40
// key: object id, value: an object
41
private ReferenceMap cache; //Entries are added by getter. The structure is not thread safe.
42
//key: int, value: int
43
private HashtableOfInt fileOffsets; //This is read once on startup when loading from the cache. Entries are never added here. They are only removed to prevent "removed" objects to be reloaded.
44

45     private int nextId = 1; //This is only used to get the next number available.
46

47     //Those two data structures are only used when the addition or the removal of a plugin occurs.
48
//They are used to keep track on a contributor basis of the extension being added or removed
49
private KeyedHashSet newContributions; //represents the contributers added during this session.
50
private Object JavaDoc formerContributions; //represents the contributers encountered in previous sessions. This is loaded lazily.
51

52     private HashMap contributors; // key: contributor ID; value: contributor name
53
private HashMap removedContributors; // key: contributor ID; value: contributor name
54
private KeyedHashSet namespacesIndex; // registry elements (extension & extensionpoints) indexed by namespaces
55

56     // Map key: extensionPointFullyQualifiedName, value int[] of orphan extensions.
57
// The orphan access does not need to be synchronized because the it is protected by the lock in extension registry.
58
private Object JavaDoc orphanExtensions;
59
60     private KeyedHashSet heldObjects = new KeyedHashSet(); //strong reference to the objects that must be hold on to
61

62     //Indicate if objects have been removed or added from the table. This only needs to be set in a couple of places (addNamespace and removeNamespace)
63
private boolean isDirty = false;
64
65     private boolean fromCache = false;
66
67     private ExtensionRegistry registry;
68
69     // TODO this option is not used
70
// OSGI system properties. Copied from EclipseStarter
71
public static final String JavaDoc PROP_NO_REGISTRY_FLUSHING = "eclipse.noRegistryFlushing"; //$NON-NLS-1$
72

73     public RegistryObjectManager(ExtensionRegistry registry) {
74         extensionPoints = new HashtableOfStringAndInt();
75         if ("true".equalsIgnoreCase(RegistryProperties.getProperty(PROP_NO_REGISTRY_FLUSHING))) { //$NON-NLS-1$
76
cache = new ReferenceMap(ReferenceMap.HARD, CACHE_INITIAL_SIZE, DEFAULT_LOADFACTOR);
77         } else {
78             cache = new ReferenceMap(ReferenceMap.SOFT, CACHE_INITIAL_SIZE, DEFAULT_LOADFACTOR);
79         }
80         newContributions = new KeyedHashSet();
81         fileOffsets = new HashtableOfInt();
82
83         this.registry = registry;
84     }
85
86     /**
87      * Initialize the object manager. Return true if the initialization succeeded, false otherwise
88      */

89     synchronized boolean init(long timeStamp) {
90         TableReader reader = registry.getTableReader();
91         Object JavaDoc[] results = reader.loadTables(timeStamp);
92         if (results == null) {
93             return false;
94         }
95         fileOffsets = (HashtableOfInt) results[0];
96         extensionPoints = (HashtableOfStringAndInt) results[1];
97         nextId = ((Integer JavaDoc) results[2]).intValue();
98         fromCache = true;
99
100         if (!registry.useLazyCacheLoading()) {
101             //TODO Here we could grow all the tables to the right size (ReferenceMap)
102
reader.setHoldObjects(true);
103             markOrphansHasDirty(getOrphans());
104             fromCache = reader.readAllCache(this);
105             formerContributions = getFormerContributions();
106         }
107         return fromCache;
108     }
109
110     synchronized void addContribution(Contribution contribution) {
111         isDirty = true;
112         Object JavaDoc Id = contribution.getKey();
113
114         KeyedElement existingContribution = getFormerContributions().getByKey(Id);
115         if (existingContribution != null) { // move it from former to new contributions
116
removeContribution(Id);
117             newContributions.add(existingContribution);
118         } else
119             existingContribution = newContributions.getByKey(Id);
120
121         if (existingContribution != null) // merge
122
((Contribution) existingContribution).mergeContribution(contribution);
123         else
124             newContributions.add(contribution);
125
126         updateNamespaceIndex(contribution, true);
127     }
128
129     // TODO make ExtensionPoint, Extension provide namespace in a same way (move it to the RegistryObject?)
130
// See if all the registryObjects have the same namespace. If not, return null.
131
// Also can return null if empty array is passed in or objects are of an unexpected type
132
private String JavaDoc findCommonNamespaceIdentifier(RegistryObject[] registryObjects) {
133         String JavaDoc namespaceName = null;
134         for (int i = 0; i < registryObjects.length; i++) {
135             RegistryObject currentObject = registryObjects[i];
136             String JavaDoc tmp = null;
137             if (currentObject instanceof ExtensionPoint)
138                 tmp = ((ExtensionPoint) currentObject).getNamespace();
139             else if (currentObject instanceof Extension)
140                 tmp = ((Extension) currentObject).getNamespaceIdentifier();
141
142             if (namespaceName == null) {
143                 namespaceName = tmp;
144                 continue;
145             }
146             if (!namespaceName.equals(tmp)) {
147                 return null;
148             }
149         }
150         return namespaceName;
151     }
152
153     synchronized void removeExtensionPointFromNamespaceIndex(int extensionPoint, String JavaDoc namespaceName) {
154         RegistryIndexElement indexElement = getNamespaceIndex(namespaceName);
155         indexElement.updateExtensionPoint(extensionPoint, false);
156     }
157
158     synchronized void removeExtensionFromNamespaceIndex(int extensions, String JavaDoc namespaceName) {
159         RegistryIndexElement indexElement = getNamespaceIndex(namespaceName);
160         indexElement.updateExtension(extensions, false);
161     }
162
163     // Called from a synchronized method
164
private void updateNamespaceIndex(Contribution contribution, boolean added) {
165         // if all extension points are from the same namespace combine them in one block and add them all together
166
int[] contribExtensionPoints = contribution.getExtensionPoints();
167         RegistryObject[] extensionPointObjects = getObjects(contribExtensionPoints, EXTENSION_POINT);
168         String JavaDoc commonExptsNamespace = null;
169         if (contribExtensionPoints.length > 1)
170             commonExptsNamespace = findCommonNamespaceIdentifier(extensionPointObjects);
171         if (commonExptsNamespace != null) {
172             RegistryIndexElement indexElement = getNamespaceIndex(commonExptsNamespace);
173             indexElement.updateExtensionPoints(contribExtensionPoints, added);
174         } else {
175             for (int i = 0; i < contribExtensionPoints.length; i++) {
176                 String JavaDoc namespaceName = ((ExtensionPoint) extensionPointObjects[i]).getNamespace();
177                 RegistryIndexElement indexElement = getNamespaceIndex(namespaceName);
178                 indexElement.updateExtensionPoint(contribExtensionPoints[i], added);
179             }
180         }
181
182         // if all extensions are from the same namespace combine them in one block and add them all together
183
int[] contrExtensions = contribution.getExtensions();
184         RegistryObject[] extensionObjects = getObjects(contrExtensions, EXTENSION);
185         String JavaDoc commonExtNamespace = null;
186         if (contrExtensions.length > 1)
187             commonExtNamespace = findCommonNamespaceIdentifier(extensionObjects);
188         if (commonExtNamespace != null) {
189             RegistryIndexElement indexElement = getNamespaceIndex(commonExtNamespace);
190             indexElement.updateExtensions(contrExtensions, added);
191         } else {
192             for (int i = 0; i < contrExtensions.length; i++) {
193                 String JavaDoc namespaceName = ((Extension) extensionObjects[i]).getNamespaceIdentifier();
194                 RegistryIndexElement indexElement = getNamespaceIndex(namespaceName);
195                 indexElement.updateExtension(contrExtensions[i], added);
196             }
197         }
198     }
199
200     synchronized int[] getExtensionPointsFrom(String JavaDoc id) {
201         KeyedElement tmp = newContributions.getByKey(id);
202         if (tmp == null)
203             tmp = getFormerContributions().getByKey(id);
204         if (tmp == null)
205             return EMPTY_INT_ARRAY;
206         return ((Contribution) tmp).getExtensionPoints();
207     }
208
209     synchronized boolean hasContribution(String JavaDoc id) {
210         Object JavaDoc result = newContributions.getByKey(id);
211         if (result == null)
212             result = getFormerContributions().getByKey(id);
213         return result != null;
214     }
215
216     private KeyedHashSet getFormerContributions() {
217         KeyedHashSet result;
218         if (fromCache == false)
219             return new KeyedHashSet(0);
220
221         if (formerContributions == null || (result = ((KeyedHashSet) ((formerContributions instanceof SoftReference JavaDoc) ? ((SoftReference JavaDoc) formerContributions).get() : formerContributions))) == null) {
222             result = registry.getTableReader().loadContributions();
223             formerContributions = new SoftReference JavaDoc(result);
224         }
225         return result;
226     }
227
228     synchronized public void add(RegistryObject registryObject, boolean hold) {
229         if (registryObject.getObjectId() == UNKNOWN) {
230             int id = nextId++;
231             registryObject.setObjectId(id);
232         }
233         cache.put(registryObject.getObjectId(), registryObject);
234         if (hold)
235             hold(registryObject);
236     }
237
238     private void remove(RegistryObject registryObject, boolean release) {
239         cache.remove(registryObject.getObjectId());
240         if (release)
241             release(registryObject);
242     }
243
244     synchronized void remove(int id, boolean release) {
245         RegistryObject toRemove = (RegistryObject) cache.get(id);
246         if (fileOffsets != null)
247             fileOffsets.removeKey(id);
248         if (toRemove != null)
249             remove(toRemove, release);
250     }
251
252     private void hold(RegistryObject toHold) {
253         heldObjects.add(toHold);
254     }
255
256     private void release(RegistryObject toRelease) {
257         heldObjects.remove(toRelease);
258     }
259
260     public synchronized Object JavaDoc getObject(int id, byte type) {
261         return basicGetObject(id, type);
262     }
263
264     private Object JavaDoc basicGetObject(int id, byte type) {
265         Object JavaDoc result = cache.get(id);
266         if (result != null)
267             return result;
268         if (fromCache)
269             result = load(id, type);
270         if (result == null)
271             throw new InvalidRegistryObjectException();
272         cache.put(id, result);
273         return result;
274     }
275
276     // The current impementation of this method assumes that we don't cache dynamic
277
// extension. In this case all extensions not yet loaded (i.e. not in the memory cache)
278
// are "not dynamic" and we actually check memory objects to see if they are dynamic.
279
//
280
// If we decide to allow caching of dynamic objects, the implementation
281
// of this method would have to retrieved the object from disk and check
282
// its "dynamic" status. The problem is that id alone is not enough to get the object
283
// from the disk; object type is needed as well.
284
public boolean shouldPersist(int id) {
285         Object JavaDoc result = cache.get(id);
286         if (result != null)
287             return ((RegistryObject) result).shouldPersist();
288         return true;
289     }
290
291     public synchronized RegistryObject[] getObjects(int[] values, byte type) {
292         if (values.length == 0) {
293             switch (type) {
294                 case EXTENSION_POINT :
295                     return ExtensionPoint.EMPTY_ARRAY;
296                 case EXTENSION :
297                     return Extension.EMPTY_ARRAY;
298                 case CONFIGURATION_ELEMENT :
299                 case THIRDLEVEL_CONFIGURATION_ELEMENT :
300                     return ConfigurationElement.EMPTY_ARRAY;
301             }
302         }
303
304         RegistryObject[] results = null;
305         switch (type) {
306             case EXTENSION_POINT :
307                 results = new ExtensionPoint[values.length];
308                 break;
309             case EXTENSION :
310                 results = new Extension[values.length];
311                 break;
312             case CONFIGURATION_ELEMENT :
313             case THIRDLEVEL_CONFIGURATION_ELEMENT :
314                 results = new ConfigurationElement[values.length];
315                 break;
316         }
317         for (int i = 0; i < values.length; i++) {
318             results[i] = (RegistryObject) basicGetObject(values[i], type);
319         }
320         return results;
321     }
322
323     synchronized ExtensionPoint getExtensionPointObject(String JavaDoc xptUniqueId) {
324         int id;
325         if ((id = extensionPoints.get(xptUniqueId)) == HashtableOfStringAndInt.MISSING_ELEMENT)
326             return null;
327         return (ExtensionPoint) getObject(id, EXTENSION_POINT);
328     }
329
330     public Handle getHandle(int id, byte type) {
331         switch (type) {
332             case EXTENSION_POINT :
333                 return new ExtensionPointHandle(this, id);
334
335             case EXTENSION :
336                 return new ExtensionHandle(this, id);
337
338             case CONFIGURATION_ELEMENT :
339                 return new ConfigurationElementHandle(this, id);
340
341             case THIRDLEVEL_CONFIGURATION_ELEMENT :
342             default : //avoid compiler error, type should always be known
343
return new ThirdLevelConfigurationElementHandle(this, id);
344         }
345     }
346
347     public Handle[] getHandles(int[] ids, byte type) {
348         Handle[] results = null;
349         int nbrId = ids.length;
350         switch (type) {
351             case EXTENSION_POINT :
352                 if (nbrId == 0)
353                     return ExtensionPointHandle.EMPTY_ARRAY;
354                 results = new ExtensionPointHandle[nbrId];
355                 for (int i = 0; i < nbrId; i++) {
356                     results[i] = new ExtensionPointHandle(this, ids[i]);
357                 }
358                 break;
359
360             case EXTENSION :
361                 if (nbrId == 0)
362                     return ExtensionHandle.EMPTY_ARRAY;
363                 results = new ExtensionHandle[nbrId];
364                 for (int i = 0; i < nbrId; i++) {
365                     results[i] = new ExtensionHandle(this, ids[i]);
366                 }
367                 break;
368
369             case CONFIGURATION_ELEMENT :
370                 if (nbrId == 0)
371                     return ConfigurationElementHandle.EMPTY_ARRAY;
372                 results = new ConfigurationElementHandle[nbrId];
373                 for (int i = 0; i < nbrId; i++) {
374                     results[i] = new ConfigurationElementHandle(this, ids[i]);
375                 }
376                 break;
377
378             case THIRDLEVEL_CONFIGURATION_ELEMENT :
379                 if (nbrId == 0)
380                     return ConfigurationElementHandle.EMPTY_ARRAY;
381                 results = new ThirdLevelConfigurationElementHandle[nbrId];
382                 for (int i = 0; i < nbrId; i++) {
383                     results[i] = new ThirdLevelConfigurationElementHandle(this, ids[i]);
384                 }
385                 break;
386         }
387         return results;
388     }
389
390     synchronized ExtensionPointHandle[] getExtensionPointsHandles() {
391         return (ExtensionPointHandle[]) getHandles(extensionPoints.getValues(), EXTENSION_POINT);
392     }
393
394     synchronized ExtensionPointHandle getExtensionPointHandle(String JavaDoc xptUniqueId) {
395         int id = extensionPoints.get(xptUniqueId);
396         if (id == HashtableOfStringAndInt.MISSING_ELEMENT)
397             return null;
398         return (ExtensionPointHandle) getHandle(id, EXTENSION_POINT);
399     }
400
401     private Object JavaDoc load(int id, byte type) {
402         TableReader reader = registry.getTableReader();
403         int offset = fileOffsets.get(id);
404         if (offset == Integer.MIN_VALUE)
405             return null;
406         switch (type) {
407             case CONFIGURATION_ELEMENT :
408                 return reader.loadConfigurationElement(offset);
409
410             case THIRDLEVEL_CONFIGURATION_ELEMENT :
411                 return reader.loadThirdLevelConfigurationElements(offset, this);
412
413             case EXTENSION :
414                 return reader.loadExtension(offset);
415
416             case EXTENSION_POINT :
417             default : //avoid compile errors. type must always be known
418
return reader.loadExtensionPointTree(offset, this);
419         }
420     }
421
422     synchronized int[] getExtensionsFrom(String JavaDoc contributorId) {
423         KeyedElement tmp = newContributions.getByKey(contributorId);
424         if (tmp == null)
425             tmp = getFormerContributions().getByKey(contributorId);
426         if (tmp == null)
427             return EMPTY_INT_ARRAY;
428         return ((Contribution) tmp).getExtensions();
429     }
430
431     synchronized boolean addExtensionPoint(ExtensionPoint currentExtPoint, boolean hold) {
432         String JavaDoc uniqueId = currentExtPoint.getUniqueIdentifier();
433         if (extensionPoints.get(uniqueId) != HashtableOfStringAndInt.MISSING_ELEMENT)
434             return false;
435         add(currentExtPoint, hold);
436         extensionPoints.put(uniqueId, currentExtPoint.getObjectId());
437         return true;
438     }
439
440     synchronized void removeExtensionPoint(String JavaDoc extensionPointId) {
441         int pointId = extensionPoints.removeKey(extensionPointId);
442         if (pointId == HashtableOfStringAndInt.MISSING_ELEMENT)
443             return;
444         remove(pointId, true);
445     }
446
447     public boolean isDirty() {
448         return isDirty;
449     }
450
451     synchronized void removeContribution(Object JavaDoc contributorId) {
452         boolean removed = newContributions.removeByKey(contributorId);
453         if (removed == false) {
454             removed = getFormerContributions().removeByKey(contributorId);
455             if (removed)
456                 formerContributions = getFormerContributions(); //This forces the removed namespace to stay around, so we do not forget about removed namespaces
457
}
458
459         if (removed) {
460             isDirty = true;
461             return;
462         }
463
464     }
465
466     private Map getOrphans() {
467         Object JavaDoc result = orphanExtensions;
468         if (orphanExtensions == null && !fromCache) {
469             result = new HashMap();
470             orphanExtensions = result;
471         } else if (orphanExtensions == null || (result = ((HashMap) ((orphanExtensions instanceof SoftReference JavaDoc) ? ((SoftReference JavaDoc) orphanExtensions).get() : orphanExtensions))) == null) {
472             result = registry.getTableReader().loadOrphans();
473             orphanExtensions = new SoftReference JavaDoc(result);
474         }
475         return (HashMap) result;
476     }
477
478     void addOrphans(String JavaDoc extensionPoint, int[] extensions) {
479         Map orphans = getOrphans();
480         int[] existingOrphanExtensions = (int[]) orphans.get(extensionPoint);
481
482         if (existingOrphanExtensions != null) {
483             // just add
484
int[] newOrphanExtensions = new int[existingOrphanExtensions.length + extensions.length];
485             System.arraycopy(existingOrphanExtensions, 0, newOrphanExtensions, 0, existingOrphanExtensions.length);
486             System.arraycopy(extensions, 0, newOrphanExtensions, existingOrphanExtensions.length, extensions.length);
487             orphans.put(extensionPoint, newOrphanExtensions);
488         } else {
489             // otherwise this is the first one
490
orphans.put(extensionPoint, extensions);
491         }
492         markOrphansHasDirty(orphans);
493     }
494
495     void markOrphansHasDirty(Map orphans) {
496         orphanExtensions = orphans;
497     }
498
499     void addOrphan(String JavaDoc extensionPoint, int extension) {
500         Map orphans = getOrphans();
501         int[] existingOrphanExtensions = (int[]) orphans.get(extensionPoint);
502
503         if (existingOrphanExtensions != null) {
504             // just add
505
int[] newOrphanExtensions = new int[existingOrphanExtensions.length + 1];
506             System.arraycopy(existingOrphanExtensions, 0, newOrphanExtensions, 0, existingOrphanExtensions.length);
507             newOrphanExtensions[existingOrphanExtensions.length] = extension;
508             orphans.put(extensionPoint, newOrphanExtensions);
509         } else {
510             // otherwise this is the first one
511
orphans.put(extensionPoint, new int[] {extension});
512         }
513         markOrphansHasDirty(orphans);
514     }
515
516     int[] removeOrphans(String JavaDoc extensionPoint) {
517         Map orphans = getOrphans();
518         int[] existingOrphanExtensions = (int[]) orphans.remove(extensionPoint);
519         if (existingOrphanExtensions != null) {
520             markOrphansHasDirty(orphans);
521         }
522         return existingOrphanExtensions;
523     }
524
525     void removeOrphan(String JavaDoc extensionPoint, int extension) {
526         Map orphans = getOrphans();
527         int[] existingOrphanExtensions = (int[]) orphans.get(extensionPoint);
528
529         if (existingOrphanExtensions == null)
530             return;
531
532         markOrphansHasDirty(orphans);
533         int newSize = existingOrphanExtensions.length - 1;
534         if (newSize == 0) {
535             orphans.remove(extensionPoint);
536             return;
537         }
538
539         int[] newOrphanExtensions = new int[existingOrphanExtensions.length - 1];
540         for (int i = 0, j = 0; i < existingOrphanExtensions.length; i++)
541             if (extension != existingOrphanExtensions[i])
542                 newOrphanExtensions[j++] = existingOrphanExtensions[i];
543
544         orphans.put(extensionPoint, newOrphanExtensions);
545         return;
546     }
547
548     //This method is only used by the writer to reach in
549
Map getOrphanExtensions() {
550         return getOrphans();
551     }
552
553     // This method is only used by the writer to reach in
554
int getNextId() {
555         return nextId;
556     }
557
558     // This method is only used by the writer to reach in
559
HashtableOfStringAndInt getExtensionPoints() {
560         return extensionPoints;
561     }
562
563     // This method is only used by the writer to reach in
564
KeyedHashSet[] getContributions() {
565         return new KeyedHashSet[] {newContributions, getFormerContributions()};
566     }
567
568     // This method is used internally and by the writer to reach in. Notice that it doesn't
569
// return contributors marked as removed.
570
HashMap getContributors() {
571         if (contributors == null) {
572             if (fromCache == false)
573                 contributors = new HashMap();
574             else
575                 contributors = registry.getTableReader().loadContributors();
576         }
577         return contributors;
578     }
579
580     synchronized RegistryContributor getContributor(String JavaDoc id) {
581         RegistryContributor contributor = (RegistryContributor) getContributors().get(id);
582         if (contributor != null)
583             return contributor;
584         // check if we have it among removed contributors - potentially
585
// notification of removals might be processed after the contributor
586
// marked as removed:
587
if (removedContributors != null)
588             return (RegistryContributor) removedContributors.get(id);
589         return null;
590     }
591
592     // only adds a contributor if it is not already present in the table
593
synchronized void addContributor(RegistryContributor newContributor) {
594         String JavaDoc key = newContributor.getActualId();
595         if (!getContributors().containsKey(key)) {
596             isDirty = true;
597             if (removedContributors != null)
598                 removedContributors.remove(key);
599             getContributors().put(key, newContributor);
600         }
601     }
602
603     synchronized void removeContributor(String JavaDoc id) {
604         isDirty = true;
605         RegistryContributor removed = (RegistryContributor) getContributors().remove(id);
606         if (removed != null) {
607             if (removedContributors == null)
608                 removedContributors = new HashMap();
609             removedContributors.put(id, removed);
610         }
611     }
612
613     KeyedHashSet getNamespacesIndex() {
614         if (namespacesIndex == null) {
615             if (fromCache == false)
616                 namespacesIndex = new KeyedHashSet(0);
617             else
618                 namespacesIndex = registry.getTableReader().loadNamespaces();
619         }
620         return namespacesIndex;
621     }
622
623     // Find or create required index element
624
private RegistryIndexElement getNamespaceIndex(String JavaDoc namespaceName) {
625         RegistryIndexElement indexElement = (RegistryIndexElement) getNamespacesIndex().getByKey(namespaceName);
626         if (indexElement == null) {
627             indexElement = new RegistryIndexElement(namespaceName);
628             namespacesIndex.add(indexElement);
629         }
630         return indexElement;
631     }
632
633     /**
634      * Collect all the objects that are removed by this operation and store
635      * them in a IObjectManager so that they can be accessed from the appropriate
636      * deltas but not from the registry.
637      */

638     synchronized Map getAssociatedObjects(String JavaDoc contributionId) {
639         //Collect all the objects associated with this contribution
640
int[] xpts = getExtensionPointsFrom(contributionId);
641         int[] exts = getExtensionsFrom(contributionId);
642         Map actualObjects = new HashMap(xpts.length + exts.length);
643         for (int i = 0; i < exts.length; i++) {
644             Extension tmp = (Extension) basicGetObject(exts[i], RegistryObjectManager.EXTENSION);
645             actualObjects.put(new Integer JavaDoc(exts[i]), tmp);
646             collectChildren(tmp, 0, actualObjects);
647         }
648         for (int i = 0; i < xpts.length; i++) {
649             ExtensionPoint xpt = (ExtensionPoint) basicGetObject(xpts[i], RegistryObjectManager.EXTENSION_POINT);
650             actualObjects.put(new Integer JavaDoc(xpts[i]), xpt);
651         }
652
653         return actualObjects;
654     }
655
656     /**
657      * Add to the set of the objects all extensions and extension points that
658      * could be navigated to from the objects in the set.
659      */

660     synchronized void addNavigableObjects(Map associatedObjects) {
661         Map result = new HashMap();
662         for (Iterator iter = associatedObjects.values().iterator(); iter.hasNext();) {
663             RegistryObject object = (RegistryObject) iter.next();
664             if (object instanceof Extension) {
665                 // add extension point
666
ExtensionPoint extPoint = getExtensionPointObject(((Extension) object).getExtensionPointIdentifier());
667                 if (extPoint == null) // already removed?
668
continue;
669
670                 Integer JavaDoc extPointIndex = new Integer JavaDoc(extPoint.getKeyHashCode());
671                 if (!associatedObjects.containsKey(extPointIndex))
672                     result.put(new Integer JavaDoc(extPoint.getKeyHashCode()), extPoint);
673
674                 // add all extensions for the extension point
675
int[] extensions = extPoint.getRawChildren();
676                 for (int j = 0; j < extensions.length; j++) {
677                     Extension tmp = (Extension) basicGetObject(extensions[j], RegistryObjectManager.EXTENSION);
678                     if (tmp == null) // already removed
679
continue;
680                     Integer JavaDoc extensionIndex = new Integer JavaDoc(extensions[j]);
681                     if (!associatedObjects.containsKey(extensionIndex)) {
682                         result.put(extensionIndex, tmp);
683                         collectChildren(tmp, 0, result);
684                     }
685                 }
686             }
687             else if (object instanceof ExtensionPoint) {
688                 // by now extensions of this extension point have been marked as orphans
689
Map orphans = getOrphans();
690                 String JavaDoc name = ((ExtensionPoint)object).getUniqueIdentifier();
691                 int[] extensions = (int[]) orphans.get(name);
692                 if (extensions != null) {
693                     for (int j = 0; j < extensions.length; j++) {
694                         Extension tmp = (Extension) basicGetObject(extensions[j], RegistryObjectManager.EXTENSION);
695                         if (tmp == null) // already removed
696
continue;
697                         Integer JavaDoc extensionIndex = new Integer JavaDoc(extensions[j]);
698                         if (!associatedObjects.containsKey(extensionIndex)) {
699                             result.put(extensionIndex, tmp);
700                             collectChildren(tmp, 0, result);
701                         }
702                     }
703                 }
704             }
705         }
706         associatedObjects.putAll(result);
707     }
708
709     synchronized void removeObjects(Map associatedObjects) {
710         //Remove the objects from the main object manager so they can no longer be accessed.
711
Collection allValues = associatedObjects.values();
712         for (Iterator iter = allValues.iterator(); iter.hasNext();) {
713             RegistryObject toRemove = (RegistryObject) iter.next();
714             remove((toRemove).getObjectId(), true);
715             if (toRemove instanceof ExtensionPoint)
716                 removeExtensionPoint(((ExtensionPoint) toRemove).getUniqueIdentifier());
717         }
718     }
719
720     IObjectManager createDelegatingObjectManager(Map object) {
721         return new TemporaryObjectManager(object, this);
722     }
723
724     private void collectChildren(RegistryObject ce, int level, Map collector) {
725         ConfigurationElement[] children = (ConfigurationElement[]) getObjects(ce.getRawChildren(), level == 0 || ce.noExtraData() ? RegistryObjectManager.CONFIGURATION_ELEMENT : RegistryObjectManager.THIRDLEVEL_CONFIGURATION_ELEMENT);
726         for (int j = 0; j < children.length; j++) {
727             collector.put(new Integer JavaDoc(children[j].getObjectId()), children[j]);
728             collectChildren(children[j], level + 1, collector);
729         }
730     }
731
732     public void close() {
733         //do nothing.
734
}
735
736     public ExtensionRegistry getRegistry() {
737         return registry;
738     }
739
740     // Called from a synchronized method only
741
private boolean unlinkChildFromContributions(KeyedElement[] contributions, int id) {
742         for (int i = 0; i < contributions.length; i++) {
743             Contribution candidate = (Contribution) contributions[i];
744             if (candidate == null)
745                 continue;
746             if (candidate.hasChild(id)) {
747                 candidate.unlinkChild(id);
748                 if (candidate.isEmpty())
749                     removeContribution(candidate.getContributorId());
750                 return true;
751             }
752         }
753         return false;
754     }
755
756     synchronized boolean unlinkChildFromContributions(int id) {
757         if (unlinkChildFromContributions(newContributions.elements, id))
758             return true;
759         return unlinkChildFromContributions(getFormerContributions().elements, id);
760     }
761
762     synchronized public ExtensionPointHandle[] getExtensionPointsFromNamespace(String JavaDoc namespaceName) {
763         RegistryIndexElement indexElement = getNamespaceIndex(namespaceName);
764         int[] namespaceExtensionPoints = indexElement.getExtensionPoints();
765         return (ExtensionPointHandle[]) getHandles(namespaceExtensionPoints, EXTENSION_POINT);
766     }
767
768     static final ExtensionHandle[] EMPTY_EXTENSIONS_ARRAY = new ExtensionHandle[0];
769
770     // This method filters out extensions with no extension point
771
synchronized public ExtensionHandle[] getExtensionsFromNamespace(String JavaDoc namespaceName) {
772         RegistryIndexElement indexElement = getNamespaceIndex(namespaceName);
773         int[] namespaceExtensions = indexElement.getExtensions();
774
775         // filter extensions with no extension point (orphan extensions)
776
List tmp = new ArrayList();
777         Extension[] exts = (Extension[]) getObjects(namespaceExtensions, EXTENSION);
778         for (int i = 0; i < exts.length; i++) {
779             if (getExtensionPointObject(exts[i].getExtensionPointIdentifier()) != null)
780                 tmp.add(getHandle(exts[i].getObjectId(), EXTENSION));
781         }
782         if (tmp.size() == 0)
783             return EMPTY_EXTENSIONS_ARRAY;
784         ExtensionHandle[] result = new ExtensionHandle[tmp.size()];
785         return (ExtensionHandle[]) tmp.toArray(result);
786     }
787 }
788
Popular Tags