--- a/jdk/src/share/classes/sun/tools/jinfo/JInfo.java Thu Apr 17 15:44:32 2014 +0100
+++ b/jdk/src/share/classes/sun/tools/jinfo/JInfo.java Thu Apr 17 18:20:31 2014 +0200
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2006, 2013, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2006, 2014, 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
@@ -39,42 +39,73 @@
* and decides if the command should be satisfied using the VM attach mechanism
* or an SA tool.
*/
-public class JInfo {
+final public class JInfo {
+ private boolean useSA = false;
+ private String[] args = null;
- @SuppressWarnings("fallthrough")
- public static void main(String[] args) throws Exception {
+ private JInfo(String[] args) throws IllegalArgumentException {
if (args.length == 0) {
- usage(1); // no arguments
+ throw new IllegalArgumentException();
}
+ int argCopyIndex = 0;
// First determine if we should launch SA or not
- boolean useSA = false;
if (args[0].equals("-F")) {
// delete the -F
- args = Arrays.copyOfRange(args, 1, args.length);
+ argCopyIndex = 1;
useSA = true;
} else if (args[0].equals("-flags")
- || args[0].equals("-sysprops"))
+ || args[0].equals("-sysprops"))
{
if (args.length == 2) {
- if (!args[1].matches("[0-9]+")) {
+ if (!isPid(args[1])) {
// If args[1] doesn't parse to a number then
// it must be the SA debug server
// (otherwise it is the pid)
useSA = true;
}
- }
- if (args.length == 3) {
+ } else if (args.length == 3) {
// arguments include an executable and a core file
useSA = true;
+ } else {
+ throw new IllegalArgumentException();
}
} else if (!args[0].startsWith("-")) {
if (args.length == 2) {
// the only arguments are an executable and a core file
useSA = true;
+ } else if (args.length == 1) {
+ if (!isPid(args[0])) {
+ // The only argument is not a PID; it must be SA debug
+ // server
+ useSA = true;
+ }
+ } else {
+ throw new IllegalArgumentException();
}
- } else if (args[0].equals("-h")
- || args[0].equals("-help")) {
+ } else if (args[0].equals("-h") || args[0].equals("-help")) {
+ if (args.length > 1) {
+ throw new IllegalArgumentException();
+ }
+ } else if (args[0].equals("-flag")) {
+ if (args.length == 3) {
+ if (!isPid(args[2])) {
+ throw new IllegalArgumentException();
+ }
+ } else {
+ throw new IllegalArgumentException();
+ }
+ } else {
+ throw new IllegalArgumentException();
+ }
+
+ this.args = Arrays.copyOfRange(args, argCopyIndex, args.length);
+ }
+
+ @SuppressWarnings("fallthrough")
+ private void execute() throws Exception {
+ if (args[0].equals("-h")
+ || args[0].equals("-help")) {
usage(0);
}
@@ -87,55 +118,69 @@
}
// invoke SA which does it's own argument parsing
- runTool(args);
+ runTool();
} else {
// Now we can parse arguments for the non-SA case
String pid = null;
switch(args[0]) {
- case "-flag":
- if (args.length != 3) {
- usage(1);
- }
- String option = args[1];
- pid = args[2];
- flag(pid, option);
- break;
- case "-flags":
- if (args.length != 2) {
- usage(1);
- }
- pid = args[1];
- flags(pid);
- break;
- case "-sysprops":
- if (args.length != 2) {
- usage(1);
- }
- pid = args[1];
- sysprops(pid);
- break;
- case "-help":
- case "-h":
- usage(0);
- // Fall through
- default:
- if (args.length == 1) {
- // no flags specified, we do -sysprops and -flags
- pid = args[0];
- sysprops(pid);
- System.out.println();
- flags(pid);
- } else {
- usage(1);
- }
+ case "-flag":
+ if (args.length != 3) {
+ usage(1);
+ }
+ String option = args[1];
+ pid = args[2];
+ flag(pid, option);
+ break;
+ case "-flags":
+ if (args.length != 2) {
+ usage(1);
+ }
+ pid = args[1];
+ flags(pid);
+ break;
+ case "-sysprops":
+ if (args.length != 2) {
+ usage(1);
+ }
+ pid = args[1];
+ sysprops(pid);
+ break;
+ case "-help":
+ case "-h":
+ usage(0);
+ // Fall through
+ default:
+ if (args.length == 1) {
+ // no flags specified, we do -sysprops and -flags
+ pid = args[0];
+ sysprops(pid);
+ System.out.println();
+ flags(pid);
+ } else {
+ usage(1);
+ }
}
}
}
+ public static void main(String[] args) throws Exception {
+ JInfo jinfo = null;
+ try {
+ jinfo = new JInfo(args);
+ jinfo.execute();
+ } catch (IllegalArgumentException e) {
+ usage(1);
+ }
+ }
+
+ private static boolean isPid(String arg) {
+ return arg.matches("[0-9]+");
+ }
+
// Invoke SA tool with the given arguments
- private static void runTool(String args[]) throws Exception {
+ private void runTool() throws Exception {
String tool = "sun.jvm.hotspot.tools.JInfo";
// Tool not available on this platform.
Class<?> c = loadClass(tool);
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/jdk/test/sun/tools/jinfo/JInfoLauncherTest.java Thu Apr 17 18:20:31 2014 +0200
@@ -0,0 +1,342 @@
+/*
+ * Copyright (c) 2014, 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. Oracle designates this
+ * particular file as subject to the "Classpath" exception as provided
+ * by Oracle in the LICENSE file that accompanied this code.
+ *
+ * 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.
+ */
+
+import org.testng.annotations.Test;
+import org.testng.annotations.BeforeClass;
+import sun.tools.jinfo.JInfo;
+
+import java.lang.reflect.Constructor;
+import java.lang.reflect.Field;
+import java.util.Arrays;
+
+import static org.testng.Assert.*;
+
+/**
+ * @test
+ * @bug 8039080
+ * @run testng JInfoLauncherTest
+ * @summary Test JInfo launcher argument parsing
+ */
+@Test
+public class JInfoLauncherTest {
+ public static final String VALIDATION_EXCEPTION_CLSNAME =
+ IllegalArgumentException.class.getName();
+
+ private Constructor<JInfo> jInfoConstructor;
+ private Field fldUseSA;
+
+ @BeforeClass
+ public void setup() throws Exception {
+ jInfoConstructor = JInfo.class.getDeclaredConstructor(String[].class);
+ jInfoConstructor.setAccessible(true);
+ fldUseSA = JInfo.class.getDeclaredField("useSA");
+ fldUseSA.setAccessible(true);
+ }
+
+ private JInfo newJInfo(String[] args) throws Exception {
+ try {
+ return jInfoConstructor.newInstance((Object) args);
+ } catch (Exception e) {
+ if (isValidationException(e.getCause())) {
+ throw (Exception)e.getCause();
+ }
+ throw e;
+ }
+ }
+
+ private boolean getUseSA(JInfo jinfo) throws Exception {
+ return fldUseSA.getBoolean(jinfo);
+ }
+
+ private void cmdPID(String cmd, String ... params) throws Exception {
+ int offset = (cmd != null ? 1 : 0);
+ String[] args = new String[offset + params.length];
+ args[0] = cmd;
+ System.arraycopy(params, 0, args, offset, params.length);
+ JInfo j = newJInfo(args);
+ assertFalse(getUseSA(j), "Local jinfo must not forward to SA");
+ }
+
+ private void cmdCore(String cmd, String ... params) throws Exception {
+ int offset = (cmd != null ? 1 : 0);
+ String[] args = new String[offset + params.length];
+ args[0] = cmd;
+ System.arraycopy(params, 0, args, offset, params.length);
+ JInfo j = newJInfo(args);
+ assertTrue(getUseSA(j), "Core jinfo must forward to SA");
+ }
+
+ private void cmdRemote(String cmd, String ... params) throws Exception {
+ int offset = (cmd != null ? 1 : 0);
+ String[] args = new String[offset + params.length];
+ args[0] = cmd;
+ System.arraycopy(params, 0, args, offset, params.length);
+ JInfo j = newJInfo(args);
+ assertTrue(getUseSA(j), "Remote jinfo must forward to SA");
+ }
+
+ private void cmdExtraArgs(String cmd, int argsLen) throws Exception {
+ String[] args = new String[argsLen + 1 + (cmd != null ? 1 : 0)];
+ Arrays.fill(args, "a");
+ if (cmd != null) {
+ args[0] = cmd;
+ } else {
+ cmd = "default";
+ }
+ try {
+ JInfo j = newJInfo(args);
+ fail("\"" + cmd + "\" does not support more than " + argsLen +
+ " arguments");
+ } catch (Exception e) {
+ if (!isValidationException(e)) {
+ throw e;
+ }
+ // ignore
+ }
+ }
+
+ private void cmdMissingArgs(String cmd, int reqArgs) throws Exception {
+ String[] args = new String[reqArgs - 1 + (cmd != null ? 1 : 0)];
+ Arrays.fill(args, "a");
+ if (cmd != null) {
+ args[0] = cmd;
+ } else {
+ cmd = "default";
+ }
+ try {
+ JInfo j = newJInfo(args);
+ fail("\"" + cmd + "\" requires at least " + reqArgs + " argument");
+ } catch (Exception e) {
+ if (!isValidationException(e)) {
+ throw e;
+ }
+ // ignore
+ }
+ }
+
+ public void testDefaultPID() throws Exception {
+ cmdPID(null, "1234");
+ }
+
+ public void testFlagsPID() throws Exception {
+ cmdPID("-flags", "1234");
+ }
+
+ public void testSyspropsPID() throws Exception {
+ cmdPID("-sysprops", "1234");
+ }
+
+ public void testReadFlagPID() throws Exception {
+ cmdPID("-flag", "SomeManagementFlag", "1234");
+ }
+
+ public void testSetFlag1PID() throws Exception {
+ cmdPID("-flag", "+SomeManagementFlag", "1234");
+ }
+
+ public void testSetFlag2PID() throws Exception {
+ cmdPID("-flag", "-SomeManagementFlag", "1234");
+ }
+
+ public void testSetFlag3PID() throws Exception {
+ cmdPID("-flag", "SomeManagementFlag=314", "1234");
+ }
+
+ public void testDefaultCore() throws Exception {
+ cmdCore(null, "myapp.exe", "my.core");
+ }
+
+ public void testFlagsCore() throws Exception {
+ cmdCore("-flags", "myapp.exe", "my.core");
+ }
+
+ public void testSyspropsCore() throws Exception {
+ cmdCore("-sysprops", "myapp.exe", "my.core");
+ }
+
+ public void testReadFlagCore() throws Exception {
+ try {
+ cmdCore("-flag", "SomeManagementFlag", "myapp.exe", "my.core");
+ fail("Flags can not be read from core files");
+ } catch (Exception e) {
+ if (!isValidationException(e)) {
+ throw e;
+ }
+ // ignore
+ }
+ }
+
+ public void testSetFlag1Core() throws Exception {
+ try {
+ cmdCore("-flag", "+SomeManagementFlag", "myapp.exe", "my.core");
+ fail("Flags can not be set in core files");
+ } catch (Exception e) {
+ if (!isValidationException(e)) {
+ throw e;
+ }
+ // ignore
+ }
+ }
+
+ public void testSetFlag2Core() throws Exception {
+ try {
+ cmdCore("-flag", "-SomeManagementFlag", "myapp.exe", "my.core");
+ fail("Flags can not be set in core files");
+ } catch (Exception e) {
+ if (!isValidationException(e)) {
+ throw e;
+ }
+ // ignore
+ }
+ }
+
+ public void testSetFlag3Core() throws Exception {
+ try {
+ cmdCore("-flag", "SomeManagementFlag=314", "myapp.exe", "my.core");
+ fail("Flags can not be set in core files");
+ } catch (Exception e) {
+ if (!isValidationException(e)) {
+ throw e;
+ }
+ // ignore
+ }
+ }
+
+ public void testDefaultRemote() throws Exception {
+ cmdRemote(null, "serverid@host");
+ }
+
+ public void testFlagsRemote() throws Exception {
+ cmdRemote("-flags", "serverid@host");
+ }
+
+ public void testSyspropsRemote() throws Exception {
+ cmdRemote("-sysprops", "serverid@host");
+ }
+
+ public void testReadFlagRemote() throws Exception {
+ try {
+ cmdCore("-flag", "SomeManagementFlag", "serverid@host");
+ fail("Flags can not be read from SA server");
+ } catch (Exception e) {
+ if (!isValidationException(e)) {
+ throw e;
+ }
+ // ignore
+ }
+ }
+
+ public void testSetFlag1Remote() throws Exception {
+ try {
+ cmdCore("-flag", "+SomeManagementFlag","serverid@host");
+ fail("Flags can not be set on SA server");
+ } catch (Exception e) {
+ if (!isValidationException(e)) {
+ throw e;
+ }
+ // ignore
+ }
+ }
+
+ public void testSetFlag2Remote() throws Exception {
+ try {
+ cmdCore("-flag", "-SomeManagementFlag", "serverid@host");
+ fail("Flags can not be read set on SA server");
+ } catch (Exception e) {
+ if (!isValidationException(e)) {
+ throw e;
+ }
+ // ignore
+ }
+ }
+
+ public void testSetFlag3Remote() throws Exception {
+ try {
+ cmdCore("-flag", "SomeManagementFlag=314", "serverid@host");
+ fail("Flags can not be read set on SA server");
+ } catch (Exception e) {
+ if (!isValidationException(e)) {
+ throw e;
+ }
+ // ignore
+ }
+ }
+
+ public void testDefaultExtraArgs() throws Exception {
+ cmdExtraArgs(null, 2);
+ }
+
+ public void testFlagsExtraArgs() throws Exception {
+ cmdExtraArgs("-flags", 2);
+ }
+
+ public void testSyspropsExtraArgs() throws Exception {
+ cmdExtraArgs("-sysprops", 2);
+ }
+
+ public void testFlagExtraArgs() throws Exception {
+ cmdExtraArgs("-flag", 2);
+ }
+
+ public void testHelp1ExtraArgs() throws Exception {
+ cmdExtraArgs("-h", 0);
+ }
+
+ public void testHelp2ExtraArgs() throws Exception {
+ cmdExtraArgs("-help", 0);
+ }
+
+ public void testDefaultMissingArgs() throws Exception {
+ cmdMissingArgs(null, 1);
+ }
+
+ public void testFlagsMissingArgs() throws Exception {
+ cmdMissingArgs("-flags", 1);
+ }
+
+ public void testSyspropsMissingArgs() throws Exception {
+ cmdMissingArgs("-sysprops", 1);
+ }
+
+ public void testFlagMissingArgs() throws Exception {
+ cmdMissingArgs("-flag", 2);
+ }
+
+ public void testUnknownCommand() throws Exception {
+ try {
+ JInfo j = newJInfo(new String[]{"-unknown_command"});
+ fail("JInfo accepts unknown commands");
+ } catch (Exception e) {
+ if (!isValidationException(e)) {
+ throw e;
+ }
+ // ignore
+ }
+ }
+
+ private static boolean isValidationException(Throwable e) {
+ return e.getClass().getName().equals(VALIDATION_EXCEPTION_CLSNAME);
+ }
+}