1 11 package org.eclipse.core.internal.filebuffers; 12 13 import java.io.IOException ; 14 import java.io.InputStream ; 15 import java.util.ArrayList ; 16 import java.util.HashMap ; 17 import java.util.Iterator ; 18 import java.util.List ; 19 import java.util.Map ; 20 21 import org.eclipse.core.filesystem.EFS; 22 import org.eclipse.core.filesystem.IFileInfo; 23 import org.eclipse.core.filesystem.IFileStore; 24 import org.eclipse.core.filesystem.URIUtil; 25 26 import org.eclipse.core.runtime.Assert; 27 import org.eclipse.core.runtime.CoreException; 28 import org.eclipse.core.runtime.IPath; 29 import org.eclipse.core.runtime.IProgressMonitor; 30 import org.eclipse.core.runtime.ISafeRunnable; 31 import org.eclipse.core.runtime.IStatus; 32 import org.eclipse.core.runtime.Platform; 33 import org.eclipse.core.runtime.SafeRunner; 34 import org.eclipse.core.runtime.Status; 35 import org.eclipse.core.runtime.content.IContentDescription; 36 import org.eclipse.core.runtime.content.IContentType; 37 import org.eclipse.core.runtime.content.IContentTypeManager; 38 39 import org.eclipse.core.filebuffers.IAnnotationModelFactory; 40 import org.eclipse.core.filebuffers.IDocumentFactory; 41 import org.eclipse.core.filebuffers.IDocumentSetupParticipant; 42 import org.eclipse.core.filebuffers.IFileBuffer; 43 import org.eclipse.core.filebuffers.IFileBufferListener; 44 import org.eclipse.core.filebuffers.IFileBufferStatusCodes; 45 import org.eclipse.core.filebuffers.ISynchronizationContext; 46 import org.eclipse.core.filebuffers.ITextFileBuffer; 47 import org.eclipse.core.filebuffers.ITextFileBufferManager; 48 import org.eclipse.core.filebuffers.LocationKind; 49 50 import org.eclipse.jface.text.IDocument; 51 import org.eclipse.jface.text.IDocumentExtension4; 52 import org.eclipse.jface.text.source.IAnnotationModel; 53 54 55 58 public class TextFileBufferManager implements ITextFileBufferManager { 59 60 private static abstract class SafeNotifier implements ISafeRunnable { 61 public void handleException(Throwable ex) { 62 IStatus status= new Status(IStatus.ERROR, FileBuffersPlugin.PLUGIN_ID, IStatus.OK, "TextFileBufferManager failed to notify an ITextFileBufferListener", ex); FileBuffersPlugin.getDefault().getLog().log(status); 64 } 65 } 66 67 protected static final IContentType TEXT_CONTENT_TYPE= Platform.getContentTypeManager().getContentType(IContentTypeManager.CT_TEXT); 68 69 private Map fFilesBuffers= new HashMap (); 70 private Map fFileStoreFileBuffers= new HashMap (); 71 private List fFileBufferListeners= new ArrayList (); 72 protected ExtensionsRegistry fRegistry; 73 private ISynchronizationContext fSynchronizationContext; 74 75 76 public TextFileBufferManager() { 77 fRegistry= new ExtensionsRegistry(); 78 } 79 80 83 public void connect(IPath location, IProgressMonitor monitor) throws CoreException { 84 connect(location, LocationKind.NORMALIZE, monitor); 85 } 86 87 91 public void connect(IPath location, LocationKind locationKind, IProgressMonitor monitor) throws CoreException { 92 Assert.isNotNull(location); 93 if (locationKind == LocationKind.NORMALIZE) 94 location= normalizeLocation(location); 95 96 AbstractFileBuffer fileBuffer= null; 97 synchronized (fFilesBuffers) { 98 fileBuffer= internalGetFileBuffer(location); 99 if (fileBuffer != null) { 100 fileBuffer.connect(); 101 return; 102 } 103 } 104 105 fileBuffer= createFileBuffer(location, locationKind); 106 if (fileBuffer == null) 107 throw new CoreException(new Status(IStatus.ERROR, FileBuffersPlugin.PLUGIN_ID, IFileBufferStatusCodes.CREATION_FAILED, FileBuffersMessages.FileBufferManager_error_canNotCreateFilebuffer, null)); 108 109 fileBuffer.create(location, monitor); 110 111 synchronized (fFilesBuffers) { 112 AbstractFileBuffer oldFileBuffer= internalGetFileBuffer(location); 113 if (oldFileBuffer != null) { 114 fileBuffer.disconnect(); 115 fileBuffer.dispose(); 116 oldFileBuffer.connect(); 117 return; 118 } 119 fileBuffer.connect(); 120 fFilesBuffers.put(location, fileBuffer); 121 } 122 123 fireBufferCreated(fileBuffer); 125 } 126 127 131 public void connectFileStore(IFileStore fileStore, IProgressMonitor monitor) throws CoreException { 132 Assert.isLegal(fileStore != null); 133 134 FileStoreFileBuffer fileBuffer= null; 135 synchronized (fFileStoreFileBuffers) { 136 fileBuffer= internalGetFileBuffer(fileStore); 137 if (fileBuffer != null) { 138 fileBuffer.connect(); 139 return; 140 } 141 } 142 143 fileBuffer= createFileBuffer(fileStore); 144 if (fileBuffer == null) 145 throw new CoreException(new Status(IStatus.ERROR, FileBuffersPlugin.PLUGIN_ID, IFileBufferStatusCodes.CREATION_FAILED, FileBuffersMessages.FileBufferManager_error_canNotCreateFilebuffer, null)); 146 147 fileBuffer.create(fileStore, monitor); 148 149 synchronized (fFileStoreFileBuffers) { 150 AbstractFileBuffer oldFileBuffer= internalGetFileBuffer(fileStore); 151 if (oldFileBuffer != null) { 152 fileBuffer.disconnect(); 153 fileBuffer.dispose(); 154 oldFileBuffer.connect(); 155 return; 156 } 157 fileBuffer.connect(); 158 fFileStoreFileBuffers.put(fileStore, fileBuffer); 159 } 160 161 fireBufferCreated(fileBuffer); 163 } 164 165 168 public void disconnect(IPath location, IProgressMonitor monitor) throws CoreException { 169 disconnect(location, LocationKind.NORMALIZE, monitor); 170 } 171 172 175 protected IPath normalizeLocation(IPath location) { 176 return location; 177 } 178 179 183 public void disconnect(IPath location, LocationKind locationKind, IProgressMonitor monitor) throws CoreException { 184 Assert.isNotNull(location); 185 if (locationKind == LocationKind.NORMALIZE) 186 location= normalizeLocation(location); 187 188 AbstractFileBuffer fileBuffer; 189 synchronized (fFilesBuffers) { 190 fileBuffer= internalGetFileBuffer(location); 191 if (fileBuffer == null) 192 return; 193 194 fileBuffer.disconnect(); 195 if (!fileBuffer.isDisconnected()) 196 return; 197 198 fFilesBuffers.remove(location); 199 } 200 201 fireBufferDisposed(fileBuffer); 203 fileBuffer.dispose(); 204 } 205 206 210 public void disconnectFileStore(IFileStore fileStore, IProgressMonitor monitor) throws CoreException { 211 Assert.isLegal(fileStore != null); 212 213 AbstractFileBuffer fileBuffer; 214 synchronized (fFileStoreFileBuffers) { 215 fileBuffer= internalGetFileBuffer(fileStore); 216 if (fileBuffer == null) 217 return; 218 219 fileBuffer.disconnect(); 220 if (!fileBuffer.isDisconnected()) 221 return; 222 223 fFileStoreFileBuffers.remove(fileStore); 224 } 225 226 fireBufferDisposed(fileBuffer); 228 fileBuffer.dispose(); 229 } 230 231 234 public boolean isTextFileLocation(IPath location) { 235 return isTextFileLocation(location, false); 236 } 237 238 259 protected boolean isTextFileLocation(IFileStore fileStore, boolean strict) { 260 if (fileStore == null) 261 return false; 262 263 IContentTypeManager manager= Platform.getContentTypeManager(); 264 IFileInfo fileInfo= fileStore.fetchInfo(); 265 if (fileInfo.exists()) { 266 InputStream is= null; 267 try { 268 is= fileStore.openInputStream(EFS.NONE, null); 269 IContentDescription description= manager.getDescriptionFor(is, fileStore.getName(), IContentDescription.ALL); 270 if (description != null) { 271 IContentType type= description.getContentType(); 272 if (type != null) 273 return type.isKindOf(TEXT_CONTENT_TYPE); 274 } 275 } catch (CoreException ex) { 276 } catch (IOException ex) { 278 } finally { 280 if (is != null ) { 281 try { 282 is.close(); 283 } catch (IOException e) { 284 } 286 } 287 } 288 289 return !strict; 290 291 } 292 293 IContentType[] contentTypes= manager.findContentTypesFor(fileStore.getName()); 294 if (contentTypes != null && contentTypes.length > 0) { 295 for (int i= 0; i < contentTypes.length; i++) 296 if (contentTypes[i].isKindOf(TEXT_CONTENT_TYPE)) 297 return true; 298 return false; 299 } 300 return !strict; 301 } 302 303 307 public boolean isTextFileLocation(IPath location, boolean strict) { 308 Assert.isNotNull(location); 309 location= normalizeLocation(location); 310 try { 311 return isTextFileLocation(EFS.getStore(URIUtil.toURI(location)), strict); 312 } catch (CoreException ex) { 313 return false; 314 } 315 } 316 317 320 public IFileBuffer getFileBuffer(IPath location) { 321 return getFileBuffer(location, LocationKind.NORMALIZE); 322 } 323 324 328 public IFileBuffer getFileBuffer(IPath location, LocationKind locationKind) { 329 if (locationKind == LocationKind.NORMALIZE) 330 location= normalizeLocation(location); 331 return internalGetFileBuffer(location); 332 } 333 334 338 public IFileBuffer getFileStoreFileBuffer(IFileStore fileStore) { 339 Assert.isLegal(fileStore != null); 340 return internalGetFileBuffer(fileStore); 341 } 342 343 private AbstractFileBuffer internalGetFileBuffer(IPath location) { 344 synchronized (fFilesBuffers) { 345 return (AbstractFileBuffer)fFilesBuffers.get(location); 346 } 347 } 348 349 private FileStoreFileBuffer internalGetFileBuffer(IFileStore fileStore) { 350 synchronized (fFileStoreFileBuffers) { 351 return (FileStoreFileBuffer)fFileStoreFileBuffers.get(fileStore); 352 } 353 } 354 355 358 public ITextFileBuffer getTextFileBuffer(IPath location) { 359 return getTextFileBuffer(location, LocationKind.NORMALIZE); 360 } 361 362 366 public ITextFileBuffer getTextFileBuffer(IPath location, LocationKind locationKind) { 367 return (ITextFileBuffer)getFileBuffer(location, locationKind); 368 } 369 370 374 public ITextFileBuffer getFileStoreTextFileBuffer(IFileStore fileStore) { 375 Assert.isLegal(fileStore != null); 376 return (ITextFileBuffer)getFileStoreFileBuffer(fileStore); 377 } 378 379 383 public ITextFileBuffer getTextFileBuffer(IDocument document) { 384 Assert.isLegal(document != null); 385 Iterator iter; 386 synchronized (fFilesBuffers) { 387 iter= new ArrayList (fFilesBuffers.values()).iterator(); 388 } 389 390 while (iter.hasNext()) { 391 Object buffer= iter.next(); 392 if (buffer instanceof ITextFileBuffer) { 393 ITextFileBuffer textFileBuffer= (ITextFileBuffer)buffer; 394 if (textFileBuffer.getDocument() == document) { 395 if (!((AbstractFileBuffer)textFileBuffer).isDisconnected()) 396 return textFileBuffer; 397 return null; 398 } 399 } 400 } 401 synchronized (fFilesBuffers) { 402 iter= new ArrayList (fFileStoreFileBuffers.values()).iterator(); 403 } 404 while (iter.hasNext()) { 405 Object buffer= iter.next(); 406 if (buffer instanceof ITextFileBuffer) { 407 ITextFileBuffer textFileBuffer= (ITextFileBuffer)buffer; 408 if (textFileBuffer.getDocument() == document) { 409 if (!((AbstractFileBuffer)textFileBuffer).isDisconnected()) 410 return textFileBuffer; 411 } 412 } 413 } 414 return null; 415 } 416 417 420 public String getDefaultEncoding() { 421 return System.getProperty("file.encoding"); } 423 424 427 public IDocument createEmptyDocument(IPath location) { 428 return createEmptyDocument(location, LocationKind.NORMALIZE); 429 } 430 431 435 public IDocument createEmptyDocument(IPath location, LocationKind locationKind) { 436 final IDocument[] runnableResult= new IDocument[1]; 437 if (location != null) { 438 final IDocumentFactory factory= fRegistry.getDocumentFactory(location, locationKind); 439 if (factory != null) { 440 ISafeRunnable runnable= new ISafeRunnable() { 441 public void run() throws Exception { 442 runnableResult[0]= factory.createDocument(); 443 } 444 public void handleException(Throwable t) { 445 IStatus status= new Status(IStatus.ERROR, FileBuffersPlugin.PLUGIN_ID, IStatus.OK, FileBuffersMessages.TextFileBufferManager_error_documentFactoryFailed, t); 446 FileBuffersPlugin.getDefault().getLog().log(status); 447 if (t instanceof VirtualMachineError ) 448 throw (VirtualMachineError )t; 449 } 450 }; 451 SafeRunner.run(runnable); 452 } 453 } 454 final IDocument document; 455 if (runnableResult[0] != null) 456 document= runnableResult[0]; 457 else 458 document= new SynchronizableDocument(); 459 460 if (location == null) 461 return document; 462 463 if (document instanceof IDocumentExtension4) { 465 String initalLineDelimiter= getLineDelimiterPreference(location, locationKind); 466 if (initalLineDelimiter != null) 467 ((IDocumentExtension4)document).setInitialLineDelimiter(initalLineDelimiter); 468 } 469 470 final IDocumentSetupParticipant[] participants= fRegistry.getDocumentSetupParticipants(location, locationKind); 471 if (participants != null) { 472 for (int i= 0; i < participants.length; i++) { 473 final IDocumentSetupParticipant participant= participants[i]; 474 ISafeRunnable runnable= new ISafeRunnable() { 475 public void run() throws Exception { 476 participant.setup(document); 477 if (document.getDocumentPartitioner() != null) { 478 String message= NLSUtility.format(FileBuffersMessages.TextFileBufferManager_warning_documentSetupInstallsDefaultPartitioner, participant.getClass()); 479 IStatus status= new Status(IStatus.WARNING, FileBuffersPlugin.PLUGIN_ID, IStatus.OK, message, null); 480 FileBuffersPlugin.getDefault().getLog().log(status); 481 } 482 } 483 public void handleException(Throwable t) { 484 IStatus status= new Status(IStatus.ERROR, FileBuffersPlugin.PLUGIN_ID, IStatus.OK, FileBuffersMessages.TextFileBufferManager_error_documentSetupFailed, t); 485 FileBuffersPlugin.getDefault().getLog().log(status); 486 if (t instanceof VirtualMachineError ) 487 throw (VirtualMachineError )t; 488 } 489 }; 490 SafeRunner.run(runnable); 491 } 492 } 493 494 return document; 495 } 496 497 500 public IAnnotationModel createAnnotationModel(IPath location) { 501 return createAnnotationModel(location, LocationKind.NORMALIZE); 502 } 503 504 508 public IAnnotationModel createAnnotationModel(IPath location, LocationKind locationKind) { 509 Assert.isNotNull(location); 510 IAnnotationModelFactory factory= fRegistry.getAnnotationModelFactory(location, locationKind); 511 if (factory != null) 512 return factory.createAnnotationModel(location); 513 return null; 514 } 515 516 519 public void addFileBufferListener(IFileBufferListener listener) { 520 Assert.isNotNull(listener); 521 synchronized (fFileBufferListeners) { 522 if (!fFileBufferListeners.contains(listener)) 523 fFileBufferListeners.add(listener); 524 } 525 } 526 527 530 public void removeFileBufferListener(IFileBufferListener listener) { 531 Assert.isNotNull(listener); 532 synchronized (fFileBufferListeners) { 533 fFileBufferListeners.remove(listener); 534 } 535 } 536 537 540 public void setSynchronizationContext(ISynchronizationContext context) { 541 fSynchronizationContext= context; 542 } 543 544 547 public void requestSynchronizationContext(IPath location) { 548 Assert.isNotNull(location); 549 location= normalizeLocation(location); 550 551 AbstractFileBuffer fileBuffer= internalGetFileBuffer(location); 552 if (fileBuffer != null) 553 fileBuffer.requestSynchronizationContext(); 554 } 555 556 559 public void releaseSynchronizationContext(IPath location) { 560 Assert.isNotNull(location); 561 location= normalizeLocation(location); 562 563 AbstractFileBuffer fileBuffer= internalGetFileBuffer(location); 564 if (fileBuffer != null) 565 fileBuffer.releaseSynchronizationContext(); 566 } 567 568 576 public void execute(Runnable runnable, boolean requestSynchronizationContext) { 577 if (requestSynchronizationContext && fSynchronizationContext != null) 578 fSynchronizationContext.run(runnable); 579 else 580 runnable.run(); 581 } 582 583 584 private AbstractFileBuffer createFileBuffer(IPath location, LocationKind locationKind) { 585 590 return createTextFileBuffer(location, locationKind); 594 } 595 596 protected AbstractFileBuffer createTextFileBuffer(IPath location, LocationKind locationKind) { 597 Assert.isLegal(locationKind != LocationKind.IFILE); 598 return new FileStoreTextFileBuffer(this); 599 } 600 601 606 private FileStoreFileBuffer createFileBuffer(IFileStore location) { 607 612 return createTextFileBuffer(location); 616 617 } 618 619 protected FileStoreFileBuffer createTextFileBuffer(IFileStore location) { 620 return new FileStoreTextFileBuffer(this); 621 } 622 623 628 private Iterator getFileBufferListenerIterator() { 629 synchronized (fFileBufferListeners) { 630 return new ArrayList (fFileBufferListeners).iterator(); 631 } 632 } 633 634 protected void fireDirtyStateChanged(final IFileBuffer buffer, final boolean isDirty) { 635 Iterator e= getFileBufferListenerIterator(); 636 while (e.hasNext()) { 637 final IFileBufferListener l= (IFileBufferListener) e.next(); 638 SafeRunner.run(new SafeNotifier() { 639 public void run() { 640 l.dirtyStateChanged(buffer, isDirty); 641 } 642 }); 643 } 644 } 645 646 protected void fireBufferContentAboutToBeReplaced(final IFileBuffer buffer) { 647 Iterator e= getFileBufferListenerIterator(); 648 while (e.hasNext()) { 649 final IFileBufferListener l= (IFileBufferListener) e.next(); 650 SafeRunner.run(new SafeNotifier() { 651 public void run() { 652 l.bufferContentAboutToBeReplaced(buffer); 653 } 654 }); 655 } 656 } 657 658 protected void fireBufferContentReplaced(final IFileBuffer buffer) { 659 Iterator e= getFileBufferListenerIterator(); 660 while (e.hasNext()) { 661 final IFileBufferListener l= (IFileBufferListener) e.next(); 662 SafeRunner.run(new SafeNotifier() { 663 public void run() { 664 l.bufferContentReplaced(buffer); 665 } 666 }); 667 } 668 } 669 670 protected void fireUnderlyingFileMoved(final IFileBuffer buffer, final IPath target) { 671 Iterator e= getFileBufferListenerIterator(); 672 while (e.hasNext()) { 673 final IFileBufferListener l= (IFileBufferListener) e.next(); 674 SafeRunner.run(new SafeNotifier() { 675 public void run() { 676 l.underlyingFileMoved(buffer, target); 677 } 678 }); 679 } 680 } 681 682 protected void fireUnderlyingFileDeleted(final IFileBuffer buffer) { 683 Iterator e= getFileBufferListenerIterator(); 684 while (e.hasNext()) { 685 final IFileBufferListener l= (IFileBufferListener) e.next(); 686 SafeRunner.run(new SafeNotifier() { 687 public void run() { 688 l.underlyingFileDeleted(buffer); 689 } 690 }); 691 } 692 } 693 694 protected void fireStateValidationChanged(final IFileBuffer buffer, final boolean isStateValidated) { 695 Iterator e= getFileBufferListenerIterator(); 696 while (e.hasNext()) { 697 final IFileBufferListener l= (IFileBufferListener) e.next(); 698 SafeRunner.run(new SafeNotifier() { 699 public void run() { 700 l.stateValidationChanged(buffer, isStateValidated); 701 } 702 }); 703 } 704 } 705 706 protected void fireStateChanging(final IFileBuffer buffer) { 707 Iterator e= getFileBufferListenerIterator(); 708 while (e.hasNext()) { 709 final IFileBufferListener l= (IFileBufferListener) e.next(); 710 SafeRunner.run(new SafeNotifier() { 711 public void run() { 712 l.stateChanging(buffer); 713 } 714 }); 715 } 716 } 717 718 protected void fireStateChangeFailed(final IFileBuffer buffer) { 719 Iterator e= getFileBufferListenerIterator(); 720 while (e.hasNext()) { 721 final IFileBufferListener l= (IFileBufferListener) e.next(); 722 SafeRunner.run(new SafeNotifier() { 723 public void run() { 724 l.stateChangeFailed(buffer); 725 } 726 }); 727 } 728 } 729 730 protected void fireBufferCreated(final IFileBuffer buffer) { 731 Iterator e= getFileBufferListenerIterator(); 732 while (e.hasNext()) { 733 final IFileBufferListener l= (IFileBufferListener) e.next(); 734 SafeRunner.run(new SafeNotifier() { 735 public void run() { 736 l.bufferCreated(buffer); 737 } 738 }); 739 } 740 } 741 742 protected void fireBufferDisposed(final IFileBuffer buffer) { 743 Iterator e= getFileBufferListenerIterator(); 744 while (e.hasNext()) { 745 final IFileBufferListener l= (IFileBufferListener) e.next(); 746 SafeRunner.run(new SafeNotifier() { 747 public void run() { 748 l.bufferDisposed(buffer); 749 } 750 }); 751 } 752 } 753 754 758 public void validateState(final IFileBuffer[] fileBuffers, IProgressMonitor monitor, final Object computationContext) throws CoreException { 759 } 760 761 protected String getLineDelimiterPreference(IPath location, LocationKind locationKind) { 762 return System.getProperty("line.separator"); } 764 765 } 766 | Popular Tags |