KickJava   Java API By Example, From Geeks To Geeks.

Java > Open Source Codes > org > eclipse > jdt > internal > ui > javaeditor > ClassFileDocumentProvider


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.jdt.internal.ui.javaeditor;
12
13
14 import java.util.ArrayList JavaDoc;
15 import java.util.Iterator JavaDoc;
16 import java.util.List JavaDoc;
17
18 import org.eclipse.core.runtime.CoreException;
19 import org.eclipse.core.runtime.IProgressMonitor;
20
21 import org.eclipse.core.filebuffers.FileBuffers;
22 import org.eclipse.core.filebuffers.LocationKind;
23
24 import org.eclipse.core.resources.IResource;
25
26 import org.eclipse.jface.text.IDocument;
27 import org.eclipse.jface.text.ISynchronizable;
28 import org.eclipse.jface.text.source.IAnnotationModel;
29
30 import org.eclipse.ui.IEditorInput;
31 import org.eclipse.ui.IFileEditorInput;
32
33 import org.eclipse.ui.editors.text.FileDocumentProvider;
34
35 import org.eclipse.jdt.core.ElementChangedEvent;
36 import org.eclipse.jdt.core.IClassFile;
37 import org.eclipse.jdt.core.IElementChangedListener;
38 import org.eclipse.jdt.core.IJavaElement;
39 import org.eclipse.jdt.core.IJavaElementDelta;
40 import org.eclipse.jdt.core.IJavaProject;
41 import org.eclipse.jdt.core.IPackageFragmentRoot;
42 import org.eclipse.jdt.core.JavaCore;
43 import org.eclipse.jdt.core.JavaModelException;
44
45 import org.eclipse.jdt.ui.text.IJavaPartitions;
46 import org.eclipse.jdt.ui.text.JavaTextTools;
47
48 import org.eclipse.jdt.internal.ui.IResourceLocator;
49 import org.eclipse.jdt.internal.ui.JavaPlugin;
50
51
52 /**
53  * A document provider for class files. Class files can be either inside
54  */

55 public class ClassFileDocumentProvider extends FileDocumentProvider {
56
57     /**
58      * An input change listener to request the editor to reread the input.
59      */

60     public interface InputChangeListener {
61         void inputChanged(IClassFileEditorInput input);
62     }
63
64     /**
65      * Synchronizes the document with external resource changes.
66      */

67     protected class ClassFileSynchronizer implements IElementChangedListener {
68
69         protected IClassFileEditorInput fInput;
70         protected IPackageFragmentRoot fPackageFragmentRoot;
71
72         /**
73          * Default constructor.
74          */

75         public ClassFileSynchronizer(IClassFileEditorInput input) {
76
77             fInput= input;
78
79             IJavaElement parent= fInput.getClassFile().getParent();
80             while (parent != null && !(parent instanceof IPackageFragmentRoot)) {
81                 parent= parent.getParent();
82             }
83             fPackageFragmentRoot= (IPackageFragmentRoot) parent;
84         }
85
86         /**
87          * Installs the synchronizer.
88          */

89         public void install() {
90             JavaCore.addElementChangedListener(this);
91         }
92
93         /**
94          * Uninstalls the synchronizer.
95          */

96         public void uninstall() {
97             JavaCore.removeElementChangedListener(this);
98         }
99
100         /*
101          * @see IElementChangedListener#elementChanged
102          */

103         public void elementChanged(ElementChangedEvent e) {
104             check(fPackageFragmentRoot, e.getDelta());
105         }
106
107         /**
108          * Recursively check whether the class file has been deleted.
109          * Returns true if delta processing can be stopped.
110          */

111         protected boolean check(IPackageFragmentRoot input, IJavaElementDelta delta) {
112             IJavaElement element= delta.getElement();
113
114             if ((delta.getKind() & IJavaElementDelta.REMOVED) != 0 || (delta.getFlags() & IJavaElementDelta.F_CLOSED) != 0) {
115                 // http://dev.eclipse.org/bugs/show_bug.cgi?id=19023
116
if (element.equals(input.getJavaProject()) || element.equals(input)) {
117                     handleDeleted(fInput);
118                     return true;
119                 }
120             }
121
122             if (((delta.getFlags() & IJavaElementDelta.F_ARCHIVE_CONTENT_CHANGED) != 0) && input.equals(element)) {
123                 handleDeleted(fInput);
124                 return true;
125             }
126
127             if (((delta.getFlags() & IJavaElementDelta.F_REMOVED_FROM_CLASSPATH) != 0) && input.equals(element)) {
128                 handleDeleted(fInput);
129                 return true;
130             }
131
132             IJavaElementDelta[] subdeltas= delta.getAffectedChildren();
133             for (int i= 0; i < subdeltas.length; i++) {
134                 if (check(input, subdeltas[i]))
135                     return true;
136             }
137
138             if ((delta.getFlags() & IJavaElementDelta.F_SOURCEDETACHED) != 0 ||
139                 (delta.getFlags() & IJavaElementDelta.F_SOURCEATTACHED) != 0)
140             {
141                 IClassFile file= fInput != null ? fInput.getClassFile() : null;
142                 IJavaProject project= input != null ? input.getJavaProject() : null;
143
144                 boolean isOnClasspath= false;
145                 if (file != null && project != null)
146                     isOnClasspath= project.isOnClasspath(file);
147
148                 if (isOnClasspath) {
149                     fireInputChanged(fInput);
150                     return false;
151                 } else {
152                     handleDeleted(fInput);
153                     return true;
154                 }
155             }
156
157             return false;
158         }
159     }
160
161     /**
162      * Correcting the visibility of <code>FileSynchronizer</code>.
163      */

164     protected class _FileSynchronizer extends FileSynchronizer {
165         public _FileSynchronizer(IFileEditorInput fileEditorInput) {
166             super(fileEditorInput);
167         }
168     }
169
170     /**
171      * Bundle of all required informations.
172      */

173     protected class ClassFileInfo extends FileInfo {
174
175         ClassFileSynchronizer fClassFileSynchronizer= null;
176
177         ClassFileInfo(IDocument document, IAnnotationModel model, _FileSynchronizer fileSynchronizer) {
178             super(document, model, fileSynchronizer);
179         }
180
181         ClassFileInfo(IDocument document, IAnnotationModel model, ClassFileSynchronizer classFileSynchronizer) {
182             super(document, model, null);
183             fClassFileSynchronizer= classFileSynchronizer;
184         }
185     }
186
187     /** Input change listeners. */
188     private List JavaDoc fInputListeners= new ArrayList JavaDoc();
189
190     /**
191      * Creates a new document provider.
192      */

193     public ClassFileDocumentProvider() {
194         super();
195     }
196
197     /*
198      * @see StorageDocumentProvider#setDocumentContent(IDocument, IEditorInput)
199      */

200     protected boolean setDocumentContent(IDocument document, IEditorInput editorInput, String JavaDoc encoding) throws CoreException {
201         if (editorInput instanceof IClassFileEditorInput) {
202             IClassFile classFile= ((IClassFileEditorInput) editorInput).getClassFile();
203             String JavaDoc source= classFile.getSource();
204             if (source == null)
205                 source= ""; //$NON-NLS-1$
206
document.set(source);
207             return true;
208         }
209         return super.setDocumentContent(document, editorInput, encoding);
210     }
211
212     /**
213      * Creates an annotation model derived from the given class file editor input.
214      *
215      * @param classFileEditorInput the editor input from which to query the annotations
216      * @return the created annotation model
217      * @exception CoreException if the editor input could not be accessed
218      */

219     protected IAnnotationModel createClassFileAnnotationModel(IClassFileEditorInput classFileEditorInput) throws CoreException {
220         IResource resource= null;
221         IClassFile classFile= classFileEditorInput.getClassFile();
222
223         IResourceLocator locator= (IResourceLocator) classFile.getAdapter(IResourceLocator.class);
224         if (locator != null)
225             resource= locator.getContainingResource(classFile);
226
227         if (resource != null) {
228             ClassFileMarkerAnnotationModel model= new ClassFileMarkerAnnotationModel(resource);
229             model.setClassFile(classFile);
230             return model;
231         }
232
233         return null;
234     }
235
236     /*
237      * @see org.eclipse.ui.editors.text.StorageDocumentProvider#createEmptyDocument()
238      * @since 3.1
239      */

240     protected IDocument createEmptyDocument() {
241         IDocument document= FileBuffers.getTextFileBufferManager().createEmptyDocument(null, LocationKind.IFILE);
242         if (document instanceof ISynchronizable)
243             ((ISynchronizable)document).setLockObject(new Object JavaDoc());
244         return document;
245     }
246
247     /*
248      * @see AbstractDocumentProvider#createDocument(Object)
249      */

250     protected IDocument createDocument(Object JavaDoc element) throws CoreException {
251         IDocument document= super.createDocument(element);
252         if (document != null) {
253             JavaTextTools tools= JavaPlugin.getDefault().getJavaTextTools();
254             tools.setupJavaDocumentPartitioner(document, IJavaPartitions.JAVA_PARTITIONING);
255         }
256         return document;
257     }
258
259     /*
260      * @see AbstractDocumentProvider#createElementInfo(Object)
261      */

262     protected ElementInfo createElementInfo(Object JavaDoc element) throws CoreException {
263
264         if (element instanceof IClassFileEditorInput) {
265
266             IClassFileEditorInput input = (IClassFileEditorInput) element;
267             ExternalClassFileEditorInput external= null;
268             if (input instanceof ExternalClassFileEditorInput)
269                 external= (ExternalClassFileEditorInput) input;
270
271             if (external != null) {
272                 try {
273                     refreshFile(external.getFile());
274                 } catch (CoreException x) {
275                     handleCoreException(x, JavaEditorMessages.ClassFileDocumentProvider_error_createElementInfo);
276                 }
277             }
278
279             IDocument d= createDocument(input);
280             IAnnotationModel m= createClassFileAnnotationModel(input);
281
282             if (external != null) {
283                 ClassFileInfo info= new ClassFileInfo(d, m, (_FileSynchronizer) null);
284                 info.fModificationStamp= computeModificationStamp(external.getFile());
285                 info.fEncoding= getPersistedEncoding(element);
286                 return info;
287             } else if (input instanceof InternalClassFileEditorInput) {
288                 ClassFileSynchronizer s= new ClassFileSynchronizer(input);
289                 s.install();
290                 ClassFileInfo info= new ClassFileInfo(d, m, s);
291                 info.fEncoding= getPersistedEncoding(element);
292                 return info;
293             }
294         }
295
296         return null;
297     }
298
299     /*
300      * @see FileDocumentProvider#disposeElementInfo(Object, ElementInfo)
301      */

302     protected void disposeElementInfo(Object JavaDoc element, ElementInfo info) {
303         ClassFileInfo classFileInfo= (ClassFileInfo) info;
304         if (classFileInfo.fClassFileSynchronizer != null) {
305             classFileInfo.fClassFileSynchronizer.uninstall();
306             classFileInfo.fClassFileSynchronizer= null;
307         }
308
309         super.disposeElementInfo(element, info);
310     }
311
312     /*
313      * @see AbstractDocumentProvider#doSaveDocument(IProgressMonitor, Object, IDocument)
314      */

315     protected void doSaveDocument(IProgressMonitor monitor, Object JavaDoc element, IDocument document) throws CoreException {
316     }
317
318
319     /*
320      * @see org.eclipse.ui.texteditor.IDocumentProviderExtension3#isSynchronized(java.lang.Object)
321      * @since 3.0
322      */

323     public boolean isSynchronized(Object JavaDoc element) {
324         Object JavaDoc elementInfo= getElementInfo(element);
325         if (elementInfo instanceof ClassFileInfo) {
326             IClassFileEditorInput input= (IClassFileEditorInput)element;
327             IResource resource;
328             try {
329                 resource= input.getClassFile().getUnderlyingResource();
330             } catch (JavaModelException e) {
331                 return true;
332             }
333             return resource == null || resource.isSynchronized(IResource.DEPTH_ZERO);
334         }
335         return false;
336     }
337
338     /**
339      * Handles the deletion of the element underlying the given class file editor input.
340      * @param input the editor input
341      */

342     protected void handleDeleted(IClassFileEditorInput input) {
343         fireElementDeleted(input);
344     }
345
346     /**
347      * Fires input changes to input change listeners.
348      */

349     protected void fireInputChanged(IClassFileEditorInput input) {
350         List JavaDoc list= new ArrayList JavaDoc(fInputListeners);
351         for (Iterator JavaDoc i = list.iterator(); i.hasNext();)
352             ((InputChangeListener) i.next()).inputChanged(input);
353     }
354
355     /**
356      * Adds an input change listener.
357      */

358     public void addInputChangeListener(InputChangeListener listener) {
359         fInputListeners.add(listener);
360     }
361
362     /**
363      * Removes an input change listener.
364      */

365     public void removeInputChangeListener(InputChangeListener listener) {
366         fInputListeners.remove(listener);
367     }
368
369 }
370
Popular Tags