mirror of
https://github.com/corda/corda.git
synced 2024-12-18 20:47:57 +00:00
Filter zero bytes from CRaSH input stream. (#460)
* Work around JavaFX injecting 0 bytes into JediTerm's STDIN stream. * Add (disabled) unit tests for running JediTerm in both Swing and JavaFX. * Remove tests for running JediTerm under Swing and JavaFX.
This commit is contained in:
parent
78a0024e00
commit
ade9a7dba8
@ -29,6 +29,7 @@ buildscript {
|
||||
ext.typesafe_config_version = '1.3.1'
|
||||
ext.fileupload_version = '1.3.2'
|
||||
ext.junit_version = '4.12'
|
||||
ext.mockito_version = '1.10.19'
|
||||
ext.jopt_simple_version = '5.0.2'
|
||||
ext.jansi_version = '1.14'
|
||||
ext.hibernate_version = '5.2.6.Final'
|
||||
|
@ -58,7 +58,7 @@
|
||||
<AppenderRef ref="RollingFile-Appender" />
|
||||
</Logger>
|
||||
<Logger name="org.apache.activemq.artemis.core.server" level="error" additivity="false">
|
||||
<AppenderRef ref="RollingFile-Appender"/>
|
||||
<AppenderRef ref="RollingFile-Appender"/>
|
||||
</Logger>
|
||||
</Loggers>
|
||||
</Configuration>
|
||||
</Configuration>
|
||||
|
@ -23,7 +23,10 @@ apply plugin: 'application'
|
||||
evaluationDependsOn(':tools:explorer:capsule')
|
||||
|
||||
mainClassName = 'net.corda.demobench.DemoBench'
|
||||
applicationDefaultJvmArgs = ['-Djava.util.logging.config.class=net.corda.demobench.config.LoggingConfig', '-Dorg.jboss.logging.provider=slf4j']
|
||||
applicationDefaultJvmArgs = [
|
||||
'-Djava.util.logging.config.class=net.corda.demobench.config.LoggingConfig',
|
||||
'-Dorg.jboss.logging.provider=slf4j'
|
||||
]
|
||||
|
||||
repositories {
|
||||
flatDir {
|
||||
@ -66,6 +69,7 @@ dependencies {
|
||||
|
||||
testCompile "junit:junit:$junit_version"
|
||||
testCompile "org.jetbrains.kotlin:kotlin-test:$kotlin_version"
|
||||
testCompile "org.mockito:mockito-core:$mockito_version"
|
||||
}
|
||||
|
||||
jar {
|
||||
|
@ -1,42 +0,0 @@
|
||||
package net.corda.demobench.pty;
|
||||
|
||||
import com.jediterm.terminal.ProcessTtyConnector;
|
||||
import com.pty4j.PtyProcess;
|
||||
import com.pty4j.WinSize;
|
||||
|
||||
import java.nio.charset.Charset;
|
||||
|
||||
/**
|
||||
* Copied from JediTerm pty.
|
||||
* JediTerm is not available in any Maven repository.
|
||||
* @author traff
|
||||
*/
|
||||
public class PtyProcessTtyConnector extends ProcessTtyConnector {
|
||||
private final PtyProcess myProcess;
|
||||
private final String name;
|
||||
|
||||
PtyProcessTtyConnector(String name, PtyProcess process, Charset charset) {
|
||||
super(process, charset);
|
||||
myProcess = process;
|
||||
this.name = name;
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void resizeImmediately() {
|
||||
if (getPendingTermSize() != null && getPendingPixelSize() != null) {
|
||||
myProcess.setWinSize(
|
||||
new WinSize(getPendingTermSize().width, getPendingTermSize().height, getPendingPixelSize().width, getPendingPixelSize().height));
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isConnected() {
|
||||
return myProcess.isRunning();
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getName() {
|
||||
return name;
|
||||
}
|
||||
|
||||
}
|
@ -0,0 +1,34 @@
|
||||
package net.corda.demobench.pty
|
||||
|
||||
import com.jediterm.terminal.ProcessTtyConnector
|
||||
import com.pty4j.PtyProcess
|
||||
import com.pty4j.WinSize
|
||||
import java.nio.charset.Charset
|
||||
|
||||
/**
|
||||
* Copied from JediTerm pty.
|
||||
* JediTerm is not available in any Maven repository.
|
||||
* @author traff
|
||||
*/
|
||||
class PtyProcessTtyConnector(
|
||||
private val name: String,
|
||||
private val process: PtyProcess,
|
||||
charset: Charset
|
||||
) : ProcessTtyConnector(process.zeroFiltered(), charset) {
|
||||
|
||||
override fun getName() = name
|
||||
|
||||
override fun isConnected() = process.isRunning
|
||||
|
||||
override fun resizeImmediately() {
|
||||
if (pendingTermSize != null && pendingPixelSize != null) {
|
||||
process.winSize = WinSize(
|
||||
pendingTermSize.width,
|
||||
pendingTermSize.height,
|
||||
pendingPixelSize.width,
|
||||
pendingPixelSize.height
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
}
|
@ -9,7 +9,6 @@ import net.corda.core.utilities.loggerFor
|
||||
import java.awt.*
|
||||
import java.io.IOException
|
||||
import java.nio.charset.StandardCharsets.UTF_8
|
||||
import java.util.*
|
||||
import java.util.concurrent.Executors
|
||||
import java.util.concurrent.TimeUnit
|
||||
|
||||
@ -44,7 +43,7 @@ class R3Pty(val name: String, settings: SettingsProvider, dimension: Dimension,
|
||||
fun run(args: Array<String>, envs: Map<String, String>, workingDir: String?) {
|
||||
check(!terminal.isSessionRunning, { "${terminal.sessionName} is already running" })
|
||||
|
||||
val environment = HashMap<String, String>(envs)
|
||||
val environment = envs.toMutableMap()
|
||||
if (!UIUtil.isWindows) {
|
||||
environment["TERM"] = "xterm"
|
||||
|
||||
@ -64,4 +63,7 @@ class R3Pty(val name: String, settings: SettingsProvider, dimension: Dimension,
|
||||
session.start()
|
||||
}
|
||||
|
||||
@Throws(InterruptedException::class)
|
||||
fun waitFor(): Int? = terminal.ttyConnector?.waitFor()
|
||||
|
||||
}
|
||||
|
@ -0,0 +1,72 @@
|
||||
package net.corda.demobench.pty
|
||||
|
||||
import java.io.FilterOutputStream
|
||||
import java.io.IOException
|
||||
import java.io.InputStream
|
||||
import java.io.OutputStream
|
||||
|
||||
/**
|
||||
* Removes any zero byte values from the output stream.
|
||||
* This stream is connected to a terminal's STDIN, and
|
||||
* any zeros received will trigger unwanted key mappings.
|
||||
* JavaFX seems to be inserting these zeros into the
|
||||
* stream as it tries to inter-operate with Swing.
|
||||
*/
|
||||
private class ZeroFilter(output: OutputStream) : FilterOutputStream(output) {
|
||||
|
||||
@Throws(IOException::class)
|
||||
override fun write(b: Int) {
|
||||
if (b != 0) {
|
||||
super.write(b)
|
||||
}
|
||||
}
|
||||
|
||||
@Throws(IOException::class)
|
||||
override fun write(raw: ByteArray, offset: Int, len: Int) {
|
||||
val filtered = ByteArray(len)
|
||||
var count = 0
|
||||
|
||||
var i = 0
|
||||
while (i < len) {
|
||||
val b = raw[offset + i]
|
||||
if (b != 0.toByte()) {
|
||||
filtered[count] = b
|
||||
++count
|
||||
}
|
||||
++i
|
||||
}
|
||||
|
||||
super.write(filtered, 0, count)
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
* Wraps a process's output stream with a zero filter.
|
||||
*/
|
||||
private class ZeroFilteringProcess(private val process: Process) : Process() {
|
||||
private val output: OutputStream
|
||||
|
||||
init {
|
||||
this.output = ZeroFilter(process.outputStream)
|
||||
}
|
||||
|
||||
override fun getOutputStream() = output
|
||||
|
||||
override fun getInputStream(): InputStream = process.inputStream
|
||||
|
||||
override fun getErrorStream(): InputStream = process.errorStream
|
||||
|
||||
@Throws(InterruptedException::class)
|
||||
override fun waitFor() = process.waitFor()
|
||||
|
||||
override fun destroy() = process.destroy()
|
||||
|
||||
override fun exitValue() = process.exitValue()
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
* Applies the ZeroFilter to this process.
|
||||
*/
|
||||
fun Process.zeroFiltered(): Process = ZeroFilteringProcess(this)
|
@ -0,0 +1,58 @@
|
||||
package net.corda.demobench.pty
|
||||
|
||||
import org.junit.Assert.assertEquals
|
||||
import org.junit.Before
|
||||
import org.junit.Test
|
||||
import org.mockito.Mockito.*
|
||||
import java.io.ByteArrayOutputStream
|
||||
import java.io.OutputStream
|
||||
import java.nio.charset.StandardCharsets.UTF_8
|
||||
|
||||
class ZeroFilterTest {
|
||||
private lateinit var output: ByteArrayOutputStream
|
||||
private lateinit var filter: OutputStream
|
||||
|
||||
@Before
|
||||
fun setup() {
|
||||
output = ByteArrayOutputStream()
|
||||
|
||||
val process = mock(Process::class.java)
|
||||
`when`(process.outputStream).thenReturn(output)
|
||||
|
||||
filter = process.zeroFiltered().outputStream
|
||||
verify(process).outputStream
|
||||
}
|
||||
|
||||
@Test
|
||||
fun `non-zero is OK`() {
|
||||
for (c in 'A'..'Z') {
|
||||
filter.write(c.toInt())
|
||||
}
|
||||
assertEquals(26, output.size())
|
||||
}
|
||||
|
||||
@Test
|
||||
fun `zero is removed`() {
|
||||
filter.write(0)
|
||||
assertEquals(0, output.size())
|
||||
}
|
||||
|
||||
@Test
|
||||
fun `zero is removed from array`() {
|
||||
val input = "He\u0000l\u0000lo".toByteArray(UTF_8)
|
||||
filter.write(input)
|
||||
|
||||
assertEquals(5, output.size())
|
||||
assertEquals("Hello", output.toString("UTF-8"))
|
||||
}
|
||||
|
||||
@Test
|
||||
fun `zero is removed starting from offset`() {
|
||||
val input = "H\u0000el\u0000lo W\u0000or\u0000ld!\u0000".toByteArray(UTF_8)
|
||||
val offset = input.indexOf('W'.toByte())
|
||||
filter.write(input, offset, input.size - offset)
|
||||
|
||||
assertEquals(6, output.size())
|
||||
assertEquals("World!", output.toString("UTF-8"))
|
||||
}
|
||||
}
|
Loading…
Reference in New Issue
Block a user