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'
version = '0.7.13-SNAPSHOT'
version = '0.7.14-SNAPSHOT'
apply plugin: 'application'

View File

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

View File

@@ -1,14 +1,12 @@
/*
* DmitriyMX <d.mihailov@samson-rus.com>
* DmitriyMX <dimon550@gmail.com>
* 2017-06-15
*/
package asys.zond.shell;
import jline.console.ConsoleReader;
import java.io.IOException;
import java.io.InputStream;
import java.io.PrintStream;
import java.io.*;
public class Shell {
private static final String DEFAULT_PROMPT = ":";
@@ -27,7 +25,7 @@ public class Shell {
}
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);
consoleReader.setPrompt(DEFAULT_PROMPT);
@@ -56,10 +54,6 @@ public class Shell {
return shellStdOut;
}
public void setOutputHook(ShellOutputHook outputHook) {
shellStdOut.setOutputHook(outputHook);
}
public void setCommandHandler(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>
* 2017-06-15
* DmitriyMX <dimon550@gmail.com>
* 2017-07-23
*/
package asys.zond.shell;
import jline.console.ConsoleReader;
import java.io.IOException;
import java.io.OutputStream;
import java.io.PrintStream;
import java.io.PrintWriter;
public class ShellStdOut extends PrintStream {
private ConsoleReader consoleReader;
private PrintWriter writer;
private ShellOutputHook shellOutputHook;
boolean needDrawLine = false;
ShellStdOut() {
super(System.out, true);
ShellStdOut(OutputStream out) {
super(out);
}
void setConsoleReader(ConsoleReader consoleReader) {
this.consoleReader = consoleReader;
this.writer = new PrintWriter(consoleReader.getOutput());
private void _write(char c) {
try {
this.out.write(c);
} catch (IOException ignore) {
}
}
private void _print(String line) {
String newLine;
if (shellOutputHook != null) {
try {
newLine = shellOutputHook.handle(line);
if (newLine == null) return;
else line = newLine;
} catch (Exception ignore) {
}
private void _write(byte[] buf) {
try {
this.out.write(buf);
} catch (IOException ignore) {
}
}
writer.print(ConsoleReader.RESET_LINE);
writer.print(line);
cleanTrashLine(line);
writer.println();
if (needDrawLine) {
try {
consoleReader.drawLine();
} catch (Throwable ignore) {
}
private void _write(byte[] buf, int off, int len) {
try {
this.out.write(buf, off, len);
} catch (IOException 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()) {
for (int i = string.length(); i <= consoleReader.getCursorBuffer().buffer.length() + 2; i++) {
writer.print(' ');
if (consoleReader.getCursorBuffer().buffer.length() + consoleReader.getPrompt().length() > len) {
for (int i = len; i <= consoleReader.getCursorBuffer().buffer.length() + 2; i++) {
this.out.write(' ');
}
this.out.flush();
}
}
void setOutputHook(ShellOutputHook shellOutputHook) {
this.shellOutputHook = shellOutputHook;
public void printEx(byte[] buf, int len) {
_write(ConsoleReader.RESET_LINE);
_write(buf, 0, len);
try {
cleanTrashLine(len);
consoleReader.drawLine();
consoleReader.flush();
} catch (Throwable ignore) {
}
_flush();
}
@Override
public void write(byte[] buf, int off, int len) {
if ((char)buf[len-1] == '\n') len--;
if ((char)buf[len-1] == '\r') len--;
_print(new String(buf, off, len));
_write(buf, off, len);
}
@Override
public void print(String s) {
_print(s);
_write(ConsoleReader.RESET_LINE);
_write(s.getBytes());
}
@Override
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.OutputStream;
import asys.zond.shell.ShellStdOut;
import org.apache.commons.exec.util.DebugUtils;
/**
@@ -106,7 +107,11 @@ public class StreamPumper implements Runnable {
try {
//hack: пропатчили алгоритм
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();
}
} catch (final Exception e) {