Skip to content

Commit

Permalink
[WFCORE-3187] add-user.sh tool prints unexpected characters if arrow …
Browse files Browse the repository at this point in the history
…keys are pushed during interactive mode
  • Loading branch information
MMarus committed Jan 26, 2018
1 parent df126d8 commit dd16837
Show file tree
Hide file tree
Showing 5 changed files with 232 additions and 10 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -37,6 +37,7 @@
</resources>

<dependencies>
<module name="org.aesh"/>
<module name="org.wildfly.openssl" />
<module name="org.wildfly.common" />
<module name="org.wildfly.security.elytron-private" />
Expand Down
4 changes: 4 additions & 0 deletions domain-management/pom.xml
Original file line number Diff line number Diff line change
Expand Up @@ -71,6 +71,10 @@
</dependencyManagement>

<dependencies>
<dependency>
<groupId>org.aesh</groupId>
<artifactId>aesh-readline</artifactId>
</dependency>
<dependency>
<groupId>org.apache.directory.api</groupId>
<artifactId>api-ldap-codec-standalone</artifactId>
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -28,7 +28,10 @@

import java.io.Console;
import java.io.IOError;
import java.io.IOException;
import java.util.IllegalFormatException;
import org.aesh.readline.Prompt;
import org.aesh.readline.tty.terminal.TerminalConnection;

/**
* Describe the purpose
Expand Down Expand Up @@ -59,26 +62,34 @@ public void printf(String format, Object... args) throws IllegalFormatException

@Override
public String readLine(String fmt, Object... args) throws IOError {
if (hasConsole()) {
return theConsole.readLine(fmt, args);
} else {
ReadLineHandler readLineHandler = new ReadLineHandler(new Prompt(String.format(fmt, args)));
return readInputLine(readLineHandler);
}

private String readInputLine(ReadLineHandler readLineHandler) {
try {
createTerminalConnection(readLineHandler);
} catch (IOException e) {
throw ROOT_LOGGER.noConsoleAvailable();
}

return readLineHandler.getLine();
}

protected void createTerminalConnection(ReadLineHandler readLineHandler) throws IOException {
//Side effect - this starts the new connection to terminal and asks user for input.
//This call will block this thread while it reads a line from user.
new TerminalConnection(readLineHandler);
}

@Override
public char[] readPassword(String fmt, Object... args) throws IllegalFormatException, IOError {
if (hasConsole()) {
return theConsole.readPassword(fmt, args);
} else {
throw ROOT_LOGGER.noConsoleAvailable();
}
ReadLineHandler readLineHandler = new ReadLineHandler(new Prompt(String.format(fmt, args), Character.MIN_VALUE));
return readInputLine(readLineHandler).toCharArray();
}

@Override
public boolean hasConsole() {
return theConsole != null;
}


}
Original file line number Diff line number Diff line change
@@ -0,0 +1,72 @@
/*
* JBoss, Home of Professional Open Source.
* Copyright 2017, Red Hat, Inc., and individual contributors
* as indicated by the @author tags. See the copyright.txt file in the
* distribution for a full listing of individual contributors.
*
* This is free software; you can redistribute it and/or modify it
* under the terms of the GNU Lesser General Public License as
* published by the Free Software Foundation; either version 2.1 of
* the License, or (at your option) any later version.
*
* This software is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public
* License along with this software; if not, write to the Free
* Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA
* 02110-1301 USA, or see the FSF site: http://www.fsf.org.
*/

package org.jboss.as.domain.management.security.adduser;

import java.util.function.Consumer;

import org.aesh.readline.Prompt;
import org.aesh.readline.Readline;
import org.aesh.readline.ReadlineBuilder;
import org.aesh.terminal.Connection;
import org.aesh.terminal.tty.Signal;

/**
* Class to read line from terminal using Aesh-readline library.
* Created by Marek Marusic <mmarusic@redhat.com> on 8/7/17.
*/
class ReadLineHandler implements Consumer<Connection> {
private String line;
private Prompt prompt;

public ReadLineHandler(Prompt prompt) {
this.prompt = prompt;
}

public String getLine() {
return line;
}

@Override
public void accept(Connection connection) {
read(connection, ReadlineBuilder.builder().enableHistory(false).build(), prompt);
// lets open the connection to the terminal using this thread
connection.openBlocking();
}

protected void read(Connection connection, Readline readline, Prompt prompt) {
// Set the Ctrl-C handler
connection.setSignalHandler(signal -> {
if (signal == Signal.INT)
connection.close();
});

readline.readline(connection, prompt, line -> {
// we specify a simple lambda consumer to read the input thats saved into line.
if (line != null) {
this.line = line;
connection.close();
} else
read(connection, readline, prompt);
});
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,134 @@
/*
* JBoss, Home of Professional Open Source.
* Copyright 2017, Red Hat, Inc., and individual contributors
* as indicated by the @author tags. See the copyright.txt file in the
* distribution for a full listing of individual contributors.
*
* This is free software; you can redistribute it and/or modify it
* under the terms of the GNU Lesser General Public License as
* published by the Free Software Foundation; either version 2.1 of
* the License, or (at your option) any later version.
*
* This software is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public
* License along with this software; if not, write to the Free
* Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA
* 02110-1301 USA, or see the FSF site: http://www.fsf.org.
*/

package org.jboss.as.domain.management.security.adduser;

import static org.junit.Assert.*;

import org.aesh.readline.terminal.Key;
import org.aesh.readline.tty.terminal.TerminalConnection;
import org.junit.Test;

import java.io.ByteArrayOutputStream;
import java.io.IOException;
import java.io.PipedInputStream;
import java.io.PipedOutputStream;
import java.nio.charset.Charset;

/**
* Created by Marek Marusic <mmarusic@redhat.com> on 8/9/17.
*/
public class AeshJavaConsoleTest {

@Test
public void testLeftArrow() throws IOException, InterruptedException {
AeshJavaConsoleTestResource aeshJavaConsoleTestResource = new AeshJavaConsoleTestResource();
aeshJavaConsoleTestResource.start();
Thread.sleep(100);

aeshJavaConsoleTestResource.write("Foo");
aeshJavaConsoleTestResource.write(Key.LEFT);
aeshJavaConsoleTestResource.write("F");
aeshJavaConsoleTestResource.write(Key.ENTER);
aeshJavaConsoleTestResource.flushWrites();

Thread.sleep(100);
assertEquals("FoFo", aeshJavaConsoleTestResource.getLine());
}

@Test
public void testUpArrow() throws IOException, InterruptedException {
AeshJavaConsoleTestResource aeshJavaConsoleTestResource = new AeshJavaConsoleTestResource();
aeshJavaConsoleTestResource.start();
Thread.sleep(100);

aeshJavaConsoleTestResource.write("Foo");
aeshJavaConsoleTestResource.write(Key.UP);
aeshJavaConsoleTestResource.write("F");
aeshJavaConsoleTestResource.write(Key.ENTER);
aeshJavaConsoleTestResource.flushWrites();

Thread.sleep(100);
assertEquals("FooF", aeshJavaConsoleTestResource.getLine());
}

@Test
public void testInterruptionSignal() throws IOException, InterruptedException {
AeshJavaConsoleTestResource aeshJavaConsoleTestResource = new AeshJavaConsoleTestResource();
aeshJavaConsoleTestResource.start();
Thread.sleep(100);

aeshJavaConsoleTestResource.write("Foo".getBytes());
aeshJavaConsoleTestResource.write(Key.CTRL_C.getKeyValuesAsString().getBytes());
aeshJavaConsoleTestResource.flushWrites();

Thread.sleep(100);
assertEquals(false, aeshJavaConsoleTestResource.isAlive());
assertEquals(Thread.State.TERMINATED, aeshJavaConsoleTestResource.getState());
}

private static class AeshJavaConsoleTestResource extends Thread {
private PipedOutputStream pipedOutputStream;
private PipedInputStream pipedInputStream;
private ByteArrayOutputStream out;
private String line;

public AeshJavaConsoleTestResource() throws IOException {
pipedOutputStream = new PipedOutputStream();
pipedInputStream = new PipedInputStream(pipedOutputStream);
out = new ByteArrayOutputStream();
}

public String getLine() {
return line;
}

public void flushWrites() throws IOException {
pipedOutputStream.flush();
}

public void write(String data) throws IOException {
write(data.getBytes());
}

public void write(byte[] data) throws IOException {
pipedOutputStream.write(data);
}

public void write(Key key) throws IOException {
write(key.getKeyValuesAsString().getBytes());
}

public void run() {
// Create JavaConsole with custom input, output streams for testing
JavaConsole javaConsole = new JavaConsole() {
@Override
protected void createTerminalConnection(ReadLineHandler readLineHandler) throws IOException {
new TerminalConnection(Charset.defaultCharset(), pipedInputStream, out, readLineHandler);
}
};

line = javaConsole.readLine("");
}
}

}

0 comments on commit dd16837

Please sign in to comment.