KickJava   Java API By Example, From Geeks To Geeks.

Java > Open Source Codes > org > eclipse > core > runtime > dynamichelpers > ExtensionTracker


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.runtime.dynamichelpers;
12
13 import java.util.HashMap JavaDoc;
14 import java.util.Map JavaDoc;
15 import org.eclipse.core.internal.registry.RegistryMessages;
16 import org.eclipse.core.internal.runtime.ReferenceHashSet;
17 import org.eclipse.core.internal.runtime.RuntimeLog;
18 import org.eclipse.core.runtime.IExtension;
19 import org.eclipse.core.runtime.IExtensionDelta;
20 import org.eclipse.core.runtime.IExtensionPoint;
21 import org.eclipse.core.runtime.IExtensionRegistry;
22 import org.eclipse.core.runtime.IRegistryChangeEvent;
23 import org.eclipse.core.runtime.IRegistryChangeListener;
24 import org.eclipse.core.runtime.IStatus;
25 import org.eclipse.core.runtime.ListenerList;
26 import org.eclipse.core.runtime.RegistryFactory;
27 import org.eclipse.core.runtime.Status;
28
29 /**
30  * Implementation of the IExtensionTracker.
31  * <p>
32  * This class can be used without OSGi running.
33  * </p>
34  * @see org.eclipse.core.runtime.dynamichelpers.IExtensionTracker
35  * @since 3.1
36  */

37 public class ExtensionTracker implements IExtensionTracker, IRegistryChangeListener {
38     //Map keeping the association between extensions and a set of objects. Key: IExtension, value: ReferenceHashSet.
39
private Map JavaDoc extensionToObjects = new HashMap JavaDoc();
40     private ListenerList handlers = new ListenerList();
41     private final Object JavaDoc lock = new Object JavaDoc();
42     private boolean closed = false;
43     private IExtensionRegistry registry; // the registry that this tacker works with
44

45     private static final Object JavaDoc[] EMPTY_ARRAY = new Object JavaDoc[0];
46
47     /**
48      * Construct a new instance of the extension tracker.
49      */

50     public ExtensionTracker() {
51         this(RegistryFactory.getRegistry());
52     }
53
54     /**
55      * Construct a new instance of the extension tracker using the given registry
56      * containing tracked extensions and extension points.
57      *
58      * @param theRegistry the extension registry to track
59      * @since org.eclipse.equinox.registry 3.2
60      */

61     public ExtensionTracker(IExtensionRegistry theRegistry) {
62         registry = theRegistry;
63         if (registry != null)
64             registry.addRegistryChangeListener(this);
65         else
66             RuntimeLog.log(new Status(IStatus.ERROR, RegistryMessages.OWNER_NAME, 0, RegistryMessages.registry_no_default, null));
67     }
68
69     /* (non-Javadoc)
70      * @see org.eclipse.core.runtime.dynamichelpers.IExtensionTracker#registerHandler(org.eclipse.core.runtime.dynamichelpers.IExtensionChangeHandler, org.eclipse.core.runtime.dynamichelpers.IFilter)
71      */

72     public void registerHandler(IExtensionChangeHandler handler, IFilter filter) {
73         synchronized (lock) {
74             if (closed)
75                 return;
76             // TODO need to store the filter with the handler
77
handlers.add(new HandlerWrapper(handler, filter));
78         }
79     }
80
81     /* (non-Javadoc)
82      * @see IExtensionTracker@unregisterHandler(IExtensionChangeHandler)
83      */

84     public void unregisterHandler(IExtensionChangeHandler handler) {
85         synchronized (lock) {
86             if (closed)
87                 return;
88             handlers.remove(new HandlerWrapper(handler, null));
89         }
90     }
91
92     /* (non-Javadoc)
93      * @see IExtensionTracker@registerObject(IExtension, Object, int)
94      */

95     public void registerObject(IExtension element, Object JavaDoc object, int referenceType) {
96         if (element == null || object == null)
97             return;
98
99         synchronized (lock) {
100             if (closed)
101                 return;
102
103             ReferenceHashSet associatedObjects = (ReferenceHashSet) extensionToObjects.get(element);
104             if (associatedObjects == null) {
105                 associatedObjects = new ReferenceHashSet();
106                 extensionToObjects.put(element, associatedObjects);
107             }
108             associatedObjects.add(object, referenceType);
109         }
110     }
111
112     /**
113      * Implementation of IRegistryChangeListener interface.
114      * <p>
115      * <em>This method must not be called by clients.</em>
116      * </p>
117      */

118     public void registryChanged(IRegistryChangeEvent event) {
119         IExtensionDelta delta[] = event.getExtensionDeltas();
120         int len = delta.length;
121         for (int i = 0; i < len; i++)
122             switch (delta[i].getKind()) {
123                 case IExtensionDelta.ADDED :
124                     doAdd(delta[i]);
125                     break;
126                 case IExtensionDelta.REMOVED :
127                     doRemove(delta[i]);
128                     break;
129                 default :
130                     break;
131             }
132     }
133
134     /**
135      * Notify all handlers whose filter matches that the given delta occurred.
136      * If the list of objects is not <code>null</code> then this is a removal and
137      * the handlers will be given a chance to process the list. If it is <code>null</code>
138      * then the notification is an addition.
139      *
140      * @param delta the change to broadcast
141      * @param objects the objects to pass to the handlers on removals
142      */

143     private void notify(IExtensionDelta delta, Object JavaDoc[] objects) {
144         // Get a copy of the handlers for safe notification
145
Object JavaDoc[] handlersCopy = null;
146         synchronized (lock) {
147             if (closed)
148                 return;
149
150             if (handlers == null || handlers.isEmpty())
151                 return;
152             handlersCopy = handlers.getListeners();
153         }
154
155         for (int i = 0; i < handlersCopy.length; i++) {
156             HandlerWrapper wrapper = (HandlerWrapper) handlersCopy[i];
157             if (wrapper.filter == null || wrapper.filter.matches(delta.getExtensionPoint())) {
158                 if (objects == null)
159                     applyAdd(wrapper.handler, delta.getExtension());
160                 else
161                     applyRemove(wrapper.handler, delta.getExtension(), objects);
162             }
163         }
164     }
165
166     protected void applyAdd(IExtensionChangeHandler handler, IExtension extension) {
167         handler.addExtension(this, extension);
168     }
169
170     private void doAdd(IExtensionDelta delta) {
171         notify(delta, null);
172     }
173
174     private void doRemove(IExtensionDelta delta) {
175         Object JavaDoc[] removedObjects = null;
176         synchronized (lock) {
177             if (closed)
178                 return;
179
180             ReferenceHashSet associatedObjects = (ReferenceHashSet) extensionToObjects.remove(delta.getExtension());
181             if (associatedObjects == null)
182                 return;
183             //Copy the objects early so we don't hold the lock too long
184
removedObjects = associatedObjects.toArray();
185         }
186         notify(delta, removedObjects);
187     }
188
189     protected void applyRemove(IExtensionChangeHandler handler, IExtension removedExtension, Object JavaDoc[] removedObjects) {
190         handler.removeExtension(removedExtension, removedObjects);
191     }
192
193     /* (non-Javadoc)
194      * @see IExtensionTracker@getObjects(IExtension)
195      */

196     public Object JavaDoc[] getObjects(IExtension element) {
197         synchronized (lock) {
198             if (closed)
199                 return EMPTY_ARRAY;
200             ReferenceHashSet objectSet = (ReferenceHashSet) extensionToObjects.get(element);
201             if (objectSet == null)
202                 return EMPTY_ARRAY;
203
204             return objectSet.toArray();
205         }
206     }
207
208     /* (non-Javadoc)
209      * @see IExtensionTracker@close()
210      */

211     public void close() {
212         synchronized (lock) {
213             if (closed)
214                 return;
215             if (registry != null)
216                 registry.removeRegistryChangeListener(this);
217             extensionToObjects = null;
218             handlers = null;
219
220             closed = true;
221         }
222     }
223
224     /* (non-Javadoc)
225      * @see IExtensionTracker@unregisterObject(IExtension, Object)
226      */

227     public void unregisterObject(IExtension extension, Object JavaDoc object) {
228         synchronized (lock) {
229             if (closed)
230                 return;
231             ReferenceHashSet associatedObjects = (ReferenceHashSet) extensionToObjects.get(extension);
232             if (associatedObjects != null)
233                 associatedObjects.remove(object);
234         }
235     }
236
237     /* (non-Javadoc)
238      * @see IExtensionTracker@unregisterObject(IExtension)
239      */

240     public Object JavaDoc[] unregisterObject(IExtension extension) {
241         synchronized (lock) {
242             if (closed)
243                 return EMPTY_ARRAY;
244             ReferenceHashSet associatedObjects = (ReferenceHashSet) extensionToObjects.remove(extension);
245             if (associatedObjects == null)
246                 return EMPTY_ARRAY;
247             return associatedObjects.toArray();
248         }
249     }
250
251     /**
252      * Return an instance of filter matching all changes for the given extension point.
253      *
254      * @param xpt the extension point
255      * @return a filter
256      */

257     public static IFilter createExtensionPointFilter(final IExtensionPoint xpt) {
258         return new IFilter() {
259             public boolean matches(IExtensionPoint target) {
260                 return xpt.equals(target);
261             }
262         };
263     }
264
265     /**
266      * Return an instance of filter matching all changes for the given extension points.
267      *
268      * @param xpts the extension points used to filter
269      * @return a filter
270      */

271     public static IFilter createExtensionPointFilter(final IExtensionPoint[] xpts) {
272         return new IFilter() {
273             public boolean matches(IExtensionPoint target) {
274                 for (int i = 0; i < xpts.length; i++)
275                     if (xpts[i].equals(target))
276                         return true;
277                 return false;
278             }
279         };
280     }
281
282     /**
283      * Return an instance of filter matching all changes from a given plugin.
284      *
285      * @param id the plugin id
286      * @return a filter
287      */

288     public static IFilter createNamespaceFilter(final String JavaDoc id) {
289         return new IFilter() {
290             public boolean matches(IExtensionPoint target) {
291                 return id.equals(target.getNamespaceIdentifier());
292             }
293         };
294     }
295
296     private class HandlerWrapper {
297         IExtensionChangeHandler handler;
298         IFilter filter;
299
300         public HandlerWrapper(IExtensionChangeHandler handler, IFilter filter) {
301             this.handler = handler;
302             this.filter = filter;
303         }
304
305         public boolean equals(Object JavaDoc target) {
306             return handler.equals(((HandlerWrapper) target).handler);
307         }
308
309         public int hashCode() {
310             return handler.hashCode();
311         }
312     }
313
314 }
315
Popular Tags