Bug 67821 DirtyBufferValidationState becomes stale when buffer closes
Eclipse RC2. if you copy a read-only file and paste it on top of another read-only file all from the package explorer you get an exception in the log but the operation succeeds: java.lang.reflect.InvocationTargetException at org.eclipse.jface.operation.ModalContext.runInCurrentThread (ModalContext.java:314) at org.eclipse.jface.operation.ModalContext.run(ModalContext.java:253) at org.eclipse.jface.dialogs.ProgressMonitorDialog.run (ProgressMonitorDialog.java:397) at org.eclipse.jdt.internal.ui.refactoring.RefactoringExecutionHelper.perform (RefactoringExecutionHelper.java:116) at org.eclipse.jdt.internal.ui.refactoring.reorg.ReorgCopyStarter.run (ReorgCopyStarter.java:70) at org.eclipse.jdt.internal.ui.refactoring.reorg.PasteAction$JavaElementAndResourc ePaster.paste(PasteAction.java:405) at org.eclipse.jdt.internal.ui.refactoring.reorg.PasteAction.run (PasteAction.java:192) at org.eclipse.jdt.ui.actions.SelectionDispatchAction.dispatchRun (SelectionDispatchAction.java:212) at org.eclipse.jdt.ui.actions.SelectionDispatchAction.run (SelectionDispatchAction.java:188) at org.eclipse.jface.action.Action.runWithEvent(Action.java:881) at org.eclipse.ui.actions.RetargetAction.runWithEvent (RetargetAction.java:212) at org.eclipse.ui.commands.ActionHandler.execute (ActionHandler.java:141) at org.eclipse.ui.internal.commands.Command.execute(Command.java:132) at org.eclipse.ui.internal.keys.WorkbenchKeyboard.executeCommand (WorkbenchKeyboard.java:469) at org.eclipse.ui.internal.keys.WorkbenchKeyboard.press (WorkbenchKeyboard.java:887) at org.eclipse.ui.internal.keys.WorkbenchKeyboard.processKeyEvent (WorkbenchKeyboard.java:928) at org.eclipse.ui.internal.keys.WorkbenchKeyboard.filterKeySequenceBindings (WorkbenchKeyboard.java:546) at org.eclipse.ui.internal.keys.WorkbenchKeyboard.access$2 (WorkbenchKeyboard.java:494) at org.eclipse.ui.internal.keys.WorkbenchKeyboard$1.handleEvent (WorkbenchKeyboard.java:259) at org.eclipse.swt.widgets.EventTable.sendEvent(EventTable.java:82) at org.eclipse.swt.widgets.Display.filterEvent(Display.java:714) at org.eclipse.swt.widgets.Widget.sendEvent(Widget.java:795) at org.eclipse.swt.widgets.Widget.sendEvent(Widget.java:820) at org.eclipse.swt.widgets.Widget.sendEvent(Widget.java:805) at org.eclipse.swt.widgets.Control.sendKeyEvent(Control.java:1729) at org.eclipse.swt.widgets.Control.sendKeyEvent(Control.java:1725) at org.eclipse.swt.widgets.Control.WM_CHAR(Control.java:3053) at org.eclipse.swt.widgets.Tree.WM_CHAR(Tree.java:1372) at org.eclipse.swt.widgets.Control.windowProc(Control.java:2956) at org.eclipse.swt.widgets.Display.windowProc(Display.java:3298) at org.eclipse.swt.internal.win32.OS.DispatchMessageW(Native Method) at org.eclipse.swt.internal.win32.OS.DispatchMessage(OS.java:1460) at org.eclipse.swt.widgets.Display.readAndDispatch(Display.java:2396) at org.eclipse.ui.internal.Workbench.runEventLoop(Workbench.java:1362) at org.eclipse.ui.internal.Workbench.runUI(Workbench.java:1333) at org.eclipse.ui.internal.Workbench.createAndRunWorkbench (Workbench.java:252) at org.eclipse.ui.PlatformUI.createAndRunWorkbench(PlatformUI.java:141) at org.eclipse.ui.internal.ide.IDEApplication.run (IDEApplication.java:96) at org.eclipse.core.internal.runtime.PlatformActivator$1.run (PlatformActivator.java:334) at org.eclipse.core.runtime.adaptor.EclipseStarter.run (EclipseStarter.java:272) at org.eclipse.core.runtime.adaptor.EclipseStarter.run (EclipseStarter.java:128) at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method) at sun.reflect.NativeMethodAccessorImpl.invoke (NativeMethodAccessorImpl.java:39) at sun.reflect.DelegatingMethodAccessorImpl.invoke (DelegatingMethodAccessorImpl.java:25) at java.lang.reflect.Method.invoke(Method.java:582) at org.eclipse.core.launcher.Main.basicRun(Main.java:185) at org.eclipse.core.launcher.Main.run(Main.java:638) at org.eclipse.core.launcher.Main.main(Main.java:622) Caused by: java.lang.NullPointerException at org.eclipse.ltk.internal.core.refactoring.DirtyBufferValidationState.dispose (BufferValidationState.java:175) at org.eclipse.ltk.core.refactoring.UndoTextFileChange.dispose (UndoTextFileChange.java:183) at org.eclipse.ltk.internal.core.refactoring.UndoManager.sendDispose (UndoManager.java:348) at org.eclipse.ltk.internal.core.refactoring.UndoManager.flushUndo (UndoManager.java:135) at org.eclipse.ltk.internal.core.refactoring.UndoManager.flush (UndoManager.java:129) at org.eclipse.ltk.core.refactoring.PerformChangeOperation$1.run (PerformChangeOperation.java:254) at org.eclipse.core.internal.resources.Workspace.run (Workspace.java:1673) at org.eclipse.core.internal.resources.Workspace.run (Workspace.java:1693) at org.eclipse.ltk.core.refactoring.PerformChangeOperation.executeChange (PerformChangeOperation.java:267) at org.eclipse.ltk.internal.ui.refactoring.UIPerformChangeOperation.executeChange (UIPerformChangeOperation.java:86) at org.eclipse.ltk.core.refactoring.PerformChangeOperation.run (PerformChangeOperation.java:190) at org.eclipse.jdt.internal.ui.refactoring.RefactoringExecutionHelper$Operation.ru n(RefactoringExecutionHelper.java:76) at org.eclipse.jdt.internal.core.BatchOperation.executeOperation (BatchOperation.java:34) at org.eclipse.jdt.internal.core.JavaModelOperation.run (JavaModelOperation.java:700) at org.eclipse.core.internal.resources.Workspace.run (Workspace.java:1673) at org.eclipse.jdt.core.JavaCore.run(JavaCore.java:3246) at org.eclipse.jdt.internal.ui.actions.WorkbenchRunnableAdapter.run (WorkbenchRunnableAdapter.java:65) at org.eclipse.jface.operation.ModalContext.runInCurrentThread (ModalContext.java:303) ... 47 more
org.eclipse.ltk.core.refactoring/src/org/eclipse/ltk/internal/core/refactoring/BufferValidationState.java
protected IDocument getDocument() {
		ITextFileBuffer buffer= getBuffer(fFile);
		if (buffer == null)
			return null;
		return buffer.getDocument();
		
	}
	
	protected static boolean isDirty(IFile file) {
		ITextFileBuffer buffer= getBuffer(file);
		if (buffer == null)
			return false;
		return buffer.isDirty();
	}
	
	protected static ITextFileBuffer getBuffer(IFile file) {
		ITextFileBufferManager manager= FileBuffers.getTextFileBufferManager();
		IPath path= file.getFullPath();
		ITextFileBuffer buffer= manager.getTextFileBuffer(path);
		return buffer;
	}
}
class DirtyBufferValidationState extends BufferValidationState {
	
	private IDocumentListener fDocumentListener;
	private FileBufferListener fFileBufferListener;
	private boolean fChanged;
	private ContentStamp fContentStamp= null;
	
	class DocumentChangedListener implements IDocumentListener {