Skip to content

Commit

Permalink
Parser - just a quick cleanup and nicer NPE message
Browse files Browse the repository at this point in the history
  • Loading branch information
dmatej committed Apr 13, 2022
1 parent 85e5290 commit 559f4ba
Showing 1 changed file with 72 additions and 38 deletions.
Original file line number Diff line number Diff line change
@@ -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
Expand All @@ -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);

Expand Down Expand Up @@ -69,28 +79,32 @@ public Parser(String[] args, int start, Collection<ParamModel> options, boolean
* @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;
}

Expand All @@ -108,17 +122,19 @@ private void parseCommandLine(final String[] argv, final int start) throws Comma
}
// 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:
Expand All @@ -139,19 +155,21 @@ private void parseCommandLine(final String[] argv, final int start) throws Comma
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;
Expand All @@ -164,8 +182,9 @@ private void parseCommandLine(final String[] argv, final int start) throws Comma

// 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;
Expand All @@ -176,13 +195,16 @@ private void parseCommandLine(final String[] argv, final int start) throws Comma
// 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) {
/*
Expand Down Expand Up @@ -222,6 +244,7 @@ public List<String> getOperands() {
return operands;
}

@Override
public String toString() {
return "CLI parser: Options = " + optionsMap + "; Operands = " + operands;
}
Expand All @@ -230,20 +253,24 @@ public String toString() {
* 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;
}
Expand All @@ -253,12 +280,14 @@ private ParamModel lookupLongOption(String s) {
*/
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;
}
Expand All @@ -275,10 +304,12 @@ private static boolean optionRequiresOperand(ParamModel opt) {
*/
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) {
Expand All @@ -292,21 +323,24 @@ private void setOption(ParamModel opt, String value) throws CommandValidationExc
} 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
Expand Down

0 comments on commit 559f4ba

Please sign in to comment.