1 /*
   2  * Copyright (c) 2012, 2015, Oracle and/or its affiliates. All rights reserved.
   3  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
   4  *
   5  * This code is free software; you can redistribute it and/or modify it
   6  * under the terms of the GNU General Public License version 2 only, as
   7  * published by the Free Software Foundation.
   8  *
   9  * This code is distributed in the hope that it will be useful, but WITHOUT
  10  * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
  11  * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
  12  * version 2 for more details (a copy is included in the LICENSE file that
  13  * accompanied this code).
  14  *
  15  * You should have received a copy of the GNU General Public License version
  16  * 2 along with this work; if not, write to the Free Software Foundation,
  17  * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
  18  *
  19  * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
  20  * or visit www.oracle.com if you need additional information or have any
  21  * questions.
  22  */
  23 
  24 import java.io.File;
  25 import java.io.IOException;
  26 import java.lang.reflect.InvocationTargetException;
  27 import java.lang.reflect.Method;
  28 import java.net.BindException;
  29 import java.net.ConnectException;
  30 import java.net.ServerSocket;
  31 import java.rmi.RemoteException;
  32 import java.rmi.registry.LocateRegistry;
  33 import java.rmi.registry.Registry;
  34 import java.util.ArrayList;
  35 import java.util.Arrays;
  36 import java.util.List;
  37 import java.util.Objects;
  38 import java.util.Random;
  39 import java.util.Set;
  40 import java.util.concurrent.TimeUnit;
  41 import java.util.concurrent.TimeoutException;
  42 import java.util.concurrent.atomic.AtomicBoolean;
  43 import java.util.function.Consumer;
  44 import java.util.stream.Collectors;
  45 
  46 import javax.management.*;
  47 import javax.management.remote.*;
  48 import javax.net.ssl.SSLHandshakeException;
  49 
  50 import jdk.testlibrary.ProcessTools;
  51 import jdk.testlibrary.JDKToolLauncher;
  52 import sun.management.Agent;
  53 import sun.management.AgentConfigurationError;
  54 
  55 /**
  56  * @test
  57  * @bug 7110104
  58  * @library /lib/testlibrary
  59  * @modules java.management/sun.management
  60  * @build jdk.testlibrary.* JMXStartStopTest JMXStartStopDoSomething
  61  * @run main/othervm/timeout=600 -XX:+UsePerfData JMXStartStopTest
  62  * @summary Makes sure that enabling/disabling the management agent through JCMD
  63  *          achieves the desired results
  64  * @key randomness
  65  */
  66 public class JMXStartStopTest {
  67 
  68     private static final String TEST_SRC = System.getProperty("test.src");
  69 
  70     private static final boolean verbose = false;
  71 
  72     /**
  73      * Dynamically allocates distinct ports from the ephemeral range 49152-65535
  74      */
  75     private static class PortAllocator {
  76 
  77         private final static int LOWER_BOUND = 49152;
  78         private final static int UPPER_BOUND = 65535;
  79 
  80         private final static Random RND = new Random(System.currentTimeMillis());
  81 
  82         private static int[] allocatePorts(final int numPorts) {
  83             int[] ports = new int[numPorts];
  84             for (int i = 0; i < numPorts; i++) {
  85                 int port = -1;
  86                 while (port == -1) {
  87                     port = RND.nextInt(UPPER_BOUND - LOWER_BOUND + 1) + LOWER_BOUND;
  88                     for (int j = 0; j < i; j++) {
  89                         if (ports[j] == port) {
  90                             port = -1;
  91                             break;
  92                         }
  93                     }
  94                 }
  95                 ports[i] = port;
  96             }
  97             return ports;
  98         }
  99     }
 100 
 101     private static void dbg_print(String msg) {
 102         if (verbose) {
 103             System.out.println("DBG: " + msg);
 104         }
 105     }
 106 
 107     private static int listMBeans(MBeanServerConnection server,
 108             ObjectName pattern,
 109             QueryExp query)
 110             throws Exception {
 111 
 112         Set<ObjectName> names = server.queryNames(pattern,query);
 113         for (ObjectName name : names) {
 114             MBeanInfo info = server.getMBeanInfo(name);
 115             dbg_print("Got MBean: " + name);
 116 
 117             MBeanAttributeInfo[] attrs = info.getAttributes();
 118             if (attrs == null)
 119                 continue;
 120             for (MBeanAttributeInfo attr : attrs) {
 121                 if (attr.isReadable()) {
 122                     server.getAttribute(name, attr.getName());
 123                 }
 124             }
 125         }
 126         return names.size();
 127     }
 128 
 129     private static void testConnectLocal(long pid)
 130             throws Exception {
 131 
 132         String jmxUrlStr = null;
 133 
 134         try {
 135             jmxUrlStr = sun.management.ConnectorAddressLink.importFrom((int)pid);
 136             dbg_print("Local Service URL: " +jmxUrlStr);
 137             if ( jmxUrlStr == null ) {
 138                 throw new Exception("No Service URL. Local agent not started?");
 139             }
 140 
 141             JMXServiceURL url = new JMXServiceURL(jmxUrlStr);
 142 
 143             JMXConnector c = JMXConnectorFactory.connect(url, null);
 144 
 145             MBeanServerConnection conn = c.getMBeanServerConnection();
 146             ObjectName pattern = new ObjectName("java.lang:type=Memory,*");
 147 
 148             int count = listMBeans(conn,pattern,null);
 149             if (count == 0)
 150                 throw new Exception("Expected at least one matching "+
 151                                     "MBean for "+pattern);
 152 
 153         } catch (IOException e) {
 154             dbg_print("Cannot find process : " + pid);
 155             throw e;
 156         }
 157     }
 158 
 159     private static void testNoConnect(int port) throws Exception {
 160         testNoConnect(port, 0);
 161     }
 162 
 163     private static void testNoConnect(int port, int rmiPort) throws Exception {
 164         try {
 165             testConnect(port, rmiPort);
 166             throw new Exception("Didn't expect the management agent running");
 167         } catch (Exception e) {
 168             Throwable t = e;
 169             while (t != null) {
 170                 if (t instanceof RemoteException ||
 171                     t instanceof SSLHandshakeException ||
 172                     t instanceof ConnectException) {
 173                     break;
 174                 }
 175                 t = t.getCause();
 176             }
 177             if (t == null) {
 178                 throw new Exception("Unexpected exception", e);
 179             }
 180         }
 181     }
 182 
 183     private static void testConnect(int port) throws Exception {
 184         testConnect(port, 0);
 185     }
 186 
 187     private static void testConnect(int port, int rmiPort) throws Exception {
 188 
 189         dbg_print("RmiRegistry lookup...");
 190 
 191         dbg_print("Using port: " + port);
 192 
 193         dbg_print("Using rmi port: " + rmiPort);
 194 
 195         Registry registry = LocateRegistry.getRegistry(port);
 196 
 197         // "jmxrmi"
 198         String[] relist = registry.list();
 199         for (int i = 0; i < relist.length; ++i) {
 200             dbg_print("Got registry: " + relist[i]);
 201         }
 202 
 203         String jmxUrlStr = (rmiPort != 0) ?
 204             String.format(
 205                         "service:jmx:rmi://localhost:%d/jndi/rmi://localhost:%d/jmxrmi",
 206                         rmiPort,
 207                 port) :
 208             String.format(
 209                         "service:jmx:rmi:///jndi/rmi://localhost:%d/jmxrmi",
 210                         port);
 211 
 212         JMXServiceURL url = new JMXServiceURL(jmxUrlStr);
 213 
 214         JMXConnector c = JMXConnectorFactory.connect(url, null);
 215 
 216         MBeanServerConnection conn = c.getMBeanServerConnection();
 217         ObjectName pattern = new ObjectName("java.lang:type=Memory,*");
 218 
 219         int count = listMBeans(conn,pattern,null);
 220         if (count == 0)
 221             throw new Exception("Expected at least one matching " +
 222                                 "MBean for " + pattern);
 223     }
 224 
 225     private static class Failure {
 226         private final Throwable cause;
 227         private final String msg;
 228 
 229         public Failure(Throwable cause, String msg) {
 230             this.cause = cause;
 231             this.msg = msg;
 232         }
 233 
 234         public Failure(String msg) {
 235             this(null, msg);
 236         }
 237 
 238         public Throwable getCause() {
 239             return cause;
 240         }
 241 
 242         public String getMsg() {
 243             return msg;
 244         }
 245 
 246         @Override
 247         public int hashCode() {
 248             int hash = 7;
 249             hash = 97 * hash + Objects.hashCode(this.cause);
 250             hash = 97 * hash + Objects.hashCode(this.msg);
 251             return hash;
 252         }
 253 
 254         @Override
 255         public boolean equals(Object obj) {
 256             if (obj == null) {
 257                 return false;
 258             }
 259             if (getClass() != obj.getClass()) {
 260                 return false;
 261             }
 262             final Failure other = (Failure) obj;
 263             if (!Objects.equals(this.cause, other.cause)) {
 264                 return false;
 265             }
 266             if (!Objects.equals(this.msg, other.msg)) {
 267                 return false;
 268             }
 269             return true;
 270         }
 271 
 272         @Override
 273         public String toString() {
 274             if (cause != null) {
 275                 return msg + "\n" + cause;
 276             } else {
 277                 return msg;
 278             }
 279         }
 280     }
 281 
 282     private static List<Failure> failures = new ArrayList<>();
 283 
 284     public static void main(String args[]) throws Exception {
 285         for (Method m : JMXStartStopTest.class.getDeclaredMethods()) {
 286             if (m.getName().startsWith("test_")) {
 287                 long t1 = System.currentTimeMillis();
 288                 try {
 289                     boolean retry = false;
 290                     do {
 291                         try {
 292                             m.invoke(null);
 293                             retry = false;
 294                         } catch (InvocationTargetException e) {
 295                             if (e.getCause() instanceof BindException ||
 296                                 e.getCause() instanceof java.rmi.ConnectException) {
 297                                 System.out.println("Failed to allocate ports. Retrying ...");
 298                                 retry = true;
 299                             } else {
 300                                 throw e;
 301                             }
 302                         }
 303                     } while (retry);
 304                     System.out.println("=== PASSED");
 305                 } catch (Throwable e) {
 306                     failures.add(new Failure(e, m.getName() + " failed"));
 307                 } finally {
 308                     System.out.println("(took " + (System.currentTimeMillis() - t1) + "ms)\n");
 309                 }
 310             }
 311         }
 312 
 313         if (!failures.isEmpty()) {
 314             for(Failure f : failures) {
 315                 System.err.println(f.getMsg());
 316                 f.getCause().printStackTrace(System.err);
 317             }
 318             throw new Error();
 319         }
 320     }
 321 
 322     private static class Something {
 323         private Process p;
 324         private final ProcessBuilder pb;
 325         private final String name;
 326         private final AtomicBoolean started = new AtomicBoolean(false);
 327         private volatile long pid = -1;
 328 
 329         public Something(ProcessBuilder pb, String name) {
 330             this.pb = pb;
 331             this.name = name;
 332         }
 333 
 334         public synchronized void start() throws InterruptedException, IOException, TimeoutException {
 335             if (started.compareAndSet(false, true)) {
 336                 try {
 337                     AtomicBoolean error = new AtomicBoolean(false);
 338                     p = ProcessTools.startProcess(
 339                             "JMXStartStopDoSomething{" + name + "}",
 340                             pb,
 341                             (line) -> {
 342                                 boolean ok = line.equals("main enter");
 343                                 error.set(line.contains("BindException"));
 344 
 345                                 return ok || error.get();
 346                             },
 347                             5,
 348                             TimeUnit.SECONDS
 349                     );
 350                     if (error.get()) {
 351                         throw new BindException("Starting process failed due to " +
 352                                                 "the requested port not being available");
 353                     }
 354                     pid = p.getPid();
 355                 } catch (TimeoutException e) {
 356                     p.destroy();
 357                     p.waitFor();
 358                     throw e;
 359                 }
 360             }
 361         }
 362 
 363         public long getPid() {
 364             return pid;
 365         }
 366 
 367         public synchronized void stop()
 368                 throws IOException, InterruptedException {
 369             if (started.compareAndSet(true, false)) {
 370                 p.getOutputStream().write(0);
 371                 p.getOutputStream().flush();
 372                 int ec = p.waitFor();
 373                 if (ec != 0) {
 374                     StringBuilder msg = new StringBuilder();
 375                     msg.append("Test application '").append(name);
 376                     msg.append("' failed with exit code: ");
 377                     msg.append(ec);
 378 
 379                     failures.add(new Failure(msg.toString()));
 380                 }
 381             }
 382         }
 383     }
 384 
 385     /**
 386      * Runs the test application "JMXStartStopDoSomething"
 387      * @param name Test run name
 388      * @param args Additional arguments
 389      * @return Returns a {@linkplain Something} instance representing the run
 390      * @throws IOException
 391      * @throws InterruptedException
 392      * @throws TimeoutException
 393      */
 394     private static Something doSomething(String name, String ... args)
 395             throws Exception {
 396         List<String> pbArgs = new ArrayList<>(Arrays.asList(
 397                 "-cp",
 398                 System.getProperty("test.class.path")
 399         ));
 400         pbArgs.addAll(Arrays.asList(args));
 401         pbArgs.add("JMXStartStopDoSomething");
 402 
 403         ProcessBuilder pb = ProcessTools.createJavaProcessBuilder(
 404                 pbArgs.toArray(new String[pbArgs.size()])
 405         );
 406         Something s = new Something(pb, name);
 407         s.start();
 408         return s;
 409     }
 410 
 411     /**
 412      * Run the "jcmd" command
 413      *
 414      * @param command Command with parameters; space separated string
 415      * @throws IOException
 416      * @throws InterruptedException
 417      */
 418     private static void jcmd(String ... command) throws IOException, InterruptedException {
 419         if (command.length == 0) {
 420             jcmd(null, c->{});
 421         } else {
 422             jcmd(null, command);
 423         }
 424     }
 425 
 426     /**
 427      * Run the "jcmd" command
 428      *
 429      * @param c {@linkplain Consumer} instance
 430      * @param command Command with parameters; space separated string
 431      * @throws IOException
 432      * @throws InterruptedException
 433      */
 434     private static void jcmd(Consumer<String> c, String ... command) throws IOException, InterruptedException {
 435         jcmd("JMXStartStopDoSomething", c, command);
 436     }
 437 
 438     /**
 439      * Run the "jcmd" command
 440      *
 441      * @param target The target application name (or PID)
 442      * @param c {@linkplain Consumer} instance
 443      * @param command Command with parameters; space separated string
 444      * @throws IOException
 445      * @throws InterruptedException
 446      */
 447     private static void jcmd(String target, final Consumer<String> c, String ... command) throws IOException, InterruptedException {
 448         dbg_print("[jcmd] " + (command.length > 0 ? command[0] : "list"));
 449 
 450         JDKToolLauncher l = JDKToolLauncher.createUsingTestJDK("jcmd");
 451         l.addToolArg(target);
 452         for (String cmd : command) {
 453             l.addToolArg(cmd);
 454         }
 455 
 456         AtomicBoolean portUnavailable = new AtomicBoolean(false);
 457         Process p = ProcessTools.startProcess(
 458             "jcmd",
 459             new ProcessBuilder(l.getCommand()),
 460             line -> {
 461                 if (line.contains("BindException") ||
 462                     line.contains(Agent.getText(AgentConfigurationError.CONNECTOR_SERVER_IO_ERROR))) {
 463                     portUnavailable.set(true);
 464                 } else {
 465                     c.accept(line);
 466                 }
 467             }
 468         );
 469 
 470         p.waitFor();
 471         dbg_print("[jcmd] --------");
 472         if (portUnavailable.get()) {
 473             String cmd = Arrays.asList(l.getCommand()).stream()
 474                     .collect(
 475                             Collectors.joining(" ", "", ": Unable to bind address")
 476                     );
 477             throw new BindException(cmd);
 478         }
 479     }
 480 
 481     private static final String CMD_STOP = "ManagementAgent.stop";
 482     private static final String CMD_START = "ManagementAgent.start";
 483     private static final String CMD_START_LOCAL = "ManagementAgent.start_local";
 484 
 485     static void test_01() throws Exception {
 486         // Run an app with JMX enabled stop it and
 487         // restart on other port
 488 
 489         System.out.println("**** Test one ****");
 490         int ports[] = PortAllocator.allocatePorts(2);
 491 
 492         Something s = doSomething(
 493                 "test_01",
 494                 "-Dcom.sun.management.jmxremote.port=" + ports[0],
 495                 "-Dcom.sun.management.jmxremote.authenticate=false",
 496                 "-Dcom.sun.management.jmxremote.ssl=false");
 497 
 498         try {
 499             testConnect(ports[0]);
 500 
 501             jcmd(CMD_STOP);
 502             testNoConnect(ports[0]);
 503 
 504             jcmd(CMD_START, "jmxremote.port=" + ports[1]);
 505             testConnect(ports[1]);
 506         } finally {
 507             s.stop();
 508         }
 509     }
 510 
 511     static void test_02() throws Exception {
 512         // Run an app without JMX enabled
 513         // start JMX by jcmd
 514 
 515         System.out.println("**** Test two ****");
 516 
 517         int[] ports = PortAllocator.allocatePorts(1);
 518         Something s = doSomething("test_02");
 519         try {
 520             jcmd(CMD_START,
 521                     "jmxremote.port=" + ports[0],
 522                     "jmxremote.authenticate=false",
 523                     "jmxremote.ssl=false");
 524 
 525             testConnect(ports[0]);
 526         } finally {
 527 //            debugPortUsage(pa);
 528             s.stop();
 529         }
 530     }
 531 
 532     static void test_03() throws Exception {
 533         // Run an app without JMX enabled
 534         // start JMX by jcmd on one port than on other one
 535 
 536         System.out.println("**** Test three ****");
 537 
 538         int[] ports = PortAllocator.allocatePorts(2);
 539         Something s = doSomething("test_03");
 540         try {
 541             jcmd(CMD_START,
 542                     "jmxremote.port=" + ports[0],
 543                     "jmxremote.authenticate=false",
 544                     "jmxremote.ssl=false");
 545 
 546             // Second agent shouldn't start
 547             jcmd(CMD_START,
 548                     "jmxremote.port=" + ports[1],
 549                     "jmxremote.authenticate=false",
 550                     "jmxremote.ssl=false");
 551 
 552             // First agent should connect
 553             testConnect(ports[0]);
 554 
 555             // Second agent should not connect
 556             testNoConnect(ports[1]);
 557         } finally {
 558             s.stop();
 559         }
 560     }
 561 
 562     static void test_04() throws Exception {
 563         // Run an app without JMX enabled
 564         // start JMX by jcmd on one port, specify rmi port explicitly
 565 
 566         System.out.println("**** Test four ****");
 567 
 568         int[] ports = PortAllocator.allocatePorts(2);
 569         Something s = doSomething("test_04");
 570         try {
 571             jcmd(CMD_START,
 572                     "jmxremote.port=" + ports[0],
 573                     "jmxremote.rmi.port=" + ports[1],
 574                     "jmxremote.authenticate=false",
 575                     "jmxremote.ssl=false");
 576 
 577             testConnect(ports[0], ports[1]);
 578         } finally {
 579             s.stop();
 580         }
 581     }
 582 
 583     static void test_05() throws Exception {
 584         // Run an app without JMX enabled, it will enable local server
 585         // but should leave remote server disabled
 586 
 587         System.out.println("**** Test five ****");
 588         int[] ports = PortAllocator.allocatePorts(1);
 589         Something s = doSomething("test_05");
 590         try {
 591             jcmd(CMD_START_LOCAL);
 592 
 593             testNoConnect(ports[0]);
 594             testConnectLocal(s.getPid());
 595         } finally {
 596             s.stop();
 597         }
 598     }
 599 
 600     static void test_06() throws Exception {
 601         // Run an app without JMX enabled
 602         // start JMX by jcmd on one port, specify rmi port explicitly
 603         // attempt to start it again with the same port
 604         // Check for valid messages in the output
 605 
 606         System.out.println("**** Test six ****");
 607 
 608         int[] ports = PortAllocator.allocatePorts(2);
 609         Something s = doSomething("test_06");
 610         try {
 611             jcmd(CMD_START,
 612                     "jmxremote.port=" + ports[0],
 613                     "jmxremote.authenticate=false",
 614                     "jmxremote.ssl=false");
 615 
 616             testConnect(ports[0], ports[1]);
 617 
 618             final AtomicBoolean checks = new AtomicBoolean(false);
 619             jcmd(
 620                     line -> {
 621                         if (line.contains("java.lang.RuntimeException: Invalid agent state")) {
 622                             checks.set(true);
 623                         }
 624                     },
 625                     CMD_START,
 626                     "jmxremote.port=" + ports[0],
 627                     "jmxremote.authenticate=false",
 628                     "jmxremote.ssl=false");
 629 
 630             if (!checks.get()) {
 631                 throw new Exception("Starting agent on port " + ports[0] + " should "
 632                         + "report an invalid agent state");
 633             }
 634         } finally {
 635             s.stop();
 636         }
 637     }
 638 
 639     static void test_07() throws Exception {
 640         // Run an app without JMX enabled
 641         // start JMX by jcmd on one port, specify rmi port explicitly
 642         // attempt to start it again with other port
 643         // Check for valid messages in the output
 644 
 645         System.out.println("**** Test seven ****");
 646 
 647         int[] ports = PortAllocator.allocatePorts(2);
 648         Something s = doSomething("test_07");
 649         try {
 650             jcmd(CMD_START,
 651                     "jmxremote.port=" + ports[0],
 652                     "jmxremote.authenticate=false",
 653                     "jmxremote.ssl=false");
 654 
 655             testConnect(ports[0], ports[1]);
 656 
 657             final AtomicBoolean checks = new AtomicBoolean(false);
 658 
 659             jcmd(
 660                     line -> {
 661                         if (line.contains("java.lang.RuntimeException: Invalid agent state")) {
 662                             checks.set(true);
 663                         }
 664                     },
 665                     CMD_START,
 666                     "jmxremote.port=" + ports[1],
 667                     "jmxremote.authenticate=false",
 668                     "jmxremote.ssl=false");
 669 
 670             if (!checks.get()) {
 671                 throw new Exception("Starting agent on poprt " + ports[1] + " should "
 672                         + "report an invalid agent state");
 673             }
 674         } finally {
 675             s.stop();
 676         }
 677     }
 678 
 679     static void test_08() throws Exception {
 680         // Run an app without JMX enabled
 681         // start JMX by jcmd on one port, specify rmi port explicitly
 682         // attempt to stop it twice
 683         // Check for valid messages in the output
 684 
 685         System.out.println("**** Test eight ****");
 686 
 687         int[] ports = PortAllocator.allocatePorts(2);
 688         Something s = doSomething("test_08");
 689         try {
 690             jcmd(CMD_START,
 691                     "jmxremote.port=" + ports[0],
 692                     "jmxremote.authenticate=false",
 693                     "jmxremote.ssl=false");
 694 
 695             testConnect(ports[0], ports[1]);
 696 
 697             jcmd(CMD_STOP);
 698             jcmd(CMD_STOP);
 699         } finally {
 700             s.stop();
 701         }
 702     }
 703 
 704     static void test_09() throws Exception {
 705         // Run an app without JMX enabled
 706         // attempt to start JMX using a non-available port
 707         // Check for valid messages in the output
 708 
 709         System.out.println("**** Test nine ****");
 710 
 711         Something s = doSomething("test_09");
 712 
 713         try (ServerSocket ss = new ServerSocket(0)) {
 714             int localPort = ss.getLocalPort();
 715             int[] ports;
 716             do {
 717                 ports = PortAllocator.allocatePorts(1);
 718             } while (localPort == ports[0]);
 719 
 720             final AtomicBoolean checks = new AtomicBoolean(false);
 721 
 722             int retryCntr = 1;
 723             do {
 724                 final AtomicBoolean retry = new AtomicBoolean(false);
 725 
 726                 try {
 727                     jcmd(
 728                         line -> {
 729                             if (line.contains(Agent.getText(AgentConfigurationError.AGENT_EXCEPTION))) {
 730                                 retry.set(true);
 731                             }
 732                         },
 733                         CMD_START,
 734                         "jmxremote.port=" + ports[0],
 735                         "jmxremote.rmi.port=" + localPort,
 736                         "jmxremote.authenticate=false",
 737                         "jmxremote.ssl=false"
 738                     );
 739                 } catch (BindException e) {
 740                     checks.set(true);
 741                 }
 742                 if (!retry.get()) {
 743                     break;
 744                 }
 745                 System.out.println("Attempt " + retryCntr + " >>>");
 746                 System.out.println("Unexpected reply from the agent. Retrying in 500ms ...");
 747                 Thread.sleep(500);
 748             } while (retryCntr++ < 10);
 749 
 750             if (!checks.get()) {
 751                 throw new Exception("Starting agent on port " + ports[0] + " should "
 752                         + "report port in use");
 753             }
 754         } finally {
 755             s.stop();
 756         }
 757 
 758     }
 759 
 760     static void test_10() throws Exception {
 761         // Run an app without JMX enabled, but with some properties set
 762         // in command line.
 763         // make sure these properties overridden corectly
 764 
 765         System.out.println("**** Test ten ****");
 766 
 767         int[] ports = PortAllocator.allocatePorts(2);
 768         Something s = doSomething(
 769                 "test_10",
 770                 "-Dcom.sun.management.jmxremote.authenticate=false",
 771                 "-Dcom.sun.management.jmxremote.ssl=true");
 772 
 773         try {
 774             testNoConnect(ports[0]);
 775             jcmd(
 776                     CMD_START,
 777                     "jmxremote.port=" + ports[1],
 778                     "jmxremote.authenticate=false",
 779                     "jmxremote.ssl=false"
 780             );
 781             testConnect(ports[1]);
 782         } finally {
 783             s.stop();
 784         }
 785     }
 786 
 787     static void test_11() throws Exception {
 788         // Run an app with JMX enabled and with some properties set
 789         // in command line.
 790         // stop JMX agent and then start it again with different property values
 791         // make sure these properties overridden corectly
 792 
 793         System.out.println("**** Test eleven ****");
 794         int[] ports = PortAllocator.allocatePorts(2);
 795         Something s = doSomething(
 796                 "test_11",
 797                 "-Dcom.sun.management.jmxremote.port=" + ports[0],
 798                 "-Dcom.sun.management.jmxremote.authenticate=false",
 799                 "-Dcom.sun.management.jmxremote.ssl=true");
 800 
 801         try {
 802             testNoConnect(ports[0]);
 803 
 804             jcmd(CMD_STOP);
 805 
 806             testNoConnect(ports[0]);
 807 
 808             jcmd(
 809                     CMD_START,
 810                     "jmxremote.port=" + ports[1],
 811                     "jmxremote.authenticate=false",
 812                     "jmxremote.ssl=false"
 813             );
 814 
 815             testConnect(ports[1]);
 816         } finally {
 817             s.stop();
 818         }
 819     }
 820 
 821     static void test_12() throws Exception {
 822         // Run an app with JMX enabled and with some properties set
 823         // in command line.
 824         // stop JMX agent and then start it again with different property values
 825         // specifing some property in management config file and some of them
 826         // in command line
 827         // make sure these properties overridden corectly
 828 
 829         System.out.println("**** Test twelve ****");
 830 
 831         int[] ports = PortAllocator.allocatePorts(2);
 832         Something s = doSomething("test_12",
 833                 "-Dcom.sun.management.config.file="
 834                 + TEST_SRC + File.separator + "management_cl.properties",
 835                 "-Dcom.sun.management.jmxremote.authenticate=false"
 836         );
 837 
 838         try {
 839             testNoConnect(ports[0]);
 840 
 841             jcmd(CMD_STOP);
 842 
 843             testNoConnect(ports[0]);
 844 
 845             jcmd(CMD_START,
 846                     "config.file=" + TEST_SRC + File.separator
 847                     + "management_jcmd.properties",
 848                     "jmxremote.authenticate=false",
 849                     "jmxremote.port=" + ports[1]
 850             );
 851 
 852             testConnect(ports[1]);
 853         } finally {
 854             s.stop();
 855         }
 856     }
 857 
 858     static void test_13() throws Exception {
 859         // Run an app with JMX enabled and with some properties set
 860         // in command line.
 861         // stop JMX agent and then start it again with different property values
 862         // stop JMX agent again and then start it without property value
 863         // make sure these properties overridden corectly
 864 
 865         System.out.println("**** Test thirteen ****");
 866         int[] ports = PortAllocator.allocatePorts(1);
 867         Something s = doSomething(
 868                 "test_13",
 869                 "-Dcom.sun.management.jmxremote.port=" + ports[0],
 870                 "-Dcom.sun.management.jmxremote.authenticate=false",
 871                 "-Dcom.sun.management.jmxremote.ssl=true");
 872 
 873         try {
 874             testNoConnect(ports[0]);
 875 
 876             jcmd(CMD_STOP);
 877             jcmd(CMD_START,
 878                     "jmxremote.ssl=false",
 879                     "jmxremote.port=" + ports[0]
 880             );
 881             testConnect(ports[0]);
 882 
 883             jcmd(CMD_STOP);
 884             jcmd(CMD_START,
 885                     "jmxremote.port=" + ports[0]
 886             );
 887 
 888             testNoConnect(ports[0]);
 889         } finally {
 890             s.stop();
 891         }
 892     }
 893 
 894     static void test_14() throws Exception {
 895         // Run an app with JMX enabled
 896         // stop remote agent
 897         // make sure local agent is not affected
 898 
 899         System.out.println("**** Test fourteen ****");
 900         int[] ports = PortAllocator.allocatePorts(1);
 901         Something s = doSomething(
 902                 "test_14",
 903                 "-Dcom.sun.management.jmxremote.port=" + ports[0],
 904                 "-Dcom.sun.management.jmxremote.authenticate=false",
 905                 "-Dcom.sun.management.jmxremote.ssl=false");
 906         try {
 907             testConnect(ports[0]);
 908             jcmd(CMD_STOP);
 909             testConnectLocal(s.getPid());
 910         } finally {
 911             s.stop();
 912         }
 913     }
 914 
 915     static void test_15() throws Exception {
 916         // Run an app with JMX disabled
 917         // start local agent only
 918 
 919         System.out.println("**** Test fifteen ****");
 920 
 921         int[] ports = PortAllocator.allocatePorts(1);
 922         Something s = doSomething("test_15");
 923 
 924         try {
 925             testNoConnect(ports[0]);
 926             jcmd(CMD_START + "_local");
 927 
 928             testConnectLocal(s.getPid());
 929 
 930         } finally {
 931             s.stop();
 932         }
 933     }
 934 
 935 }