package edu.stanford.nlp.util.logging; import java.io.PrintStream; import java.util.Locale; /** * A PrintStream that writes to Redwood logs. * The primary use of this class is to override System.out and System.err. * * @author Gabor Angeli (angeli at cs.stanford) * @author Kevin Reschke (kreschke at cs.stanford) */ public class RedwoodPrintStream extends PrintStream { private final Redwood.Flag tag; private final PrintStream realStream; private StringBuilder buffer = new StringBuilder(); private boolean checkForThrowable = false; public RedwoodPrintStream(Redwood.Flag tag, PrintStream realStream) { super(realStream); this.tag = tag; this.realStream = realStream; } private synchronized void log(Object message){ if(buffer.length() > 0){ logB(message); logB("\n"); } else { if(tag != null){ Redwood.log(tag, message); } else { Redwood.log(message); } } } private synchronized void logf(String format, Object[] args){ if(tag != null){ Redwood.channels(tag).logf(format, args); } else { Redwood.logf(format, args); } } private synchronized void logB(Object message){ char[] str = message.toString().toCharArray(); for (char c : str) { if(c == '\n'){ String msg = buffer.toString(); if (tag != null) { Redwood.log(tag, msg); } else { Redwood.log(msg); } buffer = new StringBuilder(); } else { buffer.append(String.valueOf(c)); } } } @Override public void flush() { realStream.flush(); } @Override public void close() { } @Override public boolean checkError(){ return false; } @Override protected void setError() { } protected void clearError() { } @Override public void print(boolean b) { logB(b); } @Override public void print(char c) { logB(c); } @Override public void print(int i) { logB(i); } @Override public void print(long l) { logB(l); } @Override public void print(float f) { logB(f); } @Override public void print(double d) { logB(d); } @Override public void print(char[] chars) { logB(new String(chars)); } @Override public void print(String s) { logB(s); } @Override public void print(Object o) { logB(o); } @Override public void println(boolean b) { log(b); } @Override public void println(char c) { log(c); } @Override public void println(int i) { log(i); } @Override public void println(long l) { log(l); } @Override public void println(float f) { log(f); } @Override public void println(double d) { log(d); } @Override public void println(char[] chars) { log(new String(chars)); } @Override public void println(String s) { if(checkForThrowable){ //(check if from throwable) boolean fromThrowable = false; for(StackTraceElement e : Thread.currentThread().getStackTrace()) { if(e.getClassName().equals(Throwable.class.getName())){ fromThrowable = true; } } //(handle message appropriately) if(fromThrowable){ realStream.println(s); }else{ log(s); checkForThrowable = false; } } else { log(s); } } @Override public void println(Object o) { if(o instanceof Throwable){ realStream.println(o); flush(); checkForThrowable = true; } else { log(o); } } @Override public void println() { log(""); } @Override public PrintStream printf(String s, Object... objects) { logf(s,objects); return this; } @Override public PrintStream printf(Locale locale, String s, Object... objects) { logf(s,objects); return this; } @Override public PrintStream format(String s, Object... objects) { logf(s,objects); return this; } @Override public PrintStream format(Locale locale, String s, Object... objects) { logf(s,objects); return this; } @Override public PrintStream append(CharSequence charSequence) { logB(charSequence); return this; } @Override public PrintStream append(CharSequence charSequence, int i, int i1) { logB(charSequence.subSequence(i,i1)); return this; } @Override public PrintStream append(char c) { logB(c); return this; } }