1 11 package org.eclipse.core.filebuffers.manipulation; 12 13 import java.util.ArrayList ; 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 52 public class GenericFileBufferOperationRunner { 53 54 55 private final Object fValidationContext; 56 57 private final IFileBufferManager fFileBufferManager; 58 59 60 private final Object fCompletionLock= new Object (); 61 62 private transient boolean fIsCompleted; 63 64 private transient Throwable fThrowable; 65 66 67 73 public GenericFileBufferOperationRunner(IFileBufferManager fileBufferManager, Object validationContext) { 74 fFileBufferManager= fileBufferManager; 75 fValidationContext= validationContext; 76 } 77 78 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 () { 114 public void run() { 115 synchronized(fCompletionLock) { 116 try { 117 SafeRunner.run(new ISafeRunnable() { 118 public void handleException(Throwable throwable) { 119 fThrowable= throwable; 120 } 121 public void run() throws Exception { 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 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 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 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 list= new ArrayList (); 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 list= new ArrayList (); 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 list= new ArrayList (); 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 list= new ArrayList (); 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 |