/* * Copyright (c) 2003, 2018, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it * under the terms of the GNU General Public License version 2 only, as * published by the Free Software Foundation. * * This code is distributed in the hope that it will be useful, but WITHOUT * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License * version 2 for more details (a copy is included in the LICENSE file that * accompanied this code). * * You should have received a copy of the GNU General Public License version * 2 along with this work; if not, write to the Free Software Foundation, * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. * * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA * or visit www.oracle.com if you need additional information or have any * questions. */ package nsk.monitoring.share; import nsk.share.log.Log; import nsk.share.TestBug; import nsk.share.ArgumentParser; import java.lang.management.*; /** * Parser for JSR-174 test's arguments. *

* ArgumentHandler handles specific command line arguments * related to way of execution of a test in addition to general arguments * recognized by {@link ArgumentParser ArgumentParser}. *

* Following is the list of specific options for ArgumentHandler: *

*

* See also list of basic options recognized by ArgumentParser. *

* See also comments to ArgumentParser how to work with * command line arguments and options. * * @see ArgumentParser */ public class ArgumentHandler extends ArgumentParser { static final String TEST_MODE = "testMode"; static final String DIRECTLY_MODE = "directly"; static final String SERVER_MODE = "server"; static final String PROXY_MODE = "proxy"; static final String SERVER_TYPE = "MBeanServer"; static final String DEFAULT_TYPE = "default"; static final String CUSTOM_TYPE = "custom"; static final String LOADABLE_CLASSES_COUNT = "loadableClassCount"; static final String LOADERS_COUNT = "loadersCount"; static final String SINGLE_CLASSLOADER_CLASS = "singleClassloaderClass"; static final String MEMORY_TYPE = "memory"; static final String MT_HEAP = "heap"; static final String MT_NONHEAP = "nonheap"; static final String MT_MIXED = "mixed"; static final String INVOCATION_TYPE = "invocationType"; static final String JAVA_TYPE = "java"; static final String NATIVE_TYPE = "native"; static final String MIXED_TYPE = "mixed"; static final String MONITORING = "monitoring"; static final String MON_POLLING = "polling"; static final String MON_NOTIF = "notification"; static final String THRESHOLD = "threshold"; static final String TH_USAGE = "usage"; static final String TH_COLLECTION = "collection"; static final String THREAD_DEPTH = "depth"; static final String THREAD_COUNT = "threadCount"; static final String TIMEOUT = "timeout"; static final String SCENARIO_TYPE = "scenarioType"; static final String ITERATIONS = "iterations"; /** * Keep a copy of raw command-line arguments and parse them; * but throw an exception on parsing error. * * @param args Array of the raw command-line arguments. * * @throws BadOption If unknown option or illegal * option value found * * @see ArgumentParser */ public ArgumentHandler(String args[]) { super(args); } /** * Returns the test mode. *

* To access the metrics directly, testMode option should * be defined in command line -testMode="directly". * To access the metrics via MBeanServer, "server" should be * assigned to -testMode="directly". *

* If testMode is not defined by command line, a test is * executed in directly mode. * * @return name of test mode. * */ public String getTestMode() { return options.getProperty(TEST_MODE, DIRECTLY_MODE); } /** * Returns a type of MBean server if any. * Two kinds of MBean servers are allowed: default and custom servers. * Default server is an implementation of {@link * javax.management.MBeanServer javax.management.MBeanServer} * interface provided by JMX. Custom server is an implementation provided * by NSK J2SE SQE Team. Server type is defined by MBeanServer * key in command line -MBeanServer="default" or * -MBeanServer="custom" * * @return MBeanServer server type. * */ public String getServerType() { return options.getProperty(SERVER_TYPE, DEFAULT_TYPE); } /** * Returns true if default implementation is used. * * @return true if default implementation is used. * * @see #getServerType() */ public boolean isDefaultServer() { return getServerType().equals(DEFAULT_TYPE); } /** * Returns amount of class loaders. * * @return loadersCount as an integer value */ public int getLoadersCount() { String val = options.getProperty(LOADERS_COUNT, "100"); int number; try { number = Integer.parseInt(val); } catch (NumberFormatException e) { throw new TestBug("Not integer value of \"" + LOADERS_COUNT + "\" argument: " + val); } return number; } /** * Returns true if class loaders, which perform class loading, are * instances of the same class. If -singleClassloaderClass key * is not set in command line options, then false is returned. * * @return if class loaders are instances of the same class. * */ public boolean singleClassloaderClass() { return options.getProperty(SINGLE_CLASSLOADER_CLASS) != null; } /** * Returns amount of loadable classes. If -loadableClassesCount * key is not set with command line, 100 is returned. * * @return loadableClassesCount as an integer value * * @throws TestBug loadableClassesCount is non-numeric value. * */ public int getLoadableClassesCount() { String val = options.getProperty(LOADABLE_CLASSES_COUNT, "1"); int number; try { number = Integer.parseInt(val); } catch (NumberFormatException e) { throw new TestBug("Not integer value of \"" + LOADABLE_CLASSES_COUNT + "\" argument: " + val); } return number; } /** * Returns invocation type. * * @return invocationType value * */ public String getInvocationType() { return options.getProperty(INVOCATION_TYPE, JAVA_TYPE); } /** * Returns tested memory type. * * @return memory value * */ public String getTestedMemory() { return options.getProperty(MEMORY_TYPE, MT_HEAP); } /** * Returns timeout. * * @return timeout value * */ public int getTimeout() { String value = options.getProperty(TIMEOUT, "30"); try { return Integer.parseInt(value); } catch (NumberFormatException e) { throw new TestBug("Not integer value of \"" + TIMEOUT + "\" argument: " + value); } } /** * Returns recursion depth. * * @return depth value * */ public int getThreadDepth() { String value = options.getProperty(THREAD_DEPTH, "1"); try { return Integer.parseInt(value); } catch (NumberFormatException e) { throw new TestBug("Not integer value of \"" + THREAD_DEPTH + "\" argument: " + value); } } /** * Returns number of threads. * * @return threadCount value * */ public int getThreadCount() { String value = options.getProperty(THREAD_COUNT, "1"); try { return Integer.parseInt(value); } catch (NumberFormatException e) { throw new TestBug("Not integer value of \"" + THREAD_COUNT + "\" argument: " + value); } } /** * Returns type of monitoring. * * @return monitoring value * */ public String getMonitoring() { return options.getProperty(MONITORING, MON_NOTIF); } /** * Returns type of threshold. * * @return threshold value * */ public String getThreshold() { return options.getProperty(THRESHOLD, TH_USAGE); } /** * Returns thread type to create. */ public String getScenarioType() { return options.getProperty(SCENARIO_TYPE, "running"); } public int getIterations() { return Integer.parseInt(options.getProperty(ITERATIONS, "3")); } /** * Checks if an option is allowed and has proper value. * This method is invoked by parseArguments() * * @param option option name * @param value string representation of value * (could be an empty string too) * null if this option has no value * @return true if option is allowed and has proper value * false if otion is not admissible * * @throws BadOption if option has an illegal value * * @see nsk.share.ArgumentParser#parseArguments */ protected boolean checkOption(String option, String value) { // defines directly, server or proxytest mode if (option.equals(TEST_MODE)) { if ( (!value.equals(DIRECTLY_MODE)) && (!value.equals(SERVER_MODE)) && (!value.equals(PROXY_MODE)) ) { throw new BadOption(option + ": must be one of: " + "\"" + DIRECTLY_MODE + "\", " + "\"" + SERVER_MODE + "\", " + "\"" + PROXY_MODE + "\""); } return true; } // defines invocation type for stack filling if (option.equals(INVOCATION_TYPE)) { if ( (!value.equals(JAVA_TYPE)) && (!value.equals(NATIVE_TYPE)) && (!value.equals(MIXED_TYPE)) ) { throw new BadOption(option + ": must be one of: " + "\"" + JAVA_TYPE + "\", " + "\"" + NATIVE_TYPE + "\", " + "\"" + MIXED_TYPE + "\""); } return true; } // defines default or custom MBean server if (option.equals(SERVER_TYPE)) { if ((!value.equals(DEFAULT_TYPE)) && (!value.equals(CUSTOM_TYPE))) { throw new BadOption(option + ": must be one of: \"" + DEFAULT_TYPE + "\", \"" + CUSTOM_TYPE + "\""); } return true; } // defines loadable classes and loaders counts if (option.equals(LOADABLE_CLASSES_COUNT) || option.equals(LOADERS_COUNT) || option.equals(THREAD_DEPTH) || option.equals(THREAD_COUNT)) { try { int number = Integer.parseInt(value); if (number < 0) { throw new BadOption(option + ": value must be a positive " + "integer"); } } catch (NumberFormatException e) { throw new BadOption(option + ": value must be an integer"); } return true; } // defines timeout if (option.equals(TIMEOUT)) { try { int number = Integer.parseInt(value); if (number < 0) throw new BadOption(option + ": value must be a positive " + "integer"); } catch (NumberFormatException e) { throw new BadOption(option + ": value must be an integer"); } return true; } // defines if classloader class is single if (option.equals(SINGLE_CLASSLOADER_CLASS)) { if (!(value == null || value.length() <= 0)) { throw new BadOption(option + ": no value must be specified"); } return true; } // defines memory types if (option.equals(MEMORY_TYPE)) { if ( (!value.equals(MT_HEAP)) && (!value.equals(MT_NONHEAP)) && (!value.equals(MT_MIXED)) ) throw new BadOption(option + ": must be one of: " + "\"" + MT_HEAP + "\", " + "\"" + MT_NONHEAP + "\", " + "\"" + MT_MIXED + "\""); return true; } // defines type of monitoring if (option.equals(MONITORING)) { if ( (!value.equals(MON_POLLING)) && (!value.equals(MON_NOTIF)) ) throw new BadOption(option + ": must be one of: " + "\"" + MON_POLLING + "\", " + "\"" + MON_NOTIF + "\""); return true; } // defines threshold if (option.equals(THRESHOLD)) { if ( (!value.equals(TH_USAGE)) && (!value.equals(TH_COLLECTION)) ) throw new BadOption(option + ": must be one of: " + "\"" + TH_USAGE + "\", " + "\"" + TH_COLLECTION + "\""); return true; } if (option.equals(SCENARIO_TYPE)) { return true; } if (option.equals(ITERATIONS)) { try { int number = Integer.parseInt(value); if (number < 0) throw new BadOption(option + ": value must be a positive " + "integer"); return true; } catch (NumberFormatException e) { throw new BadOption(option + ": value must be an integer"); } } return super.checkOption(option, value); } /** * Check if the values of all options are consistent. * This method is invoked by parseArguments() * * @throws BadOption if options have inconsistent values * * @see nsk.share.ArgumentParser#parseArguments */ protected void checkOptions() { super.checkOptions(); } public void dump(Log log) { log.info("Test mode: " + getTestMode()); log.info("Server type: " + getServerType()); log.info("loadableClassesCount: " + getLoadableClassesCount()); log.info("loadersCount: " + getLoadersCount()); log.info("singleClassloaderClass: " + singleClassloaderClass()); } } // ArgumentHandler