KickJava   Java API By Example, From Geeks To Geeks.

Java > Open Source Codes > org > eclipse > core > internal > refresh > MonitorManager


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 - Initial API and implementation
10  *******************************************************************************/

11 package org.eclipse.core.internal.refresh;
12
13 import java.util.*;
14 import org.eclipse.core.internal.events.ILifecycleListener;
15 import org.eclipse.core.internal.events.LifecycleEvent;
16 import org.eclipse.core.internal.resources.Workspace;
17 import org.eclipse.core.internal.utils.Messages;
18 import org.eclipse.core.internal.utils.Policy;
19 import org.eclipse.core.resources.*;
20 import org.eclipse.core.resources.refresh.IRefreshMonitor;
21 import org.eclipse.core.resources.refresh.RefreshProvider;
22 import org.eclipse.core.runtime.*;
23
24 /**
25  * Manages monitors by creating new monitors when projects are added and
26  * removing monitors when projects are removed. Also handles the polling
27  * mechanism when contributed native monitors cannot handle a project.
28  *
29  * @since 3.0
30  */

31 class MonitorManager implements ILifecycleListener, IPathVariableChangeListener, IResourceChangeListener, IResourceDeltaVisitor {
32     /**
33      * The PollingMonitor in charge of doing file-system polls.
34      */

35     protected final PollingMonitor pollMonitor;
36     /**
37      * The list of registered monitor factories.
38      */

39     private RefreshProvider[] providers;
40     /**
41      * Reference to the refresh manager.
42      */

43     protected final RefreshManager refreshManager;
44     /**
45      * A mapping of monitors to a list of resources each monitor is responsible for.
46      */

47     protected final Map registeredMonitors;
48     /**
49      * Reference to the workspace.
50      */

51     protected IWorkspace workspace;
52
53     public MonitorManager(IWorkspace workspace, RefreshManager refreshManager) {
54         this.workspace = workspace;
55         this.refreshManager = refreshManager;
56         registeredMonitors = Collections.synchronizedMap(new HashMap(10));
57         pollMonitor = new PollingMonitor(refreshManager);
58     }
59
60     /**
61      * Queries extensions of the refreshProviders extension point, and
62      * creates the provider classes. Will never return <code>null</code>.
63      *
64      * @return RefreshProvider[] The array of registered <code>RefreshProvider</code>
65      * objects or an empty array.
66      */

67     private RefreshProvider[] getRefreshProviders() {
68         if (providers != null)
69             return providers;
70         IExtensionPoint extensionPoint = Platform.getExtensionRegistry().getExtensionPoint(ResourcesPlugin.PI_RESOURCES, ResourcesPlugin.PT_REFRESH_PROVIDERS);
71         IConfigurationElement[] infos = extensionPoint.getConfigurationElements();
72         List providerList = new ArrayList(infos.length);
73         for (int i = 0; i < infos.length; i++) {
74             IConfigurationElement configurationElement = infos[i];
75             RefreshProvider provider = null;
76             try {
77                 provider = (RefreshProvider) configurationElement.createExecutableExtension("class"); //$NON-NLS-1$
78
} catch (CoreException e) {
79                 Policy.log(IStatus.WARNING, Messages.refresh_installError, e);
80             }
81             if (provider != null)
82                 providerList.add(provider);
83         }
84         providers = (RefreshProvider[]) providerList.toArray(new RefreshProvider[providerList.size()]);
85         return providers;
86     }
87
88     /**
89      * Collects the set of root resources that required monitoring. This
90      * includes projects and all linked resources.
91      */

92     private List getResourcesToMonitor() {
93         final List resourcesToMonitor = new ArrayList(10);
94         IProject[] projects = workspace.getRoot().getProjects();
95         for (int i = 0; i < projects.length; i++) {
96             if (!projects[i].isAccessible())
97                 continue;
98             resourcesToMonitor.add(projects[i]);
99             try {
100                 IResource[] members = projects[i].members();
101                 for (int j = 0; j < members.length; j++)
102                     if (members[j].isLinked())
103                         resourcesToMonitor.add(members[j]);
104             } catch (CoreException e) {
105                 Policy.log(IStatus.WARNING, Messages.refresh_refreshErr, e);
106             }
107         }
108         return resourcesToMonitor;
109     }
110
111     public void handleEvent(LifecycleEvent event) {
112         switch (event.kind) {
113             case LifecycleEvent.PRE_LINK_DELETE:
114             case LifecycleEvent.PRE_PROJECT_CLOSE:
115             case LifecycleEvent.PRE_PROJECT_DELETE:
116                 unmonitor(event.resource);
117                 break;
118         }
119     }
120
121     private boolean isMonitoring(IResource resource) {
122         synchronized (registeredMonitors) {
123             for (Iterator i = registeredMonitors.keySet().iterator(); i.hasNext();) {
124                 List resources = (List) registeredMonitors.get(i.next());
125                 if ((resources != null) && (resources.contains(resource)))
126                     return true;
127             }
128         }
129         return false;
130     }
131
132     /**
133      * Installs a monitor on the given resource. Returns true if the polling
134      * monitor was installed, and false if a refresh provider was installed.
135      */

136     boolean monitor(IResource resource) {
137         if (isMonitoring(resource))
138             return false;
139         boolean pollingMonitorNeeded = true;
140         RefreshProvider[] refreshProviders = getRefreshProviders();
141         for (int i = 0; i < refreshProviders.length; i++) {
142             IRefreshMonitor monitor = safeInstallMonitor(refreshProviders[i], resource);
143             if (monitor != null) {
144                 registerMonitor(monitor, resource);
145                 pollingMonitorNeeded = false;
146             }
147         }
148         if (pollingMonitorNeeded) {
149             pollMonitor.monitor(resource);
150             registerMonitor(pollMonitor, resource);
151         }
152         return pollingMonitorNeeded;
153     }
154
155     /* (non-Javadoc)
156      * @see IRefreshResult#monitorFailed
157      */

158     public void monitorFailed(IRefreshMonitor monitor, IResource resource) {
159         if (RefreshManager.DEBUG)
160             System.err.println(RefreshManager.DEBUG_PREFIX + " monitor (" + monitor + ") failed to monitor resource: " + resource); //$NON-NLS-1$ //$NON-NLS-2$
161
if (registeredMonitors == null || monitor == null)
162             return;
163         if (resource == null) {
164             List resources = (List) registeredMonitors.get(monitor);
165             if (resources == null || resources.isEmpty()) {
166                 registeredMonitors.remove(monitor);
167                 return;
168             }
169             // synchronized: protect the collection during iteration
170
synchronized (registeredMonitors) {
171                 for (Iterator i = resources.iterator(); i.hasNext();) {
172                     resource = (IResource) i.next();
173                     pollMonitor.monitor(resource);
174                     registerMonitor(pollMonitor, resource);
175                 }
176                 registeredMonitors.remove(monitor);
177             }
178         } else {
179             removeMonitor(monitor, resource);
180             pollMonitor.monitor(resource);
181             registerMonitor(pollMonitor, resource);
182         }
183     }
184
185     /**
186      * @see org.eclipse.core.resources.IPathVariableChangeListener#pathVariableChanged(org.eclipse.core.resources.IPathVariableChangeEvent)
187      */

188     public void pathVariableChanged(IPathVariableChangeEvent event) {
189         if (registeredMonitors.isEmpty())
190             return;
191         String JavaDoc variableName = event.getVariableName();
192         Set invalidResources = new HashSet();
193         for (Iterator i = registeredMonitors.values().iterator(); i.hasNext();) {
194             for (Iterator j = ((List) i.next()).iterator(); j.hasNext();) {
195                 IResource resource = (IResource) j.next();
196                 IPath rawLocation = resource.getRawLocation();
197                 if (rawLocation != null) {
198                     if (rawLocation.segmentCount() > 0 && variableName.equals(rawLocation.segment(0)) && !invalidResources.contains(resource)) {
199                         invalidResources.add(resource);
200                     }
201                 }
202             }
203         }
204         if (!invalidResources.isEmpty()) {
205             for (Iterator i = invalidResources.iterator(); i.hasNext();) {
206                 IResource resource = (IResource) i.next();
207                 unmonitor(resource);
208                 monitor(resource);
209             }
210         }
211     }
212
213     private void registerMonitor(IRefreshMonitor monitor, IResource resource) {
214         // synchronized: protect the collection during add
215
synchronized (registeredMonitors) {
216             List resources = (List) registeredMonitors.get(monitor);
217             if (resources == null) {
218                 resources = new ArrayList(1);
219                 registeredMonitors.put(monitor, resources);
220             }
221             if (!resources.contains(resource))
222                 resources.add(resource);
223         }
224         if (RefreshManager.DEBUG)
225             System.out.println(RefreshManager.DEBUG_PREFIX + " added monitor (" + monitor + ") on resource: " + resource); //$NON-NLS-1$ //$NON-NLS-2$
226
}
227
228     private void removeMonitor(IRefreshMonitor monitor, IResource resource) {
229         // synchronized: protect the collection during remove
230
synchronized (registeredMonitors) {
231             List resources = (List) registeredMonitors.get(monitor);
232             if (resources != null && !resources.isEmpty())
233                 resources.remove(resource);
234             else
235                 registeredMonitors.remove(monitor);
236         }
237         if (RefreshManager.DEBUG)
238             System.out.println(RefreshManager.DEBUG_PREFIX + " removing monitor (" + monitor + ") on resource: " + resource); //$NON-NLS-1$ //$NON-NLS-2$
239
}
240
241     private IRefreshMonitor safeInstallMonitor(RefreshProvider provider, IResource resource) {
242         Throwable JavaDoc t = null;
243         try {
244             return provider.installMonitor(resource, refreshManager);
245         } catch (Exception JavaDoc e) {
246             t = e;
247         } catch (LinkageError JavaDoc e) {
248             t = e;
249         }
250         IStatus error = new Status(IStatus.ERROR, ResourcesPlugin.PI_RESOURCES, 1, Messages.refresh_installError, t);
251         Policy.log(error);
252         return null;
253     }
254
255     /**
256      * Start the monitoring of resources by all monitors.
257      */

258     public void start() {
259         boolean refreshNeeded = false;
260         for (Iterator i = getResourcesToMonitor().iterator(); i.hasNext();)
261             refreshNeeded |= !monitor((IResource) i.next());
262         workspace.getPathVariableManager().addChangeListener(this);
263         workspace.addResourceChangeListener(this, IResourceChangeEvent.POST_CHANGE);
264         //adding the lifecycle listener twice does no harm
265
((Workspace)workspace).addLifecycleListener(this);
266         if (RefreshManager.DEBUG)
267             System.out.println(RefreshManager.DEBUG_PREFIX + " starting monitor manager."); //$NON-NLS-1$
268
//If not exclusively using polling, create a polling monitor and run it once, to catch
269
//changes that occurred while the native monitor was turned off.
270
if (refreshNeeded)
271             new PollingMonitor(refreshManager).runOnce();
272     }
273
274     /**
275      * Stop the monitoring of resources by all monitors.
276      */

277     public void stop() {
278         workspace.removeResourceChangeListener(this);
279         workspace.getPathVariableManager().removeChangeListener(this);
280         // synchronized: protect the collection during iteration
281
synchronized (registeredMonitors) {
282             for (Iterator i = registeredMonitors.keySet().iterator(); i.hasNext();) {
283                 IRefreshMonitor monitor = (IRefreshMonitor) i.next();
284                 monitor.unmonitor(null);
285             }
286         }
287         registeredMonitors.clear();
288         if (RefreshManager.DEBUG)
289             System.out.println(RefreshManager.DEBUG_PREFIX + " stopping monitor manager."); //$NON-NLS-1$
290
pollMonitor.cancel();
291     }
292
293     void unmonitor(IResource resource) {
294         if (resource == null || !isMonitoring(resource))
295             return;
296         synchronized (registeredMonitors) {
297             for (Iterator i = registeredMonitors.entrySet().iterator(); i.hasNext();) {
298                 Map.Entry current = (Map.Entry) i.next();
299                 List resources = (List) current.getValue();
300                 if ((resources != null) && !resources.isEmpty() && resources.contains(resource)) {
301                     ((IRefreshMonitor) current.getKey()).unmonitor(resource);
302                     resources.remove(resource);
303                 }
304             }
305         }
306         if (resource.getType() == IResource.PROJECT)
307             unmonitorLinkedContents((IProject)resource);
308     }
309
310     private void unmonitorLinkedContents(IProject project) {
311         if (!project.isAccessible())
312             return;
313         IResource[] children = null;
314         try {
315             children = project.members();
316         } catch (CoreException e) {
317             Policy.log(IStatus.WARNING, Messages.refresh_refreshErr, e);
318         }
319         if (children != null && children.length > 0)
320             for (int i = 0; i < children.length; i++)
321                 if (children[i].isLinked())
322                     unmonitor(children[i]);
323     }
324
325     public void resourceChanged(IResourceChangeEvent event) {
326         IResourceDelta delta = event.getDelta();
327         if (delta == null)
328             return;
329         try {
330             delta.accept(this);
331         } catch (CoreException e) {
332             //cannot happen as our visitor doesn't throw exceptions
333
}
334     }
335
336     public boolean visit(IResourceDelta delta) {
337         if (delta.getKind () == IResourceDelta.ADDED) {
338             IResource resource = delta.getResource();
339             if (resource.isLinked())
340                 monitor(resource);
341         }
342         if ((delta.getFlags() & IResourceDelta.OPEN) != 0) {
343             IProject project = (IProject) delta.getResource();
344             if (project.isAccessible())
345                 monitor(project);
346         }
347         return true;
348     }
349 }
350
Popular Tags