Path: blob/aarch64-shenandoah-jdk8u272-b10/jdk/test/sun/management/jmxremote/bootstrap/JMXAgentInterfaceBinding.java
38867 views
/*1* Copyright (c) 2015, Red Hat Inc2* 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.7*8* This code is distributed in the hope that it will be useful, but WITHOUT9* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or10* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License11* version 2 for more details (a copy is included in the LICENSE file that12* accompanied this code).13*14* You should have received a copy of the GNU General Public License version15* 2 along with this work; if not, write to the Free Software Foundation,16* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.17*18* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA19* or visit www.oracle.com if you need additional information or have any20* questions.21*/2223import java.io.IOException;24import java.net.InetAddress;25import java.net.InetSocketAddress;26import java.net.MalformedURLException;27import java.net.Socket;28import java.net.SocketAddress;29import java.net.UnknownHostException;30import java.util.HashMap;31import java.util.Map;32import java.util.concurrent.CountDownLatch;33import java.util.concurrent.TimeUnit;3435import javax.management.remote.JMXConnector;36import javax.management.remote.JMXConnectorFactory;37import javax.management.remote.JMXServiceURL;38import javax.management.remote.rmi.RMIConnectorServer;39import javax.net.ssl.SSLSocket;40import javax.net.ssl.SSLSocketFactory;41import javax.rmi.ssl.SslRMIClientSocketFactory;4243/**44* Tests client connections to the JDK's built-in JMX agent server on the given45* ports/interface combinations.46*47* @see JMXInterfaceBindingTest48*49* @author Severin Gehwolf <[email protected]>50*51* Usage:52*53* SSL:54* java -Dcom.sun.management.jmxremote.ssl.need.client.auth=true \55* -Dcom.sun.management.jmxremote.host=127.0.0.1 \56* -Dcom.sun.management.jmxremote.port=9111 \57* -Dcom.sun.management.jmxremote.rmi.port=9112 \58* -Dcom.sun.management.jmxremote.authenticate=false \59* -Dcom.sun.management.jmxremote.ssl=true \60* -Dcom.sun.management.jmxremote.registry.ssl=true61* -Djavax.net.ssl.keyStore=... \62* -Djavax.net.ssl.keyStorePassword=... \63* JMXAgentInterfaceBinding 127.0.0.1 9111 9112 true64*65* Non-SSL:66* java -Dcom.sun.management.jmxremote.host=127.0.0.1 \67* -Dcom.sun.management.jmxremote.port=9111 \68* -Dcom.sun.management.jmxremote.rmi.port=9112 \69* -Dcom.sun.management.jmxremote.authenticate=false \70* -Dcom.sun.management.jmxremote.ssl=false \71* JMXAgentInterfaceBinding 127.0.0.1 9111 9112 false72*73*/74public class JMXAgentInterfaceBinding {7576private final MainThread mainThread;7778public JMXAgentInterfaceBinding(InetAddress bindAddress,79int jmxPort,80int rmiPort,81boolean useSSL) {82this.mainThread = new MainThread(bindAddress, jmxPort, rmiPort, useSSL);83}8485public void startEndpoint() {86mainThread.start();87try {88mainThread.join();89} catch (InterruptedException e) {90throw new RuntimeException("Test failed", e);91}92if (mainThread.isFailed()) {93mainThread.rethrowException();94}95}9697public static void main(String[] args) {98if (args.length != 4) {99throw new RuntimeException(100"Test failed. usage: java JMXInterfaceBindingTest <BIND_ADDRESS> <JMX_PORT> <RMI_PORT> {true|false}");101}102int jmxPort = parsePortFromString(args[1]);103int rmiPort = parsePortFromString(args[2]);104boolean useSSL = Boolean.parseBoolean(args[3]);105String strBindAddr = args[0];106System.out.println(107"DEBUG: Running test for triplet (hostname,jmxPort,rmiPort) = ("108+ strBindAddr + "," + jmxPort + "," + rmiPort + "), useSSL = " + useSSL);109InetAddress bindAddress;110try {111bindAddress = InetAddress.getByName(args[0]);112} catch (UnknownHostException e) {113throw new RuntimeException("Test failed. Unknown ip: " + args[0]);114}115JMXAgentInterfaceBinding test = new JMXAgentInterfaceBinding(bindAddress,116jmxPort, rmiPort, useSSL);117test.startEndpoint(); // Expect for main test to terminate process118}119120private static int parsePortFromString(String port) {121try {122return Integer.parseInt(port);123} catch (NumberFormatException e) {124throw new RuntimeException(125"Invalid port specified. Not an integer! Value was: "126+ port);127}128}129130private static class JMXConnectorThread extends Thread {131132private final String addr;133private final int jmxPort;134private final int rmiPort;135private final boolean useSSL;136private final CountDownLatch latch;137private boolean failed;138private boolean jmxConnectWorked;139private boolean rmiConnectWorked;140141private JMXConnectorThread(String addr,142int jmxPort,143int rmiPort,144boolean useSSL,145CountDownLatch latch) {146this.addr = addr;147this.jmxPort = jmxPort;148this.rmiPort = rmiPort;149this.latch = latch;150this.useSSL = useSSL;151}152153@Override154public void run() {155try {156connect();157} catch (IOException e) {158failed = true;159}160}161162private void connect() throws IOException {163System.out.println(164"JMXConnectorThread: Attempting JMX connection on: "165+ addr + " on port " + jmxPort);166JMXServiceURL url;167try {168url = new JMXServiceURL("service:jmx:rmi:///jndi/rmi://"169+ addr + ":" + jmxPort + "/jmxrmi");170} catch (MalformedURLException e) {171throw new RuntimeException("Test failed.", e);172}173Map<String, Object> env = new HashMap<>();174if (useSSL) {175SslRMIClientSocketFactory csf = new SslRMIClientSocketFactory();176env.put("com.sun.jndi.rmi.factory.socket", csf);177env.put(RMIConnectorServer.RMI_CLIENT_SOCKET_FACTORY_ATTRIBUTE, csf);178}179// connect and immediately close180JMXConnector c = JMXConnectorFactory.connect(url, env);181c.close();182System.out.println("JMXConnectorThread: connection to JMX worked");183jmxConnectWorked = true;184checkRmiSocket();185latch.countDown(); // signal we are done.186}187188private void checkRmiSocket() throws IOException {189Socket rmiConnection;190if (useSSL) {191rmiConnection = SSLSocketFactory.getDefault().createSocket();192} else {193rmiConnection = new Socket();194}195SocketAddress target = new InetSocketAddress(addr, rmiPort);196rmiConnection.connect(target);197if (useSSL) {198((SSLSocket)rmiConnection).startHandshake();199}200System.out.println(201"JMXConnectorThread: connection to rmi socket worked host/port = "202+ addr + "/" + rmiPort);203rmiConnectWorked = true;204// Closing the channel without sending any data will cause an205// java.io.EOFException on the server endpoint. We don't care about this206// though, since we only want to test if we can connect.207rmiConnection.close();208}209210public boolean isFailed() {211return failed;212}213214public boolean jmxConnectionWorked() {215return jmxConnectWorked;216}217218public boolean rmiConnectionWorked() {219return rmiConnectWorked;220}221}222223private static class MainThread extends Thread {224225private static final int WAIT_FOR_JMX_AGENT_TIMEOUT_MS = 500;226private final String addr;227private final int jmxPort;228private final int rmiPort;229private final boolean useSSL;230private boolean terminated = false;231private boolean jmxAgentStarted = false;232private Exception excptn;233234private MainThread(InetAddress bindAddress, int jmxPort, int rmiPort, boolean useSSL) {235this.addr = wrapAddress(bindAddress.getHostAddress());236this.jmxPort = jmxPort;237this.rmiPort = rmiPort;238this.useSSL = useSSL;239}240241@Override242public void run() {243try {244waitUntilReadyForConnections();245// Do nothing, but wait for termination.246try {247while (!terminated) {248Thread.sleep(100);249}250} catch (InterruptedException e) { // ignore251}252System.out.println("MainThread: Thread stopped.");253} catch (Exception e) {254this.excptn = e;255}256}257258private void waitUntilReadyForConnections() {259CountDownLatch latch = new CountDownLatch(1);260JMXConnectorThread connectionTester = new JMXConnectorThread(261addr, jmxPort, rmiPort, useSSL, latch);262connectionTester.start();263boolean expired = false;264try {265expired = !latch.await(WAIT_FOR_JMX_AGENT_TIMEOUT_MS, TimeUnit.MILLISECONDS);266System.out.println(267"MainThread: Finished waiting for JMX agent to become available: expired == "268+ expired);269jmxAgentStarted = !expired;270} catch (InterruptedException e) {271throw new RuntimeException("Test failed", e);272}273if (!jmxAgentStarted) {274throw new RuntimeException(275"Test failed. JMX server agents not becoming available.");276}277if (connectionTester.isFailed()278|| !connectionTester.jmxConnectionWorked()279|| !connectionTester.rmiConnectionWorked()) {280throw new RuntimeException(281"Test failed. JMX agent does not seem ready. See log output for details.");282}283// The main test expects this exact message being printed284System.out.println("MainThread: Ready for connections");285}286287private boolean isFailed() {288return excptn != null;289}290291private void rethrowException() throws RuntimeException {292throw new RuntimeException(excptn);293}294}295296/**297* Will wrap IPv6 address in '[]'298*/299static String wrapAddress(String address) {300if (address.contains(":")) {301return "[" + address + "]";302}303return address;304}305}306307308