KickJava   Java API By Example, From Geeks To Geeks.

Java > Open Source Codes > org > eclipse > core > filebuffers > manipulation > GenericFileBufferOperationRunner


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

11 package org.eclipse.core.filebuffers.manipulation;
12
13 import java.util.ArrayList JavaDoc;
14
15 import org.eclipse.core.internal.filebuffers.FileBuffersPlugin;
16 import org.eclipse.core.internal.filebuffers.Progress;
17 import org.eclipse.core.internal.filebuffers.TextFileBufferManager;
18
19 import org.eclipse.core.runtime.CoreException;
20 import org.eclipse.core.runtime.IPath;
21 import org.eclipse.core.runtime.IProgressMonitor;
22 import org.eclipse.core.runtime.ISafeRunnable;
23 import org.eclipse.core.runtime.IStatus;
24 import org.eclipse.core.runtime.OperationCanceledException;
25 import org.eclipse.core.runtime.SafeRunner;
26 import org.eclipse.core.runtime.Status;
27 import org.eclipse.core.runtime.jobs.IJobManager;
28 import org.eclipse.core.runtime.jobs.ISchedulingRule;
29 import org.eclipse.core.runtime.jobs.Job;
30 import org.eclipse.core.runtime.jobs.MultiRule;
31
32 import org.eclipse.core.filebuffers.FileBuffers;
33 import org.eclipse.core.filebuffers.IFileBuffer;
34 import org.eclipse.core.filebuffers.IFileBufferManager;
35 import org.eclipse.core.filebuffers.IFileBufferStatusCodes;
36 import org.eclipse.core.filebuffers.ITextFileBuffer;
37 import org.eclipse.core.filebuffers.ITextFileBufferManager;
38 import org.eclipse.core.filebuffers.LocationKind;
39
40
41 /**
42  * A <code>GenericFileBufferOperationRunner</code> executes
43  * {@link org.eclipse.core.filebuffers.manipulation.IFileBufferOperation}.
44  * The runner takes care of all aspects that are not operation specific.
45  * <p>
46  * This class is not intended to be subclassed. Clients instantiate this class.
47  * </p>
48  *
49  * @see org.eclipse.core.filebuffers.manipulation.IFileBufferOperation
50  * @since 3.3
51  */

52 public class GenericFileBufferOperationRunner {
53
54     /** The validation context */
55     private final Object JavaDoc fValidationContext;
56     /** The file buffer manager */
57     private final IFileBufferManager fFileBufferManager;
58
59     /** The lock for waiting for completion of computation in the UI thread. */
60     private final Object JavaDoc fCompletionLock= new Object JavaDoc();
61     /** The flag indicating completion of computation in the UI thread. */
62     private transient boolean fIsCompleted;
63     /** The exception thrown during the computation in the UI thread. */
64     private transient Throwable JavaDoc fThrowable;
65
66
67     /**
68      * Creates a new file buffer operation runner.
69      *
70      * @param fileBufferManager the file buffer manager
71      * @param validationContext the validationContext
72      */

73     public GenericFileBufferOperationRunner(IFileBufferManager fileBufferManager, Object JavaDoc validationContext) {
74         fFileBufferManager= fileBufferManager;
75         fValidationContext= validationContext;
76     }
77
78     /**
79      * Executes the given operation for all file buffers specified by the given locations.
80      *
81      * @param locations the file buffer locations
82      * @param operation the operation to be performed
83      * @param monitor the progress monitor
84      * @throws CoreException in case of error
85      * @throws OperationCanceledException in case the execution get canceled
86      */

87     public void execute(IPath[] locations, final IFileBufferOperation operation, IProgressMonitor monitor) throws CoreException, OperationCanceledException {
88         final int size= locations.length;
89         final IProgressMonitor progressMonitor= Progress.getMonitor(monitor);
90         progressMonitor.beginTask(operation.getOperationName(), size * 200);
91         try {
92
93
94             IProgressMonitor subMonitor= Progress.getSubMonitor(progressMonitor, size * 10);
95             IFileBuffer[] fileBuffers= createFileBuffers(locations, subMonitor);
96             subMonitor.done();
97
98             IFileBuffer[] fileBuffers2Save= findFileBuffersToSave(fileBuffers);
99             subMonitor= Progress.getSubMonitor(progressMonitor, size * 10);
100             fFileBufferManager.validateState(fileBuffers2Save, subMonitor, fValidationContext);
101             subMonitor.done();
102             if (!isCommitable(fileBuffers2Save))
103                 throw new OperationCanceledException();
104
105             IFileBuffer[] unsynchronizedFileBuffers= findUnsynchronizedFileBuffers(fileBuffers);
106             performOperation(unsynchronizedFileBuffers, operation, progressMonitor) ;
107
108             final IFileBuffer[] synchronizedFileBuffers= findSynchronizedFileBuffers(fileBuffers);
109             fIsCompleted= false;
110             fThrowable= null;
111             synchronized (fCompletionLock) {
112
113                 executeInContext(new Runnable JavaDoc() {
114                     public void run() {
115                         synchronized(fCompletionLock) {
116                             try {
117                                 SafeRunner.run(new ISafeRunnable() {
118                                     public void handleException(Throwable JavaDoc throwable) {
119                                         fThrowable= throwable;
120                                     }
121                                     public void run() throws Exception JavaDoc {
122                                         performOperation(synchronizedFileBuffers, operation, progressMonitor);
123                                     }
124                                 });
125                             } finally {
126                                 fIsCompleted= true;
127                                 fCompletionLock.notifyAll();
128                             }
129                         }
130                     }
131                 });
132
133                 while (!fIsCompleted) {
134                     try {
135                         fCompletionLock.wait(500);
136                     } catch (InterruptedException JavaDoc x) {
137                     }
138                 }
139             }
140
141             if (fThrowable != null) {
142                 if (fThrowable instanceof CoreException)
143                     throw (CoreException) fThrowable;
144                 throw new CoreException(new Status(IStatus.ERROR, FileBuffersPlugin.PLUGIN_ID, IFileBufferStatusCodes.CONTENT_CHANGE_FAILED, fThrowable.getLocalizedMessage(), fThrowable));
145             }
146
147             subMonitor= Progress.getSubMonitor(progressMonitor, size * 80);
148             commit(fileBuffers2Save, subMonitor);
149             subMonitor.done();
150
151         } finally {
152             try {
153                 IProgressMonitor subMonitor= Progress.getSubMonitor(progressMonitor, size * 10);
154                 releaseFileBuffers(locations, subMonitor);
155                 subMonitor.done();
156             } finally {
157                 progressMonitor.done();
158             }
159         }
160     }
161
162     private void performOperation(IFileBuffer fileBuffer, IFileBufferOperation operation, IProgressMonitor progressMonitor) throws CoreException, OperationCanceledException {
163
164         ISchedulingRule rule= fileBuffer.computeCommitRule();
165         IJobManager manager= Job.getJobManager();
166         try {
167             manager.beginRule(rule, progressMonitor);
168
169             String JavaDoc name= fileBuffer.getLocation().lastSegment();
170             progressMonitor.beginTask(name, 100);
171             try {
172                 IProgressMonitor subMonitor= Progress.getSubMonitor(progressMonitor, 100);
173                 operation.run(fileBuffer, subMonitor);
174                 subMonitor.done();
175             } finally {
176                 progressMonitor.done();
177             }
178
179         } finally {
180             manager.endRule(rule);
181         }
182     }
183
184     private void performOperation(IFileBuffer[] fileBuffers, IFileBufferOperation operation, IProgressMonitor progressMonitor) throws CoreException, OperationCanceledException {
185         for (int i= 0; i < fileBuffers.length; i++) {
186             if (progressMonitor.isCanceled())
187                 throw new OperationCanceledException();
188             IProgressMonitor subMonitor= Progress.getSubMonitor(progressMonitor, 100);
189             performOperation(fileBuffers[i], operation, subMonitor);
190             subMonitor.done();
191         }
192     }
193
194     private void executeInContext(Runnable JavaDoc runnable) {
195         ITextFileBufferManager fileBufferManager= FileBuffers.getTextFileBufferManager();
196         if (fileBufferManager instanceof TextFileBufferManager) {
197             TextFileBufferManager manager= (TextFileBufferManager) fileBufferManager;
198             manager.execute(runnable, true);
199         } else {
200             runnable.run();
201         }
202     }
203
204     private IFileBuffer[] findUnsynchronizedFileBuffers(IFileBuffer[] fileBuffers) {
205         ArrayList JavaDoc list= new ArrayList JavaDoc();
206         for (int i= 0; i < fileBuffers.length; i++) {
207             if (!fileBuffers[i].isSynchronizationContextRequested())
208                 list.add(fileBuffers[i]);
209         }
210         return (IFileBuffer[]) list.toArray(new IFileBuffer[list.size()]);
211     }
212
213     private IFileBuffer[] findSynchronizedFileBuffers(IFileBuffer[] fileBuffers) {
214         ArrayList JavaDoc list= new ArrayList JavaDoc();
215         for (int i= 0; i < fileBuffers.length; i++) {
216             if (fileBuffers[i].isSynchronizationContextRequested())
217                 list.add(fileBuffers[i]);
218         }
219         return (IFileBuffer[]) list.toArray(new IFileBuffer[list.size()]);
220     }
221
222     private IFileBuffer[] createFileBuffers(IPath[] locations, IProgressMonitor progressMonitor) throws CoreException {
223         progressMonitor.beginTask(FileBuffersMessages.FileBufferOperationRunner_task_connecting, locations.length);
224         try {
225             IFileBuffer[] fileBuffers= new ITextFileBuffer[locations.length];
226             for (int i= 0; i < locations.length; i++) {
227                 IProgressMonitor subMonitor= Progress.getSubMonitor(progressMonitor, 1);
228                 fFileBufferManager.connect(locations[i], LocationKind.NORMALIZE, subMonitor);
229                 subMonitor.done();
230                 fileBuffers[i]= fFileBufferManager.getFileBuffer(locations[i], LocationKind.NORMALIZE);
231             }
232             return fileBuffers;
233
234         } catch (CoreException x) {
235             try {
236                 releaseFileBuffers(locations, Progress.getMonitor());
237             } catch (CoreException e) {
238             }
239             throw x;
240         } finally {
241             progressMonitor.done();
242         }
243     }
244
245     private void releaseFileBuffers(IPath[] locations, IProgressMonitor progressMonitor) throws CoreException {
246         progressMonitor.beginTask(FileBuffersMessages.FileBufferOperationRunner_task_disconnecting, locations.length);
247         try {
248             final ITextFileBufferManager fileBufferManager= FileBuffers.getTextFileBufferManager();
249             for (int i= 0; i < locations.length; i++) {
250                 IProgressMonitor subMonitor= Progress.getSubMonitor(progressMonitor, 1);
251                 fileBufferManager.disconnect(locations[i], LocationKind.NORMALIZE, subMonitor);
252                 subMonitor.done();
253             }
254         } finally {
255             progressMonitor.done();
256         }
257     }
258
259     private IFileBuffer[] findFileBuffersToSave(IFileBuffer[] fileBuffers) {
260         ArrayList JavaDoc list= new ArrayList JavaDoc();
261         for (int i= 0; i < fileBuffers.length; i++) {
262             IFileBuffer buffer= fileBuffers[i];
263             if (!buffer.isDirty())
264                 list.add(buffer);
265         }
266         return (IFileBuffer[]) list.toArray(new IFileBuffer[list.size()]);
267     }
268
269     private boolean isCommitable(IFileBuffer[] fileBuffers) {
270         for (int i= 0; i < fileBuffers.length; i++) {
271             if (!fileBuffers[i].isCommitable())
272                 return false;
273         }
274         return true;
275     }
276
277     protected ISchedulingRule computeCommitRule(IFileBuffer[] fileBuffers) {
278         ArrayList JavaDoc list= new ArrayList JavaDoc();
279         for (int i= 0; i < fileBuffers.length; i++) {
280             ISchedulingRule rule= fileBuffers[i].computeCommitRule();
281             if (rule != null)
282                 list.add(rule);
283         }
284         ISchedulingRule[] rules= new ISchedulingRule[list.size()];
285         list.toArray(rules);
286         return new MultiRule(rules);
287     }
288
289     protected void commit(final IFileBuffer[] fileBuffers, final IProgressMonitor progressMonitor) throws CoreException {
290         IProgressMonitor monitor= Progress.getMonitor(progressMonitor);
291         ISchedulingRule rule= computeCommitRule(fileBuffers);
292         Job.getJobManager().beginRule(rule, progressMonitor);
293         try {
294             doCommit(fileBuffers, progressMonitor);
295         } finally {
296             Job.getJobManager().endRule(rule);
297             monitor.done();
298         }
299     }
300
301     protected void doCommit(final IFileBuffer[] fileBuffers, IProgressMonitor progressMonitor) throws CoreException {
302         IProgressMonitor monitor= Progress.getMonitor(progressMonitor);
303         monitor.beginTask(FileBuffersMessages.FileBufferOperationRunner_task_committing, fileBuffers.length);
304         try {
305             for (int i= 0; i < fileBuffers.length; i++) {
306                 IProgressMonitor subMonitor= Progress.getSubMonitor(monitor, 1);
307                 fileBuffers[i].commit(subMonitor, true);
308                 subMonitor.done();
309             }
310         } finally {
311             monitor.done();
312         }
313     }
314
315 }
316
Popular Tags