From a931f0d74877548a9a156ef6fb8039456a4d35f0 Mon Sep 17 00:00:00 2001 From: "Christian P. MOMON" Date: Fri, 12 May 2017 10:39:49 +0200 Subject: [PATCH] Refactored split command action. --- src/fr/devinsy/util/cmdexec/CmdExec.java | 24 ++- src/fr/devinsy/util/cmdexec/CmdExecUtils.java | 3 +- .../util/cmdexec/util/CommandSplitter.java | 181 ++++++++++++++++++ .../cmdexec/util/CommandSplitterTest.java | 74 +++++++ 4 files changed, 277 insertions(+), 5 deletions(-) create mode 100644 src/fr/devinsy/util/cmdexec/util/CommandSplitter.java create mode 100644 test/fr/devinsy/util/cmdexec/util/CommandSplitterTest.java diff --git a/src/fr/devinsy/util/cmdexec/CmdExec.java b/src/fr/devinsy/util/cmdexec/CmdExec.java index 7742739..669c0ea 100644 --- a/src/fr/devinsy/util/cmdexec/CmdExec.java +++ b/src/fr/devinsy/util/cmdexec/CmdExec.java @@ -18,12 +18,11 @@ */ package fr.devinsy.util.cmdexec; -import java.util.ArrayList; - import org.slf4j.Logger; import org.slf4j.LoggerFactory; import fr.devinsy.util.cmdexec.StreamGobbler.StreamWay; +import fr.devinsy.util.cmdexec.util.CommandSplitter; import fr.devinsy.util.strings.StringListUtils; /** @@ -128,6 +127,22 @@ public class CmdExec // // //////////////////////////////////////////////////////////////////// + /** + * Gets the command. + * + * @return the command + */ + public String getCommand() + { + String result; + + // TODO + result = null; + + // + return result; + } + /** * Gets the err stream. * @@ -190,7 +205,7 @@ public class CmdExec logger.info("CmdExec(command) = [" + command + "]"); - String[] commands = command.split("[ \t\n\r\f]"); + String[] commands = CommandSplitter.split(command); result = run(commands, outputGobbler, errorGobbler); @@ -304,4 +319,5 @@ public class CmdExec // return result; } -} + +} \ No newline at end of file diff --git a/src/fr/devinsy/util/cmdexec/CmdExecUtils.java b/src/fr/devinsy/util/cmdexec/CmdExecUtils.java index 16509a5..b09a53e 100644 --- a/src/fr/devinsy/util/cmdexec/CmdExecUtils.java +++ b/src/fr/devinsy/util/cmdexec/CmdExecUtils.java @@ -23,6 +23,7 @@ import java.util.ArrayList; import org.slf4j.Logger; import org.slf4j.LoggerFactory; +import fr.devinsy.util.cmdexec.util.CommandSplitter; import fr.devinsy.util.strings.StringListUtils; /** @@ -115,7 +116,7 @@ public class CmdExecUtils { String result; - result = CmdExecUtils.run(command.split("[ \t\n\r\f]")); + result = CmdExecUtils.run(CommandSplitter.split(command)); // return result; diff --git a/src/fr/devinsy/util/cmdexec/util/CommandSplitter.java b/src/fr/devinsy/util/cmdexec/util/CommandSplitter.java new file mode 100644 index 0000000..0704972 --- /dev/null +++ b/src/fr/devinsy/util/cmdexec/util/CommandSplitter.java @@ -0,0 +1,181 @@ +/* + * Copyright (C) 2005-2010,2013,2015-2017 Christian Pierre MOMON + * + * This file is part of Devinsy-cmdexec. + * + * Devinsy-cmdexec 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 3 of the License, or + * (at your option) any later version. + * + * Devinsy-cmdexec 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 Devinsy-cmdexec. If not, see + */ +package fr.devinsy.util.cmdexec.util; + +import org.apache.commons.lang3.StringUtils; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + +import fr.devinsy.util.strings.StringList; + +/** + * The Class SplitWorker. + * + * @author Christian Pierre MOMON (christian.momon@devinsy.fr) + */ +public class CommandSplitter +{ + public enum State + { + MAIN, + SIMPLE_QUOTE, + QUOTE, + ENDED + } + + private static Logger logger = LoggerFactory.getLogger(CommandSplitter.class);; + + /** + * Split a string command to an array managing quote and simple quote. + * + * @param command + * the command + * @return the string[] + */ + public static String[] split(final String command) + { + String[] result; + + if (command == null) + { + result = null; + } + else + { + boolean ended = false; + State state = State.MAIN; + StringList tokens = new StringList(); + StringBuilder tokenBuffer = new StringBuilder(); + int letterIndex = 0; + while (!ended) + { + if (letterIndex < command.length()) + { + char letter = command.charAt(letterIndex); + + switch (state) + { + case MAIN: + switch (letter) + { + case ' ': + { + // + String token = tokenBuffer.toString(); + if (!StringUtils.isBlank(token)) + { + tokens.add(token); + } + + // + state = State.MAIN; + tokenBuffer = new StringBuilder(); + } + break; + + case '"': + { + // + state = State.QUOTE; + } + break; + + case '\'': + { + // + state = State.SIMPLE_QUOTE; + } + break; + + default: + { + tokenBuffer.append(letter); + } + } + break; + + case QUOTE: + switch (letter) + { + case '\"': + { + String token = tokenBuffer.toString(); + tokens.add(token); + + state = State.MAIN; + tokenBuffer = new StringBuilder(); + } + break; + + default: + { + tokenBuffer.append(letter); + } + } + break; + + case SIMPLE_QUOTE: + switch (letter) + { + case '\'': + { + String token = tokenBuffer.toString(); + tokens.add(token); + + state = State.MAIN; + tokenBuffer = new StringBuilder(); + } + break; + + default: + { + tokenBuffer.append(letter); + } + } + break; + } + + // + letterIndex += 1; + } + else + { + // + ended = true; + + // + String token = tokenBuffer.toString(); + if (!StringUtils.isBlank(token)) + { + tokens.add(token); + } + + // + state = State.ENDED; + } + } + + // + result = tokens.toStringArray(); + } + + // + return result; + } +} diff --git a/test/fr/devinsy/util/cmdexec/util/CommandSplitterTest.java b/test/fr/devinsy/util/cmdexec/util/CommandSplitterTest.java new file mode 100644 index 0000000..6128d1f --- /dev/null +++ b/test/fr/devinsy/util/cmdexec/util/CommandSplitterTest.java @@ -0,0 +1,74 @@ +/* + * Copyright (C) 2017 Christian Pierre MOMON + * + * This file is part of Devinsy-cmdexec. + * + * Devinsy-cmdexec 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 3 of the License, or + * (at your option) any later version. + * + * Devinsy-cmdexec 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 Devinsy-cmdexec. If not, see + */ +package fr.devinsy.util.cmdexec.util; + +import org.apache.log4j.BasicConfigurator; +import org.apache.log4j.Level; +import org.junit.After; +import org.junit.Before; +import org.junit.Test; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + +import fr.devinsy.util.strings.StringList; + +/** + * The Class SplitWorkerTest. + * + * @author Christian Pierre MOMON (christian.momon@devinsy.fr) + */ +public class CommandSplitterTest +{ + private static Logger logger = LoggerFactory.getLogger(CommandSplitterTest.class); + + /** + * After. + */ + @After + public void after() + { + } + + /** + * Before. + */ + @Before + public void before() + { + BasicConfigurator.configure(); + org.apache.log4j.Logger.getRootLogger().setLevel(Level.INFO); + } + + /** + * Test 01. + */ + @Test + public void testt01() + { + // + this.logger.debug("===== test starting..."); + + String[] tokens = CommandSplitter.split("bash -c \"to't o\" lala 'ti\" t i' lulu"); + + logger.info(new StringList(tokens).toStringWithBrackets()); + + // + logger.debug("===== test done."); + } +}