]> git.uio.no Git - ifi-stolz-refaktor.git/blame - case-study/jdt-before/ui/org/eclipse/jdt/internal/ui/javaeditor/ClassFileDocumentProvider.java
Case Study: adding data and statistics
[ifi-stolz-refaktor.git] / case-study / jdt-before / ui / org / eclipse / jdt / internal / ui / javaeditor / ClassFileDocumentProvider.java
CommitLineData
1b2798f6
EK
1/*******************************************************************************
2 * Copyright (c) 2000, 2011 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 *******************************************************************************/
11package org.eclipse.jdt.internal.ui.javaeditor;
12
13import java.util.ArrayList;
14import java.util.Iterator;
15import java.util.List;
16
17import org.eclipse.core.runtime.CoreException;
18
19import org.eclipse.core.resources.IResource;
20
21import org.eclipse.core.filebuffers.FileBuffers;
22import org.eclipse.core.filebuffers.LocationKind;
23
24import org.eclipse.jface.text.IDocument;
25import org.eclipse.jface.text.ISynchronizable;
26import org.eclipse.jface.text.source.IAnnotationModel;
27
28import org.eclipse.ui.IEditorInput;
29import org.eclipse.ui.IFileEditorInput;
30
31import org.eclipse.ui.editors.text.FileDocumentProvider;
32
33import org.eclipse.jdt.core.ElementChangedEvent;
34import org.eclipse.jdt.core.IClassFile;
35import org.eclipse.jdt.core.IElementChangedListener;
36import org.eclipse.jdt.core.IJavaElement;
37import org.eclipse.jdt.core.IJavaElementDelta;
38import org.eclipse.jdt.core.IJavaProject;
39import org.eclipse.jdt.core.IPackageFragmentRoot;
40import org.eclipse.jdt.core.IType;
41import org.eclipse.jdt.core.JavaCore;
42import org.eclipse.jdt.core.JavaModelException;
43
44import org.eclipse.jdt.ui.text.IJavaPartitions;
45import org.eclipse.jdt.ui.text.JavaTextTools;
46
47import org.eclipse.jdt.internal.ui.IResourceLocator;
48import org.eclipse.jdt.internal.ui.JavaPlugin;
49
50
51/**
52 * A document provider for class files. Class files can be either inside
53 */
54public class ClassFileDocumentProvider extends FileDocumentProvider {
55
56 /**
57 * An input change listener to request the editor to reread the input.
58 */
59 public interface InputChangeListener {
60 void inputChanged(IClassFileEditorInput input);
61 }
62
63 /**
64 * Synchronizes the document with external resource changes.
65 */
66 protected class ClassFileSynchronizer implements IElementChangedListener {
67
68 protected IClassFileEditorInput fInput;
69 protected IPackageFragmentRoot fPackageFragmentRoot;
70
71 /**
72 * Default constructor.
73 *
74 * @param input the class file editor input
75 */
76 public ClassFileSynchronizer(IClassFileEditorInput input) {
77
78 fInput= input;
79
80 IJavaElement parent= fInput.getClassFile().getParent();
81 while (parent != null && !(parent instanceof IPackageFragmentRoot)) {
82 parent= parent.getParent();
83 }
84 fPackageFragmentRoot= (IPackageFragmentRoot) parent;
85 }
86
87 /**
88 * Installs the synchronizer.
89 */
90 public void install() {
91 JavaCore.addElementChangedListener(this);
92 }
93
94 /**
95 * Uninstalls the synchronizer.
96 */
97 public void uninstall() {
98 JavaCore.removeElementChangedListener(this);
99 }
100
101 /*
102 * @see IElementChangedListener#elementChanged
103 */
104 public void elementChanged(ElementChangedEvent e) {
105 check(fPackageFragmentRoot, e.getDelta());
106 }
107
108 /**
109 * Recursively check whether the class file has been deleted.
110 *
111 * @param input the package fragment root
112 * @param delta the Java element delta
113 * @return <code>true</code> if delta processing can be stopped
114 */
115 protected boolean check(IPackageFragmentRoot input, IJavaElementDelta delta) {
116 IJavaElement element= delta.getElement();
117
118 if ((delta.getKind() & IJavaElementDelta.REMOVED) != 0 || (delta.getFlags() & IJavaElementDelta.F_CLOSED) != 0) {
119 // http://dev.eclipse.org/bugs/show_bug.cgi?id=19023
120 if (element.equals(input.getJavaProject()) || element.equals(input)) {
121 handleDeleted(fInput);
122 return true;
123 }
124 }
125
126 if (((delta.getFlags() & IJavaElementDelta.F_ARCHIVE_CONTENT_CHANGED) != 0) && input.equals(element)) {
127 handleDeleted(fInput);
128 return true;
129 }
130
131 if (((delta.getFlags() & IJavaElementDelta.F_REMOVED_FROM_CLASSPATH) != 0) && input.equals(element)) {
132 handleDeleted(fInput);
133 return true;
134 }
135
136 IJavaElementDelta[] subdeltas= delta.getAffectedChildren();
137 for (int i= 0; i < subdeltas.length; i++) {
138 if (check(input, subdeltas[i]))
139 return true;
140 }
141
142 if ((delta.getFlags() & IJavaElementDelta.F_SOURCEDETACHED) != 0 ||
143 (delta.getFlags() & IJavaElementDelta.F_SOURCEATTACHED) != 0)
144 {
145 IClassFile file= fInput != null ? fInput.getClassFile() : null;
146 IJavaProject project= input != null ? input.getJavaProject() : null;
147
148 boolean isOnClasspath= false;
149 if (file != null && project != null)
150 isOnClasspath= project.isOnClasspath(file);
151
152 if (isOnClasspath) {
153 fireInputChanged(fInput);
154 return false;
155 } else {
156 handleDeleted(fInput);
157 return true;
158 }
159 }
160
161 return false;
162 }
163 }
164
165 /**
166 * Correcting the visibility of <code>FileSynchronizer</code>.
167 */
168 protected class _FileSynchronizer extends FileSynchronizer {
169 public _FileSynchronizer(IFileEditorInput fileEditorInput) {
170 super(fileEditorInput);
171 }
172 }
173
174 /**
175 * Bundle of all required informations.
176 */
177 protected class ClassFileInfo extends FileInfo {
178
179 ClassFileSynchronizer fClassFileSynchronizer= null;
180
181 ClassFileInfo(IDocument document, IAnnotationModel model, _FileSynchronizer fileSynchronizer) {
182 super(document, model, fileSynchronizer);
183 }
184
185 ClassFileInfo(IDocument document, IAnnotationModel model, ClassFileSynchronizer classFileSynchronizer) {
186 super(document, model, null);
187 fClassFileSynchronizer= classFileSynchronizer;
188 }
189 }
190
191 /** Input change listeners. */
192 private List<InputChangeListener> fInputListeners= new ArrayList<InputChangeListener>();
193
194 /**
195 * Creates a new document provider.
196 */
197 public ClassFileDocumentProvider() {
198 super();
199 }
200
201 /*
202 * @see StorageDocumentProvider#setDocumentContent(IDocument, IEditorInput)
203 */
204 @Override
205 protected boolean setDocumentContent(IDocument document, IEditorInput editorInput, String encoding) throws CoreException {
206 if (editorInput instanceof IClassFileEditorInput) {
207 IClassFile classFile= ((IClassFileEditorInput) editorInput).getClassFile();
208 String source= classFile.getSource();
209 if (source == null)
210 source= ""; //$NON-NLS-1$
211 document.set(source);
212 return true;
213 }
214 return super.setDocumentContent(document, editorInput, encoding);
215 }
216
217 /**
218 * Creates an annotation model derived from the given class file editor input.
219 *
220 * @param classFileEditorInput the editor input from which to query the annotations
221 * @return the created annotation model
222 * @exception CoreException if the editor input could not be accessed
223 */
224 protected IAnnotationModel createClassFileAnnotationModel(IClassFileEditorInput classFileEditorInput) throws CoreException {
225 IResource resource= null;
226 IClassFile classFile= classFileEditorInput.getClassFile();
227
228 IResourceLocator locator= (IResourceLocator) classFile.getAdapter(IResourceLocator.class);
229 if (locator != null)
230 resource= locator.getContainingResource(classFile);
231
232 if (resource != null) {
233 ClassFileMarkerAnnotationModel model= new ClassFileMarkerAnnotationModel(resource);
234 model.setClassFile(classFile);
235 return model;
236 }
237
238 return null;
239 }
240
241 /*
242 * @see org.eclipse.ui.editors.text.StorageDocumentProvider#createEmptyDocument()
243 * @since 3.1
244 */
245 @Override
246 protected IDocument createEmptyDocument() {
247 IDocument document= FileBuffers.getTextFileBufferManager().createEmptyDocument(null, LocationKind.IFILE);
248 if (document instanceof ISynchronizable)
249 ((ISynchronizable)document).setLockObject(new Object());
250 return document;
251 }
252
253 /*
254 * @see AbstractDocumentProvider#createDocument(Object)
255 */
256 @Override
257 protected IDocument createDocument(Object element) throws CoreException {
258 IDocument document= super.createDocument(element);
259 if (document != null) {
260 JavaTextTools tools= JavaPlugin.getDefault().getJavaTextTools();
261 tools.setupJavaDocumentPartitioner(document, IJavaPartitions.JAVA_PARTITIONING);
262 }
263 return document;
264 }
265
266 /*
267 * @see AbstractDocumentProvider#createElementInfo(Object)
268 */
269 @Override
270 protected ElementInfo createElementInfo(Object element) throws CoreException {
271
272 if (element instanceof IClassFileEditorInput) {
273
274 IClassFileEditorInput input = (IClassFileEditorInput) element;
275 ExternalClassFileEditorInput external= null;
276 if (input instanceof ExternalClassFileEditorInput)
277 external= (ExternalClassFileEditorInput) input;
278
279 if (external != null) {
280 try {
281 refreshFile(external.getFile());
282 } catch (CoreException x) {
283 handleCoreException(x, JavaEditorMessages.ClassFileDocumentProvider_error_createElementInfo);
284 }
285 }
286
287 IDocument d= createDocument(input);
288 IAnnotationModel m= createClassFileAnnotationModel(input);
289
290 if (external != null) {
291 ClassFileInfo info= new ClassFileInfo(d, m, (_FileSynchronizer) null);
292 info.fModificationStamp= computeModificationStamp(external.getFile());
293 info.fEncoding= getPersistedEncoding(element);
294 return info;
295 } else if (input instanceof InternalClassFileEditorInput) {
296 ClassFileSynchronizer s= new ClassFileSynchronizer(input);
297 s.install();
298 ClassFileInfo info= new ClassFileInfo(d, m, s);
299 info.fEncoding= getPersistedEncoding(element);
300 return info;
301 }
302 }
303
304 return null;
305 }
306
307 /*
308 * @see FileDocumentProvider#disposeElementInfo(Object, ElementInfo)
309 */
310 @Override
311 protected void disposeElementInfo(Object element, ElementInfo info) {
312 ClassFileInfo classFileInfo= (ClassFileInfo) info;
313 if (classFileInfo.fClassFileSynchronizer != null) {
314 classFileInfo.fClassFileSynchronizer.uninstall();
315 classFileInfo.fClassFileSynchronizer= null;
316 }
317
318 super.disposeElementInfo(element, info);
319 }
320
321 /*
322 * @see org.eclipse.ui.texteditor.IDocumentProviderExtension3#isSynchronized(java.lang.Object)
323 * @since 3.0
324 */
325 @Override
326 public boolean isSynchronized(Object element) {
327 Object elementInfo= getElementInfo(element);
328 if (elementInfo instanceof ClassFileInfo) {
329 IClassFileEditorInput input= (IClassFileEditorInput)element;
330 IResource resource;
331 try {
332 resource= input.getClassFile().getUnderlyingResource();
333 } catch (JavaModelException e) {
334 return true;
335 }
336 return resource == null || resource.isSynchronized(IResource.DEPTH_ZERO);
337 }
338 return false;
339 }
340
341 /**
342 * Handles the deletion of the element underlying the given class file editor input.
343 * @param input the editor input
344 */
345 protected void handleDeleted(IClassFileEditorInput input) {
346 if (input == null) {
347 fireElementDeleted(input);
348 return;
349 }
350
351 if (input.exists())
352 return;
353
354 IClassFile cf= input.getClassFile();
355 try {
356 /*
357 * Let's try to find the class file - maybe the JAR changed
358 */
359 IType type= cf.getType();
360 IJavaProject project= cf.getJavaProject();
361 if (project != null) {
362 type= project.findType(type.getFullyQualifiedName());
363 if (type != null) {
364 IEditorInput editorInput= EditorUtility.getEditorInput(type.getParent());
365 if (editorInput instanceof IClassFileEditorInput) {
366 fireInputChanged((IClassFileEditorInput)editorInput);
367 return;
368 }
369 }
370 }
371 } catch (JavaModelException x) {
372 // Don't log and fall through: element deleted
373 }
374
375 fireElementDeleted(input);
376
377 }
378
379 /**
380 * Fires input changes to input change listeners.
381 *
382 * @param input the class file editor input
383 */
384 protected void fireInputChanged(IClassFileEditorInput input) {
385 List<InputChangeListener> list= new ArrayList<InputChangeListener>(fInputListeners);
386 for (Iterator<InputChangeListener> i = list.iterator(); i.hasNext();)
387 i.next().inputChanged(input);
388 }
389
390 /**
391 * Adds an input change listener.
392 *
393 * @param listener the input change listener
394 */
395 public void addInputChangeListener(InputChangeListener listener) {
396 fInputListeners.add(listener);
397 }
398
399 /**
400 * Removes an input change listener.
401 *
402 * @param listener the input change listener
403 */
404 public void removeInputChangeListener(InputChangeListener listener) {
405 fInputListeners.remove(listener);
406 }
407
408}