diff --git a/src/main/java/org/semux/gui/dialog/ConsoleDialog.java b/src/main/java/org/semux/gui/dialog/ConsoleDialog.java index 27c67d835..45fd687c9 100644 --- a/src/main/java/org/semux/gui/dialog/ConsoleDialog.java +++ b/src/main/java/org/semux/gui/dialog/ConsoleDialog.java @@ -43,6 +43,7 @@ import com.fasterxml.jackson.databind.SerializationFeature; import io.swagger.annotations.ApiOperation; +import org.semux.util.CommandParser; public class ConsoleDialog extends JDialog implements ActionListener { @@ -156,8 +157,9 @@ public void actionPerformed(ActionEvent e) { * @param input */ protected String callApi(String input) { - String[] commandArguments = input.split(" "); - String command = commandArguments[0]; + List commandArguments = CommandParser.parseInput(input); + + String command = commandArguments.get(0); MethodDescriptor md = methods.get(command); if (md == null) { @@ -168,19 +170,19 @@ protected String callApi(String input) { Method method = api.getClass().getMethod(command, md.argumentTypes); Object[] arguments = new Object[md.argumentTypes.length]; - if (arguments.length < commandArguments.length - 1) { + if (arguments.length < commandArguments.size() - 1) { return GuiMessages.get("MethodError", command); } - for (int i = 0; i < commandArguments.length - 1; i++) { - String argument = commandArguments[i + 1]; + for (int i = 0; i < commandArguments.size() - 1; i++) { + String argument = commandArguments.get(i + 1); if (md.argumentTypes[i] == Boolean.class) { arguments[i] = Boolean.parseBoolean(argument); } else { if (NULL.equals(argument)) { arguments[i] = null; } else { - arguments[i] = commandArguments[i + 1]; + arguments[i] = commandArguments.get(i + 1); } } } diff --git a/src/main/java/org/semux/util/CommandParser.java b/src/main/java/org/semux/util/CommandParser.java new file mode 100644 index 000000000..4bb5c26e3 --- /dev/null +++ b/src/main/java/org/semux/util/CommandParser.java @@ -0,0 +1,32 @@ +/** + * Copyright (c) 2017-2018 The Semux Developers + * + * Distributed under the MIT software license, see the accompanying file + * LICENSE or https://opensource.org/licenses/mit-license.php + */ +package org.semux.util; + +import java.util.ArrayList; +import java.util.List; +import java.util.regex.Matcher; +import java.util.regex.Pattern; + +public class CommandParser { + + public static List parseInput(String input) { + List commandArguments = new ArrayList<>(); + Pattern ptrn = Pattern.compile("\"[^\"\\\\]*(?:\\\\.[^\"\\\\]*)*\"|\\S+"); + Matcher matcher = ptrn.matcher(input); + while (matcher.find()) { + commandArguments.add(sanitize(matcher.group(0))); + } + return commandArguments; + } + + private static String sanitize(String value) { + if (value.startsWith("\"") && value.endsWith("\"")) { + value = value.substring(1, value.length() - 1); + } + return value.replace("\\\"", "\""); + } +} diff --git a/src/test/java/org/semux/gui/dialog/ConsoleDialogTest.java b/src/test/java/org/semux/gui/dialog/ConsoleDialogTest.java index cd7a30404..bb50ea047 100644 --- a/src/test/java/org/semux/gui/dialog/ConsoleDialogTest.java +++ b/src/test/java/org/semux/gui/dialog/ConsoleDialogTest.java @@ -14,6 +14,8 @@ import java.util.Arrays; import java.util.Collections; import java.util.List; +import java.util.regex.Matcher; +import java.util.regex.Pattern; import org.assertj.swing.edt.GuiActionRunner; import org.assertj.swing.fixture.DialogFixture; @@ -72,7 +74,7 @@ public void testBasicUse() throws InterruptedException { when(blockChain.getBlock(anyLong())).thenReturn(block); kernelRule1.getKernel().setBlockchain(blockChain); - console.textBox("txtInput").enterText("getBlockByNumber 1\n"); + console.textBox("txtInput").enterText("getBlockByNumber \"1\"\n"); await().until(() -> consoleText.text().contains("transactionsRoot")); } diff --git a/src/test/java/org/semux/util/CommandParserTest.java b/src/test/java/org/semux/util/CommandParserTest.java new file mode 100644 index 000000000..e173d5af4 --- /dev/null +++ b/src/test/java/org/semux/util/CommandParserTest.java @@ -0,0 +1,38 @@ +/** + * Copyright (c) 2017-2018 The Semux Developers + * + * Distributed under the MIT software license, see the accompanying file + * LICENSE or https://opensource.org/licenses/mit-license.php + */ +package org.semux.util; + +import org.junit.Assert; +import org.junit.Test; + +import java.util.List; + +public class CommandParserTest { + + @Test + public void testDelimiting() { + String input = "foo and \"bar stuff\" \"stuff \\\" with quotes \\\" \" more \"\""; + List parsed = CommandParser.parseInput(input); + + Assert.assertEquals(6, parsed.size()); + Assert.assertEquals("foo", parsed.get(0)); + Assert.assertEquals("and", parsed.get(1)); + Assert.assertEquals("bar stuff", parsed.get(2)); + Assert.assertEquals("stuff \" with quotes \" ", parsed.get(3)); + Assert.assertEquals("more", parsed.get(4)); + Assert.assertEquals("", parsed.get(5)); + } + + @Test + public void testBasic() { + String input = "getBlockByNumber 1"; + List parsed = CommandParser.parseInput(input); + Assert.assertEquals(2, parsed.size()); + Assert.assertEquals("getBlockByNumber", parsed.get(0)); + Assert.assertEquals("1", parsed.get(1)); + } +}