1 11 package org.eclipse.ltk.internal.core.refactoring; 12 13 import org.eclipse.core.runtime.CoreException; 14 import org.eclipse.core.runtime.IPath; 15 16 import org.eclipse.core.filebuffers.FileBuffers; 17 import org.eclipse.core.filebuffers.IFileBuffer; 18 import org.eclipse.core.filebuffers.IFileBufferListener; 19 import org.eclipse.core.filebuffers.ITextFileBuffer; 20 import org.eclipse.core.filebuffers.ITextFileBufferManager; 21 import org.eclipse.core.filebuffers.LocationKind; 22 23 import org.eclipse.core.resources.IFile; 24 import org.eclipse.core.resources.IResource; 25 26 import org.eclipse.jface.text.DocumentEvent; 27 import org.eclipse.jface.text.IDocument; 28 import org.eclipse.jface.text.IDocumentExtension4; 29 import org.eclipse.jface.text.IDocumentListener; 30 31 import org.eclipse.ltk.core.refactoring.RefactoringStatus; 32 33 public abstract class BufferValidationState { 34 35 protected final IFile fFile; 36 protected final boolean fExisted; 37 protected final boolean fDerived; 38 protected final boolean fWasDirty; 39 protected final String fEncoding; 40 41 protected static class ModificationStamp { 42 private int fKind; 43 private long fValue; 44 public static final int FILE= 1; 45 public static final int DOCUMENT= 2; 46 47 public static ModificationStamp createFile(long value) { 48 return new ModificationStamp(FILE, value); 49 } 50 public static ModificationStamp createDocument(long value) { 51 return new ModificationStamp(DOCUMENT, value); 52 } 53 private ModificationStamp(int kind, long value) { 54 fKind= kind; 55 fValue= value; 56 } 57 public boolean isFileStamp() { 58 return fKind == FILE; 59 } 60 public boolean isDocumentStamp() { 61 return fKind == DOCUMENT; 62 } 63 public int getKind() { 64 return fKind; 65 } 66 public long getValue() { 67 return fValue; 68 } 69 } 70 71 public static BufferValidationState create(IFile file) { 72 ITextFileBuffer buffer= getBuffer(file); 73 if (buffer == null) { 74 return new ModificationStampValidationState(file); 75 } else { 76 IDocument document= buffer.getDocument(); 77 if (document instanceof IDocumentExtension4) { 78 return new ModificationStampValidationState(file); 79 } else { 80 if (buffer.isDirty()) { 81 return new NoStampValidationState(file); 82 } else { 83 return new ModificationStampValidationState(file); 84 } 85 } 86 } 87 } 88 89 public boolean wasDirty() { 90 return fWasDirty; 91 } 92 93 public boolean wasDerived() { 94 return fDerived; 95 } 96 97 public RefactoringStatus isValid(boolean needsSaving) throws CoreException { 98 return isValid(needsSaving, false); 99 } 100 101 public RefactoringStatus isValid(boolean needsSaving, boolean resilientForDerived) throws CoreException { 102 if (resilientForDerived && fDerived) { 103 return new RefactoringStatus(); 104 } 105 if (!fExisted) { 106 if (fFile.exists()) 107 return RefactoringStatus.createFatalErrorStatus(Messages.format( 108 RefactoringCoreMessages.TextChanges_error_existing, 109 fFile.getFullPath().toString())); 110 } else { 111 if (!fFile.exists()) 112 return RefactoringStatus.createFatalErrorStatus(Messages.format( 113 RefactoringCoreMessages.TextChanges_error_not_existing, 114 fFile.getFullPath().toString())); 115 } 116 if (needsSaving) { 117 if (fFile.isReadOnly()) { 118 return RefactoringStatus.createFatalErrorStatus(Messages.format( 119 RefactoringCoreMessages.TextChanges_error_read_only, 120 fFile.getFullPath().toString())); 121 } else if (!fFile.isSynchronized(IResource.DEPTH_ZERO)) { 122 return RefactoringStatus.createFatalErrorStatus(Messages.format( 123 RefactoringCoreMessages.TextChanges_error_outOfSync, 124 fFile.getFullPath().toString())); 125 } 126 } 127 if (fEncoding == null) { 128 return RefactoringStatus.createFatalErrorStatus(Messages.format( 129 RefactoringCoreMessages.BufferValidationState_no_character_encoding, 130 fFile.getFullPath().toString())); 131 } else if (!fEncoding.equals(fFile.getCharset(true))) { 132 return RefactoringStatus.createFatalErrorStatus(Messages.format( 133 RefactoringCoreMessages.BufferValidationState_character_encoding_changed, 134 fFile.getFullPath().toString())); 135 } 136 return new RefactoringStatus(); 137 } 138 139 public void dispose() { 140 } 141 142 143 protected BufferValidationState(IFile file) { 144 fFile= file; 145 fExisted= file.exists(); 146 fDerived= file.isDerived(); 147 fWasDirty= isDirty(fFile); 148 String encoding; 149 try { 150 encoding= file.getCharset(true); 151 } catch (CoreException e) { 152 encoding= null; 153 } 154 fEncoding= encoding; 155 } 156 157 protected IDocument getDocument() { 158 ITextFileBuffer buffer= getBuffer(fFile); 159 if (buffer == null) 160 return null; 161 return buffer.getDocument(); 162 163 } 164 165 protected static boolean isDirty(IFile file) { 166 ITextFileBuffer buffer= getBuffer(file); 167 if (buffer == null) 168 return false; 169 return buffer.isDirty(); 170 } 171 172 protected static ITextFileBuffer getBuffer(IFile file) { 173 ITextFileBufferManager manager= FileBuffers.getTextFileBufferManager(); 174 IPath path= file.getFullPath(); 175 ITextFileBuffer buffer= manager.getTextFileBuffer(path, LocationKind.IFILE); 176 return buffer; 177 } 178 179 protected ModificationStamp getModificationStamp() { 180 ITextFileBuffer buffer= getBuffer(fFile); 181 if (buffer == null) { 182 return ModificationStamp.createFile(fFile.getModificationStamp()); 183 } else { 184 IDocument document= buffer.getDocument(); 185 if (document instanceof IDocumentExtension4) { 186 return ModificationStamp.createDocument(((IDocumentExtension4)document).getModificationStamp()); 187 } else { 188 return ModificationStamp.createFile(fFile.getModificationStamp()); 189 } 190 } 191 } 192 } 193 194 198 class NoStampValidationState extends BufferValidationState { 199 200 private IDocumentListener fDocumentListener; 201 private FileBufferListener fFileBufferListener; 202 private boolean fChanged; 203 private long fContentStamp= IResource.NULL_STAMP; 204 205 class DocumentChangedListener implements IDocumentListener { 206 public void documentAboutToBeChanged(DocumentEvent event) { 207 } 208 public void documentChanged(DocumentEvent event) { 209 NoStampValidationState.this.documentChanged(); 210 } 211 } 212 213 class FileBufferListener implements IFileBufferListener { 214 public void bufferCreated(IFileBuffer buffer) { 215 if (buffer.getLocation().equals(fFile.getFullPath()) && buffer instanceof ITextFileBuffer) { 217 ITextFileBuffer textBuffer= (ITextFileBuffer)buffer; 218 if (fDocumentListener == null) 219 fDocumentListener= new DocumentChangedListener(); 220 textBuffer.getDocument().addDocumentListener(fDocumentListener); 221 } 222 } 224 public void bufferDisposed(IFileBuffer buffer) { 225 if (fDocumentListener != null && buffer.getLocation().equals(fFile.getFullPath())) { 227 if (buffer instanceof ITextFileBuffer) { 228 ITextFileBuffer textBuffer= (ITextFileBuffer)buffer; 229 textBuffer.getDocument().removeDocumentListener(fDocumentListener); 230 fDocumentListener= null; 231 } 232 fContentStamp= fFile.getModificationStamp(); 233 } 234 } 236 public void bufferContentAboutToBeReplaced(IFileBuffer buffer) { 237 } 238 public void bufferContentReplaced(IFileBuffer buffer) { 239 } 240 public void stateChanging(IFileBuffer buffer) { 241 } 242 public void dirtyStateChanged(IFileBuffer buffer, boolean isDirty) { 243 } 244 public void stateValidationChanged(IFileBuffer buffer, boolean isStateValidated) { 245 } 246 public void underlyingFileMoved(IFileBuffer buffer, IPath path) { 247 } 248 public void underlyingFileDeleted(IFileBuffer buffer) { 249 } 250 public void stateChangeFailed(IFileBuffer buffer) { 251 } 252 } 253 254 public NoStampValidationState(IFile file) { 255 super(file); 256 fContentStamp= file.getModificationStamp(); 257 fFileBufferListener= new FileBufferListener(); 258 FileBuffers.getTextFileBufferManager().addFileBufferListener(fFileBufferListener); 259 fDocumentListener= new DocumentChangedListener(); 260 getDocument().addDocumentListener(fDocumentListener); 261 } 262 263 public RefactoringStatus isValid(boolean needsSaving, boolean resilientForDerived) throws CoreException { 264 RefactoringStatus result= super.isValid(needsSaving, resilientForDerived); 265 if (result.hasFatalError()) 266 return result; 267 if (fChanged || fContentStamp != fFile.getModificationStamp()) { 272 result.addFatalError(Messages.format( 273 RefactoringCoreMessages.TextChanges_error_content_changed, 274 fFile.getFullPath().toString() 275 )); 276 } 277 return result; 278 } 279 280 public void dispose() { 281 if (fFileBufferListener != null) { 282 FileBuffers.getTextFileBufferManager().removeFileBufferListener(fFileBufferListener); 283 fFileBufferListener= null; 285 } 286 if (fDocumentListener != null) { 287 getDocument().removeDocumentListener(fDocumentListener); 288 fDocumentListener= null; 290 } 291 } 292 293 private void documentChanged() { 294 fChanged= true; 295 getDocument().removeDocumentListener(fDocumentListener); 296 FileBuffers.getTextFileBufferManager().removeFileBufferListener(fFileBufferListener); 297 fFileBufferListener= null; 298 fDocumentListener= null; 299 } 300 } 301 302 305 class ModificationStampValidationState extends BufferValidationState { 306 307 private ModificationStamp fModificationStamp; 308 309 public ModificationStampValidationState(IFile file) { 310 super(file); 311 fModificationStamp= getModificationStamp(); 312 } 313 314 public RefactoringStatus isValid(boolean needsSaving, boolean resilientForDerived) throws CoreException { 315 RefactoringStatus result= super.isValid(needsSaving, resilientForDerived); 316 if (result.hasFatalError()) 317 return result; 318 ModificationStamp currentStamp= getModificationStamp(); 319 if (fModificationStamp.getValue() != currentStamp.getValue() 324 || (fModificationStamp.isFileStamp() 327 && fModificationStamp.getValue() == IResource.NULL_STAMP 328 && !currentStamp.isFileStamp()) 329 || (fModificationStamp.isDocumentStamp() 330 && fModificationStamp.getValue() == IDocumentExtension4.UNKNOWN_MODIFICATION_STAMP 331 && !currentStamp.isDocumentStamp()) 332 || (fModificationStamp.isFileStamp() 333 && currentStamp.isFileStamp() && isDirty(fFile))) { 334 result.addFatalError(Messages.format( 335 RefactoringCoreMessages.TextChanges_error_content_changed, 336 fFile.getFullPath().toString() 337 )); 338 339 } 340 return result; 341 } 342 } 343 344 384 | Popular Tags |