Path: blob/master/src/jdk.jcmd/share/classes/sun/tools/jstat/Arguments.java
41159 views
/*1* Copyright (c) 2004, 2018, Oracle and/or its affiliates. All rights reserved.2* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.3*4* This code is free software; you can redistribute it and/or modify it5* under the terms of the GNU General Public License version 2 only, as6* published by the Free Software Foundation. Oracle designates this7* particular file as subject to the "Classpath" exception as provided8* by Oracle in the LICENSE file that accompanied this code.9*10* This code is distributed in the hope that it will be useful, but WITHOUT11* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or12* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License13* version 2 for more details (a copy is included in the LICENSE file that14* accompanied this code).15*16* You should have received a copy of the GNU General Public License version17* 2 along with this work; if not, write to the Free Software Foundation,18* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.19*20* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA21* or visit www.oracle.com if you need additional information or have any22* questions.23*/2425package sun.tools.jstat;2627import java.io.*;28import java.net.*;29import java.util.*;30import java.util.regex.*;31import sun.jvmstat.monitor.Monitor;32import sun.jvmstat.monitor.VmIdentifier;3334/**35* Class for processing command line arguments and providing method36* level access to arguments.37*38* @author Brian Doherty39* @since 1.540*/41public class Arguments {4243private static final boolean debug = Boolean.getBoolean("jstat.debug");44private static final boolean showUnsupported =45Boolean.getBoolean("jstat.showUnsupported");4647private static final String JVMSTAT_USERDIR = ".jvmstat";48private static final String OPTIONS_FILENAME = "jstat_options";49private static final String UNSUPPORTED_OPTIONS_FILENAME = "jstat_unsupported_options";50private static final String ALL_NAMES = "\\w*";5152private Comparator<Monitor> comparator;53private int headerRate;54private boolean help;55private boolean list;56private boolean options;57private boolean constants;58private boolean constantsOnly;59private boolean strings;60private boolean timestamp;61private boolean snap;62private boolean verbose;63private String specialOption;64private String names;6566private OptionFormat optionFormat;6768private int count = -1;69private int interval = -1;70private String vmIdString;7172private VmIdentifier vmId;7374public static void printUsage(PrintStream ps) {75ps.println("Usage: jstat --help|-options");76ps.println(" jstat -<option> [-t] [-h<lines>] <vmid> [<interval> [<count>]]");77ps.println();78ps.println("Definitions:");79ps.println(" <option> An option reported by the -options option");80ps.println(" <vmid> Virtual Machine Identifier. A vmid takes the following form:");81ps.println(" <lvmid>[@<hostname>[:<port>]]");82ps.println(" Where <lvmid> is the local vm identifier for the target");83ps.println(" Java virtual machine, typically a process id; <hostname> is");84ps.println(" the name of the host running the target Java virtual machine;");85ps.println(" and <port> is the port number for the rmiregistry on the");86ps.println(" target host. See the jvmstat documentation for a more complete");87ps.println(" description of the Virtual Machine Identifier.");88ps.println(" <lines> Number of samples between header lines.");89ps.println(" <interval> Sampling interval. The following forms are allowed:");90ps.println(" <n>[\"ms\"|\"s\"]");91ps.println(" Where <n> is an integer and the suffix specifies the units as ");92ps.println(" milliseconds(\"ms\") or seconds(\"s\"). The default units are \"ms\".");93ps.println(" <count> Number of samples to take before terminating.");94ps.println(" -J<flag> Pass <flag> directly to the runtime system.");95ps.println(" -? -h --help Prints this help message.");96ps.println(" -help Prints this help message.");9798// undocumented options:99// -list [<vmid>] - list counter names100// -snap <vmid> - snapshot counter values as name=value pairs101// -name <pattern> - output counters matching given pattern102// -a - sort in ascending order (default)103// -d - sort in descending order104// -v - verbose output (-snap)105// -constants - output constants with -name output106// -strings - output strings with -name output107// -help - same as -? ...108}109110private static int toMillis(String s) throws IllegalArgumentException {111112String[] unitStrings = { "ms", "s" }; // ordered from most specific to113// least specific114String unitString = null;115String valueString = s;116117for (int i = 0; i < unitStrings.length; i++) {118int index = s.indexOf(unitStrings[i]);119if (index > 0) {120unitString = s.substring(index);121valueString = s.substring(0, index);122break;123}124}125126try {127int value = Integer.parseInt(valueString);128129if (unitString == null || unitString.compareTo("ms") == 0) {130return value;131} else if (unitString.compareTo("s") == 0) {132return value * 1000;133} else {134throw new IllegalArgumentException(135"Unknow time unit: " + unitString);136}137} catch (NumberFormatException e) {138throw new IllegalArgumentException(139"Could not convert interval: " + s);140}141}142143public Arguments(String[] args) throws IllegalArgumentException {144int argc = 0;145146if (args.length == 0) {147help = true;148return;149}150151if ((args[0].compareTo("-?") == 0)152|| (args[0].compareTo("-h") == 0)153|| (args[0].compareTo("--help") == 0)154// -help: legacy.155|| (args[0].compareTo("-help") == 0)) {156help = true;157return;158} else if (args[0].compareTo("-options") == 0) {159options = true;160return;161} else if (args[0].compareTo("-list") == 0) {162list = true;163if (args.length > 2) {164throw new IllegalArgumentException("invalid argument count");165}166// list can take one arg - a vmid - fall through for arg processing167argc++;168}169170for ( ; (argc < args.length) && (args[argc].startsWith("-")); argc++) {171String arg = args[argc];172173if (arg.compareTo("-a") == 0) {174comparator = new AscendingMonitorComparator();175} else if (arg.compareTo("-d") == 0) {176comparator = new DescendingMonitorComparator();177} else if (arg.compareTo("-t") == 0) {178timestamp = true;179} else if (arg.compareTo("-v") == 0) {180verbose = true;181} else if ((arg.compareTo("-constants") == 0)182|| (arg.compareTo("-c") == 0)) {183constants = true;184} else if ((arg.compareTo("-strings") == 0)185|| (arg.compareTo("-s") == 0)) {186strings = true;187} else if (arg.startsWith("-h")) {188String value;189if (arg.compareTo("-h") != 0) {190value = arg.substring(2);191} else {192argc++;193if (argc >= args.length) {194throw new IllegalArgumentException(195"-h requires an integer argument");196}197value = args[argc];198}199try {200headerRate = Integer.parseInt(value);201} catch (NumberFormatException e) {202headerRate = -1;203}204if (headerRate < 0) {205throw new IllegalArgumentException(206"illegal -h argument: " + value);207}208} else if (arg.startsWith("-name")) {209if (arg.startsWith("-name=")) {210names = arg.substring(7);211} else {212argc++;213if (argc >= args.length) {214throw new IllegalArgumentException(215"option argument expected");216}217names = args[argc];218}219} else {220/*221* there are scenarios here: special jstat_options file option222* or the rare case of a negative lvmid. The negative lvmid223* can occur in some operating environments (such as Windows224* 95/98/ME), so we provide for this case here by checking if225* the argument has any numerical characters. This assumes that226* there are no special jstat_options that contain numerical227* characters in their name.228*/229230// extract the lvmid part of possible [email protected]:port231String lvmidStr = null;232int at_index = args[argc].indexOf('@');233if (at_index < 0) {234lvmidStr = args[argc];235} else {236lvmidStr = args[argc].substring(0, at_index);237}238239// try to parse the lvmid part as an integer240try {241int vmid = Integer.parseInt(lvmidStr);242// it parsed, assume a negative lvmid and continue243break;244} catch (NumberFormatException nfe) {245// it didn't parse. check for the -snap or jstat_options246// file options.247if ((argc == 0) && (args[argc].compareTo("-snap") == 0)) {248snap = true;249} else if (argc == 0) {250specialOption = args[argc].substring(1);251} else {252throw new IllegalArgumentException(253"illegal argument: " + args[argc]);254}255}256}257}258259// prevent 'jstat <pid>' from being accepted as a valid argument260if (!(specialOption != null || list || snap || names != null)) {261throw new IllegalArgumentException("-<option> required");262}263264switch (args.length - argc) {265case 3:266if (snap) {267throw new IllegalArgumentException("invalid argument count");268}269try {270count = Integer.parseInt(args[args.length-1]);271} catch (NumberFormatException e) {272throw new IllegalArgumentException("illegal count value: "273+ args[args.length-1]);274}275interval = toMillis(args[args.length-2]);276vmIdString = args[args.length-3];277break;278case 2:279if (snap) {280throw new IllegalArgumentException("invalid argument count");281}282interval = toMillis(args[args.length-1]);283vmIdString = args[args.length-2];284break;285case 1:286vmIdString = args[args.length-1];287break;288case 0:289if (!list) {290throw new IllegalArgumentException("invalid argument count");291}292break;293default:294throw new IllegalArgumentException("invalid argument count");295}296297// set count and interval to their default values if not set above.298if (count == -1 && interval == -1) {299// default is for a single sample300count = 1;301interval = 0;302}303304// validate arguments305if (comparator == null) {306comparator = new AscendingMonitorComparator();307}308309// allow ',' characters to separate names, convert to '|' chars310names = (names == null) ? ALL_NAMES : names.replace(',', '|');311312// verify that the given pattern parses without errors313try {314Pattern pattern = Pattern.compile(names);315} catch (PatternSyntaxException e) {316throw new IllegalArgumentException("Bad name pattern: "317+ e.getMessage());318}319320// verify that the special option is valid and get it's formatter321if (specialOption != null) {322OptionFinder finder = new OptionFinder(optionsSources());323optionFormat = finder.getOptionFormat(specialOption, timestamp);324if (optionFormat == null) {325throw new IllegalArgumentException("Unknown option: -"326+ specialOption);327}328}329330// verify that the vm identifier is valied331try {332vmId = new VmIdentifier(vmIdString);333} catch (URISyntaxException e) {334IllegalArgumentException iae = new IllegalArgumentException(335"Malformed VM Identifier: " + vmIdString);336iae.initCause(e);337throw iae;338}339}340341public Comparator<Monitor> comparator() {342return comparator;343}344345public boolean isHelp() {346return help;347}348349public boolean isList() {350return list;351}352353public boolean isSnap() {354return snap;355}356357public boolean isOptions() {358return options;359}360361public boolean isVerbose() {362return verbose;363}364365public boolean printConstants() {366return constants;367}368369public boolean isConstantsOnly() {370return constantsOnly;371}372373public boolean printStrings() {374return strings;375}376377public boolean showUnsupported() {378return showUnsupported;379}380381public int headerRate() {382return headerRate;383}384385public String counterNames() {386return names;387}388389public VmIdentifier vmId() {390return vmId;391}392393public String vmIdString() {394return vmIdString;395}396397public int sampleInterval() {398return interval;399}400401public int sampleCount() {402return count;403}404405public boolean isTimestamp() {406return timestamp;407}408409public boolean isSpecialOption() {410return specialOption != null;411}412413public String specialOption() {414return specialOption;415}416417public OptionFormat optionFormat() {418return optionFormat;419}420421public List<URL> optionsSources() {422List<URL> sources = new ArrayList<URL>();423int i = 0;424425String filename = OPTIONS_FILENAME;426427try {428String userHome = System.getProperty("user.home");429String userDir = userHome + "/" + JVMSTAT_USERDIR;430File home = new File(userDir + "/" + filename);431sources.add(home.toURI().toURL());432} catch (Exception e) {433if (debug) {434System.err.println(e.getMessage());435e.printStackTrace();436}437throw new IllegalArgumentException("Internal Error: Bad URL: "438+ e.getMessage());439}440URL u = this.getClass().getResource("resources/" + filename);441assert u != null;442sources.add(u);443444if (showUnsupported) {445u = this.getClass().getResource("resources/" + UNSUPPORTED_OPTIONS_FILENAME);446assert u != null;447sources.add(u);448}449return sources;450}451}452453454