Parser - just a quick cleanup and nicer NPE message
diff --git a/nucleus/admin/cli/src/main/java/com/sun/enterprise/admin/cli/Parser.java b/nucleus/admin/cli/src/main/java/com/sun/enterprise/admin/cli/Parser.java index 69f6138..4b05048 100644 --- a/nucleus/admin/cli/src/main/java/com/sun/enterprise/admin/cli/Parser.java +++ b/nucleus/admin/cli/src/main/java/com/sun/enterprise/admin/cli/Parser.java
@@ -1,4 +1,5 @@ /* + * Copyright (c) 2022 Contributors to the Eclipse Foundation * Copyright (c) 1997, 2018 Oracle and/or its affiliates. All rights reserved. * * This program and the accompanying materials are made available under the @@ -16,29 +17,38 @@ package com.sun.enterprise.admin.cli; -import java.io.*; -import java.util.*; -import org.glassfish.api.admin.*; -import org.glassfish.api.admin.CommandModel.ParamModel; -import com.sun.enterprise.admin.util.*; import com.sun.enterprise.admin.util.CommandModelData.ParamModelData; import com.sun.enterprise.universal.i18n.LocalStringsImpl; +import java.io.File; +import java.io.FileInputStream; +import java.io.IOException; +import java.io.InputStream; +import java.util.ArrayList; +import java.util.Collection; +import java.util.List; +import java.util.Locale; +import java.util.Objects; + +import org.glassfish.api.admin.CommandModel.ParamModel; +import org.glassfish.api.admin.CommandValidationException; +import org.glassfish.api.admin.ParameterMap; + /** * The <code>Parser</code> object is used to parse the command line and verify that the command line is CLIP compliant. */ public class Parser { // MultiMap of options and values from command-line - private ParameterMap optionsMap = new ParameterMap(); + private final ParameterMap optionsMap = new ParameterMap(); // Array of operands from command-line - private List<String> operands = new ArrayList<String>(); + private final List<String> operands = new ArrayList<>(); // The valid options for the command we're parsing - private Collection<ParamModel> options; + private final Collection<ParamModel> options; // Ignore unknown options when parsing? - private boolean ignoreUnknown; + private final boolean ignoreUnknown; private static final LocalStringsImpl strings = new LocalStringsImpl(Parser.class); @@ -69,28 +79,32 @@ * @throws CommandValidationException if command line is invalid */ private void parseCommandLine(final String[] argv, final int start) throws CommandValidationException { - + Objects.requireNonNull(argv, "parseCommandLine doesn't accept null as argv"); for (int si = start; si < argv.length; si++) { String arg = argv[si]; if (arg.equals("--")) { // end of options // if we're ignoring unknown options, we include this // delimiter as an operand, it will be eliminated later // when we process all remaining options - if (!ignoreUnknown) + if (!ignoreUnknown) { si++; - while (si < argv.length) + } + while (si < argv.length) { operands.add(argv[si++]); + } break; } // is it an operand or option value? if (!arg.startsWith("-") || arg.length() <= 1) { operands.add(arg); - if (ignoreUnknown) + if (ignoreUnknown) { continue; + } si++; - while (si < argv.length) + while (si < argv.length) { operands.add(argv[si++]); + } break; } @@ -108,17 +122,19 @@ } // if of the form "--option=value", extract value int ne = arg.indexOf('='); - if (ne < 0) + if (ne < 0) { name = arg.substring(ns); - else { - if (value != null) + } else { + if (value != null) { throw new CommandValidationException(strings.get("parser.noValueAllowed", arg)); + } name = arg.substring(ns, ne); value = arg.substring(ne + 1); } opt = lookupLongOption(name); - if (sawno && optionRequiresOperand(opt)) + if (sawno && optionRequiresOperand(opt)) { throw new CommandValidationException(strings.get("parser.illegalNo", opt.getName())); + } } else { // short option /* * possibilities are: @@ -139,19 +155,21 @@ for (int i = 1; i < arg.length(); i++) { opt = lookupShortOption(arg.charAt(i)); if (opt == null) { - if (!ignoreUnknown) + if (!ignoreUnknown) { throw new CommandValidationException( strings.get("parser.invalidOption", Character.toString(arg.charAt(i)))); + } // unknown option, skip all the rest operands.add(arg); break; } - if (opt.getType() == Boolean.class || opt.getType() == boolean.class) + if (opt.getType() == Boolean.class || opt.getType() == boolean.class) { setOption(opt, "true"); - else { - if (!ignoreUnknown) + } else { + if (!ignoreUnknown) { throw new CommandValidationException( strings.get("parser.nonbooleanNotAllowed", Character.toString(arg.charAt(i)), arg)); + } // unknown option, skip all the rest operands.add(arg); break; @@ -164,8 +182,9 @@ // is it a known option? if (opt == null) { - if (!ignoreUnknown) + if (!ignoreUnknown) { throw new CommandValidationException(strings.get("parser.invalidOption", arg)); + } // unknown option, skip it operands.add(arg); continue; @@ -176,13 +195,16 @@ // if no valid options were specified, we use the next argument // as an option as long as it doesn't look like an option if (options == null) { - if (si + 1 < argv.length && !argv[si + 1].startsWith("-")) + if (si + 1 < argv.length && !argv[si + 1].startsWith("-")) { value = argv[++si]; - else + } + else { ((ParamModelData) opt).type = Boolean.class; // fake it + } } else if (optionRequiresOperand(opt)) { - if (++si >= argv.length) + if (++si >= argv.length) { throw new CommandValidationException(strings.get("parser.missingValue", name)); + } value = argv[si]; } else if (opt.getType() == Boolean.class || opt.getType() == boolean.class) { /* @@ -222,6 +244,7 @@ return operands; } + @Override public String toString() { return "CLI parser: Options = " + optionsMap + "; Operands = " + operands; } @@ -230,20 +253,24 @@ * Get ParamModel for long option name. */ private ParamModel lookupLongOption(String s) { - if (s == null || s.length() == 0) + if (s == null || s.length() == 0) { return null; + } // XXX - for now, fake it if no options if (options == null) { // no valid options specified so everything is valid return new ParamModelData(s, String.class, true, null); } for (ParamModel od : options) { - if (od.getParam().primary()) + if (od.getParam().primary()) { continue; - if (s.equalsIgnoreCase(od.getName())) + } + if (s.equalsIgnoreCase(od.getName())) { return od; - if (s.equalsIgnoreCase(od.getParam().alias())) + } + if (s.equalsIgnoreCase(od.getParam().alias())) { return od; + } } return null; } @@ -253,12 +280,14 @@ */ private ParamModel lookupShortOption(char c) { // XXX - for now, fake it if no options - if (options == null) + if (options == null) { return null; + } String sc = Character.toString(c); for (ParamModel od : options) { - if (od.getParam().shortName().equals(sc)) + if (od.getParam().shortName().equals(sc)) { return od; + } } return null; } @@ -275,10 +304,12 @@ */ private void setOption(ParamModel opt, String value) throws CommandValidationException { // VERY basic validation - if (opt == null) + if (opt == null) { throw new NullPointerException("null option name"); - if (value != null) + } + if (value != null) { value = value.trim(); + } String name = opt.getName(); if (opt.getType() == File.class) { @@ -292,21 +323,24 @@ } catch (IOException ioex) { throw new CommandValidationException(strings.get("parser.invalidFileEx", name, ioex.toString())); } finally { - if (is != null) + if (is != null) { try { is.close(); } catch (IOException cex) { } + } } throw new CommandValidationException(strings.get("parser.invalidFile", name, value)); } } else if (opt.getType() == Boolean.class || opt.getType() == boolean.class) { - if (value == null) + if (value == null) { value = "true"; - else if (!(value.toLowerCase(Locale.ENGLISH).equals("true") || value.toLowerCase(Locale.ENGLISH).equals("false"))) + } else if (!(value.toLowerCase(Locale.ENGLISH).equals("true") || value.toLowerCase(Locale.ENGLISH).equals("false"))) { throw new CommandValidationException(strings.get("parser.invalidBoolean", name, value)); - } else if (opt.getParam().password()) + } + } else if (opt.getParam().password()) { throw new CommandValidationException(strings.get("parser.passwordNotAllowed", opt.getName())); + } if (!opt.getParam().multiple()) { // repeats not allowed