com.linkedin.harisekhon.Utils.java Source code

Java tutorial

Introduction

Here is the source code for com.linkedin.harisekhon.Utils.java

Source

//
//  Author: Hari Sekhon
//  Date: 2015-05-30 12:53:28 +0100 (Sat, 30 May 2015)
//
//  vim:ts=4:sts=4:sw=4:et
//
//  https://github.com/harisekhon/lib-java
//
//  License: see accompanying Hari Sekhon LICENSE file
//
//  If you're using my code you're welcome to connect with me on LinkedIn and optionally send me feedback
//  to help improve or steer this or other code I publish
//
//  https://www.linkedin.com/in/harisekhon
//

// Port of my personal libraries from other languages I've been using for several years

// my linkedin account is unique and will outlast my personal domains
package com.linkedin.harisekhon;

import org.apache.commons.lang.StringUtils;
//import org.apache.log4j.Level;
import org.apache.log4j.Logger;

import java.io.*;
import java.net.InetAddress;
import java.net.UnknownHostException;
import java.util.*;
import java.util.regex.Matcher;
import java.util.regex.Pattern;
import java.util.regex.PatternSyntaxException;

import static java.lang.Math.pow;

// Stuff to still be ported:
// TODO: autoflush
// TODO: env support
// TODO: threshold range support
// TODO: cmd
// TODO: curl and curl_json
// TODO: get_field
// TODO: get_path_owner
// TODO: go_flock_yourself / flock_off

// TODO: if progname check_* stderr to stdout and trap exit codes to 2

// Methods should not allow unhandled Exceptions since we want to catch and provide concise one liner errors

public final class Utils {

    private static final String utils_version = "1.17.2";

    public static String msg = "";
    public static final String nagios_plugins_support_msg = "Please try latest version from https://github.com/harisekhon/nagios-plugins, re-run on command line with -vvv and if problem persists paste full output from -vvv mode in to a ticket requesting a fix/update at https://github.com/harisekhon/nagios-plugins/issues/new";
    public static final String option_format_calling_method = "%-50s %-25s %s";
    public static final String option_format = "%-25s %s";
    public static final String nagios_plugins_support_msg_api = "API may have changed. "
            + nagios_plugins_support_msg;

    private static final HashMap<String, Integer> exit_codes = new HashMap<String, Integer>();
    private static String status = "UNKNOWN";

    // keeping this lowercase to make it easier to do String.toLowerCase() case insensitive matches
    private static final ArrayList<String> valid_units = new ArrayList<String>(
            Arrays.asList("%", "s", "ms", "us", "b", "kb", "mb", "gb", "tb", "c"));

    public static final Logger log = Logger.getLogger(com.linkedin.harisekhon.Utils.class.getName());
    //    public static final Logger log = Logger.getLogger("com.linkedin.harisekhon.Utils");

    // ===================================================================== //
    //
    //                             R e g e x
    //
    // ===================================================================== //

    // neither Google's com.Guava google.common.net.HostSpecifier nor Apache Commons org.apache.commons.validator.routines.DomainValidator are suitable for my needs here, must port the more flexible regex methods from my old Perl library

    // years and years of Regex expertise and testing has gone in to this, do not edit!
    // This also gives flexibility to work around some situations where domain names may not be quite valid (eg .local/.intranet) but still keep things quite tight
    // There are certain scenarios where Google Guava and Apache Commons libraries don't help with these
    // AWS regex from http://blogs.aws.amazon.com/security/blog/tag/key+rotation
    public static final String aws_access_key_regex = "(?<![A-Z0-9])[A-Z0-9]{20}(?![A-Z0-9])";
    public static final String aws_host_component = "ip-(?:10-\\d+-\\d+-\\d+|172-1[6-9]-\\d+-\\d+|172-2[0-9]-\\d+-\\d+|172-3[0-1]-\\d+-\\d+|192-168-\\d+-\\d+)";
    public static final String aws_secret_key_regex = "(?<![A-Za-z0-9/+=])[A-Za-z0-9/+=]{40}(?![A-Za-z0-9/+=])";
    public static final String ip_prefix_regex = "\\b(?:(?:25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?)\\.){3}";
    // now allowing 0 or 255 as the final octet due to CIDR
    public static final String ip_regex = ip_prefix_regex
            + "(?:25[0-5]|2[0-4][0-9]|[01]?[1-9][0-9]|[01]?0[1-9]|[12]00|[0-9])\\b";
    // must permit numbers as valid host identifiers that are being used in the wild in FQDNs
    public static final String hostname_component_regex = "\\b[A-Za-z0-9](?:[A-Za-z0-9_\\-]{0,61}[a-zA-Z0-9])?\\b";
    public static final String domain_component = "\\b[a-zA-Z0-9](?:[a-zA-Z0-9\\-]{0,61}[a-zA-Z0-9])?\\b";
    public static final String domain_regex;
    public static final String domain_regex_strict;
    public static final String hostname_regex;
    public static final String aws_hostname_regex;
    public static final String host_regex;
    public static final String dirname_regex = "[/\\w\\s\\\\.:,*()=%?+-]+";
    public static final String filename_regex = dirname_regex + "[^/]";
    public static final String rwxt_regex = "[r-][w-][x-][r-][w-][x-][r-][w-][xt-]";
    public static final String fqdn_regex;
    public static final String aws_fqdn_regex;
    public static final String email_regex;
    public static final String subnet_mask_regex = "\\b(?:(?:25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?)\\.){3}(?:25[0-5]|2[0-4][0-9]|[01]?[1-9][0-9]|[01]?0[1-9]|[12]00|[0-9])\\b";
    public static final String mac_regex = "\\b[0-9A-F-af]{1,2}[:-](?:[0-9A-Fa-f]{1,2}[:-]){4}[0-9A-Fa-f]{1,2}\\b";
    public static final String process_name_regex = "\\s*[\\w./<>-][\\w\\s./<>-]+";
    public static final String url_path_suffix_regex = "/(?:[\\w.,:/%&?#!=*|\\[\\]~+-]+)?"; // there is an RFC3987 regex but it's gigantic, this is easier to reason about and serves my needs
    public static final String user_regex = "\\b[A-Za-z0-9][A-Za-z0-9_-]*[A-Za-z0-9]\\b";
    public static final String url_regex;
    public static final String column_regex = "\\b[\\w:]+\\b";
    public static final String ldap_dn_regex = "\\b\\w+=[\\w\\s]+(?:,\\w+=[\\w\\s]+)*\\b";
    public static final String krb5_principal_regex;
    public static final String threshold_range_regex = "^(@)?(-?\\d+(?:\\.\\d+)?)(:)(-?\\d+(?:\\.\\d+)?)?$";
    public static final String threshold_simple_regex = "^(-?\\d+(?:\\.\\d+)?)$";
    public static final String label_regex = "\\s*[\\%\\(\\)\\/\\*\\w-][\\%\\(\\)\\/\\*\\w\\s-]*";
    public static final String version_regex = "\\d(\\.\\d+)*";
    public static final String version_regex_lax = version_regex + "-?.*";

    public static HashSet<String> tlds = new HashSet<String>();
    public static final String tld_regex;

    protected static final void loadTlds(String filename) throws IOException {
        int tld_count = 0;
        try {
            final InputStream resourceAsStream = Utils.class.getResourceAsStream("/" + filename);
            if (resourceAsStream == null) {
                throw new IOException(String.format("file '%s' does not exist under resources!", filename));
            }
            // works on disk, not on jar
            //            URL url = com.linkedin.harisekhon.Utils.class.getResource("/" + filename);
            //            File file = new File(url.getFile());
            //            Scanner scanner = new Scanner(file);
            BufferedReader br = new BufferedReader(new InputStreamReader(resourceAsStream));
            String line;
            while ((line = br.readLine()) != null) {
                line = line.replaceFirst("[#;].*", "");
                line = line.trim();
                if (line.matches("^\\s*$")) {
                    continue;
                }
                if (line.matches("^[A-Za-z0-9-]+$")) {
                    tlds.add(line);
                    tld_count += 1;
                } else {
                    log.warn(String.format("TLD: '%s' from tld file '%s' not validated, skipping that TLD", line,
                            filename));
                }
            }
            br.close();
        } catch (IOException e) {
            log.error(e.getMessage());
            throw e;
        }
        log.debug(tld_count + " TLDs loaded from '" + filename + "'");
    }

    public static void checkTldCount() throws IllegalStateException {
        long tld_count = tlds.size();
        log.debug(String.format("%d total unique TLDs loaded from resources", tld_count));
        if (tld_count < 1000) {
            String err_msg = String.format("%d TLDs loaded, expected >= 1000", tld_count);
            log.fatal(err_msg);
            throw new IllegalStateException(err_msg);
        }
        if (tld_count > 2000) {
            String err_msg = String.format("%d TLDs loaded, expected <= 2000", tld_count);
            log.fatal(err_msg);
            throw new IllegalStateException(err_msg);
        }
    }

    // can't throw any Exception up from static initializer
    static {
        // autoboxing
        exit_codes.put("OK", 0);
        exit_codes.put("WARNING", 1);
        exit_codes.put("CRITICAL", 2);
        exit_codes.put("UNKNOWN", 3);
        exit_codes.put("DEPENDENT", 4);

        // let the class fail to initialize if missing a resource to prevent relying on the regexes which won't match
        try {
            loadTlds("tlds-alpha-by-domain.txt");
            checkTldCount();
            loadTlds("custom_tlds.txt");
            // XXX: TODO: this fails correctly but doesn't give stack trace or file name
            //            loadTlds("custom_tldsa.txt");
            //            log.trace("tld_regex = " + tld_regex);
        } catch (IOException e) {
            // logged by loadTlds when throwing exception
            //            log.error(e.getMessage());
            quit("UNKNOWN", String.format(
                    "unable to load a resource file containing TLDs for generated domain/fqdn regex generation: %s",
                    e.getMessage()));
            //            throw e;
        }

        tld_regex = "\\b(?i:" + StringUtils.join(tlds.iterator(), "|") + ")\\b";

        //tld_regex                   = "\\b(?i:[A-Za-z]{2,4}|london|museum|travel|local|localdomain|intra|intranet|internal)\\b";
        domain_regex = "(?:" + domain_component + "\\.)*" + tld_regex;
        domain_regex_strict = "(?:" + domain_component + "\\.)+" + tld_regex;
        hostname_regex = String.format("%s(?:\\.%s)?", hostname_component_regex, domain_regex);
        aws_hostname_regex = aws_host_component + "(?:\\." + domain_regex + ")?";
        aws_fqdn_regex = aws_host_component + "\\." + domain_regex;
        host_regex = String.format("\\b(?:%s|%s)\\b", hostname_regex, ip_regex);
        fqdn_regex = hostname_component_regex + "\\." + domain_regex;
        krb5_principal_regex = String.format("%s(?:/%s)?(?:@%s)?", user_regex, hostname_regex, domain_regex);
        email_regex = "\\b[A-Za-z0-9](?:[A-Za-z0-9\\._\\%\\'\\+-]{0,62}[A-Za-z0-9\\._\\%\\+-])?@" + domain_regex
                + "\\b";
        url_regex = "\\b(?i:https?://)?" + host_regex + "(?::\\d{1,5})?(?:" + url_path_suffix_regex + ")?";
    }

    // ===================================================================== //
    //
    //                S t a t u s   h e l p e r   m e t h o d s
    //
    // ===================================================================== //

    public static final String getStatus() {
        return status;
    }

    public static final int getStatusCode() {
        return exit_codes.get(status);
    }

    public static final void setStatus(String key) {
        if (exit_codes.containsKey(key)) {
            status = key;
        } else {
            throw new IllegalArgumentException("invalid status '" + key
                    + "' passed to setStatus(), must be one of: " + exit_codes.keySet().toString());
        }
    }

    public static final void unknown() {
        if (getStatus() == null || "OK".equalsIgnoreCase(getStatus())) {
            setStatus("UNKNOWN");
        }
    }

    public static final void warning() {
        if (getStatus() == null || !"CRITICAL".equalsIgnoreCase(getStatus())) {
            setStatus("WARNING");
        }
    }

    public static final void critical() {
        setStatus("CRITICAL");
    }

    public static final Boolean isOk() {
        // encapsulated and cannot return null, also reversed equality below cannot get NPE
        //        if(getStatus() == null){
        //            return false;
        //        }
        return "OK".equals(getStatus());
    }

    public static final Boolean isWarning() {
        // encapsulated and cannot return null, also reversed equality below cannot get NPE
        //        if(getStatus() == null){
        //            return false;
        //        }
        return "WARNING".equalsIgnoreCase(getStatus());
    }

    public static final Boolean isCritical() {
        // encapsulated and cannot return null, also reversed equality below cannot get NPE
        //        if(getStatus() == null){
        //            return false;
        //        }
        return "CRITICAL".equalsIgnoreCase(getStatus());
    }

    public static final Boolean isUnknown() {
        // encapsulated and cannot return null, also reversed equality below cannot get NPE
        //        if(getStatus() == null){
        //            return false;
        //        }
        return "UNKNOWN".equalsIgnoreCase(getStatus());
    }

    public static final int getStatusCode(String key) {
        if (key != null && exit_codes.containsKey(key)) {
            return exit_codes.get(key);
        } else {
            throw new IllegalArgumentException("invalid status '" + key + "' passed to getStatusCode()");
        }
    }

    public static final void status() {
        vlog("status: " + getStatus());
    }

    public static final void status2() {
        vlog2("status: " + getStatus());
    }

    public static final void status3() {
        vlog3("status: " + getStatus());
    }

    // ===================================================================== //

    public static final Boolean checkRegex(String string, String regex) {
        if (string == null) {
            //            throw new IllegalArgumentException("undefined string passed to checkRegex()");
            return false;
        }
        if (regex == null) {
            throw new IllegalArgumentException("undefined regex passed to checkRegex()");
        }
        if (!isRegex(regex)) {
            throw new IllegalArgumentException("invalid regex passed to checkRegex()");
        }
        if (string.matches(regex)) {
            return true;
        }
        //        critical();
        return false;
    }

    public static final Boolean checkString(String str, String expected, Boolean no_msg) {
        if (expected == null) {
            throw new IllegalArgumentException("passed null as expected string to checkString()");
        }
        if (str == null) {
            return false;
        }
        if (str.equals(expected)) {
            return true;
        }
        //        critical();
        /* implement when msg and thresholds are done
        if(nomsg){
            
        }
        */
        return false;
    }

    public static final Boolean checkString(String str, String expected) {
        return checkString(str, expected, false);
    }

    public static final double expandUnits(double num, String units, String name) {
        if (units == null) {
            throw new IllegalArgumentException("null passed for units to expandUnits()");
        }
        String name2 = name(name).trim();
        String units2 = units.trim();
        if (!name2.isEmpty()) {
            name2 = " for " + name2;
        }
        int power = 1;
        if (units2.matches("(?i)^B?$")) {
            return num;
        } else if (units2.matches("(?i)^KB?$")) {
            power = 1;
        } else if (units2.matches("(?i)^MB?$")) {
            power = 2;
        } else if (units2.matches("(?i)^GB?$")) {
            power = 3;
        } else if (units2.matches("(?i)^TB?$")) {
            power = 4;
        } else if (units2.matches("(?i)^PB?$")) {
            power = 5;
        } else {
            throw new IllegalArgumentException(
                    String.format("unrecognized units '%s' passed to expandUnits()%s", units2, name2));
        }
        return (num * (pow(1024, power)));
    }

    public static final double expandUnits(double num, String units) {
        return expandUnits(num, units, null);
    }

    public static final long expandUnits(long num, String units, String name) {
        return (long) expandUnits((double) num, units, name);
    }

    public static final long expandUnits(long num, String units) {
        return expandUnits(num, units, null);
    }

    public static final void hr() {
        log.info("# " + StringUtils.repeat("=", 76) + " #");
    }

    public static final String humanUnits(double num, String units, Boolean terse) {
        double num2;
        String units2;
        if (units == null) {
            units2 = "";
        } else {
            units2 = units.trim();
        }
        if (!units2.isEmpty()) {
            num2 = expandUnits(num, units2, "humanUnits");
        } else {
            num2 = num;
        }
        if (num2 >= pow(1024, 7)) {
            throw new IllegalArgumentException(
                    String.format("determined suspicious units for number '%s', larger than Exabytes?!!", num2));
        } else if (num2 >= pow(1024, 6)) {
            //num_str = String.format("%.2f", num / pow(1024, 6)).replaceFirst("\\.0+$", "");
            num2 = num2 / pow(1024, 6);
            units2 = "EB";
        } else if (num2 >= pow(1024, 5)) {
            //num_str = String.format("%.2f", num / pow(1024, 5));
            num2 = num2 / pow(1024, 5);
            units2 = "PB";
        } else if (num2 >= pow(1024, 4)) {
            //num_str = String.format("%.2f", num / pow(1024, 4));
            num2 = num2 / pow(1024, 4);
            units2 = "TB";
        } else if (num2 >= pow(1024, 3)) {
            //num_str = String.format("%.2f", num / pow(1024, 3));
            num2 = num2 / pow(1024, 3);
            units2 = "GB";
        } else if (num2 >= pow(1024, 2)) {
            //num_str = String.format("%.2f", num / pow(1024, 2));
            num2 = num2 / pow(1024, 2);
            units2 = "MB";
        } else if (num2 >= pow(1024, 1)) {
            //num_str = String.format("%.2f", num / pow(1024, 1));
            num2 = num2 / pow(1024, 1);
            units2 = "KB";
        } else if (num2 < 1024) {
            //num_str = String.valueOf(num);
            if (terse) {
                //return String.format("%sB", num);
                units2 = "B";
            } else {
                //return String.format("%s bytes", num);
                units2 = " bytes";
            }
            // unreachable
            //        } else {
            //            throw new IllegalArgumentException(String.format("unable to determine units for number '%s'", num));
        }
        // remove trailing zeros past the decimal point
        String num_str = String.format("%.2f", num2).replaceFirst("(\\.\\d+)0$", "$1").replaceFirst("\\.0+$", "");
        return num_str + units2;
    }

    public static final String humanUnits(double num, String units) {
        return humanUnits(num, units, false);
    }

    public static final String humanUnits(double num) {
        return humanUnits(num, null, false);
    }

    public static final String stripScheme(String str) {
        if (str.matches("^\\w+://[^/].*")) {
            return str.replaceFirst("^\\w+://", "");
        } else {
            return str.replaceFirst("^\\w+:/+", "/");
        }
    }

    public static final String stripSchemeHost(String str) {
        if (str.matches("^\\w+:///[^/].*")) {
            return str.replaceFirst("^\\w+:///", "/");
        } else {
            //return str.replaceFirst("^\\w+:(?://[^/]+)?/", "/");
            return str.replaceFirst("^\\w+:(?://" + host_regex + "(?::\\d+)?)?/", "/");
        }
    }

    // ===================================================================== //
    //
    //                 C o n v e r s i o n   U t i l i t i e s
    //
    // ===================================================================== //

    public static final ArrayList<String> arrayToArraylist(String[] array) {
        return new ArrayList<String>(Arrays.asList(array));
    }

    public static final String[] arraylistToArray(ArrayList<String> arrayList) {
        String[] array = new String[arrayList.size()];
        return arrayList.toArray(array);
    }

    public static final String[] setToArray(Set<String> set) {
        String[] array = set.toArray(new String[set.size()]);
        return array;
    }

    // ===================================================================== //
    //
    //                     Non-deterministic Ordering
    //
    public static final String[] uniqArray(String[] list) {
        HashSet<String> set = new HashSet<String>();
        for (String item : list) {
            set.add(item);
        }
        String[] a = {};
        return set.toArray(a);
    }

    // TODO: change this to be uniq_list instead and use List<String>
    public static final ArrayList<String> uniqArraylist(List<String> list) {
        HashSet<String> set = new HashSet<String>(list);
        ArrayList<String> a = new ArrayList<String>();
        a.addAll(set);
        return a;
    }

    // ===================================================================== //
    //
    //                     Order Preserving
    //
    public static final String[] uniqArrayOrdered(String[] list) {
        Set<String> set = new LinkedHashSet<String>();
        for (String item : list) {
            set.add(item);
        }
        String[] a = {};
        return set.toArray(a);
    }

    public static final ArrayList<String> uniqArraylistOrdered(ArrayList<String> list) {
        Set<String> set = new LinkedHashSet<String>(list);
        ArrayList<String> a = new ArrayList<String>();
        a.addAll(set);
        return a;
    }

    // ===================================================================== //
    //
    //                          V a l i d a t i o n
    //
    // ===================================================================== //

    public static final Boolean isAlNum(String str) {
        if (str == null) {
            return false;
        }
        return str.matches("^[A-za-z0-9]+$");
    }

    public static final Boolean isAwsAccessKey(String str) {
        if (str == null) {
            return false;
        }
        return str.matches("^" + aws_access_key_regex + "$");
    }

    public static final Boolean isAwsBucket(String arg) {
        return isDnsShortName(arg);
    }

    public static final Boolean isAwsHostname(String str) {
        if (str == null) {
            return false;
        }
        return str.matches("^" + aws_hostname_regex + "$");
    }

    public static final Boolean isAwsFqdn(String str) {
        if (str == null) {
            return false;
        }
        return str.matches("^" + aws_fqdn_regex + "$");
    }

    public static final Boolean isAwsSecretKey(String str) {
        if (str == null) {
            return false;
        }
        return str.matches("^" + aws_secret_key_regex + "$");
    }

    public static final Boolean isChars(String str, String char_range) {
        if (str == null || char_range == null) {
            return false;
        }
        if (!isRegex(String.format("[%s]", char_range))) {
            throw new IllegalArgumentException("invalid regex char range passed to isChars()");
        }
        return str.matches(String.format("^[%s]+$", char_range));
    }

    public static final Boolean isCollection(String collection) {
        if (collection == null || collection.trim().isEmpty()) {
            return false;
        }
        return collection.matches("^(\\w(?:[\\w.]*\\w)?)$");
    }

    public static final Boolean isDatabaseName(String database) {
        if (database == null || database.trim().isEmpty()) {
            return false;
        }
        return database.matches("^\\w+$");
    }

    public static final Boolean isDatabaseColumnName(String column) {
        if (column == null || column.trim().isEmpty()) {
            return false;
        }
        return column.matches("^" + column_regex + "$");
    }

    public static final Boolean isDatabaseFieldName(String field) {
        if (field == null || field.trim().isEmpty()) {
            return false;
        }
        // allows field number integer or field name
        return field.matches("^(?:\\d+|[\\w()*,._-]+)$");
    }

    public static final Boolean isDatabaseTableName(String table, Boolean allow_qualified) {
        if (table == null || table.trim().isEmpty()) {
            return false;
        }
        if (allow_qualified) {
            return table.matches("^[A-Za-z0-9][\\w.]*[A-Za-z0-9]$");
        } else {
            return table.matches("^[A-Za-z0-9]\\w*[A-Za-z0-9]$");
        }
    }

    public static final Boolean isDatabaseTableName(String table) {
        return isDatabaseTableName(table, false);
    }

    public static final Boolean isDatabaseViewName(String view, Boolean allow_qualified) {
        return isDatabaseTableName(view, allow_qualified);
    }

    public static final Boolean isDatabaseViewName(String view) {
        return isDatabaseViewName(view, false);
    }

    public static final Boolean isDirname(String dir) {
        if (dir == null || dir.trim().isEmpty()) {
            return false;
        }
        return dir.matches("^" + dirname_regex + "$");
    }

    public static final Boolean isDomain(String domain) {
        if (domain == null || domain.trim().isEmpty()) {
            return false;
        }
        return domain.matches("^" + domain_regex + "$");
    }

    public static final Boolean isDomainStrict(String domain) {
        if (domain == null || domain.trim().isEmpty()) {
            return false;
        }
        return domain.matches("^" + domain_regex_strict + "$");
    }

    public static final Boolean isDnsShortName(String dns) {
        if (dns == null || dns.trim().length() < 3 || dns.length() > 63) {
            return false;
        }
        return dns.matches("^" + hostname_component_regex + "$");
    }

    public static final Boolean isEmail(String email) {
        if (email == null || email.trim().isEmpty() || email.length() > 256) {
            return false;
        }
        return email.matches("^" + email_regex + "$");
    }

    public static final Boolean isFilename(String filename) {
        if (filename == null || filename.trim().isEmpty()) {
            return false;
        }
        return filename.matches("^" + filename_regex + "$");
    }

    public static final Boolean isFqdn(String fqdn) {
        if (fqdn == null || fqdn.trim().isEmpty() || fqdn.length() > 255) {
            return false;
        }
        return fqdn.matches("^" + fqdn_regex + "$");
    }

    public static final Boolean isHex(String hex) {
        if (hex != null && hex.matches("^0x[A-Fa-f\\d]+$")) {
            return true;
        } else {
            return false;
        }
    }

    // at casual glance this looks like it's duplicating isHostname but it's using a different unified regex of isHostname + isIP
    public static final Boolean isHost(String host) {
        if (host == null || host.trim().isEmpty()) {
            return false;
        }
        if (host.length() > 255) {
            return false;
        } else if (isIP(host)) {
            return true;
        } else if (host.matches("^" + host_regex + "$")) {
            return true;
        } else {
            return false;
        }
    }

    public static final Boolean isHostname(String hostname) {
        if (hostname != null && hostname.length() < 256 && hostname.matches("^" + hostname_regex + "$")) {
            return true;
        } else {
            return false;
        }
    }

    public static final Boolean isInterface(String networkInterface) {
        if (networkInterface != null
                && networkInterface.matches("^(?:em|eth|bond|lo|docker)\\d+|lo|veth[A-Fa-f0-9]+$")) {
            return true;
        } else {
            return false;
        }
    }

    // TODO: isJson
    // TODO: isXML

    public static final Boolean isKrb5Princ(String princ) {
        if (princ != null && princ.matches("^" + krb5_principal_regex + "$")) {
            return true;
        } else {
            return false;
        }
    }

    public static final Boolean isLabel(String label) {
        if (label != null && label.matches("^" + label_regex + "$")) {
            return true;
        } else {
            return false;
        }
    }

    public static final Boolean isLdapDn(String dn) {
        if (dn != null && dn.matches("^" + ldap_dn_regex + "$")) {
            return true;
        } else {
            return false;
        }
    }

    // doubles are easier as can still call against floats if needed
    public static final Boolean isMinVersion(String version, Double min) {
        if (version == null) {
            return false;
        }
        if (min == null) {
            return false;
        }
        if (!isVersionLax(version)) {
            return false;
        }
        Pattern pattern = Pattern.compile("(\\d+(?:\\.\\d+)?)");
        Matcher matcher = pattern.matcher(version);
        if (matcher.find()) {
            String m1 = matcher.group(1);
            // this will never happen because of the regex
            //            try {
            // float >= double fails for 1.3 vs 1.3, make detected_version a double too
            double detected_version = Double.parseDouble(m1);
            //            } except (NumberFormatException, e) {
            //                throw IllegalArgumentException(String.format("failed to detect version from string '%s': %s", version, e));
            //            }
            if (detected_version >= min) {
                return true;
            }
        }
        return false;
    }

    public static final Boolean isNagiosUnit(String unit) {
        if (unit != null && valid_units.contains(unit.toLowerCase())) {
            return true;
        } else {
            return false;
        }
    }

    public static final Boolean isNoSqlKey(String key) {
        if (key != null && key.matches("^[\\w_,.:+-]+$")) {
            return true;
        } else {
            return false;
        }
    }

    public static final Boolean isIP(String ip) {
        if (ip == null) {
            return false;
        }
        String[] octets = ip.split("\\.");
        if (octets.length != 4) {
            return false;
        }
        for (String octet : octets) {
            int octet_int;
            try {
                octet_int = Integer.parseInt(octet);
            } catch (NumberFormatException e) {
                return false;
            }
            if (octet_int < 0 || octet_int > 255) {
                return false;
            }
        }
        if (ip.matches("^" + ip_regex + "$")) {
            return true;
        }
        return false;
    }

    public static final Boolean isPort(String port) {
        if (port == null) {
            return false;
        }
        int port_int;
        try {
            port_int = Integer.parseInt(port);
        } catch (NumberFormatException e) {
            return false;
        }
        if (port.matches("^\\d+$")) {
            return isPort(port_int);
        }
        return false;
    }

    public static final Boolean isPort(int port_int) {
        if (port_int < 1 || port_int > 65535) {
            return false;
        }
        return true;
    }

    public static final Boolean isProcessName(String proc) {
        if (proc != null && proc.matches("^" + process_name_regex + "$")) {
            return true;
        } else {
            return false;
        }
    }

    public static final Boolean isRegex(String regex) {
        if (regex == null) {
            return false;
        }
        try {
            // this seems to allow null, so catch above
            "".matches(regex);
            return true;
        } catch (PatternSyntaxException e) {
            // pass
        }
        return false;
    }

    // not implementing isScientific

    // TODO: isThreshold()

    public static final Boolean isUrl(String url) {
        if (url == null || url.trim().isEmpty()) {
            return false;
        }
        if (url.matches("^" + url_regex + "$")) {
            return true;
        } else {
            return false;
        }
    }

    public static final Boolean isUrlPathSuffix(String url) {
        if (url != null && url.matches("^" + url_path_suffix_regex + "$")) {
            return true;
        } else {
            return false;
        }
    }

    public static final Boolean isUser(String user) {
        if (user == null) {
            return false;
        }
        if (user.matches("^" + user_regex + "$")) {
            return true;
        }
        return false;
    }

    public static final Boolean isVersion(String version) {
        if (version != null && version.matches("^" + version_regex + "$")) {
            return true;
        } else {
            return false;
        }
    }

    public static final Boolean isVersionLax(String version) {
        if (version != null && version.matches(version_regex_lax)) {
            return true;
        } else {
            return false;
        }
    }

    // ===================================================================== //
    //
    //                      O S   H e l p e r s
    //
    // ===================================================================== //

    /*
    public static final void print_java_properties(){
    System.getProperties().list(System.out);
    }
    */

    public static final String getOS() {
        String os = System.getProperty("os.name");
        if (os == null) {
            throw new IllegalStateException("unknown OS, retrieved null for OS");
        }
        if (os.trim().isEmpty()) {
            throw new IllegalStateException("unknown OS, retrieved blank for OS");
        }
        return os;
    }

    public static final Boolean isOS(String os) {
        if (os != null && os.equals(getOS())) {
            return true;
        } else {
            return false;
        }
    }

    public static final Boolean isMac() {
        return isOS("Mac OS X");
    }

    public static final Boolean isLinux() {
        return isOS("Linux");
    }

    public static final Boolean isLinuxOrMac() {
        return isLinux() || isMac();
    }

    public static final void linuxOnly() throws UnsupportedOSException {
        if (!isLinux()) {
            throw new UnsupportedOSException("Linux");
        }
    }

    public static final void macOnly() throws UnsupportedOSException {
        if (!isMac()) {
            throw new UnsupportedOSException("Mac OS X");
        }
    }

    public static final void linuxMacOnly() throws UnsupportedOSException {
        if (!(isLinux() || isMac())) {
            throw new UnsupportedOSException("Linux or Mac OS X");
        }
    }

    // ===================================================================== //

    // minimum_value - use Math.min

    // TODO: msg_perf_thresholds()
    // TODO: msg_thresholds()

    /*
    public static final int month2int (String month) {
    if(month == null){
        throw new IllegalArgumentException("null passed to month2int");
    }
    HashMap<String, Integer> month_map = new HashMap<String, Integer>() {{
        put("jan", 1);
        put("feb", 2);
        put("mar", 3);
        put("apr", 4);
        put("may", 5);
        put("jun", 6);
        put("jul", 7);
        put("aug", 8);
        put("sep", 9);
        put("oct", 10);
        put("nov", 11);
        put("dec", 12);
    }};
    if(month_map.containsKey(month.toLowerCase())){
        return month_map.get(month.toLowerCase());
    } else {
        throw new IllegalArgumentException("invalid month passed to month2int()");
    }
    return -1; // purely to appease Java - won't reach here
    }
    */

    // TODO:
    // open_file
    // parse_file_option
    // plural
    // prompt
    // isYes
    // random_alnum
    // sec2min
    // sec2human
    // set_sudo
    // set_timeout

    public static final String plural(String arg) {
        if (arg == null) {
            return "";
        }
        try {
            double a = Double.valueOf(arg);
            if (a == 1.0) {
                return "";
            } else {
                return "s";
            }
        } catch (NumberFormatException e) {
            return "";
        }
    }

    public static final String plural(double arg) {
        return plural(Double.toString(arg));
    }
    // not using any more as both List<Object> and Object[] makes plural(null) calls ambiguous with plural(String) :-/
    //    public static final String plural(List<Object> args){
    //        if(args.size() == 1){
    //            return "";
    //        } else {
    //            return "s";
    //        }
    //    }
    //    public static final String plural(Object[] args){
    //        if(args.length == 1){
    //            return "";
    //        } else {
    //            return "s";
    //        }
    //    }

    public static final String resolveIp(String host) throws UnknownHostException {
        if (host == null) {
            throw new IllegalArgumentException("no host passed to resolveIp (null)");
        }
        if (host.trim().isEmpty()) {
            throw new IllegalArgumentException("no host passed to resolveIp (blank)");
        }
        //        try {
        InetAddress address = InetAddress.getByName(host);
        return address.getHostAddress();
        //        } catch (UnknownHostException e) {
        //            return null;
        //        }
    }

    // only works on unix systems
    public static final Boolean userExists(String user) throws IOException, UnsupportedOSException {
        linuxMacOnly();
        if (user == null) {
            return false;
        }
        if (user.trim().isEmpty()) {
            return false;
        }
        if (!isUser(user)) {
            return false;
        }
        StringBuilder id = new StringBuilder();
        //        try {
        Process child = Runtime.getRuntime().exec("id -u " + user);
        InputStream in = child.getInputStream();
        int c;
        while ((c = in.read()) != -1) {
            id.append((char) c);
        }
        in.close();
        //        } catch (IOException e){
        //            return false;
        //        }
        String id2 = id.toString();
        //        println("id2" + id2);
        if (id2 != null && !id2.isEmpty()) {
            return true;
        }
        return false;
    }

    //    public static final void arg_error (String msg) {
    //        println("CODE ERROR: " + msg);
    //        System.exit(exit_codes.get("UNKNOWN"));
    //        throw new IllegalArgumentException(msg);
    //    }

    //    public static final void state_error (String msg) {
    //        println("CODE ERROR: " + msg);
    //        System.exit(exit_codes.get("UNKNOWN"));
    //        throw new IllegalStateException(msg);
    //    }

    public static final void quit(String status, String message) {
        //        log.error(status + ": " + message);
        if (exit_codes.containsKey(status)) {
            //            println(status + ": " + message);
            //            System.exit(exit_codes.get(status));
            throw new QuitException(status, message);
        } else {
            throw new IllegalArgumentException(String
                    .format("specified an invalid exit status '%s' to quit(), message was '%s'", status, message));
        }
    }

    public static final void quit(String message) {
        //        log.error("CRITICAL: " + msg);
        //        println("CRITICAL: " + msg);
        //        System.exit(exit_codes.get("CRITICAL"));
        //        quit("CRITICAL", msg);
        throw new QuitException("CRITICAL", message);
    }

    // because System.out.println is still annoying and Scala has a short version
    public static final void println(String msg) {
        //if(stdout){
        System.out.println(msg);
        //} else {
        //  System.err.println(msg);
        //}
    }

    public static final void println(double num) {
        println(String.valueOf(num));
    }

    public static final void println(long num) {
        println(String.valueOf(num));
    }

    public static final void println(Boolean b) {
        println(b.toString());
    }

    /*
    private static final void printf (String msg, String... args) {
    System.out.printf(String.format("%s", msg), (Object[]) args); // cast to Object[] to avoid warning about String and Object not quite matching up
    }
    */

    public static final String repeatString(String chars, int num) {
        StringBuilder string = new StringBuilder();
        for (int i = 0; i < num; i++) {
            string.append(chars);
        }
        return string.toString();
    }

    // ===================================================================== //
    //
    //                          V a l i d a t i o n
    //
    // ===================================================================== //

    // these methods are intentionally not throwing exceptions as they are designed for CLI.java usage and exit with usage()
    // for try and recover behaviour use the corresponding is* methods which return Boolean

    public static final String name(String name) {
        if (name == null) {
            return "";
        }
        String name2 = name.trim();
        if (!name2.isEmpty()) {
            name2 = name2 + " ";
        }
        return name2;
    }

    public static final String requireName(String name) {
        if (name == null || name.trim().isEmpty()) {
            // TODO: improve the feedback location
            //StackTraceElement[] stackTraceElements = Thread.currentThread().getStackTrace()
            throw new IllegalArgumentException("name arg not defined when calling method");
        }
        return name.trim();
    }

    public static final String validateAlnum(String alnum, String name) {
        String name2 = requireName(name);
        if (alnum == null) {
            throw new IllegalArgumentException(name2 + "not defined (null)");
        }
        String alnum2 = alnum.trim();
        if (alnum2.isEmpty()) {
            throw new IllegalArgumentException(name2 + "not defined (blank)");
        }
        if (!alnum2.matches("^[A-Za-z0-9]+$")) {
            throw new IllegalArgumentException("invalid " + name2 + " defined: must be alphanumeric");
        }
        vlogOption(name2, alnum2);
        return alnum2;
    }

    public static final String validateChars(String arg, String name, String chars) {
        String name2 = requireName(name);
        if (chars == null) {
            throw new IllegalArgumentException("chars field not defined (null) when calling validateChars()");
        }
        String chars2 = chars.trim();
        if (chars2.isEmpty()) {
            throw new IllegalArgumentException("chars field not defined (blank) when calling validateChars()");
        }
        if (arg == null || arg.trim().isEmpty()) {
            throw new IllegalArgumentException(name + "not defined");
        }
        if (!isChars(arg, chars2)) {
            throw new IllegalArgumentException(
                    "invalid " + name2 + " defined: must be one of the following chars - " + chars2);
        }
        vlogOption(name2, arg);
        return arg;
    }

    public static final String validateAwsAccessKey(String key) {
        if (key == null) {
            throw new IllegalArgumentException("aws access key not defined (null)");
        }
        String key2 = key.trim();
        if (key2.isEmpty()) {
            throw new IllegalArgumentException("aws access key not defined (blank)");
        }
        if (!isAwsAccessKey(key2)) {
            throw new IllegalArgumentException("invalid aws access key defined: must be 20 alphanumeric chars");
        }
        vlogOption("aws access key", repeatString("X", 18) + key2.substring(18, 20));
        return key2;
    }

    public static final String validateAwsBucket(String bucket) {
        if (bucket == null) {
            throw new IllegalArgumentException("aws bucket not defined (null)");
        }
        String bucket2 = bucket.trim();
        if (bucket2.trim().isEmpty()) {
            throw new IllegalArgumentException("aws bucket not defined (blank)");
        }
        if (isIP(bucket2)) {
            throw new IllegalArgumentException(
                    "invalid aws bucket name defined: may not be formatted as an IP address");
        }
        if (!isDnsShortName(bucket2)) {
            throw new IllegalArgumentException(
                    "invalid aws bucket name defined: must be alphanumeric between 3 and 63 characters long");
        }
        vlogOption("aws bucket:", bucket2);
        return bucket2;
    }

    public static final String validateAwsHostname(String arg) {
        if (arg == null) {
            throw new IllegalArgumentException("aws hostname not defined (null)");
        }
        String arg2 = arg.trim();
        if (arg2.isEmpty()) {
            throw new IllegalArgumentException("aws hostname not defined (blank)");
        }
        if (isIP(arg2)) {
            throw new IllegalArgumentException(
                    "invalid aws hostname arg name defined: may not be formmatted as an IP address");
        }
        if (!isAwsHostname(arg2)) {
            throw new IllegalArgumentException(
                    "invalid aws hostname name defined: must be alphanumeric between 3 and 63 characters long");
        }
        vlogOption("aws hostname:", arg2);
        return arg2;
    }

    public static final String validateAwsFqdn(String arg) {
        if (arg == null) {
            throw new IllegalArgumentException("aws fqdn not defined (null)");
        }
        String arg2 = arg.trim();
        if (arg2.isEmpty()) {
            throw new IllegalArgumentException("aws fqdn not defined (blank)");
        }
        if (isIP(arg2)) {
            throw new IllegalArgumentException(
                    "invalid aws fqdn arg name defined: may not be formmatted as an IP address");
        }
        if (!isAwsFqdn(arg2)) {
            throw new IllegalArgumentException(
                    "invalid aws fqdn name defined: must be alphanumeric between 3 and 63 characters long hostname followed by domain");
        }
        vlogOption("aws fqdn:", arg2);
        return arg2;
    }

    public static final String validateAwsSecretKey(String key) {
        if (key == null) {
            throw new IllegalArgumentException("aws secret key not defined (null)");
        }
        String key2 = key.trim();
        if (key2.isEmpty()) {
            throw new IllegalArgumentException("aws secret key not defined (blank)");
        }
        if (!isAwsSecretKey(key2)) {
            throw new IllegalArgumentException("invalid aws secret key defined: must be 20 alphanumeric chars");
        }
        vlogOption("aws secret key", repeatString("X", 38) + key2.substring(38, 40));
        return key2;
    }

    public static final String validateCollection(String collection, String name) {
        String name2 = name(name);
        if (collection == null) {
            throw new IllegalArgumentException(name + "collection not defined (null)");
        }
        String collection2 = collection.trim();
        if (collection2.isEmpty()) {
            throw new IllegalArgumentException(name + "collection not defined (blank)");
        }
        if (!isCollection(collection2)) {
            throw new IllegalArgumentException("invalid " + name2
                    + "collection defined: must be alphanumeric, with optional periods in the middle");
        }
        vlogOption(name2 + "collection", collection2);
        return collection2;
    }

    public static final String validateCollection(String collection) {
        return validateCollection(collection, null);
    }

    public static final String validateDatabase(String database, String name) {
        String name2 = name(name);
        if (database == null) {
            throw new IllegalArgumentException(name2 + "database not defined (null)");
        }
        String database2 = database.trim();
        if (database2.isEmpty()) {
            throw new IllegalArgumentException(name2 + "database not defined (blank)");
        }
        if (!isDatabaseName(database2)) {
            throw new IllegalArgumentException("invalid " + name2 + "database defined: must be alphanumeric");
        }
        vlogOption(name2 + "database", database2);
        return database2;
    }

    public static final String validateDatabase(String database) {
        return validateDatabase(database, null);
    }

    public static final String validateDatabaseColumnname(String column) {
        if (column == null) {
            throw new IllegalArgumentException("column not defined (null)");
        }
        String column2 = column.trim();
        if (column2.isEmpty()) {
            throw new IllegalArgumentException("column not defined (blank)");
        }
        if (!isDatabaseColumnName(column2)) {
            throw new IllegalArgumentException("invalid column defined: must be alphanumeric");
        }
        vlogOption("column", column2);
        return column2;
    }

    public static final String validateDatabaseFieldname(String field) {
        if (field == null) {
            throw new IllegalArgumentException("field not defined (null)");
        }
        String field2 = field.trim();
        if (field2.trim().isEmpty()) {
            throw new IllegalArgumentException("field not defined (blank)");
        }
        if (!isDatabaseFieldName(field2)) {
            throw new IllegalArgumentException("invalid field defined: must be alphanumeric");
        }
        vlogOption("field", field2);
        return field2;
    }

    public static final String validateDatabaseQuerySelectShow(String query, String name) {
        String name2 = name(name);
        if (query == null) {
            throw new IllegalArgumentException(name2 + "query not defined (null)");
        }
        String query2 = query.trim();
        if (query2.isEmpty()) {
            throw new IllegalArgumentException(name2 + "query not defined (blank)");
        }
        // XXX: fix this to be case insensitive and re-enable case insensitive unit test
        if (!query2.matches("^(?i)\\s*(?:SHOW|SELECT)\\s+.+$")) {
            throw new IllegalArgumentException(
                    "invalid " + name2 + "query defined: may only be a SELECT or SHOW statement");
        }
        if (query2.matches("(?i).*\\b(?:insert|update|delete|create|drop|alter|truncate)\\b.*")) {
            throw new IllegalArgumentException(
                    "invalid " + name2 + "query defined: DML statement or suspect chars detected in query");
        }
        vlogOption(name2 + "query", query2);
        return query2;
    }

    public static final String validateDatabaseQuerySelectShow(String query) {
        return validateDatabaseQuerySelectShow(query, null);
    }

    public static final String validateDatabaseTablename(String table, String name, Boolean allow_qualified) {
        String name2 = name(name);
        if (table == null) {
            throw new IllegalArgumentException(name2 + "table not defined (null)");
        }
        String table2 = table.trim();
        if (table2.trim().isEmpty()) {
            throw new IllegalArgumentException(name2 + "table not defined (blank)");
        }
        if (!isDatabaseTableName(table2, allow_qualified)) {
            throw new IllegalArgumentException("invalid " + name2 + "table defined: must be alphanumeric");
        }
        vlogOption(name2 + "table", table2);
        return table2;
    }

    public static final String validateDatabaseTablename(String table, String name) {
        return validateDatabaseTablename(table, name, false);
    }

    public static final String validateDatabaseTablename(String table, Boolean allow_qualified) {
        return validateDatabaseTablename(table, null, allow_qualified);
    }

    public static final String validateDatabaseTablename(String table) {
        return validateDatabaseTablename(table, null, false);
    }

    public static final String validateDatabaseViewname(String view, String name, Boolean allow_qualified) {
        String name2 = name(name);
        if (view == null) {
            throw new IllegalArgumentException(name2 + "view not defined (null)");
        }
        String view2 = view.trim();
        if (view2.trim().isEmpty()) {
            throw new IllegalArgumentException(name2 + "view not defined (blank)");
        }
        if (!isDatabaseViewName(view2, allow_qualified)) {
            throw new IllegalArgumentException("invalid " + name2 + "view defined: must be alphanumeric");
        }
        vlogOption(name2 + "view", view2);
        return view2;
    }

    public static final String validateDatabaseViewname(String view, String name) {
        return validateDatabaseViewname(view, name, false);
    }

    public static final String validateDatabaseViewname(String view, Boolean allow_qualified) {
        return validateDatabaseViewname(view, null, allow_qualified);
    }

    public static final String validateDatabaseViewname(String view) {
        return validateDatabaseViewname(view, null, false);
    }

    public static final String validateDomain(String domain, String name) {
        String name2 = name(name);
        if (domain == null) {
            throw new IllegalArgumentException(name2 + "domain not defined (null)");
        }
        String domain2 = domain.trim();
        if (domain2.isEmpty()) {
            throw new IllegalArgumentException(name2 + "domain not defined (blank)");
        }
        if (!isDomain(domain2)) {
            throw new IllegalArgumentException("invalid " + name2 + "domain name defined ('" + domain2 + "')");
        }
        vlogOption(name2 + "domain", domain2);
        return domain2;
    }

    public static final String validateDomain(String domain) {
        return validateDomain(domain, null);
    }

    public static final String validateDomainStrict(String domain, String name) {
        String name2 = name(name);
        if (domain == null) {
            throw new IllegalArgumentException(name2 + "domain not defined (null)");
        }
        String domain2 = domain.trim();
        if (domain2.isEmpty()) {
            throw new IllegalArgumentException(name2 + "domain not defined (blank)");
        }
        if (!isDomainStrict(domain2)) {
            throw new IllegalArgumentException("invalid " + name2 + "domain name defined ('" + domain + "')");
        }
        vlogOption(name2 + "domain", domain2);
        return domain2;
    }

    public static final String validateDomainStrict(String domain) {
        return validateDomainStrict(domain, null);
    }

    public static final String validateDirname(String dir, String name, Boolean novlog) {
        String name2 = name(name);
        if (dir == null) {
            throw new IllegalArgumentException(name2 + "directory not defined (null)");
        }
        String dir2 = dir.trim();
        if (dir2.isEmpty()) {
            throw new IllegalArgumentException(name2 + "directory not defined (blank)");
        }
        if (!isDirname(dir2)) {
            throw new IllegalArgumentException(
                    "invalid " + name2 + "directory (does not match regex criteria): '" + dir2 + "'");
        }
        if (!novlog) {
            vlogOption(name2 + "directory", dir2);
        }
        return dir2;
    }

    public static final String validateDirname(String dir, String name) {
        return validateDirname(dir, name, false);
    }

    public static final String validateDirname(String dir) {
        return validateDirname(dir, null, false);
    }

    public static final String validateDirectory(String dir, String name, Boolean novlog) {
        String name2 = name(name);
        if (dir == null) {
            throw new IllegalArgumentException(name2 + "directory not defined (null)");
        }
        String dir2 = dir.trim();
        if (dir2.isEmpty()) {
            throw new IllegalArgumentException(name2 + "directory not defined (blank)");
        }
        String dir3 = validateDirname(dir2, name2, novlog);
        File d = new File(dir3);
        if (!d.isDirectory()) {
            throw new IllegalArgumentException(String.format("directory '%s' does not exist", dir3));
        }
        return dir3;
    }

    public static final String validateDirectory(String dir, String name) {
        return validateDirectory(dir, name, false);
    }

    public static final String validateDirectory(String dir) {
        return validateDirectory(dir, null, false);
    }

    public static final String validateDir(String dir, String name, Boolean novlog) {
        return validateDirectory(dir, name, novlog);
    }

    public static final String validateDir(String dir, String name) {
        return validateDirectory(dir, name, false);
    }

    public static final String validateDir(String dir) {
        return validateDirectory(dir, null, false);
    }

    public static final String validateEmail(String email) {
        if (email == null) {
            throw new IllegalArgumentException("email not defined (null)");
        }
        String email2 = email.trim();
        if (email2.isEmpty()) {
            throw new IllegalArgumentException("email not defined (blank)");
        }
        if (!isEmail(email2)) {
            throw new IllegalArgumentException("invalid email address defined: failed regex validation");
        }
        vlogOption("email", email2);
        return email2;
    }

    public static final String validateFile(String filename, String name, Boolean novlog) {
        String name2 = name(name);
        validateFilename(filename, name2, novlog);
        File f = new File(filename);
        if (!(f.exists() && !f.isDirectory())) {
            throw new IllegalArgumentException(name2 + "file not found: " + filename);
        }
        return filename;
    }

    public static final String validateFile(String filename, String name) {
        return validateFile(filename, name, false);
    }

    public static final String validateFile(String filename) {
        return validateFile(filename, null, false);
    }

    public static final String validateFilename(String filename, String name, Boolean novlog) {
        String name2 = name(name);
        if (name2.isEmpty()) {
            name2 = "filename ";
        }
        if (filename == null) {
            throw new IllegalArgumentException(name2 + "not defined (null)");
        }
        String filename2 = filename.trim();
        if (filename2.isEmpty()) {
            throw new IllegalArgumentException(name2 + "not defined (blank)");
        }
        if (!isFilename(filename2)) {
            throw new IllegalArgumentException(
                    "invalid " + name2 + "(does not match regex criteria): '" + filename2 + "'");
        }
        if (!novlog) {
            vlogOption(name2.trim(), filename2);
        }
        return filename2;
    }

    public static final String validateFilename(String filename, String name) {
        return validateFilename(filename, name, false);
    }

    public static final String validateFilename(String filename) {
        return validateFilename(filename, null, false);
    }

    public static final String validateFqdn(String fqdn, String name) {
        String name2 = name(name);
        if (fqdn == null) {
            throw new IllegalArgumentException(name2 + "FQDN not defined (null)");
        }
        String fqdn2 = fqdn.trim();
        if (fqdn2.trim().isEmpty()) {
            throw new IllegalArgumentException(name2 + "FQDN not defined (blank)");
        }
        if (!isFqdn(fqdn2)) {
            throw new IllegalArgumentException("invalid " + name2 + "FQDN defined");
        }
        vlogOption(name2 + "fqdn", fqdn2);
        return fqdn2;
    }

    public static final String validateFqdn(String fqdn) {
        return validateFqdn(fqdn, null);
    }

    /*
    public static final String[] validate_host_port_user_password(String host, String port, String user, String password){
    return (validateHost(host), validatePort(port), validateUser(user), validatePassword(password));
    }
    */

    public static final String validateHost(String host, String name) {
        String name2 = name(name);
        if (host == null) {
            throw new IllegalArgumentException(name2 + "host not defined (null)");
        }
        String host2 = host.trim();
        if (host2.isEmpty()) {
            throw new IllegalArgumentException(name2 + "host not defined (blank)");
        }
        if (!isHost(host2)) {
            throw new IllegalArgumentException(
                    "invalid " + name2 + "host defined: not a valid hostname or IP address");
        }
        vlogOption(name2 + "host", host2);
        return host2;
    }

    public static final String validateHost(String host) {
        return validateHost(host, null);
    }

    public static final int parsePort(String port) {
        int port_int = -1;
        try {
            port_int = Integer.parseInt(port);
        } catch (NumberFormatException e) {
            throw new IllegalArgumentException("invalid port defined, not an integer");
        }
        if (!isPort(port)) {
            throw new IllegalArgumentException("invalid port defined for hosts, must be between 1 and 65535");
        }
        return port_int;
    }

    public static final String[] validateHosts(String[] hosts, int port) {
        if (!isPort(port)) {
            throw new IllegalArgumentException("invalid port defined, integer must be between 1 and 65535");
        }
        String[] hosts2 = uniqArrayOrdered(hosts);
        if (hosts.length < 1) {
            throw new IllegalArgumentException("hosts not defined");
        }
        Pattern p = Pattern.compile(":(\\d+)$");
        for (int i = 0; i < hosts2.length; i++) {
            String node_port = null;
            Matcher m = p.matcher(hosts2[i]);
            if (m.find()) {
                node_port = m.group(1);
                if (!isPort(node_port)) {
                    throw new IllegalArgumentException("invalid port given for host " + Integer.toString(i + 1));
                }
                hosts2[i] = hosts2[i].replaceAll(":\\d+$", "");
            }
            hosts2[i] = validateHost(hosts2[i]);
            //hosts2[i] = validateResolvable(hosts2[i]);
            if (node_port == null) {
                node_port = Integer.toString(port);
            }
            hosts2[i] = hosts2[i] + ":" + node_port;
            vlogOption("port", node_port);
        }
        return hosts2;
    }

    public static final String[] validateHosts(String[] hosts, String port) {
        // don't uniq here it's done in called validateHosts method
        return validateHosts(hosts, parsePort(port));
    }

    public static final ArrayList<String> validateHosts(ArrayList<String> hosts, int port) {
        // don't uniq here it's done in called validateHosts method
        return arrayToArraylist(validateHosts(arraylistToArray(hosts), port));
    }

    public static final ArrayList<String> validateHosts(ArrayList<String> hosts, String port) {
        // don't uniq here it's done in called validateHosts method
        return validateHosts(hosts, parsePort(port));
    }

    public static final String validateHosts(String hosts, int port) {
        if (hosts == null) {
            throw new IllegalArgumentException("hosts not defined (null)");
        }
        if (hosts.trim().isEmpty()) {
            throw new IllegalArgumentException("hosts not defined (blank)");
        }
        String[] hosts2 = validateHosts(hosts.split("[,\\s]+"), port);
        String final_hosts = StringUtils.join(hosts2, ",");
        // vlogged in validateNodePortList
        //vlogOption("node list", final_hosts);
        return final_hosts;
    }

    public static final String validateHosts(String hosts, String port) {
        return validateHosts(hosts, parsePort(port));
    }

    public static final String validateHostPort(String hostport, String name, Boolean port_required,
            Boolean novlog) {
        String name2 = name(name);
        if (hostport == null) {
            throw new IllegalArgumentException(name2 + "host:port not defined (null)");
        }
        String hostport2 = hostport.trim();
        if (hostport2.isEmpty()) {
            throw new IllegalArgumentException(name2 + "host:port not defined (blank)");
        }
        String[] host_port = hostport2.split(":");
        if (host_port.length > 2) {
            throw new IllegalArgumentException(
                    "invalid " + name2 + "host:port supplied (too many colon separated components)");
        }
        if (!isHost(host_port[0])) {
            throw new IllegalArgumentException("invalid " + name2 + "host:port '" + hostport2
                    + "' defined: host portion '" + host_port[0] + "' is not a valid hostname or IP address");
        }
        if (host_port.length > 1) {
            if (!isPort(host_port[1])) {
                throw new IllegalArgumentException(String.format(
                        "invalid port '%s' defined for " + name2 + "host:port: must be a positive integer",
                        host_port[1]));
            }
        } else if (port_required) {
            throw new IllegalArgumentException("port is required");
        }
        if (!novlog) {
            vlogOption(name2 + "hostport", hostport2);
        }
        return hostport2;
    }

    public static final String validateHostPort(String host, String name, Boolean port_required) {
        return validateHostPort(host, name, port_required, false);
    }

    public static final String validateHostPort(String host, String name) {
        return validateHostPort(host, name, false, false);
    }

    public static final String validateHostPort(String host) {
        return validateHostPort(host, null, false, false);
    }

    public static final String validateHostname(String hostname, String name) {
        String name2 = name(name);
        if (hostname == null) {
            throw new IllegalArgumentException("hostname not defined (null)");
        }
        String hostname2 = hostname.trim();
        if (hostname2.isEmpty()) {
            throw new IllegalArgumentException("hostname not defined (blank)");
        }
        if (!isHostname(hostname2)) {
            throw new IllegalArgumentException("invalid " + name2 + "hostname '" + hostname2 + "' defined");
        }
        vlogOption(name2 + "hostname", hostname2);
        return hostname2;
    }

    public static final String validateHostname(String hostname) {
        return validateHostname(hostname, null);
    }

    public static final double validateDouble(double d, String name, double minVal, double maxVal) {
        String name2 = requireName(name);
        if (minVal > maxVal) {
            throw new IllegalArgumentException("minVal cannot be > maxVal");
        }
        if (d < minVal) {
            throw new IllegalArgumentException("invalid " + name2 + " defined: cannot be lower than " + minVal);
        }
        if (d > maxVal) {
            throw new IllegalArgumentException("invalid " + name2 + " defined: cannot be greater than " + maxVal);
        }
        // TODO: trim trailing zeros from double
        vlogOption(name2, String.valueOf(d));
        return d;
    }

    public static final long validateLong(long l, String name, long minVal, long maxVal) {
        validateDouble(l, name, minVal, maxVal);
        return l;
    }

    public static final int validateInt(int i, String name, int minVal, int maxVal) {
        validateDouble(i, name, minVal, maxVal);
        return i;
    }

    public static final float validateFloat(float f, String name, float minVal, float maxVal) {
        validateDouble(f, name, minVal, maxVal);
        return f;
    }

    public static final double validateDouble(String d, String name, double minVal, double maxVal) {
        String name2 = requireName(name);
        double d_double = -1;
        try {
            d_double = Double.parseDouble(d);
        } catch (NumberFormatException e) {
            throw new IllegalArgumentException("invalid " + name2 + " defined: must be numeric (double)");
        }
        // log.info(String.format(option_format, option + ":", value)); done in validateDouble
        validateDouble(d_double, name2, minVal, maxVal);
        return d_double;
    }

    public static final long validateLong(String l, String name, long minVal, long maxVal) {
        String name2 = requireName(name);
        long l_long = -1;
        try {
            l_long = Long.parseLong(l);
        } catch (NumberFormatException e) {
            throw new IllegalArgumentException("invalid " + name2 + " defined: must be numeric (long)");
        }
        // log.info(String.format(option_format, option + ":", value)); done in validateLong
        validateDouble(l_long, name2, minVal, maxVal);
        return l_long;
    }

    public static final int validateInt(String i, String name, int minVal, int maxVal) {
        String name2 = requireName(name);
        int i_int = -1;
        try {
            i_int = Integer.parseInt(i);
        } catch (NumberFormatException e) {
            //if(debug){
            //  e.printStackTrace();
            //}
            throw new IllegalArgumentException("invalid " + name2 + " defined: must be numeric (int)");
        }
        // log.info(String.format(option_format, option + ":", value)); done in pass through to validateLong
        validateDouble(i_int, name2, minVal, maxVal);
        return i_int;
    }

    public static final float validateFloat(String f, String name, float minVal, float maxVal) {
        String name2 = requireName(name);
        float f_float = -1;
        try {
            f_float = Float.parseFloat(f);
        } catch (NumberFormatException e) {
            throw new IllegalArgumentException("invalid " + name2 + " defined: must be numeric (float)");
        }
        // log.info(String.format(option_format, option + ":", value)); done in pass through to validateLong
        validateDouble(f_float, name2, minVal, maxVal);
        return f_float;
    }

    public static final String validateInterface(String networkInterface) {
        if (networkInterface == null) {
            throw new IllegalArgumentException("network interface not defined (null)");
        }
        String networkInterface2 = networkInterface.trim();
        if (networkInterface2.isEmpty()) {
            throw new IllegalArgumentException("network interface not defined (blank)");
        }
        if (!isInterface(networkInterface2)) {
            throw new IllegalArgumentException(
                    "invalid network interface defined: must be either eth<N>, bond<N> or lo<N>");
        }
        vlogOption("interface", networkInterface2);
        return networkInterface2;
    }

    public static final String validateIP(String ip, String name) {
        String name2 = name(name);
        if (ip == null) {
            throw new IllegalArgumentException(name2 + "IP not defined (null)");
        }
        String ip2 = ip.trim();
        if (ip2.isEmpty()) {
            throw new IllegalArgumentException(name2 + "IP not defined (blank)");
        }
        if (!isIP(ip2)) {
            throw new IllegalArgumentException("invalid " + name2 + "IP defined");
        }
        vlogOption(name2 + "ip", ip2);
        return ip2;
    }

    public static final String validateIP(String ip) {
        return validateIP(ip, null);
    }

    public static final String validateKrb5Princ(String princ, String name) {
        String name2 = name(name);
        if (princ == null) {
            throw new IllegalArgumentException(name2 + "krb5 principal not defined (null)");
        }
        String princ2 = princ.trim();
        if (princ2.isEmpty()) {
            throw new IllegalArgumentException(name2 + "krb5 principal not defined (blank)");
        }
        if (!isKrb5Princ(princ2)) {
            throw new IllegalArgumentException("invalid " + name2 + "krb5 principal defined");
        }
        vlogOption(name2 + "krb5 principal", princ2);
        return princ2;
    }

    public static final String validateKrb5Princ(String princ) {
        return validateKrb5Princ(princ, null);
    }

    public static final String validateKrb5Realm(String realm, String name) {
        String name2 = name(name);
        if (realm == null) {
            throw new IllegalArgumentException(name2 + "realm not defined (null)");
        }
        String realm2 = realm.trim();
        if (realm2.isEmpty()) {
            throw new IllegalArgumentException(name2 + "realm not defined (blank)");
        }
        if (!isDomain(realm2)) {
            throw new IllegalArgumentException("invalid " + name2 + "realm defined");
        }
        vlogOption(name2 + "realm", realm2);
        return realm2;
    }

    public static final String validateKrb5Realm(String realm) {
        return validateKrb5Realm(realm, null);
    }

    public static final String validateLabel(String label) {
        if (label == null) {
            throw new IllegalArgumentException("label not defined (null)");
        }
        String label2 = label.trim();
        if (label2.isEmpty()) {
            throw new IllegalArgumentException("label not defined (blank)");
        }
        if (!isLabel(label2)) {
            throw new IllegalArgumentException("invalid label defined: must be an alphanumeric identifier");
        }
        vlogOption("label", label2);
        return label2;
    }

    public static final String validateLdapDn(String dn, String name) {
        String name2 = name(name);
        if (dn == null) {
            throw new IllegalArgumentException("ldap " + name2 + "dn not defined (null)");
        }
        String dn2 = dn.trim();
        if (dn2.isEmpty()) {
            throw new IllegalArgumentException("ldap " + name2 + "dn not defined (blank)");
        }
        if (!isLdapDn(dn2)) {
            throw new IllegalArgumentException("invalid " + name2 + "ldap dn defined");
        }
        vlogOption("ldap " + name2 + "dn", dn2);
        return dn2;
    }

    public static final String validateLdapDn(String dn) {
        return validateLdapDn(dn, null);
    }

    public static final ArrayList<String> validateNodeList(ArrayList<String> nodes) {
        ArrayList<String> final_nodes = new ArrayList<String>();
        ArrayList<String> nodes2 = uniqArraylistOrdered(nodes);
        if (nodes2.size() < 1) {
            throw new IllegalArgumentException("node(s) not defined");
        }
        for (String node : nodes2) {
            //node = node.trim();
            for (String node2 : node.split("[,\\s]+")) {
                node2 = node2.trim();
                if (!isHost(node2)) {
                    throw new IllegalArgumentException(
                            "invalid node name '" + node2 + "': must be hostname/FQDN or IP address");
                }
                final_nodes.add(node2);
            }
        }
        if (final_nodes.size() < 1) {
            throw new IllegalArgumentException("node(s) not defined (empty nodes given)");
        }
        vlogOption("node list", final_nodes.toString());
        return final_nodes;
    }

    public static final String[] validateNodeList(String[] nodes) {
        // don't uniq here it's done in called validateNodeList method
        return arraylistToArray(validateNodeList(arrayToArraylist(nodes)));
    }

    public static final String validateNodeList(String nodelist) {
        if (nodelist == null) {
            throw new IllegalArgumentException("node(s) not defined (null)");
        }
        if (nodelist.trim().isEmpty()) {
            throw new IllegalArgumentException("node(s) not defined (blank)");
        }
        String[] nodelist2 = validateNodeList(nodelist.split("[,\\s]+"));
        String final_nodes = StringUtils.join(nodelist2, ",");
        // vlogged in validateNodeList
        //vlogOption("node list", final_nodes);
        return final_nodes;
    }

    public static final ArrayList<String> validateNodePortList(ArrayList<String> nodes, String name) {
        String name2 = "";
        if (name != null) {
            name2 = name + " ";
        }
        ArrayList<String> final_nodes = new ArrayList<String>();
        ArrayList<String> nodes2 = uniqArraylistOrdered(nodes);
        if (nodes2.size() < 1) {
            throw new IllegalArgumentException(String.format("%snode(s) not defined", name2));
        }
        for (String node : nodes2) {
            //node = node.trim();
            for (String node2 : node.split("[,\\s]+")) {
                //node2 = node2.trim();
                final_nodes.add(validateHostPort(node2));
            }
        }
        vlogOption(String.format("%snodeport list", name2), final_nodes.toString());
        return final_nodes;
    }

    public static final ArrayList<String> validateNodePortList(ArrayList<String> nodes) {
        return validateNodePortList(nodes, null);
    }

    public static final String[] validateNodePortList(String[] nodes, String name) {
        // don't uniq here it's done in called validateNodePortList method
        return arraylistToArray(validateNodePortList(arrayToArraylist(nodes), name));
    }

    public static final String[] validateNodePortList(String[] nodes) {
        return validateNodePortList(nodes, null);
    }

    public static final String validateNodePortList(String nodelist, String name) {
        String name2 = "";
        if (name == null) {
            name2 = name + " ";
        }
        if (nodelist == null) {
            throw new IllegalArgumentException(String.format("%snode(s) not defined (null)", name2));
        }
        if (nodelist.trim().isEmpty()) {
            throw new IllegalArgumentException(String.format("%snode(s) not defined (blank)", name2));
        }
        String[] nodelist2 = validateNodePortList(nodelist.split("[,\\s]+"));
        String final_nodes = StringUtils.join(nodelist2, ",");
        // vlogged in validateNodePortList
        //vlogOption("node list", final_nodes);
        return final_nodes;
    }

    public static final String validateNodePortList(String nodelist) {
        return validateNodePortList(nodelist, null);
    }

    public static final String validateNoSqlKey(String key, String name) {
        String name2 = name(name);
        if (key == null) {
            throw new IllegalArgumentException(name2 + "key not defined (null)");
        }
        if (key.trim().isEmpty()) {
            throw new IllegalArgumentException(name2 + "key not defined (blank)");
        }
        String key2 = key.trim();
        if (!isNoSqlKey(key2)) {
            throw new IllegalArgumentException("invalid " + name2
                    + "key defined: may only contain characters: alphanumeric, commas, colons, underscores, pluses and dashes");
        }
        vlogOption(name2 + "key", key2);
        return key2;
    }

    public static final String validateNoSqlKey(String key) {
        return validateNoSqlKey(key, null);
    }

    public static final int validatePort(int port, String name) {
        String name2 = name(name);
        if (!isPort(port)) {
            throw new IllegalArgumentException("invalid " + name2 + "port defined");
        }
        vlogOption(name2 + "port", String.valueOf(port));
        return port;
    }

    public static final String validatePort(String port, String name) {
        String name2 = name(name);
        int port_int = -1;
        try {
            port_int = Integer.parseInt(port);
        } catch (NumberFormatException e) {
            throw new IllegalArgumentException("invalid " + name2 + "port specified: must be numeric");
        }
        return String.valueOf(validatePort(port_int, name2));
    }

    public static final int validatePort(int port) {
        return validatePort(port, null);
    }

    public static final String validatePort(String port) {
        return validatePort(port, null);
    }

    public static final String validateProcessName(String process, String name) {
        String name2 = name(name);
        if (process == null) {
            throw new IllegalArgumentException(name2 + "process name not defined (null)");
        }
        String process2 = process.trim();
        if (process2.isEmpty()) {
            throw new IllegalArgumentException(name2 + "process name not defined (blank)");
        }
        if (!isProcessName(process2)) {
            throw new IllegalArgumentException("invalid " + name2 + "process name defined:");
        }
        return process2;
    }

    public static final String validateProcessName(String process) {
        return validateProcessName(process, null);
    }

    public static final String validateProgramPath(String path, String name, String regex) {
        String name2 = requireName(name).trim();
        if (path == null) {
            throw new IllegalArgumentException(name2 + " path not defined (null)");
        }
        String path2 = path.trim();
        if (path2.isEmpty()) {
            throw new IllegalArgumentException(name2 + " path not defined (blank)");
        }
        if (!path2.matches("^[./]")) {
            try {
                path2 = which(path2);
            } catch (IOException e) {
                //                throw new IllegalArgumentException(name + " program not found in $PATH (" + System.getenv("PATH") + ")");
                throw new IllegalArgumentException(e.getMessage());
            }
        }
        String regex2;
        if (regex == null || regex.trim().isEmpty()) {
            regex2 = name2;
        } else {
            regex2 = regex.trim();
        }
        if (validateRegex(regex2, "program path regex", true) == null) {
            throw new IllegalArgumentException("invalid regex given to validateProgramPath()");
        }
        validateFilename(path2, null, true);
        //        if(validateFilename(path, null, true) == null){
        //            throw new IllegalArgumentException("invalid path given for " + name + ", failed filename regex");
        //        }
        if (!path2.matches("(?:^|.*/)" + regex2 + "$")) {
            throw new IllegalArgumentException(
                    "invalid path given for " + name2 + ", is not a path to the " + name2 + " command");
        }
        File f = new File(path2);
        if (!(f.exists() && f.isFile())) {
            throw new IllegalArgumentException(path2 + " not found");
        }
        if (!f.canExecute()) {
            throw new IllegalArgumentException(path2 + " not executable");
        }
        vlogOption(name2 + " program path", path2);
        return path2;
    }

    public static final String validateProgramPath(String path, String name) {
        return validateProgramPath(path, name, null);
    }

    public static final String validateRegex(String regex, String name, Boolean posix) {
        String name2 = name(name);
        // intentionally not trimming
        if (regex == null) {
            throw new IllegalArgumentException(name2 + "regex not defined (null)");
        }
        if (regex.trim().isEmpty()) {
            throw new IllegalArgumentException(name2 + "regex not defined (blank)");
        }
        if (posix) {
            if (regex.matches(".*(?:\\$\\(|`).*")) {
                throw new IllegalArgumentException("invalid " + name2
                        + "posix regex supplied: contains sub shell metachars ( $( / ` ) that would be dangerous to pass to shell");
            }
            // TODO: cmd("egrep '$regex' < /dev/null") and check for any output signifying error with the regex
        } else {
            try {
                "".matches(regex);
            } catch (PatternSyntaxException e) {
                throw new IllegalArgumentException("invalid " + name2 + "regex defined");
            }
        }
        vlogOption(name2 + "regex", regex);
        return regex;
    }

    public static final String validateRegex(String regex, String name) {
        return validateRegex(regex, name, false);
    }

    public static final String validateUser(String user, String name) {
        String name2 = name(name);
        if (user == null) {
            throw new IllegalArgumentException(name2 + "user not defined (null)");
        }
        String user2 = user.trim();
        if (user2.isEmpty()) {
            throw new IllegalArgumentException(name2 + "user not defined (blank)");
        }
        if (!isUser(user2)) {
            throw new IllegalArgumentException("invalid " + name2 + "username defined: must be alphanumeric");
        }
        vlogOption(name2 + "user", user2);
        return user2;
    }

    public static final String validateUser(String user) {
        return validateUser(user, null);
    }

    public static final String validateUserExists(String user, String name)
            throws IOException, UnsupportedOSException {
        String user2 = validateUser(user, name);
        String name2 = name(name);
        if (!userExists(user2)) {
            throw new IllegalArgumentException("invalid " + name2 + "user defined, not found on local system");
        }
        return user2;
    }

    public static final String validatePassword(String password, String name, Boolean allow_all) {
        String name2 = name(name);
        if (password == null) {
            throw new IllegalArgumentException(name2 + "password not defined (null)");
        }
        if (password.trim().isEmpty()) {
            throw new IllegalArgumentException(name2 + "password not defined (blank)");
        }
        if (allow_all) {
            return password;
        }
        if (password.matches(".*[\"'`].*")) {
            throw new IllegalArgumentException(
                    "invalid " + name2 + "password defined: may not contain quotes or backticks");
        }
        if (password.matches(".*\\$\\(.*")) {
            throw new IllegalArgumentException("invalid " + name2
                    + "password defined: may not contain $( as this is a subshell escape and could be dangerous to pass through to programs, especially on the command line");
        }
        vlogOption("password", "<omitted>");
        return password;
    }

    public static final String validatePassword(String password, String name) {
        return validatePassword(password, name, false);
    }

    public static final String validatePassword(String password) {
        return validatePassword(password, null, false);
    }

    public static final String validateResolvable(String host, String name) throws UnknownHostException {
        String name2 = name(name);
        if (host == null) {
            throw new IllegalArgumentException(name2 + "host not defined (null)");
        }
        String host2 = host.trim();
        if (host2.isEmpty()) {
            throw new IllegalArgumentException(name2 + "host not defined (blank)");
        }
        // throws exception now, no nulls
        String ip = resolveIp(host2);
        //        if(ip == null){
        //            quit("CRITICAL", "failed to resolve " + name + "host '" + host + "'");
        //        }
        return ip;
    }

    public static final String validateResolvable(String host) throws UnknownHostException {
        return validateResolvable(host, null);
    }

    public static final String validateUnits(String units, String name) {
        String name2 = name(name);
        if (units == null) {
            throw new IllegalArgumentException(name2 + "units not defined (null)");
        }
        String units2 = units.trim();
        if (units2.isEmpty()) {
            throw new IllegalArgumentException(name2 + "units not defined (blank)");
        }
        if (!isNagiosUnit(units2)) {
            throw new IllegalArgumentException("invalid " + name2 + "units '" + units2
                    + "' defined, must be one of: " + valid_units.toString());
        }
        vlogOption(name2 + "units", units2);
        return units2;
    }

    public static final String validateUnits(String units) {
        return validateUnits(units, null);
    }

    public static final String validateUrl(String url, String name) {
        String name2 = name(name);
        if (url == null) {
            throw new IllegalArgumentException(name2 + "url not defined (null)");
        }
        String url2 = url.trim();
        if (url2.isEmpty()) {
            throw new IllegalArgumentException(name2 + "url not defined (blank)");
        }
        if (!url2.contains("://")) {
            url2 = "http://" + url2;
        }
        if (!isUrl(url2)) {
            throw new IllegalArgumentException("invalid " + name2 + "url defined: '" + url2 + "'");
        }
        vlogOption(name2 + "url", url2);
        return url2;
    }

    public static final String validateUrl(String url) {
        return validateUrl(url, null);
    }

    public static final String validateUrlPathSuffix(String url, String name) {
        String name2 = name(name);
        if (url == null) {
            throw new IllegalArgumentException(name2 + "url not defined (null)");
        }
        String url2 = url.trim();
        if (url2.isEmpty()) {
            throw new IllegalArgumentException(name2 + "url not defined (blank)");
        }
        if (!isUrlPathSuffix(url2)) {
            throw new IllegalArgumentException("invalid " + name2 + "url defined: '" + url2 + "'");
        }
        return url2;
    }

    public static final String validateUrlPathSuffix(String url) {
        return validateUrlPathSuffix(url, null);
    }

    public static final String getVersion() {
        return utils_version;
    }

    public static final void version() {
        println("Hari Sekhon Java Utils version " + getVersion());
    }

    public static final String which(String bin) throws IOException {
        if (bin == null || bin.trim().isEmpty()) {
            throw new IllegalArgumentException("no bin passed to which()");
        }
        // TODO: should probably consider switching this to os path sep instead of unix biased /
        if (bin.matches("^(?:/|\\./).*")) {
            File f = new File(bin);
            if (f.isFile()) {
                if (f.canExecute()) {
                    return bin;
                } else {
                    throw new IOException(String.format("'%s' is not executable!", bin));
                }
            } else {
                throw new IOException(String.format("couldn't find executable '%s'", bin));
            }
        } else {
            for (String path : System.getenv("PATH").split(":")) {
                String fullpath = path + "/" + bin;
                File f = new File(fullpath);
                //                if(f.exists() && ! f.isDirectory()){
                //                    if(! f.canExecute()){
                //                        throw new IOException(String.format("'%s' is not executable!", bin);
                //                    }
                if (f.isFile() && f.canExecute()) {
                    return fullpath;
                }
            }
            throw new IOException(String.format("couldn't find '%s' in PATH (%s)", bin, System.getenv("PATH")));
        }
    }

    // ===================================================================== //
    //
    //                            L o g g i n g
    //
    // ===================================================================== //

    // use verbose to set log.setLogLevel one higher

    //    public static final int getVerbose(){
    //        return log.getLogLevel();
    //    }

    // should be handled in CLI
    //    public static final void setVerbose(int verbosity){
    //        if(verbosity > 4) {
    //            log.setLevel(Level.ALL);
    //        } else if(verbosity > 3) {
    //            log.setLevel(Level.TRACE);
    //        } else if(verbosity == 3) {
    //            log.setLevel(Level.INFO);
    //        } else if (verbosity == 2) {
    //            log.setLevel(Level.WARN);
    //        } else if (verbosity == 1) {
    //            log.setLevel(Level.ERROR);
    //        } else if (verbosity == 0) {
    //            log.setLevel(Level.FATAL);
    //        } else {
    //            log.setLevel(Level.INFO);
    //        }
    //    }

    public static final String getCallingMethod() {
        StackTraceElement[] stackTraceElements = Thread.currentThread().getStackTrace();
        String parent = "Could not find calling method";
        if (stackTraceElements.length > 3) {
            parent = String.valueOf(stackTraceElements[3]);
        }
        return parent.replaceFirst("com.linkedin.harisekhon.Utils.", "");
    }

    public static final void vlog(String msg) {
        //        log.info(String.format(getCallingMethod() + " - " + msg));
        log.warn(msg);
    }

    public static final void vlog2(String msg) {
        //        log.debug(String.format(getCallingMethod() + " - " + msg));
        log.info(msg);
    }

    public static final void vlog3(String msg) {
        //        log.trace(String.format(getCallingMethod() + " - " + msg));
        log.debug(msg);
    }

    public static final void vlogOption(String name, String value) {
        //        log.info(String.format(option_format_calling_method, getCallingMethod(), name + ":", value));
        vlog2(String.format(option_format, name + ":", value));
    }

    public static final void vlogOption(String name, boolean value) {
        vlogOption(name, String.valueOf(value));
    }

    //    public static final void log.info(String.format(option_format, option + ":", value));_bool (String option, Boolean value) {
    //        vlogOption(option, value.toString());
    //    }
}