KickJava   Java API By Example, From Geeks To Geeks.

Java > Open Source Codes > org > eclipse > ui > editors > text > TextFileDocumentProvider


1 /*******************************************************************************
2  * Copyright (c) 2000, 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.ui.editors.text;
12
13 import java.io.File JavaDoc;
14 import java.lang.reflect.InvocationTargetException JavaDoc;
15 import java.net.URI JavaDoc;
16 import java.util.ArrayList JavaDoc;
17 import java.util.HashMap JavaDoc;
18 import java.util.HashSet JavaDoc;
19 import java.util.Iterator JavaDoc;
20 import java.util.List JavaDoc;
21 import java.util.Map JavaDoc;
22 import java.util.NoSuchElementException JavaDoc;
23
24 import org.osgi.framework.Bundle;
25
26 import org.eclipse.core.filesystem.EFS;
27 import org.eclipse.core.filesystem.IFileInfo;
28 import org.eclipse.core.filesystem.IFileStore;
29
30 import org.eclipse.core.runtime.Assert;
31 import org.eclipse.core.runtime.CoreException;
32 import org.eclipse.core.runtime.IAdaptable;
33 import org.eclipse.core.runtime.ILog;
34 import org.eclipse.core.runtime.IPath;
35 import org.eclipse.core.runtime.IProgressMonitor;
36 import org.eclipse.core.runtime.IStatus;
37 import org.eclipse.core.runtime.MultiStatus;
38 import org.eclipse.core.runtime.NullProgressMonitor;
39 import org.eclipse.core.runtime.Platform;
40 import org.eclipse.core.runtime.Status;
41 import org.eclipse.core.runtime.content.IContentType;
42 import org.eclipse.core.runtime.jobs.ISchedulingRule;
43
44 import org.eclipse.core.resources.IFile;
45 import org.eclipse.core.resources.IResource;
46 import org.eclipse.core.resources.IResourceRuleFactory;
47 import org.eclipse.core.resources.IResourceStatus;
48 import org.eclipse.core.resources.IWorkspace;
49 import org.eclipse.core.resources.ResourcesPlugin;
50
51 import org.eclipse.core.filebuffers.FileBuffers;
52 import org.eclipse.core.filebuffers.IFileBuffer;
53 import org.eclipse.core.filebuffers.IFileBufferListener;
54 import org.eclipse.core.filebuffers.IFileBufferManager;
55 import org.eclipse.core.filebuffers.ITextFileBuffer;
56 import org.eclipse.core.filebuffers.ITextFileBufferManager;
57 import org.eclipse.core.filebuffers.LocationKind;
58
59 import org.eclipse.jface.operation.IRunnableContext;
60 import org.eclipse.jface.operation.IRunnableWithProgress;
61
62 import org.eclipse.jface.text.IDocument;
63 import org.eclipse.jface.text.ISynchronizable;
64 import org.eclipse.jface.text.source.IAnnotationModel;
65
66 import org.eclipse.ui.IEditorInput;
67 import org.eclipse.ui.IFileEditorInput;
68 import org.eclipse.ui.IURIEditorInput;
69 import org.eclipse.ui.PlatformUI;
70 import org.eclipse.ui.internal.editors.text.NLSUtility;
71 import org.eclipse.ui.internal.editors.text.UISynchronizationContext;
72 import org.eclipse.ui.internal.editors.text.WorkspaceOperationRunner;
73 import org.eclipse.ui.part.FileEditorInput;
74 import org.eclipse.ui.texteditor.AbstractMarkerAnnotationModel;
75 import org.eclipse.ui.texteditor.IDocumentProvider;
76 import org.eclipse.ui.texteditor.IDocumentProviderExtension;
77 import org.eclipse.ui.texteditor.IDocumentProviderExtension2;
78 import org.eclipse.ui.texteditor.IDocumentProviderExtension3;
79 import org.eclipse.ui.texteditor.IDocumentProviderExtension4;
80 import org.eclipse.ui.texteditor.IDocumentProviderExtension5;
81 import org.eclipse.ui.texteditor.IElementStateListener;
82 import org.eclipse.ui.texteditor.IElementStateListenerExtension;
83 import org.eclipse.ui.texteditor.ISchedulingRuleProvider;
84
85
86 /**
87  * Shared document provider specialized for {@link org.eclipse.core.resources.IFile} based domain elements.
88  * A text file document provider can have a parent document provider to which
89  * it may delegate calls i.e. instead of delegating work to a super class it
90  * delegates to a parent document provider. The parent chain acts as chain
91  * of command.
92  * <p>
93  * Text file document providers use {@linkplain org.eclipse.core.filebuffers.ITextFileBuffer text file buffers}
94  * to access the file content. This allows to share it between various clients including
95  * headless ones. Text file document providers should be preferred over file document
96  * providers due to this advantage.
97  * </p>
98  * <p>
99  * Use a {@linkplain org.eclipse.ui.editors.text.ForwardingDocumentProvider forwarding document provider}
100  * if you need to ensure that all documents provided to clients are appropriately set up.
101  * </p>
102  * <p>
103  * Clients can directly instantiate and configure this class with a suitable parent
104  * document provider or provide their own subclass.
105  * </p>
106  *
107  * @since 3.0
108  */

109 public class TextFileDocumentProvider implements IDocumentProvider, IDocumentProviderExtension, IDocumentProviderExtension2, IDocumentProviderExtension3, IDocumentProviderExtension5, IStorageDocumentProvider, IDocumentProviderExtension4 {
110
111     /**
112      * Operation created by the document provider and to be executed by the providers runnable context.
113      */

114     protected static abstract class DocumentProviderOperation implements IRunnableWithProgress, ISchedulingRuleProvider {
115
116         /**
117          * The actual functionality of this operation.
118          *
119          * @param monitor the progress monitor
120          * @throws CoreException
121          */

122         protected abstract void execute(IProgressMonitor monitor) throws CoreException;
123
124         /*
125          * @see org.eclipse.jface.operation.IRunnableWithProgress#run(org.eclipse.core.runtime.IProgressMonitor)
126          */

127         public void run(IProgressMonitor monitor) throws InvocationTargetException JavaDoc, InterruptedException JavaDoc {
128             try {
129                 execute(monitor);
130             } catch (CoreException x) {
131                 throw new InvocationTargetException JavaDoc(x);
132             }
133         }
134
135         /*
136          * @see org.eclipse.ui.texteditor.ISchedulingRuleProvider#getSchedulingRule()
137          */

138         public ISchedulingRule getSchedulingRule() {
139             return ResourcesPlugin.getWorkspace().getRoot();
140         }
141     }
142
143     /**
144      * @deprecated since 3.3 - do not use
145      */

146     static protected class NullProvider implements IDocumentProvider, IDocumentProviderExtension, IDocumentProviderExtension2, IDocumentProviderExtension3, IDocumentProviderExtension4, IDocumentProviderExtension5, IStorageDocumentProvider {
147
148         static final private IStatus STATUS_ERROR= new Status(IStatus.ERROR, EditorsUI.PLUGIN_ID, IStatus.OK, TextEditorMessages.NullProvider_error, null);
149
150         public void connect(Object JavaDoc element) throws CoreException {}
151         public void disconnect(Object JavaDoc element) {}
152         public IDocument getDocument(Object JavaDoc element) { return null; }
153         public void resetDocument(Object JavaDoc element) throws CoreException {}
154         public void saveDocument(IProgressMonitor monitor, Object JavaDoc element, IDocument document, boolean overwrite) throws CoreException {}
155         public long getModificationStamp(Object JavaDoc element) { return 0; }
156         public long getSynchronizationStamp(Object JavaDoc element) { return 0; }
157         public boolean isDeleted(Object JavaDoc element) { return true; }
158         public boolean mustSaveDocument(Object JavaDoc element) { return false; }
159         public boolean canSaveDocument(Object JavaDoc element) { return false; }
160         public IAnnotationModel getAnnotationModel(Object JavaDoc element) { return null; }
161         public void aboutToChange(Object JavaDoc element) {}
162         public void changed(Object JavaDoc element) {}
163         public void addElementStateListener(IElementStateListener listener) {}
164         public void removeElementStateListener(IElementStateListener listener) {}
165         public boolean isReadOnly(Object JavaDoc element) { return true; }
166         public boolean isModifiable(Object JavaDoc element) { return false; }
167         public void validateState(Object JavaDoc element, Object JavaDoc computationContext) throws CoreException {}
168         public boolean isStateValidated(Object JavaDoc element) { return true; }
169         public void updateStateCache(Object JavaDoc element) throws CoreException {}
170         public void setCanSaveDocument(Object JavaDoc element) {}
171         public IStatus getStatus(Object JavaDoc element) { return STATUS_ERROR; }
172         public void synchronize(Object JavaDoc element) throws CoreException {}
173         public void setProgressMonitor(IProgressMonitor progressMonitor) {}
174         public IProgressMonitor getProgressMonitor() { return new NullProgressMonitor(); }
175         public boolean isSynchronized(Object JavaDoc element) { return true; }
176         public boolean isNotSynchronizedException(Object JavaDoc element, CoreException ex) { return false; }
177         public String JavaDoc getDefaultEncoding() { return null; }
178         public String JavaDoc getEncoding(Object JavaDoc element) { return null; }
179         public void setEncoding(Object JavaDoc element, String JavaDoc encoding) {}
180         public IContentType getContentType(Object JavaDoc element) throws CoreException { return null; }
181     }
182
183     static protected class FileInfo {
184         public Object JavaDoc fElement;
185         public int fCount;
186         public ITextFileBuffer fTextFileBuffer;
187         
188         // private due to 3.3 API freeze, see https://bugs.eclipse.org/bugs/show_bug.cgi?id=182086
189
private LocationKind fTextFileBufferLocationKind;
190         
191         public IAnnotationModel fModel;
192         public boolean fCachedReadOnlyState;
193     }
194
195     static private class SingleElementIterator implements Iterator JavaDoc {
196
197         private Object JavaDoc fElement;
198
199         public SingleElementIterator(Object JavaDoc element) {
200             fElement= element;
201         }
202
203         /*
204          * @see java.util.Iterator#hasNext()
205          */

206         public boolean hasNext() {
207             return fElement != null;
208         }
209
210         /*
211          * @see java.util.Iterator#next()
212          */

213         public Object JavaDoc next() {
214             if (fElement != null) {
215                 Object JavaDoc result= fElement;
216                 fElement= null;
217                 return result;
218             }
219             throw new NoSuchElementException JavaDoc();
220         }
221
222         /*
223          * @see java.util.Iterator#remove()
224          */

225         public void remove() {
226             throw new UnsupportedOperationException JavaDoc();
227         }
228     }
229
230     protected class FileBufferListener implements IFileBufferListener {
231
232         public FileBufferListener() {
233         }
234
235         /*
236          * @see org.eclipse.core.buffer.text.IBufferedFileListener#bufferContentAboutToBeReplaced(org.eclipse.core.buffer.text.IBufferedFile)
237          */

238         public void bufferContentAboutToBeReplaced(IFileBuffer file) {
239             List JavaDoc list= new ArrayList JavaDoc(fElementStateListeners);
240             Iterator JavaDoc e= list.iterator();
241             while (e.hasNext()) {
242                 IElementStateListener l= (IElementStateListener) e.next();
243                 Iterator JavaDoc i= getElements(file);
244                 while (i.hasNext())
245                     l.elementContentAboutToBeReplaced(i.next());
246             }
247         }
248
249         /*
250          * @see org.eclipse.core.buffer.text.IBufferedFileListener#bufferContentReplaced(org.eclipse.core.buffer.text.IBufferedFile)
251          */

252         public void bufferContentReplaced(IFileBuffer file) {
253             List JavaDoc list= new ArrayList JavaDoc(fElementStateListeners);
254             Iterator JavaDoc e= list.iterator();
255             while (e.hasNext()) {
256                 IElementStateListener l= (IElementStateListener) e.next();
257                 Iterator JavaDoc i= getElements(file);
258                 while (i.hasNext())
259                     l.elementContentReplaced(i.next());
260             }
261         }
262
263         /*
264          * @see org.eclipse.core.buffer.text.IBufferedFileListener#stateChanging(org.eclipse.core.buffer.text.IBufferedFile)
265          */

266         public void stateChanging(IFileBuffer file) {
267             Iterator JavaDoc i= getElements(file);
268             while (i.hasNext())
269                 fireElementStateChanging(i.next());
270         }
271
272         /*
273          * @see org.eclipse.core.buffer.text.IBufferedFileListener#dirtyStateChanged(org.eclipse.core.buffer.text.IBufferedFile, boolean)
274          */

275         public void dirtyStateChanged(IFileBuffer file, boolean isDirty) {
276             List JavaDoc list= new ArrayList JavaDoc(fElementStateListeners);
277             Iterator JavaDoc e= list.iterator();
278             while (e.hasNext()) {
279                 IElementStateListener l= (IElementStateListener) e.next();
280                 Iterator JavaDoc i= getElements(file);
281                 while (i.hasNext())
282                     l.elementDirtyStateChanged(i.next(), isDirty);
283             }
284         }
285
286         /*
287          * @see org.eclipse.core.buffer.text.IBufferedFileListener#stateValidationChanged(org.eclipse.core.buffer.text.IBufferedFile, boolean)
288          */

289         public void stateValidationChanged(IFileBuffer file, boolean isStateValidated) {
290             List JavaDoc list= new ArrayList JavaDoc(fElementStateListeners);
291             Iterator JavaDoc e= list.iterator();
292             while (e.hasNext()) {
293                 Object JavaDoc l= e.next();
294                 if (l instanceof IElementStateListenerExtension) {
295                     IElementStateListenerExtension x= (IElementStateListenerExtension) l;
296                     Iterator JavaDoc i= getElements(file);
297                     while (i.hasNext())
298                         x.elementStateValidationChanged(i.next(), isStateValidated);
299                 }
300             }
301         }
302
303         /*
304          * @see org.eclipse.core.buffer.text.IBufferedFileListener#underlyingFileMoved(org.eclipse.core.buffer.text.IBufferedFile, org.eclipse.core.runtime.IPath)
305          */

306         public void underlyingFileMoved(IFileBuffer file, IPath newLocation) {
307             IWorkspace workspace=ResourcesPlugin.getWorkspace();
308             IFile newFile= workspace.getRoot().getFile(newLocation);
309             IEditorInput input= newFile == null ? null : new FileEditorInput(newFile);
310             List JavaDoc list= new ArrayList JavaDoc(fElementStateListeners);
311             Iterator JavaDoc e= list.iterator();
312             while (e.hasNext()) {
313                 IElementStateListener l= (IElementStateListener) e.next();
314                 Iterator JavaDoc i= getElements(file);
315                 while (i.hasNext())
316                     l.elementMoved(i.next(), input);
317             }
318         }
319
320         /*
321          * @see org.eclipse.core.buffer.text.IBufferedFileListener#underlyingFileDeleted(org.eclipse.core.buffer.text.IBufferedFile)
322          */

323         public void underlyingFileDeleted(IFileBuffer file) {
324             List JavaDoc list= new ArrayList JavaDoc(fElementStateListeners);
325             Iterator JavaDoc e= list.iterator();
326             while (e.hasNext()) {
327                 IElementStateListener l= (IElementStateListener) e.next();
328                 Iterator JavaDoc i= getElements(file);
329                 while (i.hasNext())
330                     l.elementDeleted(i.next());
331             }
332         }
333
334         /*
335          * @see org.eclipse.core.buffer.text.IBufferedFileListener#stateChangeFailed(org.eclipse.core.buffer.text.IBufferedFile)
336          */

337         public void stateChangeFailed(IFileBuffer file) {
338             Iterator JavaDoc i= getElements(file);
339             while (i.hasNext())
340                 fireElementStateChangeFailed(i.next());
341         }
342
343         /*
344          * @see org.eclipse.core.filebuffers.IFileBufferListener#bufferCreated(org.eclipse.core.filebuffers.IFileBuffer)
345          */

346         public void bufferCreated(IFileBuffer buffer) {
347             // ignore
348
}
349
350         /*
351          * @see org.eclipse.core.filebuffers.IFileBufferListener#bufferDisposed(org.eclipse.core.filebuffers.IFileBuffer)
352          */

353         public void bufferDisposed(IFileBuffer buffer) {
354             // ignore
355
}
356     }
357
358     /** The parent document provider. */
359     private IDocumentProvider fParentProvider;
360     /** Element information of all connected elements. */
361     private final Map JavaDoc fFileInfoMap= new HashMap JavaDoc();
362     /** Map from file buffers to their connected elements. */
363     private final Map JavaDoc fFileBufferMap= new HashMap JavaDoc();
364     /** The list of element state listeners. */
365     private List JavaDoc fElementStateListeners= new ArrayList JavaDoc();
366     /** The file buffer listener. */
367     private final IFileBufferListener fFileBufferListener= new FileBufferListener();
368     /** The progress monitor. */
369     private IProgressMonitor fProgressMonitor;
370     /** The operation runner. */
371     private WorkspaceOperationRunner fOperationRunner;
372     /** The rule factory. */
373     private IResourceRuleFactory fResourceRuleFactory;
374
375
376     /**
377      * Creates a new text file document provider
378      * with no parent.
379      */

380     public TextFileDocumentProvider() {
381         this(null);
382     }
383
384     /**
385      * Creates a new text file document provider
386      * which has the given parent provider.
387      *
388      * @param parentProvider the parent document provider
389      */

390     public TextFileDocumentProvider(IDocumentProvider parentProvider) {
391         IFileBufferManager manager= FileBuffers.getTextFileBufferManager();
392         manager.setSynchronizationContext(new UISynchronizationContext());
393         if (parentProvider != null)
394             setParentDocumentProvider(parentProvider);
395
396         fResourceRuleFactory= ResourcesPlugin.getWorkspace().getRuleFactory();
397     }
398
399     /**
400      * Sets the given parent provider as this document
401      * provider's parent document provider.
402      *
403      * @param parentProvider the parent document provider
404      */

405     final public void setParentDocumentProvider(IDocumentProvider parentProvider) {
406
407         Assert.isTrue(parentProvider instanceof IDocumentProviderExtension);
408         Assert.isTrue(parentProvider instanceof IDocumentProviderExtension2);
409         Assert.isTrue(parentProvider instanceof IDocumentProviderExtension3);
410         Assert.isTrue(parentProvider instanceof IStorageDocumentProvider);
411
412         fParentProvider= parentProvider;
413     }
414
415     /**
416      * Returns the parent document provider.
417      *
418      * @return the parent document provider
419      */

420     final protected IDocumentProvider getParentProvider() {
421         if (fParentProvider == null)
422             fParentProvider= new StorageDocumentProvider();
423         return fParentProvider;
424     }
425
426     /**
427      * Returns the runnable context for this document provider.
428      *
429      * @param monitor the progress monitor
430      * @return the runnable context for this document provider
431      */

432     protected IRunnableContext getOperationRunner(IProgressMonitor monitor) {
433         if (fOperationRunner == null)
434             fOperationRunner = new WorkspaceOperationRunner();
435         fOperationRunner.setProgressMonitor(monitor);
436         return fOperationRunner;
437     }
438
439     /**
440      * Executes the given operation in the providers runnable context.
441      *
442      * @param operation the operation to be executes
443      * @param monitor the progress monitor
444      * @throws CoreException the operation's core exception
445      */

446     protected void executeOperation(DocumentProviderOperation operation, IProgressMonitor monitor) throws CoreException {
447         try {
448             IRunnableContext runner= getOperationRunner(monitor);
449             if (runner != null)
450                 runner.run(false, false, operation);
451             else
452                 operation.run(monitor);
453         } catch (InvocationTargetException JavaDoc x) {
454             Throwable JavaDoc e= x.getTargetException();
455             if (e instanceof CoreException)
456                 throw (CoreException) e;
457             String JavaDoc message= (e.getMessage() != null ? e.getMessage() : ""); //$NON-NLS-1$
458
throw new CoreException(new Status(IStatus.ERROR, EditorsUI.PLUGIN_ID, IStatus.OK, message, e));
459         } catch (InterruptedException JavaDoc x) {
460             String JavaDoc message= (x.getMessage() != null ? x.getMessage() : ""); //$NON-NLS-1$
461
throw new CoreException(new Status(IStatus.CANCEL, EditorsUI.PLUGIN_ID, IStatus.OK, message, x));
462         }
463     }
464
465     /*
466      * @see org.eclipse.ui.texteditor.IDocumentProvider#connect(java.lang.Object)
467      */

468     public void connect(Object JavaDoc element) throws CoreException {
469         FileInfo info= (FileInfo) fFileInfoMap.get(element);
470         if (info == null) {
471
472             info= createFileInfo(element);
473             if (info == null) {
474                 getParentProvider().connect(element);
475                 return;
476             }
477
478             info.fElement= element;
479             fFileInfoMap.put(element, info);
480             storeFileBufferMapping(element, info);
481         }
482         ++ info.fCount;
483     }
484
485     /**
486      * Updates the file buffer map with a new relation between the file buffer
487      * of the given info and the given element.
488      *
489      * @param element the element
490      * @param info the element's file info object
491      */

492     private void storeFileBufferMapping(Object JavaDoc element, FileInfo info) {
493         Object JavaDoc value= fFileBufferMap.get(info.fTextFileBuffer);
494
495         if (value instanceof List JavaDoc) {
496             List JavaDoc list= (List JavaDoc) value;
497             list.add(element);
498             return;
499         }
500
501         if (value == null) {
502             value= element;
503         } else {
504             List JavaDoc list= new ArrayList JavaDoc(2);
505             list.add(value);
506             list.add(element);
507
508             value= list;
509         }
510         fFileBufferMap.put(info.fTextFileBuffer, value);
511     }
512
513     /**
514      * Creates and returns a new and empty file info object.
515      * <p>
516      * Subclasses which extend {@link org.eclipse.ui.editors.text.TextFileDocumentProvider.FileInfo}
517      * should override this method.
518      * </p>
519      *
520      * @return a new and empty object of type <code>FileInfo</code>
521      */

522     protected FileInfo createEmptyFileInfo() {
523         return new FileInfo();
524     }
525
526     /**
527      * Creates and returns the file info object
528      * for the given element.
529      * <p>
530      * Subclasses which extend {@link org.eclipse.ui.editors.text.TextFileDocumentProvider.FileInfo}
531      * will probably have to extend this method as well.
532      * </p>
533      *
534      * @param element the element
535      * @return a file info object of type <code>FileInfo</code>
536      * or <code>null</code> if none can be created
537      * @throws CoreException if the file info object could not successfully be created
538      */

539     protected FileInfo createFileInfo(Object JavaDoc element) throws CoreException {
540         if (!(element instanceof IAdaptable))
541             return null;
542         IAdaptable adaptable= (IAdaptable) element;
543         
544         IFile file= null;
545         ITextFileBufferManager manager= FileBuffers.getTextFileBufferManager();
546         ITextFileBuffer fileBuffer= null;
547         LocationKind locationKind= null;
548         
549         file= (IFile)adaptable.getAdapter(IFile.class);
550         if (file != null) {
551             IPath location= file.getFullPath();
552             locationKind= LocationKind.IFILE;
553             manager.connect(location, locationKind,getProgressMonitor());
554             fileBuffer= manager.getTextFileBuffer(location, locationKind);
555         } else {
556             ILocationProvider provider= (ILocationProvider) adaptable.getAdapter(ILocationProvider.class);
557             if (provider instanceof ILocationProviderExtension) {
558                 URI JavaDoc uri= ((ILocationProviderExtension)provider).getURI(element);
559                 if (ResourcesPlugin.getWorkspace().getRoot().findFilesForLocationURI(uri).length == 0) {
560                     IFileStore fileStore= EFS.getStore(uri);
561                     manager.connectFileStore(fileStore, getProgressMonitor());
562                     fileBuffer= manager.getFileStoreTextFileBuffer(fileStore);
563                 }
564             }
565             if (fileBuffer == null && provider != null) {
566                 IPath location= provider.getPath(element);
567                 if (location == null)
568                     return null;
569                 locationKind= LocationKind.NORMALIZE;
570                 manager.connect(location, locationKind, getProgressMonitor());
571                 fileBuffer= manager.getTextFileBuffer(location, locationKind);
572                 file= FileBuffers.getWorkspaceFileAtLocation(location);
573             }
574         }
575
576         if (fileBuffer != null) {
577             fileBuffer.requestSynchronizationContext();
578
579             FileInfo info= createEmptyFileInfo();
580             info.fTextFileBuffer= fileBuffer;
581             info.fTextFileBufferLocationKind= locationKind;
582             info.fCachedReadOnlyState= isSystemFileReadOnly(info);
583
584             if (file != null)
585                 info.fModel= createAnnotationModel(file);
586
587             return info;
588         }
589         return null;
590     }
591
592     /**
593      * Sets up the synchronization for the document
594      * and the annotation mode.
595      *
596      * @param info the file info
597      * @since 3.2
598      */

599     protected void setUpSynchronization(FileInfo info) {
600         if (info == null || info.fTextFileBuffer == null)
601             return;
602         
603         IDocument document= info.fTextFileBuffer.getDocument();
604         IAnnotationModel model= info.fModel;
605
606         if (document instanceof ISynchronizable) {
607             Object JavaDoc lock= ((ISynchronizable)document).getLockObject();
608             if (lock == null) {
609                 lock= new Object JavaDoc();
610                 ((ISynchronizable)document).setLockObject(lock);
611             }
612             if (model instanceof ISynchronizable)
613                 ((ISynchronizable) model).setLockObject(lock);
614         }
615     }
616
617     /**
618      * Creates and returns the annotation model for the given file.
619      *
620      * @param file the file
621      * @return the file's annotation model or <code>null</code> if none
622      */

623     protected IAnnotationModel createAnnotationModel(IFile file) {
624         return null;
625     }
626
627     /*
628      * @see org.eclipse.ui.texteditor.IDocumentProvider#disconnect(java.lang.Object)
629      */

630     public void disconnect(Object JavaDoc element) {
631         FileInfo info= (FileInfo) fFileInfoMap.get(element);
632
633         if (info == null) {
634             getParentProvider().disconnect(element);
635             return;
636         }
637
638         if (info.fCount == 1) {
639
640             fFileInfoMap.remove(element);
641             removeFileBufferMapping(element, info);
642             disposeFileInfo(element, info);
643
644         } else
645             -- info.fCount;
646     }
647
648     /**
649      * Removes the relation between the file buffer of the given info and the
650      * given element from the file buffer mapping.
651      *
652      * @param element the element
653      * @param info the element's file info object
654      */

655     private void removeFileBufferMapping(Object JavaDoc element, FileInfo info) {
656         Object JavaDoc value= fFileBufferMap.get(info.fTextFileBuffer);
657         if (value == null)
658             return;
659
660         if (value instanceof List JavaDoc) {
661             List JavaDoc list= (List JavaDoc) value;
662             list.remove(element);
663             if (list.size() == 1)
664                 fFileBufferMap.put(info.fTextFileBuffer, list.get(0));
665         } else if (value == element) {
666             fFileBufferMap.remove(info.fTextFileBuffer);
667         }
668     }
669
670     /**
671      * Releases all resources described by given element's info object.
672      * <p>
673      * Subclasses which extend {@link org.eclipse.ui.editors.text.TextFileDocumentProvider.FileInfo}
674      * will probably have to extend this method as well.
675      * </p>
676      *
677      * @param element the element
678      * @param info the element's file info object
679      */

680     protected void disposeFileInfo(Object JavaDoc element, FileInfo info) {
681         IFileBufferManager manager= FileBuffers.getTextFileBufferManager();
682         try {
683             info.fTextFileBuffer.releaseSynchronizationContext();
684             if (info.fTextFileBufferLocationKind != null)
685                 manager.disconnect(info.fTextFileBuffer.getLocation(), info.fTextFileBufferLocationKind, getProgressMonitor());
686             else
687                 manager.disconnectFileStore(info.fTextFileBuffer.getFileStore(), getProgressMonitor());
688         } catch (CoreException x) {
689             handleCoreException(x, "FileDocumentProvider.disposeElementInfo"); //$NON-NLS-1$
690
}
691     }
692
693     /**
694      * Returns an iterator for all the elements that are connected to this file buffer.
695      *
696      * @param file the file buffer
697      * @return an iterator for all elements connected with the given file buffer
698      */

699     protected Iterator JavaDoc getElements(IFileBuffer file) {
700         Object JavaDoc value= fFileBufferMap.get(file);
701         if (value instanceof List JavaDoc)
702             return new ArrayList JavaDoc((List JavaDoc) value).iterator();
703         return new SingleElementIterator(value);
704     }
705
706     /*
707      * @see org.eclipse.ui.texteditor.IDocumentProvider#getDocument(java.lang.Object)
708      */

709     public IDocument getDocument(Object JavaDoc element) {
710         FileInfo info= (FileInfo) fFileInfoMap.get(element);
711         if (info != null)
712             return info.fTextFileBuffer.getDocument();
713         return getParentProvider().getDocument(element);
714     }
715
716     /*
717      * @see org.eclipse.ui.texteditor.IDocumentProvider#resetDocument(java.lang.Object)
718      */

719     public void resetDocument(Object JavaDoc element) throws CoreException {
720         final FileInfo info= (FileInfo) fFileInfoMap.get(element);
721         if (info != null) {
722             DocumentProviderOperation operation= new DocumentProviderOperation() {
723                 /*
724                  * @see org.eclipse.ui.editors.text.TextFileDocumentProvider.DocumentProviderOperation#execute(org.eclipse.core.runtime.IProgressMonitor)
725                  */

726                 protected void execute(IProgressMonitor monitor) throws CoreException {
727                     info.fTextFileBuffer.revert(monitor);
728
729                     if (info.fModel instanceof AbstractMarkerAnnotationModel) {
730                         AbstractMarkerAnnotationModel markerModel= (AbstractMarkerAnnotationModel) info.fModel;
731                         markerModel.resetMarkers();
732                     }
733                 }
734                 /*
735                  * @see org.eclipse.ui.editors.text.TextFileDocumentProvider.DocumentProviderOperation#getSchedulingRule()
736                  */

737                 public ISchedulingRule getSchedulingRule() {
738                     if (info.fElement instanceof IFileEditorInput) {
739                         IFileEditorInput input= (IFileEditorInput) info.fElement;
740                         return fResourceRuleFactory.refreshRule((input).getFile());
741                     }
742                     return null;
743                 }
744             };
745             executeOperation(operation, getProgressMonitor());
746         } else {
747             getParentProvider().resetDocument(element);
748         }
749     }
750
751     /*
752      * @see IDocumentProvider#saveDocument(IProgressMonitor, Object, IDocument, boolean)
753      */

754     public final void saveDocument(IProgressMonitor monitor, Object JavaDoc element, IDocument document, boolean overwrite) throws CoreException {
755
756         if (element == null)
757             return;
758
759         DocumentProviderOperation operation= createSaveOperation(element, document, overwrite);
760         if (operation != null)
761             executeOperation(operation, monitor);
762         else
763             getParentProvider().saveDocument(monitor, element, document, overwrite);
764     }
765
766     protected DocumentProviderOperation createSaveOperation(final Object JavaDoc element, final IDocument document, final boolean overwrite) throws CoreException {
767         final FileInfo info= (FileInfo) fFileInfoMap.get(element);
768         if (info != null) {
769
770             if (info.fTextFileBuffer.getDocument() != document) {
771                 // the info exists, but not for the given document
772
// -> saveAs was executed with a target that is already open
773
// in another editor
774
// see https://bugs.eclipse.org/bugs/show_bug.cgi?id=85519
775
Status status= new Status(IStatus.WARNING, EditorsUI.PLUGIN_ID, IStatus.OK, TextEditorMessages.TextFileDocumentProvider_saveAsTargetOpenInEditor, null);
776                 throw new CoreException(status);
777             }
778
779             return new DocumentProviderOperation() {
780                 /*
781                  * @see org.eclipse.ui.editors.text.TextFileDocumentProvider.DocumentProviderOperation#execute(org.eclipse.core.runtime.IProgressMonitor)
782                  */

783                 public void execute(IProgressMonitor monitor) throws CoreException {
784                     commitFileBuffer(monitor, info, overwrite);
785                 }
786                 /*
787                  * @see org.eclipse.ui.editors.text.TextFileDocumentProvider.DocumentProviderOperation#getSchedulingRule()
788                  */

789                 public ISchedulingRule getSchedulingRule() {
790                     if (info.fElement instanceof IFileEditorInput) {
791                         IFileEditorInput input= (IFileEditorInput) info.fElement;
792                         return computeSchedulingRule(input.getFile());
793                     }
794                     return null;
795                 }
796             };
797
798         } else if (element instanceof IFileEditorInput) {
799
800             final IFile file= ((IFileEditorInput) element).getFile();
801             return new DocumentProviderOperation() {
802                 /*
803                  * @see org.eclipse.ui.editors.text.TextFileDocumentProvider.DocumentProviderOperation#execute(org.eclipse.core.runtime.IProgressMonitor)
804                  */

805                 public void execute(IProgressMonitor monitor) throws CoreException {
806                     createFileFromDocument(monitor, file, document);
807                 }
808                 /*
809                  * @see org.eclipse.ui.editors.text.TextFileDocumentProvider.DocumentProviderOperation#getSchedulingRule()
810                  */

811                 public ISchedulingRule getSchedulingRule() {
812                     return computeSchedulingRule(file);
813                 }
814             };
815         } else if (element instanceof IURIEditorInput) {
816             final URI JavaDoc uri= ((IURIEditorInput)element).getURI();
817             return new DocumentProviderOperation() {
818                 /*
819                  * @see org.eclipse.ui.editors.text.TextFileDocumentProvider.DocumentProviderOperation#execute(org.eclipse.core.runtime.IProgressMonitor)
820                  */

821                 public void execute(IProgressMonitor monitor) throws CoreException {
822                     createFileStoreFromDocument(monitor, uri, document);
823                 }
824                 /*
825                  * @see org.eclipse.ui.editors.text.TextFileDocumentProvider.DocumentProviderOperation#getSchedulingRule()
826                  */

827                 public ISchedulingRule getSchedulingRule() {
828                     return null;
829                 }
830             };
831         }
832
833         return null;
834     }
835
836     /**
837      * Commits the given file info's file buffer by changing the contents
838      * of the underlying file to the contents of this file buffer. After that
839      * call, <code>isDirty</code> returns <code>false</code> and <code>isSynchronized</code>
840      * returns <code>true</code>.
841      *
842      * @param monitor the progress monitor
843      * @param info the element's file info object
844      * @param overwrite indicates whether the underlying file should be overwritten if it is not synchronized with the file system
845      * @throws CoreException if writing or accessing the underlying file fails
846      */

847     protected void commitFileBuffer(IProgressMonitor monitor, FileInfo info, boolean overwrite) throws CoreException {
848         Assert.isNotNull(info);
849         
850         /* https://bugs.eclipse.org/bugs/show_bug.cgi?id=98327
851          * Make sure file gets save in commit() if the underlying file has been deleted */

852         if (info.fElement instanceof IFileEditorInput) {
853             IFileEditorInput input= (IFileEditorInput) info.fElement;
854             IResource resource= input.getFile();
855             if (!resource.isSynchronized(IResource.DEPTH_ZERO) && isDeleted(input))
856                 info.fTextFileBuffer.setDirty(true);
857         }
858         
859         info.fTextFileBuffer.commit(monitor, overwrite);
860         if (info.fModel instanceof AbstractMarkerAnnotationModel) {
861             AbstractMarkerAnnotationModel model= (AbstractMarkerAnnotationModel) info.fModel;
862             model.updateMarkers(info.fTextFileBuffer.getDocument());
863         }
864     }
865
866     /**
867      * Creates the given file with the given document content.
868      *
869      * @param monitor the progress monitor
870      * @param file the file to be created
871      * @param document the document to be written to the file
872      * @throws CoreException if the creation of the file fails
873      */

874     protected void createFileFromDocument(IProgressMonitor monitor, IFile file, IDocument document) throws CoreException {
875         try {
876             monitor.beginTask(TextEditorMessages.TextFileDocumentProvider_beginTask_saving, 2000);
877             ITextFileBufferManager manager= FileBuffers.getTextFileBufferManager();
878             manager.connect(file.getFullPath(), LocationKind.IFILE, monitor);
879             ITextFileBuffer buffer= ITextFileBufferManager.DEFAULT.getTextFileBuffer(file.getFullPath(), LocationKind.IFILE);
880             buffer.getDocument().set(document.get());
881             buffer.commit(monitor, true);
882             manager.disconnect(file.getFullPath(), LocationKind.IFILE, monitor);
883         } finally {
884             monitor.done();
885         }
886     }
887
888     /**
889      * Creates the given file store with the given document content.
890      *
891      * @param monitor the progress monitor
892      * @param uri the location where the file store should be created
893      * @param document the document to be written to the file store
894      * @throws CoreException if the creation of the file store fails
895      * @since 3.3
896      */

897     private void createFileStoreFromDocument(IProgressMonitor monitor, URI JavaDoc uri, IDocument document) throws CoreException {
898         try {
899             monitor.beginTask(TextEditorMessages.TextFileDocumentProvider_beginTask_saving, 2000);
900             IFileStore fileStore= EFS.getStore(uri);
901             FileBuffers.getTextFileBufferManager().connectFileStore(fileStore, monitor);
902             ITextFileBuffer buffer= FileBuffers.getTextFileBufferManager().getFileStoreTextFileBuffer(fileStore);
903             buffer.getDocument().set(document.get());
904             buffer.commit(monitor, true);
905             FileBuffers.getTextFileBufferManager().disconnectFileStore(fileStore, monitor);
906         } finally {
907             monitor.done();
908         }
909     }
910
911     /*
912      * @see org.eclipse.ui.texteditor.IDocumentProvider#getModificationStamp(java.lang.Object)
913      */

914     public long getModificationStamp(Object JavaDoc element) {
915         FileInfo info= (FileInfo) fFileInfoMap.get(element);
916         if (info != null)
917             return info.fTextFileBuffer.getModificationStamp();
918         return getParentProvider().getModificationStamp(element);
919     }
920
921     /*
922      * @see org.eclipse.ui.texteditor.IDocumentProvider#getSynchronizationStamp(java.lang.Object)
923      */

924     public long getSynchronizationStamp(Object JavaDoc element) {
925         FileInfo info= (FileInfo) fFileInfoMap.get(element);
926         if (info != null)
927             return 0;
928         return getParentProvider().getSynchronizationStamp(element);
929     }
930
931     /*
932      * @see org.eclipse.ui.texteditor.IDocumentProvider#isDeleted(java.lang.Object)
933      */

934     public boolean isDeleted(Object JavaDoc element) {
935         FileInfo info= (FileInfo) fFileInfoMap.get(element);
936         if (info != null) {
937             IFileStore fileStore= getFileStore(info);
938             return fileStore == null ? true : !fileStore.fetchInfo().exists();
939         }
940         return getParentProvider().isDeleted(element);
941     }
942
943     /*
944      * @see org.eclipse.ui.texteditor.IDocumentProvider#mustSaveDocument(java.lang.Object)
945      */

946     public boolean mustSaveDocument(Object JavaDoc element) {
947         FileInfo info= (FileInfo) fFileInfoMap.get(element);
948         if (info != null)
949             return (info.fCount == 1) && info.fTextFileBuffer.isDirty();
950         return getParentProvider().mustSaveDocument(element);
951     }
952
953     /*
954      * @see org.eclipse.ui.texteditor.IDocumentProvider#canSaveDocument(java.lang.Object)
955      */

956     public boolean canSaveDocument(Object JavaDoc element) {
957         FileInfo info= (FileInfo) fFileInfoMap.get(element);
958         if (info != null)
959             return info.fTextFileBuffer.isDirty();
960         return getParentProvider().canSaveDocument(element);
961     }
962
963     /*
964      * @see org.eclipse.ui.texteditor.IDocumentProvider#getAnnotationModel(java.lang.Object)
965      */

966     public IAnnotationModel getAnnotationModel(Object JavaDoc element) {
967         FileInfo info= (FileInfo) fFileInfoMap.get(element);
968         if (info != null) {
969             if (info.fModel != null)
970                 return info.fModel;
971             return info.fTextFileBuffer.getAnnotationModel();
972         }
973         return getParentProvider().getAnnotationModel(element);
974     }
975
976     /*
977      * @see org.eclipse.ui.texteditor.IDocumentProvider#aboutToChange(java.lang.Object)
978      */

979     public void aboutToChange(Object JavaDoc element) {
980         FileInfo info= (FileInfo) fFileInfoMap.get(element);
981         if (info == null)
982             getParentProvider().aboutToChange(element);
983     }
984
985     /*
986      * @see org.eclipse.ui.texteditor.IDocumentProvider#changed(java.lang.Object)
987      */

988     public void changed(Object JavaDoc element) {
989         FileInfo info= (FileInfo) fFileInfoMap.get(element);
990         if (info == null)
991             getParentProvider().changed(element);
992     }
993
994     /*
995      * @see org.eclipse.ui.texteditor.IDocumentProvider#addElementStateListener(org.eclipse.ui.texteditor.IElementStateListener)
996      */

997     public void addElementStateListener(IElementStateListener listener) {
998         Assert.isNotNull(listener);
999         if (!fElementStateListeners.contains(listener)) {
1000            fElementStateListeners.add(listener);
1001            if (fElementStateListeners.size() == 1) {
1002                IFileBufferManager manager= FileBuffers.getTextFileBufferManager();
1003                manager.addFileBufferListener(fFileBufferListener);
1004            }
1005        }
1006        getParentProvider().addElementStateListener(listener);
1007    }
1008
1009    /*
1010     * @see org.eclipse.ui.texteditor.IDocumentProvider#removeElementStateListener(org.eclipse.ui.texteditor.IElementStateListener)
1011     */

1012    public void removeElementStateListener(IElementStateListener listener) {
1013        Assert.isNotNull(listener);
1014        fElementStateListeners.remove(listener);
1015        if (fElementStateListeners.size() == 0) {
1016            IFileBufferManager manager= FileBuffers.getTextFileBufferManager();
1017            manager.removeFileBufferListener(fFileBufferListener);
1018        }
1019        getParentProvider().removeElementStateListener(listener);
1020    }
1021
1022    /*
1023     * @see org.eclipse.ui.texteditor.IDocumentProviderExtension#isReadOnly(java.lang.Object)
1024     */

1025    public boolean isReadOnly(Object JavaDoc element) {
1026        FileInfo info= (FileInfo) fFileInfoMap.get(element);
1027        if (info != null)
1028            return info.fCachedReadOnlyState;
1029        return ((IDocumentProviderExtension) getParentProvider()).isReadOnly(element);
1030    }
1031
1032    /*
1033     * @see org.eclipse.ui.texteditor.IDocumentProviderExtension#isModifiable(java.lang.Object)
1034     */

1035    public boolean isModifiable(Object JavaDoc element) {
1036        FileInfo info= (FileInfo) fFileInfoMap.get(element);
1037        if (info != null)
1038            return info.fTextFileBuffer.isStateValidated() ? !isReadOnly(element) : true;
1039        return ((IDocumentProviderExtension) getParentProvider()).isModifiable(element);
1040    }
1041
1042    /*
1043     * @see org.eclipse.ui.texteditor.IDocumentProviderExtension#validateState(java.lang.Object, java.lang.Object)
1044     */

1045    public void validateState(Object JavaDoc element, final Object JavaDoc computationContext) throws CoreException {
1046        final FileInfo info= (FileInfo) fFileInfoMap.get(element);
1047        if (info != null) {
1048            DocumentProviderOperation operation= new DocumentProviderOperation() {
1049                /*
1050                 * @see org.eclipse.ui.editors.text.TextFileDocumentProvider.DocumentProviderOperation#execute(org.eclipse.core.runtime.IProgressMonitor)
1051                 */

1052                protected void execute(IProgressMonitor monitor) throws CoreException {
1053                    info.fTextFileBuffer.validateState(monitor, computationContext);
1054                }
1055                /*
1056                 * @see org.eclipse.ui.editors.text.TextFileDocumentProvider.DocumentProviderOperation#getSchedulingRule()
1057                 */

1058                public ISchedulingRule getSchedulingRule() {
1059                    if (info.fElement instanceof IFileEditorInput) {
1060                        IFileEditorInput input= (IFileEditorInput) info.fElement;
1061                        return fResourceRuleFactory.validateEditRule(new IResource[] { input.getFile() });
1062                    }
1063                    return null;
1064                }
1065            };
1066            executeOperation(operation, getProgressMonitor());
1067        } else
1068            ((IDocumentProviderExtension) getParentProvider()).validateState(element, computationContext);
1069    }
1070
1071    /*
1072     * @see org.eclipse.ui.texteditor.IDocumentProviderExtension#isStateValidated(java.lang.Object)
1073     */

1074    public boolean isStateValidated(Object JavaDoc element) {
1075        FileInfo info= (FileInfo) fFileInfoMap.get(element);
1076        if (info != null)
1077            return info.fTextFileBuffer.isStateValidated();
1078        return ((IDocumentProviderExtension) getParentProvider()).isStateValidated(element);
1079    }
1080
1081    /*
1082     * @see org.eclipse.ui.texteditor.IDocumentProviderExtension#updateStateCache(java.lang.Object)
1083     */

1084    public void updateStateCache(Object JavaDoc element) throws CoreException {
1085        FileInfo info= (FileInfo) fFileInfoMap.get(element);
1086        if (info != null) {
1087            boolean isReadOnly= isSystemFileReadOnly(info);
1088            // See http://bugs.eclipse.org/bugs/show_bug.cgi?id=14469 for the dirty bit check
1089
// See https://bugs.eclipse.org/bugs/show_bug.cgi?id=50699 for commenting that out
1090
if (!info.fCachedReadOnlyState && isReadOnly /*&& !info.fTextFileBuffer.isDirty()*/)
1091                info.fTextFileBuffer.resetStateValidation();
1092            info.fCachedReadOnlyState= isReadOnly;
1093        } else {
1094            ((IDocumentProviderExtension) getParentProvider()).updateStateCache(element);
1095        }
1096    }
1097
1098    /*
1099     * @see org.eclipse.ui.texteditor.IDocumentProviderExtension#setCanSaveDocument(java.lang.Object)
1100     */

1101    public void setCanSaveDocument(Object JavaDoc element) {
1102        FileInfo info= (FileInfo) fFileInfoMap.get(element);
1103        if (info == null)
1104            ((IDocumentProviderExtension) getParentProvider()).setCanSaveDocument(element);
1105    }
1106
1107    /*
1108     * @see org.eclipse.ui.texteditor.IDocumentProviderExtension#getStatus(java.lang.Object)
1109     */

1110    public IStatus getStatus(Object JavaDoc element) {
1111        FileInfo info= (FileInfo) fFileInfoMap.get(element);
1112        if (info == null)
1113            return ((IDocumentProviderExtension) getParentProvider()).getStatus(element);
1114
1115        IStatus status= info.fTextFileBuffer.getStatus();
1116
1117        // Ensure that we don't open an empty document for an non-existent IFile
1118
if (element instanceof IFileEditorInput || element instanceof IURIEditorInput) {
1119            IFileStore fileStore= info.fTextFileBuffer.getFileStore();
1120            if (fileStore != null && !fileStore.fetchInfo().exists()) {
1121                String JavaDoc message= NLSUtility.format(TextEditorMessages.TextFileDocumentProvider_error_doesNotExist, fileStore.toString());
1122                return new Status(IStatus.ERROR, EditorsUI.PLUGIN_ID, IResourceStatus.RESOURCE_NOT_FOUND, message, null);
1123            }
1124        }
1125
1126        return status;
1127    }
1128
1129    /*
1130     * @see org.eclipse.ui.texteditor.IDocumentProviderExtension#synchronize(java.lang.Object)
1131     */

1132    public void synchronize(Object JavaDoc element) throws CoreException {
1133        final FileInfo info= (FileInfo) fFileInfoMap.get(element);
1134        if (info != null) {
1135            DocumentProviderOperation operation= new DocumentProviderOperation() {
1136                /*
1137                 * @see org.eclipse.ui.editors.text.TextFileDocumentProvider.DocumentProviderOperation#execute(org.eclipse.core.runtime.IProgressMonitor)
1138                 */

1139                protected void execute(IProgressMonitor monitor) throws CoreException {
1140                    info.fTextFileBuffer.revert(monitor);
1141                }
1142                /*
1143                 * @see org.eclipse.ui.editors.text.TextFileDocumentProvider.DocumentProviderOperation#getSchedulingRule()
1144                 */

1145                public ISchedulingRule getSchedulingRule() {
1146                    if (info.fElement instanceof IFileEditorInput) {
1147                        IFileEditorInput input= (IFileEditorInput) info.fElement;
1148                        return fResourceRuleFactory.refreshRule(input.getFile());
1149                    }
1150                    return null;
1151                }
1152            };
1153            executeOperation(operation, getProgressMonitor());
1154        } else {
1155            ((IDocumentProviderExtension) getParentProvider()).synchronize(element);
1156        }
1157    }
1158
1159    /*
1160     * @see org.eclipse.ui.texteditor.IDocumentProviderExtension2#setProgressMonitor(org.eclipse.core.runtime.IProgressMonitor)
1161     */

1162    public void setProgressMonitor(IProgressMonitor progressMonitor) {
1163        fProgressMonitor= progressMonitor;
1164        ((IDocumentProviderExtension2) getParentProvider()).setProgressMonitor(progressMonitor);
1165    }
1166
1167    /*
1168     * @see org.eclipse.ui.texteditor.IDocumentProviderExtension2#getProgressMonitor()
1169     */

1170    public IProgressMonitor getProgressMonitor() {
1171        return fProgressMonitor;
1172    }
1173
1174    /*
1175     * @see org.eclipse.ui.texteditor.IDocumentProviderExtension3#isSynchronized(java.lang.Object)
1176     */

1177    public boolean isSynchronized(Object JavaDoc element) {
1178        FileInfo info= (FileInfo) fFileInfoMap.get(element);
1179        if (info != null)
1180            return info.fTextFileBuffer.isSynchronized();
1181        return ((IDocumentProviderExtension3) getParentProvider()).isSynchronized(element);
1182    }
1183    
1184    /*
1185     * @see org.eclipse.ui.texteditor.IDocumentProviderExtension5#isNotSynchronizedException(Object, CoreException)
1186     * @since 3.2
1187     */

1188    public boolean isNotSynchronizedException(Object JavaDoc element, CoreException ex) {
1189        IStatus status= ex.getStatus();
1190        if (status == null || status instanceof MultiStatus)
1191            return false;
1192        
1193        if (status.getException() != null)
1194            return false;
1195        
1196        return status.getCode() == IResourceStatus.OUT_OF_SYNC_LOCAL;
1197    }
1198
1199    /*
1200     * @see org.eclipse.ui.editors.text.IStorageDocumentProvider#getDefaultEncoding()
1201     */

1202    public String JavaDoc getDefaultEncoding() {
1203        return FileBuffers.getTextFileBufferManager().getDefaultEncoding();
1204    }
1205
1206    /*
1207     * @see org.eclipse.ui.editors.text.IStorageDocumentProvider#getEncoding(java.lang.Object)
1208     */

1209    public String JavaDoc getEncoding(Object JavaDoc element) {
1210        FileInfo info= (FileInfo) fFileInfoMap.get(element);
1211        if (info != null)
1212            return info.fTextFileBuffer.getEncoding();
1213        return ((IStorageDocumentProvider) getParentProvider()).getEncoding(element);
1214    }
1215
1216    /*
1217     * @see org.eclipse.ui.editors.text.IStorageDocumentProvider#setEncoding(java.lang.Object, java.lang.String)
1218     */

1219    public void setEncoding(Object JavaDoc element, String JavaDoc encoding) {
1220        FileInfo info= (FileInfo) fFileInfoMap.get(element);
1221        if (info != null)
1222            info.fTextFileBuffer.setEncoding(encoding);
1223        else
1224            ((IStorageDocumentProvider) getParentProvider()).setEncoding(element, encoding);
1225    }
1226
1227    /*
1228     * @see org.eclipse.ui.texteditor.IDocumentProviderExtension4#getContentType(java.lang.Object)
1229     * @since 3.1
1230     */

1231    public IContentType getContentType(Object JavaDoc element) throws CoreException {
1232        FileInfo info= (FileInfo) fFileInfoMap.get(element);
1233        if (info != null)
1234            return info.fTextFileBuffer.getContentType();
1235        IDocumentProvider parent= getParentProvider();
1236        if (parent instanceof IDocumentProviderExtension4)
1237            return ((IDocumentProviderExtension4) parent).getContentType(element);
1238        return null;
1239    }
1240
1241    /**
1242     * Defines the standard procedure to handle <code>CoreExceptions</code>. Exceptions
1243     * are written to the plug-in log.
1244     *
1245     * @param exception the exception to be logged
1246     * @param message the message to be logged
1247     */

1248    protected void handleCoreException(CoreException exception, String JavaDoc message) {
1249        Bundle bundle = Platform.getBundle(PlatformUI.PLUGIN_ID);
1250        ILog log= Platform.getLog(bundle);
1251        IStatus status= message != null ? new Status(IStatus.ERROR, PlatformUI.PLUGIN_ID, IStatus.OK, message, exception) : exception.getStatus();
1252        log.log(status);
1253    }
1254
1255    /**
1256     * Returns the file store denoted by the given info.
1257     *
1258     * @param info the element's file info object
1259     * @return the {@link IFileStore} for the given file info
1260     * @since 3.2
1261     */

1262    protected IFileStore getFileStore(FileInfo info) {
1263        return info.fTextFileBuffer.getFileStore();
1264    }
1265    
1266    /**
1267     * Returns the system file denoted by the given info.
1268     *
1269     * @param info the element's file info object
1270     * @return the system file for the given file info
1271     * @deprecated As of 3.2, replaced by {@link #getFileStore(org.eclipse.ui.editors.text.TextFileDocumentProvider.FileInfo)}
1272     */

1273    protected File JavaDoc getSystemFile(FileInfo info) {
1274        IPath path= info.fTextFileBuffer.getLocation();
1275        return FileBuffers.getSystemFileAtLocation(path);
1276    }
1277
1278    /**
1279     * Returns whether the system file denoted by
1280     * the given info is read-only.
1281     *
1282     * @param info the element's file info object
1283     * @return <code>true</code> iff read-only
1284     */

1285    protected boolean isSystemFileReadOnly(FileInfo info) {
1286        IFileStore fileStore= getFileStore(info);
1287        if (fileStore == null)
1288            return false;
1289        IFileInfo fileInfo= fileStore.fetchInfo();
1290        return fileInfo.exists() && fileInfo.getAttribute(EFS.ATTRIBUTE_READ_ONLY);
1291    }
1292
1293    /**
1294     * Returns the file info object for the given element.
1295     *
1296     * @param element the element
1297     * @return the file info object, or <code>null</code> if none
1298     */

1299    protected FileInfo getFileInfo(Object JavaDoc element) {
1300        return (FileInfo) fFileInfoMap.get(element);
1301    }
1302
1303    /**
1304     * Returns an iterator over the elements connected via this document provider.
1305     *
1306     * @return an iterator over the list of elements (element type: {@link java.lang.Object}
1307     */

1308    protected Iterator JavaDoc getConnectedElementsIterator() {
1309        return new HashSet JavaDoc(fFileInfoMap.keySet()).iterator();
1310    }
1311
1312    /**
1313     * Returns an iterator over this document provider's file info objects.
1314     *
1315     * @return the iterator over list of file info objects (element type: {@link TextFileDocumentProvider.FileInfo}
1316     */

1317    protected Iterator JavaDoc getFileInfosIterator() {
1318        return new ArrayList JavaDoc(fFileInfoMap.values()).iterator();
1319    }
1320
1321    /**
1322     * Informs all registered element state listeners
1323     * about the current state change of the element.
1324     *
1325     * @param element the element
1326     * @see IElementStateListenerExtension#elementStateChanging(Object)
1327     */

1328    protected void fireElementStateChanging(Object JavaDoc element) {
1329        List JavaDoc list= new ArrayList JavaDoc(fElementStateListeners);
1330        Iterator JavaDoc e= list.iterator();
1331        while (e.hasNext()) {
1332            Object JavaDoc l= e.next();
1333            if (l instanceof IElementStateListenerExtension) {
1334                IElementStateListenerExtension x= (IElementStateListenerExtension) l;
1335                x.elementStateChanging(element);
1336            }
1337        }
1338    }
1339
1340    /**
1341     * Informs all registered element state listeners
1342     * about the failed state change of the element.
1343     *
1344     * @param element the element
1345     * @see IElementStateListenerExtension#elementStateChangeFailed(Object)
1346     */

1347    protected void fireElementStateChangeFailed(Object JavaDoc element) {
1348        List JavaDoc list= new ArrayList JavaDoc(fElementStateListeners);
1349        Iterator JavaDoc e= list.iterator();
1350        while (e.hasNext()) {
1351            Object JavaDoc l= e.next();
1352            if (l instanceof IElementStateListenerExtension) {
1353                IElementStateListenerExtension x= (IElementStateListenerExtension) l;
1354                x.elementStateChangeFailed(element);
1355            }
1356        }
1357    }
1358
1359    /**
1360     * Computes the scheduling rule needed to create or modify a resource. If
1361     * the resource exists, its modify rule is returned. If it does not, the
1362     * resource hierarchy is iterated towards the workspace root to find the
1363     * first parent of <code>toCreateOrModify</code> that exists. Then the
1364     * 'create' rule for the last non-existing resource is returned.
1365     *
1366     * @param toCreateOrModify the resource to create or modify
1367     * @return the minimal scheduling rule needed to modify or create a resource
1368     * @since 3.1
1369     */

1370    protected ISchedulingRule computeSchedulingRule(IResource toCreateOrModify) {
1371        if (toCreateOrModify.exists())
1372            return fResourceRuleFactory.modifyRule(toCreateOrModify);
1373
1374        IResource parent= toCreateOrModify;
1375        do {
1376            toCreateOrModify= parent;
1377            parent= toCreateOrModify.getParent();
1378        } while (parent != null && !parent.exists());
1379
1380        return fResourceRuleFactory.createRule(toCreateOrModify);
1381    }
1382}
1383
Popular Tags