1 11 package org.eclipse.ui.editors.text; 12 13 import java.io.ByteArrayInputStream ; 14 import java.io.IOException ; 15 import java.io.InputStream ; 16 import java.io.Reader ; 17 import java.io.SequenceInputStream ; 18 import java.nio.ByteBuffer ; 19 import java.nio.CharBuffer ; 20 import java.nio.charset.CharacterCodingException ; 21 import java.nio.charset.Charset ; 22 import java.nio.charset.CharsetEncoder ; 23 import java.nio.charset.CodingErrorAction ; 24 import java.nio.charset.IllegalCharsetNameException ; 25 import java.nio.charset.UnmappableCharacterException ; 26 import java.nio.charset.UnsupportedCharsetException ; 27 28 import org.eclipse.swt.widgets.Display; 29 30 import org.eclipse.core.runtime.Assert; 31 import org.eclipse.core.runtime.CoreException; 32 import org.eclipse.core.runtime.IPath; 33 import org.eclipse.core.runtime.IProgressMonitor; 34 import org.eclipse.core.runtime.IStatus; 35 import org.eclipse.core.runtime.MultiStatus; 36 import org.eclipse.core.runtime.OperationCanceledException; 37 import org.eclipse.core.runtime.Platform; 38 import org.eclipse.core.runtime.QualifiedName; 39 import org.eclipse.core.runtime.Status; 40 import org.eclipse.core.runtime.SubProgressMonitor; 41 import org.eclipse.core.runtime.content.IContentDescription; 42 import org.eclipse.core.runtime.content.IContentType; 43 import org.eclipse.core.runtime.jobs.ISchedulingRule; 44 import org.eclipse.core.runtime.preferences.IScopeContext; 45 import org.eclipse.core.runtime.preferences.InstanceScope; 46 47 import org.eclipse.core.resources.IFile; 48 import org.eclipse.core.resources.IResource; 49 import org.eclipse.core.resources.IResourceChangeEvent; 50 import org.eclipse.core.resources.IResourceChangeListener; 51 import org.eclipse.core.resources.IResourceDelta; 52 import org.eclipse.core.resources.IResourceDeltaVisitor; 53 import org.eclipse.core.resources.IResourceRuleFactory; 54 import org.eclipse.core.resources.IResourceStatus; 55 import org.eclipse.core.resources.IWorkspace; 56 import org.eclipse.core.resources.ProjectScope; 57 import org.eclipse.core.resources.ResourcesPlugin; 58 59 import org.eclipse.core.filebuffers.manipulation.ContainerCreator; 60 61 import org.eclipse.jface.operation.IRunnableContext; 62 63 import org.eclipse.jface.text.IDocument; 64 import org.eclipse.jface.text.IDocumentExtension4; 65 import org.eclipse.jface.text.source.IAnnotationModel; 66 67 import org.eclipse.ui.IEditorInput; 68 import org.eclipse.ui.IFileEditorInput; 69 import org.eclipse.ui.IWorkbench; 70 import org.eclipse.ui.IWorkbenchWindow; 71 import org.eclipse.ui.PlatformUI; 72 import org.eclipse.ui.internal.editors.text.NLSUtility; 73 import org.eclipse.ui.internal.editors.text.WorkspaceOperationRunner; 74 import org.eclipse.ui.part.FileEditorInput; 75 import org.eclipse.ui.texteditor.AbstractMarkerAnnotationModel; 76 import org.eclipse.ui.texteditor.ResourceMarkerAnnotationModel; 77 78 79 84 public class FileDocumentProvider extends StorageDocumentProvider { 85 86 91 private static final QualifiedName ENCODING_KEY = new QualifiedName(EditorsUI.PLUGIN_ID, "encoding"); 96 private static final String CHARSET_UTF_8= "UTF-8"; 98 99 103 private WorkspaceOperationRunner fOperationRunner; 104 108 private IResourceRuleFactory fResourceRuleFactory; 109 110 117 protected class SafeChange implements Runnable { 118 119 120 private IFileEditorInput fInput; 121 122 127 public SafeChange(IFileEditorInput input) { 128 fInput= input; 129 } 130 131 138 protected void execute(IFileEditorInput input) throws Exception { 139 } 140 141 144 public void run() { 145 146 if (getElementInfo(fInput) == null) { 147 fireElementStateChangeFailed(fInput); 148 return; 149 } 150 151 try { 152 execute(fInput); 153 } catch (Exception e) { 154 fireElementStateChangeFailed(fInput); 155 } 156 } 157 } 158 159 160 163 protected class FileSynchronizer implements IResourceChangeListener, IResourceDeltaVisitor { 164 165 166 protected IFileEditorInput fFileEditorInput; 167 172 protected boolean fIsInstalled= false; 173 174 179 public FileSynchronizer(IFileEditorInput fileEditorInput) { 180 fFileEditorInput= fileEditorInput; 181 } 182 183 189 public FileSynchronizer(FileEditorInput fileEditorInput) { 190 fFileEditorInput= fileEditorInput; 191 } 192 193 198 protected IFile getFile() { 199 return fFileEditorInput.getFile(); 200 } 201 202 205 public void install() { 206 getFile().getWorkspace().addResourceChangeListener(this); 207 fIsInstalled= true; 208 } 209 210 213 public void uninstall() { 214 getFile().getWorkspace().removeResourceChangeListener(this); 215 fIsInstalled= false; 216 } 217 218 221 public void resourceChanged(IResourceChangeEvent e) { 222 IResourceDelta delta= e.getDelta(); 223 try { 224 if (delta != null && fIsInstalled) 225 delta.accept(this); 226 } catch (CoreException x) { 227 handleCoreException(x, "FileDocumentProvider.resourceChanged"); } 229 } 230 231 234 public boolean visit(IResourceDelta delta) throws CoreException { 235 if (delta == null) 236 return false; 237 238 delta= delta.findMember(getFile().getFullPath()); 239 240 if (delta == null) 241 return false; 242 243 Runnable runnable= null; 244 245 switch (delta.getKind()) { 246 case IResourceDelta.CHANGED: 247 FileInfo info= (FileInfo) getElementInfo(fFileEditorInput); 248 if (info == null || info.fCanBeSaved) 249 break; 250 251 boolean isSynchronized= computeModificationStamp(getFile()) == info.fModificationStamp; 252 if ((IResourceDelta.ENCODING & delta.getFlags()) != 0 && isSynchronized) { 253 runnable= new SafeChange(fFileEditorInput) { 254 protected void execute(IFileEditorInput input) throws Exception { 255 handleElementContentChanged(input); 256 } 257 }; 258 } 259 260 if (runnable == null && (IResourceDelta.CONTENT & delta.getFlags()) != 0 && !isSynchronized) { 261 runnable= new SafeChange(fFileEditorInput) { 262 protected void execute(IFileEditorInput input) throws Exception { 263 handleElementContentChanged(input); 264 } 265 }; 266 } 267 break; 268 269 case IResourceDelta.REMOVED: 270 if ((IResourceDelta.MOVED_TO & delta.getFlags()) != 0) { 271 final IPath path= delta.getMovedToPath(); 272 runnable= new SafeChange(fFileEditorInput) { 273 protected void execute(IFileEditorInput input) throws Exception { 274 handleElementMoved(input, path); 275 } 276 }; 277 } else { 278 info= (FileInfo) getElementInfo(fFileEditorInput); 279 if (info != null && !info.fCanBeSaved) { 280 runnable= new SafeChange(fFileEditorInput) { 281 protected void execute(IFileEditorInput input) throws Exception { 282 handleElementDeleted(input); 283 } 284 }; 285 } 286 } 287 break; 288 } 289 290 if (runnable != null) 291 update(runnable); 292 293 return false; 294 } 295 296 301 protected void update(Runnable runnable) { 302 303 if (runnable instanceof SafeChange) 304 fireElementStateChanging(fFileEditorInput); 305 306 IWorkbench workbench= PlatformUI.getWorkbench(); 307 IWorkbenchWindow[] windows= workbench.getWorkbenchWindows(); 308 if (windows != null && windows.length > 0) { 309 Display display= windows[0].getShell().getDisplay(); 310 display.asyncExec(runnable); 311 } else { 312 runnable.run(); 313 } 314 } 315 } 316 317 318 319 322 protected class FileInfo extends StorageInfo { 323 324 325 public FileSynchronizer fFileSynchronizer; 326 327 public long fModificationStamp= IResource.NULL_STAMP; 328 331 private boolean fHasBOM; 332 333 340 public FileInfo(IDocument document, IAnnotationModel model, FileSynchronizer fileSynchronizer) { 341 super(document, model); 342 fFileSynchronizer= fileSynchronizer; 343 } 344 } 345 346 347 350 public FileDocumentProvider() { 351 super(); 352 fResourceRuleFactory= ResourcesPlugin.getWorkspace().getRuleFactory(); 353 } 354 355 362 protected boolean setDocumentContent(IDocument document, IEditorInput editorInput) throws CoreException { 363 if (editorInput instanceof IFileEditorInput) { 364 IFile file= ((IFileEditorInput) editorInput).getFile(); 365 InputStream stream= file.getContents(false); 366 try { 367 setDocumentContent(document, stream); 368 } finally { 369 try { 370 stream.close(); 371 } catch (IOException x) { 372 } 373 } 374 return true; 375 } 376 return super.setDocumentContent(document, editorInput); 377 } 378 379 383 protected boolean setDocumentContent(IDocument document, IEditorInput editorInput, String encoding) throws CoreException { 384 if (editorInput instanceof IFileEditorInput) { 385 IFile file= ((IFileEditorInput) editorInput).getFile(); 386 InputStream contentStream= file.getContents(false); 387 try { 388 389 FileInfo info= (FileInfo)getElementInfo(editorInput); 390 boolean removeBOM= false; 391 if (CHARSET_UTF_8.equals(encoding)) { 392 if (info != null) 393 removeBOM= info.fHasBOM; 394 else 395 removeBOM= hasBOM(editorInput); 396 } 397 398 403 if (removeBOM) { 404 int n= 0; 405 do { 406 int bytes= contentStream.read(new byte[IContentDescription.BOM_UTF_8.length]); 407 if (bytes == -1) 408 throw new IOException (); 409 n += bytes; 410 } while (n < IContentDescription.BOM_UTF_8.length); 411 } 412 413 setDocumentContent(document, contentStream, encoding); 414 415 } catch (IOException ex) { 416 String message= (ex.getMessage() != null ? ex.getMessage() : ""); IStatus s= new Status(IStatus.ERROR, PlatformUI.PLUGIN_ID, IStatus.OK, message, ex); 418 throw new CoreException(s); 419 } finally { 420 try { 421 contentStream.close(); 422 } catch (IOException e1) { 423 } 424 } 425 return true; 426 } 427 return super.setDocumentContent(document, editorInput, encoding); 428 } 429 430 433 protected IAnnotationModel createAnnotationModel(Object element) throws CoreException { 434 if (element instanceof IFileEditorInput) { 435 IFileEditorInput input= (IFileEditorInput) element; 436 return new ResourceMarkerAnnotationModel(input.getFile()); 437 } 438 439 return super.createAnnotationModel(element); 440 } 441 442 452 protected void checkSynchronizationState(long cachedModificationStamp, IResource resource) throws CoreException { 453 if (cachedModificationStamp != computeModificationStamp(resource)) { 454 Status status= new Status(IStatus.ERROR, PlatformUI.PLUGIN_ID, IResourceStatus.OUT_OF_SYNC_LOCAL, TextEditorMessages.FileDocumentProvider_error_out_of_sync, null); 455 throw new CoreException(status); 456 } 457 } 458 459 465 protected long computeModificationStamp(IResource resource) { 466 long modificationStamp= resource.getModificationStamp(); 467 468 IPath path= resource.getLocation(); 469 if (path == null) 470 return modificationStamp; 471 472 modificationStamp= path.toFile().lastModified(); 473 return modificationStamp; 474 } 475 476 479 public long getModificationStamp(Object element) { 480 481 if (element instanceof IFileEditorInput) { 482 IFileEditorInput input= (IFileEditorInput) element; 483 return computeModificationStamp(input.getFile()); 484 } 485 486 return super.getModificationStamp(element); 487 } 488 489 492 public long getSynchronizationStamp(Object element) { 493 494 if (element instanceof IFileEditorInput) { 495 FileInfo info= (FileInfo) getElementInfo(element); 496 if (info != null) 497 return info.fModificationStamp; 498 } 499 500 return super.getSynchronizationStamp(element); 501 } 502 503 507 protected void doSynchronize(Object element, IProgressMonitor monitor) throws CoreException { 508 if (element instanceof IFileEditorInput) { 509 510 IFileEditorInput input= (IFileEditorInput) element; 511 512 FileInfo info= (FileInfo) getElementInfo(element); 513 if (info != null) { 514 515 if (info.fFileSynchronizer != null) { 516 info.fFileSynchronizer.uninstall(); 517 refreshFile(input.getFile(), monitor); 518 info.fFileSynchronizer.install(); 519 } else { 520 refreshFile(input.getFile(), monitor); 521 } 522 523 handleElementContentChanged((IFileEditorInput) element); 524 } 525 return; 526 527 } 528 super.doSynchronize(element, monitor); 529 } 530 531 534 public boolean isDeleted(Object element) { 535 536 if (element instanceof IFileEditorInput) { 537 IFileEditorInput input= (IFileEditorInput) element; 538 539 IPath path= input.getFile().getLocation(); 540 if (path == null) 541 return true; 542 543 return !path.toFile().exists(); 544 } 545 546 return super.isDeleted(element); 547 } 548 549 552 protected void doSaveDocument(IProgressMonitor monitor, Object element, IDocument document, boolean overwrite) throws CoreException { 553 if (element instanceof IFileEditorInput) { 554 555 IFileEditorInput input= (IFileEditorInput) element; 556 String encoding= null; 557 558 FileInfo info= (FileInfo) getElementInfo(element); 559 IFile file= input.getFile(); 560 encoding= getCharsetForNewFile(file, document, info); 561 562 Charset charset; 563 try { 564 charset= Charset.forName(encoding); 565 } catch (UnsupportedCharsetException ex) { 566 String message= NLSUtility.format(TextEditorMessages.DocumentProvider_error_unsupported_encoding_message_arg, encoding); 567 IStatus s= new Status(IStatus.ERROR, EditorsUI.PLUGIN_ID, IStatus.OK, message, ex); 568 throw new CoreException(s); 569 } catch (IllegalCharsetNameException ex) { 570 String message= NLSUtility.format(TextEditorMessages.DocumentProvider_error_illegal_encoding_message_arg, encoding); 571 IStatus s= new Status(IStatus.ERROR, EditorsUI.PLUGIN_ID, IStatus.OK, message, ex); 572 throw new CoreException(s); 573 } 574 575 CharsetEncoder encoder= charset.newEncoder(); 576 encoder.onMalformedInput(CodingErrorAction.REPLACE); 577 encoder.onUnmappableCharacter(CodingErrorAction.REPORT); 578 579 InputStream stream; 580 581 try { 582 byte[] bytes; 583 ByteBuffer byteBuffer= encoder.encode(CharBuffer.wrap(document.get())); 584 if (byteBuffer.hasArray()) 585 bytes= byteBuffer.array(); 586 else { 587 bytes= new byte[byteBuffer.limit()]; 588 byteBuffer.get(bytes); 589 } 590 stream= new ByteArrayInputStream (bytes, 0, byteBuffer.limit()); 591 } catch (CharacterCodingException ex) { 592 Assert.isTrue(ex instanceof UnmappableCharacterException ); 593 String message= NLSUtility.format(TextEditorMessages.DocumentProvider_error_charset_mapping_failed_message_arg, encoding); 594 IStatus s= new Status(IStatus.ERROR, EditorsUI.PLUGIN_ID, EditorsUI.CHARSET_MAPPING_FAILED, message, null); 595 throw new CoreException(s); 596 } 597 598 603 if (info != null && info.fHasBOM && CHARSET_UTF_8.equals(encoding)) 604 stream= new SequenceInputStream (new ByteArrayInputStream (IContentDescription.BOM_UTF_8), stream); 605 606 if (file.exists()) { 607 608 if (info != null && !overwrite) 609 checkSynchronizationState(info.fModificationStamp, file); 610 611 fireElementStateChanging(element); 613 try { 614 file.setContents(stream, overwrite, true, monitor); 615 } catch (CoreException x) { 616 fireElementStateChangeFailed(element); 618 throw x; 619 } catch (RuntimeException x) { 620 fireElementStateChangeFailed(element); 622 throw x; 623 } 624 625 628 if (info != null) { 629 630 ResourceMarkerAnnotationModel model= (ResourceMarkerAnnotationModel) info.fModel; 631 if (model != null) 632 model.updateMarkers(info.fDocument); 633 634 info.fModificationStamp= computeModificationStamp(file); 635 } 636 637 } else { 638 try { 639 monitor.beginTask(TextEditorMessages.FileDocumentProvider_task_saving, 2000); 640 ContainerCreator creator = new ContainerCreator(file.getWorkspace(), file.getParent().getFullPath()); 641 creator.createContainer(new SubProgressMonitor(monitor, 1000)); 642 file.create(stream, false, new SubProgressMonitor(monitor, 1000)); 643 } 644 finally { 645 monitor.done(); 646 } 647 } 648 649 } else { 650 super.doSaveDocument(monitor, element, document, overwrite); 651 } 652 } 653 654 657 private String getCharsetForNewFile(IFile targetFile, IDocument document, FileInfo info) { 658 String encoding; 660 try { 661 encoding= targetFile.getCharset(false); 662 } catch (CoreException ex) { 663 encoding= null; 664 } 665 if (encoding != null) 666 return encoding; 667 668 Reader reader= new DocumentReader(document); 670 try { 671 QualifiedName[] options= new QualifiedName[] { IContentDescription.CHARSET, IContentDescription.BYTE_ORDER_MARK }; 672 IContentDescription description= Platform.getContentTypeManager().getDescriptionFor(reader, targetFile.getName(), options); 673 if (description != null) { 674 encoding= description.getCharset(); 675 if (encoding != null) 676 return encoding; 677 } 678 } catch (IOException ex) { 679 } finally { 681 try { 682 reader.close(); 683 } catch (IOException x) { 684 } 685 } 686 687 if (info != null && info.fHasBOM) 689 return info.fEncoding; 690 691 try { 693 return targetFile.getParent().getDefaultCharset(); 694 } catch (CoreException ex) { 695 return ResourcesPlugin.getEncoding(); 697 } 698 } 699 700 703 protected ElementInfo createElementInfo(Object element) throws CoreException { 704 if (element instanceof IFileEditorInput) { 705 706 IFileEditorInput input= (IFileEditorInput) element; 707 708 try { 709 refreshFile(input.getFile()); 710 } catch (CoreException x) { 711 handleCoreException(x, TextEditorMessages.FileDocumentProvider_createElementInfo); 712 } 713 714 IDocument d= null; 715 IStatus s= null; 716 717 try { 718 d= createDocument(element); 719 } catch (CoreException x) { 720 handleCoreException(x, TextEditorMessages.FileDocumentProvider_createElementInfo); 721 s= x.getStatus(); 722 d= createEmptyDocument(); 723 } 724 725 if (d instanceof IDocumentExtension4) { 727 String initalLineDelimiter= getLineDelimiterPreference(input.getFile()); 728 if (initalLineDelimiter != null) 729 ((IDocumentExtension4)d).setInitialLineDelimiter(initalLineDelimiter); 730 } 731 732 IAnnotationModel m= createAnnotationModel(element); 733 FileSynchronizer f= new FileSynchronizer(input); 734 f.install(); 735 736 FileInfo info= new FileInfo(d, m, f); 737 info.fModificationStamp= computeModificationStamp(input.getFile()); 738 info.fStatus= s; 739 info.fEncoding= getPersistedEncoding(element); 740 info.fHasBOM= hasBOM(element); 741 742 748 cacheEncodingState(element); 749 750 return info; 751 } 752 753 return super.createElementInfo(element); 754 } 755 756 763 private String getLineDelimiterPreference(IFile file) { 764 IScopeContext[] scopeContext; 765 if (file != null && file.getProject() != null) { 766 scopeContext= new IScopeContext[] { new ProjectScope(file.getProject()) }; 768 String lineDelimiter= Platform.getPreferencesService().getString(Platform.PI_RUNTIME, Platform.PREF_LINE_SEPARATOR, null, scopeContext); 769 if (lineDelimiter != null) 770 return lineDelimiter; 771 } 772 scopeContext= new IScopeContext[] { new InstanceScope() }; 774 return Platform.getPreferencesService().getString(Platform.PI_RUNTIME, Platform.PREF_LINE_SEPARATOR, null, scopeContext); 775 } 776 777 780 protected void disposeElementInfo(Object element, ElementInfo info) { 781 if (info instanceof FileInfo) { 782 FileInfo fileInfo= (FileInfo) info; 783 if (fileInfo.fFileSynchronizer != null) 784 fileInfo.fFileSynchronizer.uninstall(); 785 } 786 787 super.disposeElementInfo(element, info); 788 } 789 790 796 protected void handleElementContentChanged(IFileEditorInput fileEditorInput) { 797 FileInfo info= (FileInfo) getElementInfo(fileEditorInput); 798 if (info == null) 799 return; 800 801 IDocument document= createEmptyDocument(); 802 IStatus status= null; 803 804 try { 805 806 try { 807 refreshFile(fileEditorInput.getFile()); 808 } catch (CoreException x) { 809 handleCoreException(x, "FileDocumentProvider.handleElementContentChanged"); } 811 812 cacheEncodingState(fileEditorInput); 813 setDocumentContent(document, fileEditorInput, info.fEncoding); 814 815 } catch (CoreException x) { 816 status= x.getStatus(); 817 } 818 819 String newContent= document.get(); 820 821 if ( !newContent.equals(info.fDocument.get())) { 822 823 fireElementContentAboutToBeReplaced(fileEditorInput); 825 826 removeUnchangedElementListeners(fileEditorInput, info); 827 828 info.fDocument.removeDocumentListener(info); 829 info.fDocument.set(newContent); 830 info.fCanBeSaved= false; 831 info.fModificationStamp= computeModificationStamp(fileEditorInput.getFile()); 832 info.fStatus= status; 833 834 addUnchangedElementListeners(fileEditorInput, info); 835 836 fireElementContentReplaced(fileEditorInput); 837 838 } else { 839 840 removeUnchangedElementListeners(fileEditorInput, info); 841 842 info.fCanBeSaved= false; 844 info.fModificationStamp= computeModificationStamp(fileEditorInput.getFile()); 845 info.fStatus= status; 846 847 addUnchangedElementListeners(fileEditorInput, info); 848 849 fireElementDirtyStateChanged(fileEditorInput, false); 850 } 851 } 852 853 859 protected void handleElementMoved(IFileEditorInput fileEditorInput, IPath path) { 860 IWorkspace workspace= ResourcesPlugin.getWorkspace(); 861 IFile newFile= workspace.getRoot().getFile(path); 862 fireElementMoved(fileEditorInput, newFile == null ? null : new FileEditorInput(newFile)); 863 } 864 865 870 protected void handleElementDeleted(IFileEditorInput fileEditorInput) { 871 fireElementDeleted(fileEditorInput); 872 } 873 874 878 protected ElementInfo getElementInfo(Object element) { 879 return super.getElementInfo(element); 880 } 881 882 886 protected void doValidateState(Object element, Object computationContext) throws CoreException { 887 888 if (element instanceof IFileEditorInput) { 889 IFileEditorInput input= (IFileEditorInput) element; 890 FileInfo info= (FileInfo) getElementInfo(input); 891 if (info != null) { 892 IFile file= input.getFile(); 893 if (file.isReadOnly()) { IWorkspace workspace= file.getWorkspace(); 895 info.fStatus= workspace.validateEdit(new IFile[] { file }, computationContext); 896 } 897 if (isDerived(file)) { 898 IStatus status= new Status(IStatus.WARNING, EditorsUI.PLUGIN_ID, EditorsUI.DERIVED_FILE, TextEditorMessages.FileDocumentProvider_warning_fileIsDerived, null); 899 if (info.fStatus == null || info.fStatus.isOK()) 900 info.fStatus= status; 901 else 902 info.fStatus= new MultiStatus(EditorsUI.PLUGIN_ID, EditorsUI.STATE_VALIDATION_FAILED, new IStatus[] {info.fStatus, status}, TextEditorMessages.FileDocumentProvider_stateValidationFailed, null); 903 } 904 } 905 } 906 907 super.doValidateState(element, computationContext); 908 } 909 910 915 private boolean isDerived(IResource resource) { 916 while (resource != null) { 917 if (resource.isDerived()) 918 return true; 919 resource= resource.getParent(); 920 } 921 return false; 922 } 923 924 928 public boolean isModifiable(Object element) { 929 if (!isStateValidated(element)) { 930 if (element instanceof IFileEditorInput) 931 return true; 932 } 933 return super.isModifiable(element); 934 } 935 936 940 protected void doResetDocument(Object element, IProgressMonitor monitor) throws CoreException { 941 if (element instanceof IFileEditorInput) { 942 IFileEditorInput input= (IFileEditorInput) element; 943 try { 944 refreshFile(input.getFile(), monitor); 945 cacheEncodingState(element); 946 } catch (CoreException x) { 947 handleCoreException(x,TextEditorMessages.FileDocumentProvider_resetDocument); 948 } 949 } 950 951 super.doResetDocument(element, monitor); 952 953 IAnnotationModel model= getAnnotationModel(element); 954 if (model instanceof AbstractMarkerAnnotationModel) { 955 AbstractMarkerAnnotationModel markerModel= (AbstractMarkerAnnotationModel) model; 956 markerModel.resetMarkers(); 957 } 958 } 959 960 967 protected void refreshFile(IFile file) throws CoreException { 968 refreshFile(file, getProgressMonitor()); 969 } 970 971 979 protected void refreshFile(IFile file, IProgressMonitor monitor) throws CoreException { 980 try { 981 file.refreshLocal(IResource.DEPTH_INFINITE, monitor); 982 } catch (OperationCanceledException x) { 983 } 984 } 985 986 990 public boolean isSynchronized(Object element) { 991 if (element instanceof IFileEditorInput) { 992 if (getElementInfo(element) != null) { 993 IFileEditorInput input= (IFileEditorInput) element; 994 IResource resource= input.getFile(); 995 return resource.isSynchronized(IResource.DEPTH_ZERO); 996 } 997 return false; 998 } 999 return super.isSynchronized(element); 1000 } 1001 1002 1006 public IContentType getContentType(Object element) throws CoreException { 1007 IContentType contentType= null; 1008 if (!canSaveDocument(element) && element instanceof IFileEditorInput) 1009 contentType= getContentType((IFileEditorInput) element); 1010 1011 if (contentType == null) 1012 contentType= super.getContentType(element); 1013 1014 if (contentType == null && element instanceof IFileEditorInput) 1015 contentType= getContentType((IFileEditorInput) element); 1016 1017 return contentType; 1018 } 1019 1020 1030 private IContentType getContentType(IFileEditorInput input) throws CoreException { 1031 IContentDescription desc= input.getFile().getContentDescription(); 1032 if (desc != null) 1033 return desc.getContentType(); 1034 return null; 1035 } 1036 1037 1039 1046 protected String getPersistedEncoding(Object element) { 1047 if (element instanceof IFileEditorInput) { 1048 IFileEditorInput editorInput= (IFileEditorInput)element; 1049 IFile file= editorInput.getFile(); 1050 if (file != null) { 1051 String encoding= null; 1052 try { 1053 encoding= file.getPersistentProperty(ENCODING_KEY); 1054 } catch (CoreException x) { 1055 } 1057 if (encoding != null) { 1058 try { 1060 file.setCharset(encoding, getProgressMonitor()); 1061 file.setPersistentProperty(ENCODING_KEY, null); 1063 } catch (CoreException ex) { 1064 handleCoreException(ex, TextEditorMessages.FileDocumentProvider_getPersistedEncoding); 1065 } 1066 } else { 1067 try { 1068 encoding= file.getCharset(); 1069 } catch (CoreException e) { 1070 return null; 1071 } 1072 } 1073 return encoding; 1074 } 1075 } 1076 return super.getPersistedEncoding(element); 1077 } 1078 1079 1087 protected void persistEncoding(Object element, String encoding) throws CoreException { 1088 if (element instanceof IFileEditorInput) { 1089 IFileEditorInput editorInput= (IFileEditorInput)element; 1090 IFile file= editorInput.getFile(); 1091 if (file != null) { 1092 file.setCharset(encoding, getProgressMonitor()); 1093 StorageInfo info= (StorageInfo)getElementInfo(element); 1094 if (info != null) { 1095 if (encoding == null) 1096 info.fEncoding= file.getCharset(); 1097 if (info instanceof FileInfo) 1098 ((FileInfo)info).fHasBOM= hasBOM(element); 1099 } 1100 } 1101 } 1102 } 1103 1104 1108 protected IRunnableContext getOperationRunner(IProgressMonitor monitor) { 1109 if (fOperationRunner == null) 1110 fOperationRunner = new WorkspaceOperationRunner(); 1111 fOperationRunner.setProgressMonitor(monitor); 1112 return fOperationRunner; 1113 } 1114 1115 1119 protected ISchedulingRule getResetRule(Object element) { 1120 if (element instanceof IFileEditorInput) { 1121 IFileEditorInput input= (IFileEditorInput) element; 1122 return fResourceRuleFactory.refreshRule(input.getFile()); 1123 } 1124 return null; 1125 } 1126 1127 1131 protected ISchedulingRule getSaveRule(Object element) { 1132 if (element instanceof IFileEditorInput) { 1133 IFileEditorInput input= (IFileEditorInput) element; 1134 return computeSchedulingRule(input.getFile()); 1135 } 1136 return null; 1137 } 1138 1139 1143 protected ISchedulingRule getSynchronizeRule(Object element) { 1144 if (element instanceof IFileEditorInput) { 1145 IFileEditorInput input= (IFileEditorInput) element; 1146 return fResourceRuleFactory.refreshRule(input.getFile()); 1147 } 1148 return null; 1149 } 1150 1151 1155 protected ISchedulingRule getValidateStateRule(Object element) { 1156 if (element instanceof IFileEditorInput) { 1157 IFileEditorInput input= (IFileEditorInput) element; 1158 return fResourceRuleFactory.validateEditRule(new IResource[] { input.getFile() }); 1159 } 1160 return null; 1161 } 1162 1163 1169 private boolean hasBOM(Object element) { 1170 if (element instanceof IFileEditorInput) { 1171 IFile file= ((IFileEditorInput)element).getFile(); 1172 if (file != null) { 1173 try { 1174 IContentDescription description= file.getContentDescription(); 1175 return description != null && description.getProperty(IContentDescription.BYTE_ORDER_MARK) != null; 1176 } catch (CoreException ex) { 1177 return false; 1178 } 1179 } 1180 } 1181 return false; 1182 } 1183 1184 1198 protected void readUTF8BOM(IFile file, String encoding, Object element) throws CoreException { 1199 } 1200 1201 1208 protected void cacheEncodingState(Object element) throws CoreException { 1209 if (element instanceof IFileEditorInput) { 1210 IFileEditorInput editorInput= (IFileEditorInput)element; 1211 IFile file= editorInput.getFile(); 1212 if (file != null) { 1213 ElementInfo info= getElementInfo(element); 1214 if (info instanceof StorageInfo) 1215 ((StorageInfo)info).fEncoding= getPersistedEncoding(element); 1216 1217 if (info instanceof FileInfo) 1218 ((FileInfo)info).fHasBOM= hasBOM(element); 1219 } 1220 } 1221 } 1222 1223 1233 private ISchedulingRule computeSchedulingRule(IResource toCreateOrModify) { 1234 if (toCreateOrModify.exists()) 1235 return fResourceRuleFactory.modifyRule(toCreateOrModify); 1236 1237 IResource parent= toCreateOrModify; 1238 do { 1239 toCreateOrModify= parent; 1240 parent= toCreateOrModify.getParent(); 1241 } while (parent != null && !parent.exists()); 1242 1243 return fResourceRuleFactory.createRule(toCreateOrModify); 1244 } 1245} 1246 | Popular Tags |