package net.sf.eclipsefp.haskell.util; import java.io.IOException; import java.io.PrintWriter; import java.io.StringWriter; import java.io.Writer; import java.util.LinkedList; /** * A separate thread to write the communication with the server see * https://bugs.eclipse.org/bugs/show_bug.cgi?id=259107 */ public abstract class OutputWriter extends Thread { /** the console doesn't like long lines **/ private static int LINE_LENGTH=200; /** the message list **/ private final LinkedList<String> messages = new LinkedList<>(); /** should we stop? **/ private boolean terminateFlag; private Writer serverOutput; public OutputWriter(String name,Writer output) { super(name); this.serverOutput=output; } public void setTerminate() { terminateFlag = true; interrupt(); } public void addMessage(String msg) { synchronized (messages) { messages.add(msg); messages.notify(); } } public void addMessage(char[] buf, int start, int length) { synchronized (messages) { messages.add(new String(buf, start, length)); messages.notify(); } } public void addMessage(Exception e) { StringWriter sw = new StringWriter(); PrintWriter pw = new PrintWriter(sw); e.printStackTrace(pw); pw.flush(); synchronized (messages) { messages.add(sw.toString()); messages.notify(); } } @Override public void run() { while (!terminateFlag && serverOutput != null) { String m = null; synchronized (messages) { try { while (messages.isEmpty()) { messages.wait(); } } catch (InterruptedException ignore) { // noop } if (!messages.isEmpty()) { m = messages.removeFirst(); } } if (m != null) { try { final int mLen = m.length(); int written=0; int sinceLastLine=0; for (int i=0;i<mLen;i++){ char c=m.charAt(i); serverOutput.write(c); written++; if (i=='\n'){ sinceLastLine=0; } else { sinceLastLine++; } if (sinceLastLine==LINE_LENGTH){ serverOutput.write(PlatformUtil.NL); serverOutput.flush(); written=0; sinceLastLine=0; } else if (written>=80){ serverOutput.flush(); written=0; } } // Break the message up into 1K chunks for better UI responsiveness, since this all is going to // an IOConsole. /* while ( mLen - i > 1024 ) { serverOutput.write(m, i, 1024); serverOutput.flush(); i += 1024; } serverOutput.write(m, i, mLen - i);*/ if (sinceLastLine>0){ serverOutput.write(PlatformUtil.NL); } serverOutput.flush(); } catch (IOException ex) { if (!terminateFlag) { onIOError(ex); } } catch (Throwable se) { // probably device has been disposed if (!terminateFlag) { onThrowable(se); } } } } } public abstract void onIOError(IOException ex); public abstract void onThrowable(Throwable se); }