| /* |
| * 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. |
| * |
| * 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 com.sun.tools.attach.AttachOperationFailedException; |
| import com.sun.tools.attach.VirtualMachine; |
| |
| import java.io.File; |
| import java.io.FileWriter; |
| import java.util.Properties; |
| import java.util.HashMap; |
| |
| import javax.management.remote.JMXServiceURL; |
| import javax.management.remote.JMXConnector; |
| import javax.management.remote.JMXConnectorFactory; |
| |
| import jdk.testlibrary.ProcessThread; |
| import jdk.testlibrary.Utils; |
| |
| /* |
| * @test |
| * @summary Test for VirtualMachine.startManagementAgent and VirtualMachine.startLocalManagementAgent |
| * @library /lib/testlibrary |
| * @run build Application Shutdown SimpleProvider jdk.testlibrary.* |
| * @run main StartManagementAgent |
| */ |
| |
| /* |
| * This test is not meant to test all possible configuration parameters to |
| * the JMX agent, there are other tests for that. This test makes sure it is |
| * possible to start the agent via attach. |
| */ |
| public class StartManagementAgent { |
| public static void main(String[] args) throws Throwable { |
| final String pidFile = "StartManagementAgent.Application.pid"; |
| ProcessThread processThread = null; |
| RunnerUtil.ProcessInfo info = null; |
| try { |
| processThread = RunnerUtil.startApplication(pidFile); |
| info = RunnerUtil.readProcessInfo(pidFile); |
| runTests(info.pid); |
| } catch (Throwable t) { |
| System.out.println("StartManagementAgent got unexpected exception: " + t); |
| t.printStackTrace(); |
| throw t; |
| } finally { |
| // Make sure the Application process is stopped. |
| RunnerUtil.stopApplication(info.shutdownPort, processThread); |
| } |
| } |
| |
| private static void basicTests(VirtualMachine vm) throws Exception { |
| |
| // Try calling with null argument |
| boolean exception = false; |
| try { |
| vm.startManagementAgent(null); |
| } catch (NullPointerException e) { |
| exception = true; |
| } |
| if (!exception) { |
| throw new Exception("startManagementAgent(null) should throw NPE"); |
| } |
| |
| // Try calling with a property value with a space in it |
| Properties p = new Properties(); |
| File f = new File("file with space"); |
| try (FileWriter fw = new FileWriter(f)) { |
| fw.write("com.sun.management.jmxremote.port=apa"); |
| } |
| p.put("com.sun.management.config.file", f.getAbsolutePath()); |
| try { |
| vm.startManagementAgent(p); |
| } catch(AttachOperationFailedException ex) { |
| // We expect parsing of "apa" above to fail, but if the file path |
| // can't be read we get a different exception message |
| if (!ex.getMessage().contains("Invalid com.sun.management.jmxremote.port number")) { |
| throw ex; |
| } |
| } |
| } |
| |
| private static final String LOCAL_CONNECTOR_ADDRESS_PROP = |
| "com.sun.management.jmxremote.localConnectorAddress"; |
| |
| private static final int MAX_RETRIES = 10; |
| |
| public static void runTests(int pid) throws Exception { |
| VirtualMachine vm = VirtualMachine.attach(""+pid); |
| try { |
| |
| basicTests(vm); |
| |
| testLocalAgent(vm); |
| |
| // we retry the remote case several times in case the error |
| // was caused by a port conflict |
| int i = 0; |
| boolean success = false; |
| do { |
| try { |
| System.err.println("Trying remote agent. Try #" + i); |
| testRemoteAgent(vm); |
| success = true; |
| } catch(Exception ex) { |
| System.err.println("testRemoteAgent failed with exception:"); |
| ex.printStackTrace(); |
| System.err.println("Retrying."); |
| } |
| i++; |
| } while(!success && i < MAX_RETRIES); |
| if (!success) { |
| throw new Exception("testRemoteAgent failed after " + MAX_RETRIES + " tries"); |
| } |
| } finally { |
| vm.detach(); |
| } |
| } |
| |
| public static void testLocalAgent(VirtualMachine vm) throws Exception { |
| Properties agentProps = vm.getAgentProperties(); |
| String address = (String) agentProps.get(LOCAL_CONNECTOR_ADDRESS_PROP); |
| if (address != null) { |
| throw new Exception("Local management agent already started"); |
| } |
| |
| String result = vm.startLocalManagementAgent(); |
| |
| // try to parse the return value as a JMXServiceURL |
| new JMXServiceURL(result); |
| |
| agentProps = vm.getAgentProperties(); |
| address = (String) agentProps.get(LOCAL_CONNECTOR_ADDRESS_PROP); |
| if (address == null) { |
| throw new Exception("Local management agent could not be started"); |
| } |
| } |
| |
| public static void testRemoteAgent(VirtualMachine vm) throws Exception { |
| int port = Utils.getFreePort(); |
| |
| // try to connect - should fail |
| tryConnect(port, false); |
| |
| // start agent |
| System.out.println("Starting agent on port: " + port); |
| Properties mgmtProps = new Properties(); |
| mgmtProps.put("com.sun.management.jmxremote.port", port); |
| mgmtProps.put("com.sun.management.jmxremote.authenticate", "false"); |
| mgmtProps.put("com.sun.management.jmxremote.ssl", "false"); |
| vm.startManagementAgent(mgmtProps); |
| |
| // try to connect - should work |
| tryConnect(port, true); |
| |
| // try to start again - should fail |
| boolean exception = false; |
| try { |
| vm.startManagementAgent(mgmtProps); |
| } catch(AttachOperationFailedException ex) { |
| // expected |
| exception = true; |
| } |
| if (!exception) { |
| throw new Exception("Expected the second call to vm.startManagementAgent() to fail"); |
| } |
| } |
| |
| private static void tryConnect(int port, boolean shouldSucceed) throws Exception { |
| String jmxUrlStr = |
| String.format( |
| "service:jmx:rmi:///jndi/rmi://localhost:%d/jmxrmi", |
| port); |
| JMXServiceURL url = new JMXServiceURL(jmxUrlStr); |
| HashMap<String, ?> env = new HashMap<>(); |
| |
| boolean succeeded; |
| try { |
| JMXConnector c = JMXConnectorFactory.connect(url, env); |
| c.getMBeanServerConnection(); |
| succeeded = true; |
| } catch(Exception ex) { |
| succeeded = false; |
| } |
| if (succeeded && !shouldSucceed) { |
| throw new Exception("Could connect to agent, but should not have been possible"); |
| } |
| if (!succeeded && shouldSucceed) { |
| throw new Exception("Could not connect to agent"); |
| } |
| } |
| } |