KickJava   Java API By Example, From Geeks To Geeks.

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


1 /*******************************************************************************
2  * Copyright (c) 2004, 2005 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.utils.Messages;
15 import org.eclipse.core.internal.utils.Policy;
16 import org.eclipse.core.resources.*;
17 import org.eclipse.core.runtime.*;
18 import org.eclipse.osgi.util.NLS;
19
20 /**
21  * The <code>RefreshJob</code> class maintains a list of resources that
22  * need to be refreshed, and periodically schedules itself to perform the
23  * refreshes in the background.
24  *
25  * @since 3.0
26  */

27 public class RefreshJob extends WorkspaceJob {
28     private static final long UPDATE_DELAY = 200;
29     /**
30      * List of refresh requests. Requests are processed in order from
31      * the end of the list. Requests can be added to either the beginning
32      * or the end of the list depending on whether they are explicit user
33      * requests or background refresh requests.
34      */

35     private final List fRequests;
36
37     public RefreshJob() {
38         super(Messages.refresh_jobName);
39         fRequests = new ArrayList(1);
40     }
41
42     /**
43      * Adds the given resource to the set of resources that need refreshing.
44      * Synchronized in order to protect the collection during add.
45      * @param resource
46      */

47     private synchronized void addRequest(IResource resource) {
48         IPath toAdd = resource.getFullPath();
49         for (Iterator it = fRequests.iterator(); it.hasNext();) {
50             IPath request = ((IResource) it.next()).getFullPath();
51             //discard any existing requests the same or below the resource to be added
52
if (toAdd.isPrefixOf(request))
53                 it.remove();
54             //nothing to do if the resource to be added is a child of an existing request
55
else if (request.isPrefixOf(toAdd))
56                 return;
57         }
58         //finally add the new request to the front of the queue
59
fRequests.add(resource);
60     }
61
62     private synchronized void addRequests(List list) {
63         //add requests to the end of the queue
64
fRequests.addAll(0, list);
65     }
66
67     /* (non-Javadoc)
68      * @see org.eclipse.core.runtime.jobs.Job#belongsTo(Object)
69      */

70     public boolean belongsTo(Object JavaDoc family) {
71         return family == ResourcesPlugin.FAMILY_AUTO_REFRESH;
72     }
73
74     /**
75      * This method adds all members at the specified depth from the resource
76      * to the provided list.
77      */

78     private List collectChildrenToDepth(IResource resource, ArrayList children, int depth) {
79         if (resource.getType() == IResource.FILE)
80             return children;
81         IResource[] members;
82         try {
83             members = ((IContainer) resource).members();
84         } catch (CoreException e) {
85             //resource is not accessible - just return what we have
86
return children;
87         }
88         for (int i = 0; i < members.length; i++) {
89             if (members[i].getType() == IResource.FILE)
90                 continue;
91             if (depth <= 1)
92                 children.add(members[i]);
93             else
94                 collectChildrenToDepth(members[i], children, depth - 1);
95         }
96         return children;
97     }
98
99     /**
100      * Returns the next item to refresh, or <code>null</code> if there are no requests
101      */

102     private synchronized IResource nextRequest() {
103         // synchronized: in order to atomically obtain and clear requests
104
int len = fRequests.size();
105         if (len == 0)
106             return null;
107         return (IResource) fRequests.remove(len - 1);
108     }
109
110     /* (non-Javadoc)
111      * @see org.eclipse.core.resources.refresh.IRefreshResult#refresh
112      */

113     public void refresh(IResource resource) {
114         if (resource == null)
115             return;
116         addRequest(resource);
117         schedule(UPDATE_DELAY);
118     }
119
120     /* (non-Javadoc)
121      * @see WorkspaceJob#runInWorkspace
122      */

123     public IStatus runInWorkspace(IProgressMonitor monitor) {
124         long start = System.currentTimeMillis();
125         String JavaDoc msg = Messages.refresh_refreshErr;
126         MultiStatus errors = new MultiStatus(ResourcesPlugin.PI_RESOURCES, 1, msg, null);
127         long longestRefresh = 0;
128         try {
129             if (RefreshManager.DEBUG)
130                 Policy.debug(RefreshManager.DEBUG_PREFIX + " starting refresh job"); //$NON-NLS-1$
131
int refreshCount = 0;
132             int depth = 2;
133             monitor.beginTask("", IProgressMonitor.UNKNOWN); //$NON-NLS-1$
134
IResource toRefresh;
135             while ((toRefresh = nextRequest()) != null) {
136                 if (monitor.isCanceled())
137                     throw new OperationCanceledException();
138                 try {
139                     refreshCount++;
140                     long refreshTime = -System.currentTimeMillis();
141                     toRefresh.refreshLocal(1000 + depth, null);
142                     refreshTime += System.currentTimeMillis();
143                     if (refreshTime > longestRefresh)
144                         longestRefresh = refreshTime;
145                     //show occasional progress
146
if (refreshCount % 100 == 0)
147                         monitor.subTask(NLS.bind(Messages.refresh_task, Integer.toString(fRequests.size())));
148                     if (refreshCount % 1000 == 0) {
149                         //be polite to other threads (no effect on some platforms)
150
Thread.yield();
151                         //throttle depth if it takes too long
152
if (longestRefresh > 2000 && depth > 1) {
153                             depth = 1;
154                         }
155                         if (longestRefresh < 1000) {
156                             depth *= 2;
157                         }
158                         longestRefresh = 0;
159                     }
160                     addRequests(collectChildrenToDepth(toRefresh, new ArrayList(), depth));
161                 } catch (CoreException e) {
162                     errors.merge(new Status(IStatus.ERROR, ResourcesPlugin.PI_RESOURCES, 1, errors.getMessage(), e));
163                 }
164             }
165         } finally {
166             monitor.done();
167             if (RefreshManager.DEBUG)
168                 System.out.println(RefreshManager.DEBUG_PREFIX + " finished refresh job in: " + (System.currentTimeMillis() - start) + "ms"); //$NON-NLS-1$ //$NON-NLS-2$
169
}
170         if (!errors.isOK())
171             return errors;
172         return Status.OK_STATUS;
173     }
174
175     /* (non-Javadoc)
176      * @see org.eclipse.core.runtime.jobs.Job#shouldRun()
177      */

178     public synchronized boolean shouldRun() {
179         return !fRequests.isEmpty();
180     }
181
182     /**
183      * Starts the refresh job
184      */

185     public void start() {
186         if (RefreshManager.DEBUG)
187             System.out.println(RefreshManager.DEBUG_PREFIX + " enabling auto-refresh"); //$NON-NLS-1$
188
}
189
190     /**
191      * Stops the refresh job
192      */

193     public void stop() {
194         if (RefreshManager.DEBUG)
195             System.out.println(RefreshManager.DEBUG_PREFIX + " disabling auto-refresh"); //$NON-NLS-1$
196
cancel();
197     }
198 }
199
Popular Tags