1 11 12 package org.eclipse.jdt.internal.ui.javaeditor; 13 14 15 import java.util.ArrayList ; 16 import java.util.HashSet ; 17 import java.util.Iterator ; 18 import java.util.List ; 19 import java.util.Set ; 20 21 import org.eclipse.core.runtime.Assert; 22 import org.eclipse.core.runtime.CoreException; 23 import org.eclipse.core.runtime.IPath; 24 import org.eclipse.core.runtime.IProgressMonitor; 25 import org.eclipse.core.runtime.IStatus; 26 import org.eclipse.core.runtime.NullProgressMonitor; 27 import org.eclipse.core.runtime.Status; 28 29 import org.eclipse.core.filebuffers.FileBuffers; 30 import org.eclipse.core.filebuffers.ITextFileBuffer; 31 import org.eclipse.core.filebuffers.ITextFileBufferManager; 32 import org.eclipse.core.filebuffers.LocationKind; 33 34 import org.eclipse.core.resources.IFile; 35 import org.eclipse.core.resources.IResource; 36 import org.eclipse.core.resources.ResourceAttributes; 37 38 import org.eclipse.swt.widgets.Display; 39 40 import org.eclipse.jface.text.BadLocationException; 41 import org.eclipse.jface.text.DefaultLineTracker; 42 import org.eclipse.jface.text.DocumentEvent; 43 import org.eclipse.jface.text.IDocument; 44 import org.eclipse.jface.text.IDocumentListener; 45 import org.eclipse.jface.text.ISynchronizable; 46 47 import org.eclipse.jdt.core.BufferChangedEvent; 48 import org.eclipse.jdt.core.IBuffer; 49 import org.eclipse.jdt.core.IBufferChangedListener; 50 import org.eclipse.jdt.core.IOpenable; 51 import org.eclipse.jdt.core.JavaModelException; 52 53 import org.eclipse.jdt.ui.JavaUI; 54 55 import org.eclipse.jdt.internal.ui.JavaPlugin; 56 57 58 64 public class DocumentAdapter implements IBuffer, IDocumentListener { 65 66 69 static private class NullBuffer implements IBuffer { 70 public void addBufferChangedListener(IBufferChangedListener listener) {} 71 public void append(char[] text) {} 72 public void append(String text) {} 73 public void close() {} 74 public char getChar(int position) { return 0; } 75 public char[] getCharacters() { return null; } 76 public String getContents() { return null; } 77 public int getLength() { return 0; } 78 public IOpenable getOwner() { return null; } 79 public String getText(int offset, int length) { return null; } 80 public IResource getUnderlyingResource() { return null; } 81 public boolean hasUnsavedChanges() { return false; } 82 public boolean isClosed() { return false; } 83 public boolean isReadOnly() { return true; } 84 public void removeBufferChangedListener(IBufferChangedListener listener) {} 85 public void replace(int position, int length, char[] text) {} 86 public void replace(int position, int length, String text) {} 87 public void save(IProgressMonitor progress, boolean force) throws JavaModelException {} 88 public void setContents(char[] contents) {} 89 public void setContents(String contents) {} 90 } 91 92 93 94 public final static IBuffer NULL= new NullBuffer(); 95 96 97 103 private static final void run(Runnable runnable) { 104 Display currentDisplay= Display.getCurrent(); 105 if (currentDisplay != null) 106 runnable.run(); 107 else 108 Display.getDefault().syncExec(runnable); 109 } 110 111 112 115 protected class DocumentSetCommand implements Runnable { 116 117 private String fContents; 118 119 public void run() { 120 if (!isClosed()) 121 fDocument.set(fContents); 122 } 123 124 public void set(String contents) { 125 fContents= contents; 126 DocumentAdapter.run(this); 127 } 128 } 129 130 131 134 protected class DocumentReplaceCommand implements Runnable { 135 136 private int fOffset; 137 private int fLength; 138 private String fText; 139 140 public void run() { 141 try { 142 if (!isClosed()) 143 fDocument.replace(fOffset, fLength, fText); 144 } catch (BadLocationException x) { 145 } 147 } 148 149 public void replace(int offset, int length, String text) { 150 fOffset= offset; 151 fLength= length; 152 fText= text; 153 DocumentAdapter.run(this); 154 } 155 } 156 157 158 private static final boolean DEBUG_LINE_DELIMITERS= true; 159 160 private IOpenable fOwner; 161 private IFile fFile; 162 private ITextFileBuffer fTextFileBuffer; 163 private IDocument fDocument; 164 165 private DocumentSetCommand fSetCmd= new DocumentSetCommand(); 166 private DocumentReplaceCommand fReplaceCmd= new DocumentReplaceCommand(); 167 168 private Set fLegalLineDelimiters; 169 170 private List fBufferListeners= new ArrayList (3); 171 private IStatus fStatus; 172 173 176 private IPath fPath; 177 178 181 private LocationKind fLocationKind; 182 183 184 191 public DocumentAdapter(IOpenable owner, IPath path) { 192 Assert.isLegal(path != null); 193 194 fOwner= owner; 195 fPath= path; 196 fLocationKind= LocationKind.NORMALIZE; 197 198 initialize(); 199 } 200 201 207 public DocumentAdapter(IOpenable owner, IFile file) { 208 209 fOwner= owner; 210 fFile= file; 211 fPath= fFile.getFullPath(); 212 fLocationKind= LocationKind.IFILE; 213 214 initialize(); 215 } 216 217 private void initialize() { 218 ITextFileBufferManager manager= FileBuffers.getTextFileBufferManager(); 219 try { 220 manager.connect(fPath, fLocationKind, new NullProgressMonitor()); 221 fTextFileBuffer= manager.getTextFileBuffer(fPath, fLocationKind); 222 fDocument= fTextFileBuffer.getDocument(); 223 } catch (CoreException x) { 224 fStatus= x.getStatus(); 225 fDocument= manager.createEmptyDocument(fPath, fLocationKind); 226 if (fDocument instanceof ISynchronizable) 227 ((ISynchronizable)fDocument).setLockObject(new Object ()); 228 } 229 fDocument.addPrenotifiedDocumentListener(this); 230 } 231 232 237 public IStatus getStatus() { 238 if (fStatus != null) 239 return fStatus; 240 if (fTextFileBuffer != null) 241 return fTextFileBuffer.getStatus(); 242 return null; 243 } 244 245 250 public IDocument getDocument() { 251 return fDocument; 252 } 253 254 257 public void addBufferChangedListener(IBufferChangedListener listener) { 258 Assert.isNotNull(listener); 259 if (!fBufferListeners.contains(listener)) 260 fBufferListeners.add(listener); 261 } 262 263 266 public void removeBufferChangedListener(IBufferChangedListener listener) { 267 Assert.isNotNull(listener); 268 fBufferListeners.remove(listener); 269 } 270 271 274 public void append(char[] text) { 275 append(new String (text)); 276 } 277 278 281 public void append(String text) { 282 if (DEBUG_LINE_DELIMITERS) { 283 validateLineDelimiters(text); 284 } 285 fReplaceCmd.replace(fDocument.getLength(), 0, text); 286 } 287 288 291 public void close() { 292 293 if (isClosed()) 294 return; 295 296 IDocument d= fDocument; 297 fDocument= null; 298 d.removePrenotifiedDocumentListener(this); 299 300 if (fTextFileBuffer != null) { 301 ITextFileBufferManager manager= FileBuffers.getTextFileBufferManager(); 302 try { 303 manager.disconnect(fPath, fLocationKind, new NullProgressMonitor()); 304 } catch (CoreException x) { 305 } 307 fTextFileBuffer= null; 308 } 309 310 fireBufferChanged(new BufferChangedEvent(this, 0, 0, null)); 311 fBufferListeners.clear(); 312 } 313 314 317 public char getChar(int position) { 318 try { 319 return fDocument.getChar(position); 320 } catch (BadLocationException x) { 321 throw new ArrayIndexOutOfBoundsException (); 322 } 323 } 324 325 328 public char[] getCharacters() { 329 String content= getContents(); 330 return content == null ? null : content.toCharArray(); 331 } 332 333 336 public String getContents() { 337 return fDocument.get(); 338 } 339 340 343 public int getLength() { 344 return fDocument.getLength(); 345 } 346 347 350 public IOpenable getOwner() { 351 return fOwner; 352 } 353 354 357 public String getText(int offset, int length) { 358 try { 359 return fDocument.get(offset, length); 360 } catch (BadLocationException x) { 361 throw new ArrayIndexOutOfBoundsException (); 362 } 363 } 364 365 368 public IResource getUnderlyingResource() { 369 return fFile; 370 } 371 372 375 public boolean hasUnsavedChanges() { 376 return fTextFileBuffer != null ? fTextFileBuffer.isDirty() : false; 377 } 378 379 382 public boolean isClosed() { 383 return fDocument == null; 384 } 385 386 389 public boolean isReadOnly() { 390 if (fTextFileBuffer != null) 391 return !fTextFileBuffer.isCommitable(); 392 393 IResource resource= getUnderlyingResource(); 394 if (resource == null) 395 return true; 396 397 final ResourceAttributes attributes= resource.getResourceAttributes(); 398 return attributes == null ? false : attributes.isReadOnly(); 399 } 400 401 404 public void replace(int position, int length, char[] text) { 405 replace(position, length, new String (text)); 406 } 407 408 411 public void replace(int position, int length, String text) { 412 if (DEBUG_LINE_DELIMITERS) { 413 validateLineDelimiters(text); 414 } 415 fReplaceCmd.replace(position, length, text); 416 } 417 418 421 public void save(IProgressMonitor progress, boolean force) throws JavaModelException { 422 try { 423 if (fTextFileBuffer != null) 424 fTextFileBuffer.commit(progress, force); 425 } catch (CoreException e) { 426 throw new JavaModelException(e); 427 } 428 } 429 430 433 public void setContents(char[] contents) { 434 setContents(new String (contents)); 435 } 436 437 440 public void setContents(String contents) { 441 int oldLength= fDocument.getLength(); 442 443 if (contents == null) { 444 445 if (oldLength != 0) 446 fSetCmd.set(""); 448 } else { 449 450 if (DEBUG_LINE_DELIMITERS) { 452 validateLineDelimiters(contents); 453 } 454 455 if (!contents.equals(fDocument.get())) 456 fSetCmd.set(contents); 457 } 458 } 459 460 461 private void validateLineDelimiters(String contents) { 462 463 if (fLegalLineDelimiters == null) { 464 HashSet existingDelimiters= new HashSet (); 466 467 for (int i= fDocument.getNumberOfLines() - 1; i >= 0; i-- ) { 468 try { 469 String curr= fDocument.getLineDelimiter(i); 470 if (curr != null) { 471 existingDelimiters.add(curr); 472 } 473 } catch (BadLocationException e) { 474 JavaPlugin.log(e); 475 } 476 } 477 if (existingDelimiters.isEmpty()) { 478 return; } 480 fLegalLineDelimiters= existingDelimiters; 481 482 } 483 484 DefaultLineTracker tracker= new DefaultLineTracker(); 485 tracker.set(contents); 486 487 int lines= tracker.getNumberOfLines(); 488 if (lines <= 1) 489 return; 490 491 for (int i= 0; i < lines; i++) { 492 try { 493 String curr= tracker.getLineDelimiter(i); 494 if (curr != null && !fLegalLineDelimiters.contains(curr)) { 495 StringBuffer buf= new StringBuffer ("WARNING: javaeditor.DocumentAdapter added new line delimiter to code: "); for (int k= 0; k < curr.length(); k++) { 497 if (k > 0) 498 buf.append(' '); 499 buf.append((int)curr.charAt(k)); 500 } 501 IStatus status= new Status(IStatus.WARNING, JavaUI.ID_PLUGIN, IStatus.OK, buf.toString(), new Throwable ()); 502 JavaPlugin.log(status); 503 } 504 } catch (BadLocationException e) { 505 JavaPlugin.log(e); 506 } 507 } 508 } 509 510 513 public void documentAboutToBeChanged(DocumentEvent event) { 514 } 516 517 520 public void documentChanged(DocumentEvent event) { 521 fireBufferChanged(new BufferChangedEvent(this, event.getOffset(), event.getLength(), event.getText())); 522 } 523 524 private void fireBufferChanged(BufferChangedEvent event) { 525 if (fBufferListeners != null && fBufferListeners.size() > 0) { 526 Iterator e= new ArrayList (fBufferListeners).iterator(); 527 while (e.hasNext()) 528 ((IBufferChangedListener) e.next()).bufferChanged(event); 529 } 530 } 531 } 532 | Popular Tags |