Martin Peřina has uploaded a new change for review. Change subject: core: Adds cli parsers with POSIX and GNU long args ......................................................................
core: Adds cli parsers with POSIX and GNU long args Adds command line arguments parser that supports parsing POSIX and GNU long arguments. Change-Id: If0dd854826433b577b902eaba6b4fcd8967d1199 Bug-Url: https://bugzilla.redhat.com/904029 Signed-off-by: Martin Perina <mper...@redhat.com> --- A backend/manager/modules/utils/src/main/java/org/ovirt/engine/core/utils/cli/ExtendedCliParser.java A backend/manager/modules/utils/src/test/java/org/ovirt/engine/core/utils/cli/ExtendedCliParserTest.java 2 files changed, 332 insertions(+), 0 deletions(-) git pull ssh://gerrit.ovirt.org:29418/ovirt-engine refs/changes/28/19128/1 diff --git a/backend/manager/modules/utils/src/main/java/org/ovirt/engine/core/utils/cli/ExtendedCliParser.java b/backend/manager/modules/utils/src/main/java/org/ovirt/engine/core/utils/cli/ExtendedCliParser.java new file mode 100644 index 0000000..c89dff1 --- /dev/null +++ b/backend/manager/modules/utils/src/main/java/org/ovirt/engine/core/utils/cli/ExtendedCliParser.java @@ -0,0 +1,157 @@ +package org.ovirt.engine.core.utils.cli; + +import java.util.HashMap; +import java.util.Map; + + +/** + * Implements argument parser, that supports parsing POSIX and GNU long arguments + */ +public class ExtendedCliParser { + /** + * POSIX argument prefix + */ + private static final String PREFIX_POSIX = "-"; + + /** + * GNU long argument prefix + */ + private static final String PREFIX_GNU_LONG = "--"; + + /** + * POSIX argument value separator + */ + private static final String POSIX_VALUE_SEP = " "; + + /** + * GNU long argument value separator + */ + private static final String GNU_LONG_VALUE_SEP = "="; + + /** + * {@inheritDoc} + */ + public Map<String, String> parse(String[] args) { + Map<String, String> argMap = new HashMap<>(); + // parse arguments + for (int i = 0; i < args.length;) { + if (args[i] == null) { + // just to be sure + i++; + continue; + } + + String name = null; + String value = null; + + if (isGnuLongArg(args[i])) { + // parse GNU long argument + name = parseGnuLongArgName(args[i]); + value = parseGnuLongArgValue(args[i]); + } else if (isPosixArg(args[i])) { + // parse POSIX argument + name = args[i]; + if (i + 1 < args.length) { + if (!isPosixArg(args[i + 1]) && !isGnuLongArg(args[i + 1])) { + // argument has a value + value = args[i + 1]; + i++; + } + } + } else { + // invalid argument format + throw new IllegalArgumentException(args[i]); + } + + argMap.put(name, value); + i++; + } + return argMap; + } + + /** + * Tests if specified argument contains valid POSIX argument name + * + * @param arg + * argument + * @return {@code true} if string contains valid POSIX argument, otherwise {@code false} + */ + private boolean isPosixArg(String arg) { + boolean result = true; + if (arg == null || arg.length() != 2) { + result = false; + } else if (!arg.startsWith(PREFIX_POSIX)) { + result = false; + } else if (!Character.isLetterOrDigit(arg.charAt(1))) { + result = false; + } + return result; + } + + /** + * Tests if specified argument contains valid GNU long argument name. + * + * @param arg + * argument + * @param value + * {@code true} if argument may contain value, otherwise {@code false} + * @return {@code true} if string contains valid GNU long argument, otherwise {@code false} + */ + private boolean isGnuLongArg(String arg) { + boolean result = true; + if (arg == null || arg.length() < 3) { + result = false; + } else if (!arg.startsWith(PREFIX_GNU_LONG)) { + result = false; + } else { + for (int i = 2; i < arg.length(); i++) { + if (i > 2 && i + 2 < arg.length() && GNU_LONG_VALUE_SEP.equals(arg.substring(i, i + 1))) { + // argument contains value + break; + } + char c = arg.charAt(i); + if (!Character.isLetterOrDigit(c) && c != '-') { + result = false; + break; + } + } + } + return result; + } + + /** + * Parses name of GNU long argument from specified string. Method DOES NOT validate argument, it just creates + * substring from start to value separator (or to the end if separator is not present) + * + * @param str + * specified string + * @returns GNU long argument name + */ + private String parseGnuLongArgName(String str) { + int idx = str.indexOf(GNU_LONG_VALUE_SEP); + if (idx == -1) { + // argument does not contain value + return str; + } else { + return str.substring(0, idx); + } + } + + /** + * Parses value of GNU long argument from specified string. Method DOES NOT validate argument, it just creates + * substring value separator to the end or returns {@code null} if value separator is not present + * + * @param str + * specified string + * @returns GNU long argument value or {@code null} + */ + private String parseGnuLongArgValue(String str) { + int idx = str.indexOf(GNU_LONG_VALUE_SEP); + if (idx == -1) { + // arg does not contain value + return null; + } else { + return str.substring(idx + 1); + } + } +} diff --git a/backend/manager/modules/utils/src/test/java/org/ovirt/engine/core/utils/cli/ExtendedCliParserTest.java b/backend/manager/modules/utils/src/test/java/org/ovirt/engine/core/utils/cli/ExtendedCliParserTest.java new file mode 100644 index 0000000..b0f515a --- /dev/null +++ b/backend/manager/modules/utils/src/test/java/org/ovirt/engine/core/utils/cli/ExtendedCliParserTest.java @@ -0,0 +1,175 @@ +package org.ovirt.engine.core.utils.cli; + +import static org.junit.Assert.assertEquals; +import static org.junit.Assert.assertFalse; +import static org.junit.Assert.assertNotNull; +import static org.junit.Assert.assertNull; +import static org.junit.Assert.assertTrue; +import static org.junit.Assert.fail; + +import java.util.Map; + +import org.junit.Test; +import org.junit.runner.RunWith; +import org.junit.runners.JUnit4; + +/** + * Parsing POSIX and GNU long arguments with {@code ExtendedCliParser} tests + */ +@RunWith(JUnit4.class) +public class ExtendedCliParserTest { + /** + * Tests parsing empty arguments + */ + @Test + public void emptyArgs() { + Map<String, String> results; + ExtendedCliParser parser = new ExtendedCliParser(); + + final String[] args = {}; + + results = parser.parse(args); + + assertNotNull(results); + assertTrue(results.isEmpty()); + } + + /** + * Tests parsing POSIX argument without value + */ + @Test + public void posixArgWithoutValue() { + Map<String, String> results; + ExtendedCliParser parser = new ExtendedCliParser(); + String argName = "-h"; + + final String[] args = { argName }; + + results = parser.parse(args); + + assertNotNull(results); + assertFalse(results.isEmpty()); + + assertTrue(results.containsKey(argName)); + assertNull(results.get(argName)); + } + + /** + * Tests parsing POSIX argument with value + */ + @Test + public void posixArgWithValue() { + Map<String, String> results; + ExtendedCliParser parser = new ExtendedCliParser(); + String argName = "-f"; + String argValue = "/tmp/xxx.txt"; + + final String[] args = { argName, argValue }; + + results = parser.parse(args); + + assertNotNull(results); + assertFalse(results.isEmpty()); + + assertTrue(results.containsKey(argName)); + assertEquals(argValue, results.get(argName)); + } + + /** + * Tests parsing GNU long argument without value + */ + @Test + public void gnuLongArWithoutValue() { + Map<String, String> results; + ExtendedCliParser parser = new ExtendedCliParser(); + String argName = "--help"; + + final String[] args = { argName }; + + results = parser.parse(args); + + assertNotNull(results); + assertFalse(results.isEmpty()); + + assertTrue(results.containsKey(argName)); + assertNull(results.get(argName)); + } + + /** + * Tests parsing GNU long argument with value + */ + @Test + public void gnuLongArgWithValue() { + Map<String, String> results; + ExtendedCliParser parser = new ExtendedCliParser(); + String argName = "--file"; + String argValue = "/tmp/xxx.txt"; + + final String[] args = { argName + "=" + argValue }; + + results = parser.parse(args); + + assertNotNull(results); + assertFalse(results.isEmpty()); + + assertTrue(results.containsKey(argName)); + assertEquals(argValue, results.get(argName)); + } + + /** + * Tests parsing POSIX argument with value delimited by GNU long argument value separator + */ + @Test(expected = IllegalArgumentException.class) + public void posixArgWithGnuValueSep() { + ExtendedCliParser parser = new ExtendedCliParser(); + String argName = "-f"; + String argValue = "/tmp/xxx.txt"; + + final String[] args = { argName + "=" + argValue }; + + parser.parse(args); + } + + /** + * Tests parsing GNU long argument with value delimited by POSIX argument value separator + */ + @Test(expected = IllegalArgumentException.class) + public void gnuLongArgWithPosixValueSep() { + ExtendedCliParser parser = new ExtendedCliParser(); + String argName = "--file"; + String argValue = "/tmp/xxx.txt"; + + final String[] args = { argName, argValue }; + + parser.parse(args); + } + + /** + * Tries to parse argument with specified invalid name + * + * @param name + * invalid argument name + */ + protected void invalidArgName(String name) { + try { + ExtendedCliParser parser = new ExtendedCliParser(); + parser.parse(new String[] {name}); + fail("IllegalArgumentException expected for '" + name + "' argument!"); + } catch (IllegalArgumentException ex) { + } + } + + /** + * Tests arguments with invalid names + */ + @Test + public void invalidArgName() { + invalidArgName("\t "); + invalidArgName("A"); + invalidArgName("- "); + invalidArgName("-test"); + invalidArgName("--"); + invalidArgName("--?"); + invalidArgName("--force="); + } +} -- To view, visit http://gerrit.ovirt.org/19128 To unsubscribe, visit http://gerrit.ovirt.org/settings Gerrit-MessageType: newchange Gerrit-Change-Id: If0dd854826433b577b902eaba6b4fcd8967d1199 Gerrit-PatchSet: 1 Gerrit-Project: ovirt-engine Gerrit-Branch: master Gerrit-Owner: Martin Peřina <mper...@redhat.com> _______________________________________________ Engine-patches mailing list Engine-patches@ovirt.org http://lists.ovirt.org/mailman/listinfo/engine-patches