Archived
0

Zond:fix: StackOverflow под linux

Пришлось переписывать алгоритм работы ShellStdOut, что бы заработало
как надо под Linux-based системами
This commit is contained in:
2017-07-23 16:35:18 +03:00
parent a4f1d78c2e
commit cc218c1391
6 changed files with 62 additions and 66 deletions

View File

@@ -1,5 +1,5 @@
group = 'asys' group = 'asys'
version = '0.7.13-SNAPSHOT' version = '0.7.14-SNAPSHOT'
apply plugin: 'application' apply plugin: 'application'

View File

@@ -1,5 +1,5 @@
/* /*
* DmitriyMX <d.mihailov@samson-rus.com> * DmitriyMX <dimon550@gmail.com>
* 2017-06-15 * 2017-06-15
*/ */
package asys.zond.shell; package asys.zond.shell;
@@ -11,12 +11,10 @@ import java.io.IOException;
public class CommandLooper implements Runnable { public class CommandLooper implements Runnable {
private ConsoleReader consoleReader; private ConsoleReader consoleReader;
private CommandHandler commandHandler; private CommandHandler commandHandler;
private ShellStdOut output;
CommandLooper(ConsoleReader consoleReader, CommandHandler commandHandler) { CommandLooper(ConsoleReader consoleReader, CommandHandler commandHandler) {
this.consoleReader = consoleReader; this.consoleReader = consoleReader;
this.commandHandler = commandHandler; this.commandHandler = commandHandler;
this.output = (ShellStdOut) Shell.getInstance().getOutput();
} }
@Override @Override
@@ -24,9 +22,7 @@ public class CommandLooper implements Runnable {
while (!Thread.currentThread().isInterrupted()) { while (!Thread.currentThread().isInterrupted()) {
String line; String line;
try { try {
output.needDrawLine = true;
line = consoleReader.readLine(); line = consoleReader.readLine();
output.needDrawLine = false;
} catch (IOException e) { } catch (IOException e) {
break; break;
} }

View File

@@ -1,14 +1,12 @@
/* /*
* DmitriyMX <d.mihailov@samson-rus.com> * DmitriyMX <dimon550@gmail.com>
* 2017-06-15 * 2017-06-15
*/ */
package asys.zond.shell; package asys.zond.shell;
import jline.console.ConsoleReader; import jline.console.ConsoleReader;
import java.io.IOException; import java.io.*;
import java.io.InputStream;
import java.io.PrintStream;
public class Shell { public class Shell {
private static final String DEFAULT_PROMPT = ":"; private static final String DEFAULT_PROMPT = ":";
@@ -27,7 +25,7 @@ public class Shell {
} }
public void start(InputStream inputStream) throws IOException { public void start(InputStream inputStream) throws IOException {
consoleReader = new ConsoleReader(inputStream, (shellStdOut = new ShellStdOut())); consoleReader = new ConsoleReader(inputStream, (shellStdOut = new ShellStdOut(System.out)));
shellStdOut.setConsoleReader(consoleReader); shellStdOut.setConsoleReader(consoleReader);
consoleReader.setPrompt(DEFAULT_PROMPT); consoleReader.setPrompt(DEFAULT_PROMPT);
@@ -56,10 +54,6 @@ public class Shell {
return shellStdOut; return shellStdOut;
} }
public void setOutputHook(ShellOutputHook outputHook) {
shellStdOut.setOutputHook(outputHook);
}
public void setCommandHandler(CommandHandler commandHandler) { public void setCommandHandler(CommandHandler commandHandler) {
this.commandHandler = commandHandler; this.commandHandler = commandHandler;
} }

View File

@@ -1,9 +0,0 @@
/*
* DmitriyMX <d.mihailov@samson-rus.com>
* 2017-06-15
*/
package asys.zond.shell;
public interface ShellOutputHook {
String handle(String line);
}

View File

@@ -1,83 +1,93 @@
/* /*
* DmitriyMX <d.mihailov@samson-rus.com> * DmitriyMX <dimon550@gmail.com>
* 2017-06-15 * 2017-07-23
*/ */
package asys.zond.shell; package asys.zond.shell;
import jline.console.ConsoleReader; import jline.console.ConsoleReader;
import java.io.IOException;
import java.io.OutputStream;
import java.io.PrintStream; import java.io.PrintStream;
import java.io.PrintWriter;
public class ShellStdOut extends PrintStream { public class ShellStdOut extends PrintStream {
private ConsoleReader consoleReader; private ConsoleReader consoleReader;
private PrintWriter writer;
private ShellOutputHook shellOutputHook;
boolean needDrawLine = false;
ShellStdOut() { ShellStdOut(OutputStream out) {
super(System.out, true); super(out);
} }
void setConsoleReader(ConsoleReader consoleReader) { private void _write(char c) {
this.consoleReader = consoleReader; try {
this.writer = new PrintWriter(consoleReader.getOutput()); this.out.write(c);
} catch (IOException ignore) {
}
} }
private void _print(String line) { private void _write(byte[] buf) {
String newLine; try {
if (shellOutputHook != null) { this.out.write(buf);
try { } catch (IOException ignore) {
newLine = shellOutputHook.handle(line);
if (newLine == null) return;
else line = newLine;
} catch (Exception ignore) {
}
} }
}
writer.print(ConsoleReader.RESET_LINE); private void _write(byte[] buf, int off, int len) {
writer.print(line); try {
cleanTrashLine(line); this.out.write(buf, off, len);
writer.println(); } catch (IOException ignore) {
if (needDrawLine) { }
try { }
consoleReader.drawLine();
} catch (Throwable ignore) { private void _flush() {
} try {
this.out.flush();
} catch (IOException ignore) {
} }
writer.flush();
} }
/** /**
* Очистка печатной строки от мусора * Очистка печатной строки от мусора
*/ */
private void cleanTrashLine(String string) { private void cleanTrashLine(int len) throws IOException {
// очищает полностью строку // очищает полностью строку
if (consoleReader.getCursorBuffer().buffer.length() + consoleReader.getPrompt().length() > string.length()) { if (consoleReader.getCursorBuffer().buffer.length() + consoleReader.getPrompt().length() > len) {
for (int i = string.length(); i <= consoleReader.getCursorBuffer().buffer.length() + 2; i++) { for (int i = len; i <= consoleReader.getCursorBuffer().buffer.length() + 2; i++) {
writer.print(' '); this.out.write(' ');
} }
this.out.flush();
} }
} }
void setOutputHook(ShellOutputHook shellOutputHook) { public void printEx(byte[] buf, int len) {
this.shellOutputHook = shellOutputHook; _write(ConsoleReader.RESET_LINE);
_write(buf, 0, len);
try {
cleanTrashLine(len);
consoleReader.drawLine();
consoleReader.flush();
} catch (Throwable ignore) {
}
_flush();
} }
@Override @Override
public void write(byte[] buf, int off, int len) { public void write(byte[] buf, int off, int len) {
if ((char)buf[len-1] == '\n') len--; _write(buf, off, len);
if ((char)buf[len-1] == '\r') len--;
_print(new String(buf, off, len));
} }
@Override @Override
public void print(String s) { public void print(String s) {
_print(s); _write(ConsoleReader.RESET_LINE);
_write(s.getBytes());
} }
@Override @Override
public void println(String x) { public void println(String x) {
_print(x); print(x.concat("\n"));
_flush();
}
void setConsoleReader(ConsoleReader consoleReader) {
this.consoleReader = consoleReader;
} }
} }

View File

@@ -22,6 +22,7 @@ import java.io.IOException;
import java.io.InputStream; import java.io.InputStream;
import java.io.OutputStream; import java.io.OutputStream;
import asys.zond.shell.ShellStdOut;
import org.apache.commons.exec.util.DebugUtils; import org.apache.commons.exec.util.DebugUtils;
/** /**
@@ -106,7 +107,11 @@ public class StreamPumper implements Runnable {
try { try {
//hack: пропатчили алгоритм //hack: пропатчили алгоритм
while (!Thread.currentThread().isInterrupted() && (length = is.read(buf)) > 0) { while (!Thread.currentThread().isInterrupted() && (length = is.read(buf)) > 0) {
os.write(buf, 0, length); if (os instanceof ShellStdOut) {
((ShellStdOut)os).printEx(buf, length);
} else {
os.write(buf, 0, length);
}
os.flush(); os.flush();
} }
} catch (final Exception e) { } catch (final Exception e) {