1 19 24 25 package org.netbeans.core.output2; 26 27 import java.util.logging.Logger ; 28 import org.openide.util.NbBundle; 29 import org.openide.windows.OutputListener; 30 import java.io.*; 31 import java.nio.ByteBuffer ; 32 import java.util.StringTokenizer ; 33 import org.openide.util.Exceptions; 34 import org.openide.util.Utilities; 35 36 41 class OutWriter extends PrintWriter { 42 43 private boolean trouble = false; 44 45 private NbIO owner; 46 47 private boolean disposed = false; 48 49 private static final boolean USE_HEAP_STORAGE = 51 Boolean.getBoolean("nb.output.heap") || Utilities.getOperatingSystem() == Utilities.OS_WIN98 || 53 Utilities.getOperatingSystem() == Utilities.OS_WIN95; 54 55 58 static byte[] lineSepBytes; 59 static { 60 if (Utilities.isWindows()) { 61 lineSepBytes = new byte[] { '\0', '\r', '\0', '\n'}; 62 } else { 63 lineSepBytes = new byte[] { '\0', '\n'}; 64 } 65 } 66 67 private Storage storage; 68 69 71 private AbstractLines lines = new LinesImpl(); 72 73 76 private boolean terminated = false; 77 78 80 static boolean lowDiskSpace = false; 81 82 83 87 private int lineStart; 88 private int lineLength; 89 90 91 OutWriter(NbIO owner) { 92 this(); 93 this.owner = owner; 94 } 95 96 99 OutWriter() { 100 super (new DummyWriter()); 101 lineStart = -1; 102 lineLength = 0; 103 } 104 105 Storage getStorage() { 106 if (disposed) { 107 throw new IllegalStateException ("Output file has been disposed!"); 108 } 109 if (storage == null) { 110 storage = USE_HEAP_STORAGE || lowDiskSpace ? 111 (Storage)new HeapStorage() : (Storage)new FileMapStorage(); 112 } 113 return storage; 114 } 115 116 boolean hasStorage() { 117 return storage != null; 118 } 119 120 boolean isDisposed() { 121 return disposed; 122 } 123 124 boolean isEmpty() { 125 return storage == null ? true : lines == null ? true : 126 lines.getLineCount() == 0; 127 } 128 129 public String toString() { 130 return "OutWriter@" + System.identityHashCode(this) + " for " + owner + " closed "; 131 } 132 133 private int doPrintln (String s) { 134 try { 135 int idx = s.indexOf("\n"); 136 int result = 1; 137 if (idx != -1) { StringTokenizer tok = new StringTokenizer (s, "\n", true); result = 0; 141 boolean lastWasNewLine = true; 142 while (tok.hasMoreTokens()) { 143 String token = tok.nextToken(); 144 if ("\n".equals(token)) { 145 if (lastWasNewLine) { 146 doPrintln(""); 147 result++; 148 } 149 lastWasNewLine = true; 150 } else { 151 lastWasNewLine = false; 152 doPrintln(token); 153 result++; 154 } 155 } 156 } else { 157 ByteBuffer buf; 158 synchronized (this) { 159 if (s.startsWith("\t")) { char[] c = s.toCharArray(); 161 int ix = 0; 162 StringBuffer sb = new StringBuffer (s.length() + 10); 166 for (int i=0; i < c.length; i++) { 167 if ('\t' == c[i]) { 168 sb.append(" "); } else { 170 sb.append (c[i]); 171 } 172 } 173 s = sb.toString(); 174 } 175 buf = getStorage().getWriteBuffer(AbstractLines.toByteIndex(s.length())); 176 buf.asCharBuffer().put(s); 177 buf.position (buf.position() + AbstractLines.toByteIndex(s.length())); 178 write (buf, true); 179 } 180 } 181 return result; 182 } catch (IOException ioe) { 183 handleException (ioe); 184 return 0; 185 } 186 } 187 188 189 190 private void handleException (Exception e) { 191 setError(); 192 String msg = Exceptions.findLocalizedMessage(e); 193 if (msg == null) { 194 Exceptions.attachLocalizedMessage(e, 195 NbBundle.getMessage(OutWriter.class, 196 "MSG_GenericError")); } 198 if (Controller.LOG) { 199 StackTraceElement [] el = e.getStackTrace(); 200 Controller.log ("EXCEPTION: " + e.getClass() + e.getMessage()); 201 for (int i=1; i < el.length; i++) { 202 Controller.log (el[i].toString()); 203 } 204 } 205 Exceptions.printStackTrace(e); 206 } 207 208 215 public synchronized void write(ByteBuffer bb, boolean completeLine) throws IOException { 216 if (checkError() || terminated) { 217 return; 218 } 219 lines.markDirty(); 220 int length = bb.limit(); 221 closed = false; 222 int start = -1; 223 try { 224 start = getStorage().write(bb, completeLine); 225 } catch (java.nio.channels.ClosedByInterruptException cbie) { 226 threadDeathClose(); 229 } catch (java.nio.channels.AsynchronousCloseException ace) { 230 threadDeathClose(); 233 } catch (IOException ioe) { 234 if (ioe.getMessage().indexOf("There is not enough space on the disk") != -1) { lowDiskSpace = true; 237 String msg = NbBundle.getMessage(OutWriter.class, 238 "MSG_DiskSpace", storage); Exceptions.attachLocalizedMessage(ioe, msg); 240 Exceptions.printStackTrace(ioe); 241 setError(); 242 storage.dispose(); 243 } else { 244 Exceptions.printStackTrace(ioe); 248 threadDeathClose(); 249 } 250 } 251 boolean startedNow = false; 252 if (start >= 0 && lineStart == -1) { 253 lineStart = start; 254 lineLength = lineLength + length; 255 startedNow = true; 256 } 257 if (completeLine) { 258 if (lineStart >= 0 && !terminated && lines != null) { 259 if (Controller.VERBOSE) Controller.log (this + ": Wrote " + 260 ((ByteBuffer )bb.flip()).asCharBuffer() + " at " + start); 261 if (startedNow) { 262 lines.lineWritten (lineStart, lineLength); 263 } else { 264 lines.lineFinished(lineLength); 265 } 266 lineStart = -1; 267 lineLength = 0; 268 if (owner != null && owner.hasStreamClosed()) { 269 owner.setStreamClosed(false); 270 lines.fire(); 271 } 272 } 273 } else { 274 if (startedNow && lineStart >= 0 && !terminated && lines != null) { 275 lines.lineStarted(lineStart); 276 if (owner != null && owner.hasStreamClosed()) { 277 owner.setStreamClosed(false); 278 lines.fire(); 279 } 280 } 281 } 282 } 283 284 289 void threadDeathClose() { 290 terminated = true; 291 if (Controller.LOG) Controller.log (this + " Close due to termination"); 292 ErrWriter err = owner.writer().err(); 293 if (err != null) { 294 err.closed=true; 295 } 296 owner.setStreamClosed(true); 297 close(); 298 } 299 300 305 public synchronized void dispose() { 306 if (disposed) { 307 return; 310 } 311 if (Controller.LOG) Controller.log (this + ": OutWriter.dispose - owner is " + (owner == null ? "null" : owner.getName())); 312 clearListeners(); 313 if (storage != null) { 314 storage.dispose(); 315 storage = null; 316 } 317 if (lines != null) { 318 lines.clear(); 319 } 320 trouble = true; 321 if (Controller.LOG) Controller.log (this + ": Setting owner to null, trouble to true, dirty to false. This OutWriter is officially dead."); 322 owner = null; 323 disposed = true; 324 } 325 326 327 private void clearListeners() { 328 if (Controller.LOG) Controller.log (this + ": Sending outputLineCleared to all listeners"); 329 if (owner == null) { 330 return; 332 } 333 synchronized (this) { 334 if (lines != null && lines.hasHyperlinks()) { 335 int[] listenerLines = lines.allListenerLines(); 336 Controller.ControllerOutputEvent e = new Controller.ControllerOutputEvent(owner, 0); 337 for (int i=0; i < listenerLines.length; i++) { 338 OutputListener ol = (OutputListener) lines.getListenerForLine(listenerLines[i]); 339 if (Controller.LOG) { 340 Controller.log("Clearing listener " + ol); 341 } 342 e.setLine(listenerLines[i]); 343 if (ol != null) { 344 ol.outputLineCleared(e); 345 } else { 346 Logger.getAnonymousLogger().warning("issue #56826 - There was a null OutputListener on line:" + listenerLines[i]); 348 } 349 } 350 } else { 351 if (Controller.LOG) Controller.log (this + ": No listeners to clear"); 352 } 353 } 354 } 355 356 public synchronized boolean isClosed() { 357 if (checkError() || storage == null || storage.isClosed()) { 358 return true; 359 } else { 360 return closed; 361 } 362 } 363 364 public Lines getLines() { 365 return lines; 366 } 367 368 private boolean closed = false; 369 public synchronized void close() { 370 closed = true; 371 try { 372 if (storage != null) { 375 storage.close(); 376 } 377 if (lines != null) { 378 lines.fire(); 379 } 380 } catch (IOException ioe) { 381 handleException (ioe); 382 } 383 } 384 385 public synchronized void println(String s) { 386 if (checkError()) { 387 return; 388 } 389 doPrintln(s); 390 } 391 392 public synchronized void flush() { 393 if (checkError()) { 394 return; 395 } 396 try { 397 getStorage().flush(); 398 if (lines != null) { 399 lines.fire(); 400 } 401 } catch (IOException e) { 402 handleException (e); 403 } 404 } 405 406 407 public boolean checkError() { 408 return disposed || trouble; 409 } 410 411 public synchronized void write(int c) { 412 if (checkError()) { 413 return; 414 } 415 try { 416 ByteBuffer buf = getStorage().getWriteBuffer(AbstractLines.toByteIndex(1)); 417 buf.asCharBuffer().put((char)c); 418 buf.position (buf.position() + AbstractLines.toByteIndex(1)); 419 write (buf, false); 420 } catch (IOException ioe) { 421 handleException (ioe); 422 } 423 } 424 425 public synchronized void write(char data[], int off, int len) { 426 if (checkError()) { 427 return; 428 } 429 if (len > 0 && data[off] == '\t') { 430 StringBuffer sb = new StringBuffer (data.length + 10); 434 int cnt = 0; 435 for (int i=0; i < data.length; i++) { 436 if (data[i] == '\t') { 437 sb.append(" "); cnt = cnt + 1; 439 } else { 440 sb.append (data[i]); 441 } 442 } 443 data = sb.toString().toCharArray(); 444 len = len + (cnt * 7); 445 } 446 447 int count = off; 448 int start = off; 449 while (count < len + off) { 450 char curr = data[count]; 451 if (curr == '\n') { String sx = new String (data, start, (count + 1 - start)); 456 println (sx); 457 start = count + 1; 458 if (start >= len + off) { 459 return; 460 } 461 } 462 count++; 463 } 464 try { 465 synchronized (this) { 466 int lenght = count - (start); 467 ByteBuffer buf = getStorage().getWriteBuffer(AbstractLines.toByteIndex(lenght)); 468 buf.asCharBuffer().put(data, start, lenght); 469 buf.position(buf.position() + AbstractLines.toByteIndex(lenght)); 470 write(buf, false); 471 } 472 } catch (IOException ioe) { 473 handleException(ioe); 474 return; 475 } 476 } 477 478 public synchronized void write(char data[]) { 479 write (data, 0, data.length); 480 } 481 482 public synchronized void println() { 483 doPrintln(""); 484 } 485 486 492 public synchronized void write(String s, int off, int len) { 493 write (s.toCharArray(), off, len); 494 } 495 496 public synchronized void write(String s) { 497 write (s.toCharArray()); 498 } 499 500 501 public synchronized void println(String s, OutputListener l) throws IOException { 502 println(s, l, false); 503 } 504 505 506 public synchronized void println(String s, OutputListener l, boolean important) throws IOException { 507 if (checkError()) { 508 return; 509 } 510 int addedCount = doPrintln (s); 511 int newCount = lines.getLineCount(); 512 for (int i=newCount - addedCount; i < newCount; i++) { 513 lines.addListener (i, l, important); 514 lines.fire(); 517 } 518 } 519 520 524 static class DummyWriter extends Writer { 525 526 DummyWriter() { 527 super (new Object ()); 528 } 529 530 public void close() throws IOException { 531 } 532 533 public void flush() throws IOException { 534 } 535 536 public void write(char[] cbuf, int off, int len) throws IOException { 537 } 538 } 539 540 private class LinesImpl extends AbstractLines { 541 LinesImpl() { 542 super(); 543 } 544 545 protected Storage getStorage() { 546 return OutWriter.this.getStorage(); 547 } 548 549 protected boolean isDisposed() { 550 return OutWriter.this.disposed; 551 } 552 553 protected boolean isTrouble() { 554 return OutWriter.this.trouble; 555 } 556 557 public Object readLock() { 558 return OutWriter.this; 559 } 560 561 public boolean isGrowing() { 562 return !isClosed(); 563 } 564 565 protected void handleException (Exception e) { 566 OutWriter.this.handleException(e); 567 } 568 } 569 } 570 | Popular Tags |