1 /*
   2  * Copyright (c) 2003, 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 /*
  25  * @test
  26  * @bug 8058865
  27  * @summary Checks various authentication behavior from remote jmx client
  28  * @author Olivier Lagneau
  29  * @modules java.management.rmi
  30  * @library /lib/testlibrary
  31  * @library /test/lib
  32  * @compile Simple.java
  33  * @run main/othervm/timeout=300 -DDEBUG_STANDARD -Dusername=username1 -Dpassword=password1 AuthorizationTest -server -mapType x.access.file;x.password.file -populate -client -mapType credentials
  34  * @run main/othervm/timeout=300 -DDEBUG_STANDARD -Dusername=username2 -Dpassword=password2 AuthorizationTest -server -mapType x.access.file;x.password.file -populate -client -mapType credentials -expectedCreateException -expectedSetException -expectedInvokeException
  35  * @run main/othervm/timeout=300 -DDEBUG_STANDARD -Dusername=username6 -Dpassword=password6 AuthorizationTest -server -mapType x.access.file;x.password.file -populate -client -mapType credentials -expectedCreateException -expectedGetException -expectedSetException -expectedInvokeException
  36  * @run main/othervm/timeout=300/policy=java.policy.authorization -DDEBUG_STANDARD -Dusername=username1 -Dpassword=password1 AuthorizationTest -server -mapType x.password.file -populate -client -mapType credentials
  37  * @run main/othervm/timeout=300/policy=java.policy.authorization -DDEBUG_STANDARD -Dusername=username3 -Dpassword=password3 AuthorizationTest -server -mapType x.password.file -populate -client -mapType credentials -expectedGetException
  38  * @run main/othervm/timeout=300/policy=java.policy.authorization -DDEBUG_STANDARD -Dusername=username5 -Dpassword=password5 AuthorizationTest -server -mapType x.password.file -populate -client -mapType credentials -expectedCreateException -expectedGetException -expectedSetException -expectedInvokeException
  39  * @run main/othervm/timeout=300/policy=java.policy.authorization -DDEBUG_STANDARD -Dusername=username6 -Dpassword=password6 AuthorizationTest -server -mapType x.password.file -populate -client -mapType credentials -expectedCreateException -expectedGetException -expectedSetException -expectedInvokeException
  40  * @run main/othervm/timeout=300/policy=java.policy.authorization -DDEBUG_STANDARD -Dusername=username1 -Dpassword=password1 AuthorizationTest -server -mapType x.access.file;x.password.file -populate -client -mapType credentials
  41  * @run main/othervm/timeout=300/policy=java.policy.authorization -DDEBUG_STANDARD -Dusername=username2 -Dpassword=password2 AuthorizationTest -server -mapType x.access.file;x.password.file -populate -client -mapType credentials -expectedCreateException -expectedSetException -expectedInvokeException
  42  * @run main/othervm/timeout=300/policy=java.policy.authorization -DDEBUG_STANDARD -Dusername=username3 -Dpassword=password3 AuthorizationTest -server -mapType x.access.file;x.password.file -populate -client -mapType credentials -expectedCreateException -expectedGetException -expectedSetException -expectedInvokeException
  43  * @run main/othervm/timeout=300/policy=java.policy.authorization -DDEBUG_STANDARD -Dusername=username4 -Dpassword=password4 AuthorizationTest -server -mapType x.access.file;x.password.file -populate -client -mapType credentials -expectedGetException -expectedSetException
  44  * @run main/othervm/timeout=300/policy=java.policy.authorization -DDEBUG_STANDARD -Dusername=username5 -Dpassword=password5 AuthorizationTest -server -mapType x.access.file;x.password.file -populate -client -mapType credentials -expectedCreateException -expectedGetException -expectedSetException -expectedInvokeException
  45  */
  46 
  47 import java.io.File;
  48 import java.util.Map ;
  49 import java.util.HashMap ;
  50 import java.util.List;
  51 import java.util.ArrayList;
  52 import java.util.Arrays;
  53 
  54 import java.lang.management.ManagementFactory;
  55 
  56 import javax.management.MBeanServer;
  57 import javax.management.MBeanServerFactory ;
  58 import javax.management.MBeanServerConnection;
  59 import javax.management.remote.JMXConnector;
  60 import javax.management.remote.JMXConnectorFactory;
  61 import javax.management.remote.JMXConnectorServer;
  62 import javax.management.remote.JMXConnectorServerFactory;
  63 import javax.management.remote.JMXServiceURL;
  64 
  65 import javax.management.Attribute ;
  66 import javax.management.ObjectName ;
  67 
  68 import jdk.test.lib.process.ProcessTools;
  69 import jdk.testlibrary.JDKToolFinder;
  70 
  71 public class AuthorizationTest {
  72 
  73     static final String SERVER_CLASS_NAME = "AuthorizationTest";
  74     static final String CLIENT_CLASS_NAME = "AuthorizationTest$ClientSide";
  75     static final String CLIENT_CLASS_MAIN = CLIENT_CLASS_NAME;
  76 
  77     static final String USERNAME_PROPERTY = "username";
  78     static final String PASSWORD_PROPERTY = "password";
  79 
  80     private JMXConnectorServer cs;
  81 
  82     /*
  83      * First Debug properties and arguments are collect in expected
  84      * map  (argName, value) format, then calls original test's run method.
  85      */
  86     public static void main(String args[]) throws Exception {
  87 
  88         System.out.println("=================================================");
  89 
  90         // Parses parameters
  91         Utils.parseDebugProperties();
  92 
  93         // Supported parameters list format is :
  94         // "MainClass [-server <param-spec> ...] [-client <param-spec> ...]
  95         // with <param-spec> either "-parami valuei" or "-parami"
  96         HashMap<String, Object> serverMap = new HashMap<>() ;
  97         int clientArgsIndex =
  98             Utils.parseServerParameters(args, SERVER_CLASS_NAME, serverMap);
  99 
 100         // Extract and records client params
 101         String[] clientParams = null;
 102         if (clientArgsIndex < args.length) {
 103             int clientParamsSize = args.length - clientArgsIndex;
 104             clientParams = new String[clientParamsSize];
 105             System.arraycopy(args, clientArgsIndex, clientParams, 0, clientParamsSize);
 106         } else {
 107             clientParams = new String[0];
 108         }
 109 
 110         // Run test
 111         AuthorizationTest test = new AuthorizationTest();
 112         test.run(serverMap, clientParams);
 113 
 114     }
 115 
 116     /*
 117      * Create the MBeansServer side of the test and returns its address
 118      */
 119     private JMXServiceURL createServerSide(Map<String, Object> serverMap)
 120     throws Exception {
 121         final int NINETY_SECONDS = 90;
 122 
 123         System.out.println("AuthorizationTest::createServerSide: Start") ;
 124 
 125         MBeanServer mbs = MBeanServerFactory.newMBeanServer();
 126         JMXServiceURL url = new JMXServiceURL("rmi", null, 0);
 127 
 128         // Creates connection environment from server side params
 129         HashMap<String, Object> env = new HashMap<>();
 130         String value = null;
 131 
 132         if ((value = (String)serverMap.get("-mapType")) != null) {
 133             if (value.contains("x.access.file")) {
 134                 String accessFileStr = System.getProperty("test.src") +
 135                     File.separator + "access.properties";
 136                 env.put("jmx.remote.x.access.file", accessFileStr);
 137                 System.out.println("Added " + accessFileStr + " file as jmx.remote.x.access.file");
 138             }
 139             if (value.contains("x.password.file")) {
 140                 String passwordFileStr = System.getProperty("test.src") +
 141                     File.separator + "password.properties";
 142                 env.put("jmx.remote.x.password.file", passwordFileStr);
 143                 System.out.println("Added " + passwordFileStr + " file as jmx.remote.x.password.file");
 144             }
 145         }
 146 
 147         if (serverMap.containsKey("-populate")) {
 148             String populateClassName = "Simple";
 149             ObjectName on =
 150                 new ObjectName("defaultDomain:class=Simple");
 151 
 152             Utils.debug(Utils.DEBUG_STANDARD, "create and register Simple MBean") ;
 153             mbs.createMBean(populateClassName, on);
 154         }
 155 
 156         cs = JMXConnectorServerFactory.newJMXConnectorServer(url, env, mbs);
 157         cs.start();
 158 
 159         Utils.waitReady(cs, NINETY_SECONDS);
 160 
 161         JMXServiceURL addr = cs.getAddress();
 162 
 163         System.out.println("AuthorizationTest::createServerSide: Done.") ;
 164 
 165         return addr;
 166     }
 167 
 168     /*
 169      * Creating command-line for running subprocess JVM:
 170      *
 171      * JVM command line is like:
 172      * {test_jdk}/bin/java {defaultopts} -cp {test.class.path} {testopts} main
 173      *
 174      * {defaultopts} are the default java options set by the framework.
 175      *
 176      */
 177     private List<String> buildCommandLine(String args[]) {
 178         List<String> opts = new ArrayList<>();
 179         opts.add(JDKToolFinder.getJDKTool("java"));
 180         opts.addAll(Arrays.asList(jdk.testlibrary.Utils.getTestJavaOpts()));
 181 
 182         String usernameValue = System.getProperty(USERNAME_PROPERTY);
 183         if (usernameValue != null) {
 184             opts.add("-D" + USERNAME_PROPERTY + "=" + usernameValue);
 185         }
 186         String passwordValue = System.getProperty(PASSWORD_PROPERTY);
 187         if (passwordValue != null) {
 188             opts.add("-D" + PASSWORD_PROPERTY + "=" + passwordValue);
 189         }
 190 
 191         opts.add("-cp");
 192         opts.add(System.getProperty("test.class.path", "test.class.path"));
 193         opts.add(CLIENT_CLASS_MAIN);
 194         opts.addAll(Arrays.asList(args));
 195         return opts;
 196     }
 197 
 198     /**
 199      * Runs AuthorizationTest$ClientSide with the passed options and redirects
 200      * subprocess standard I/O to the current (parent) process. This provides a
 201      * trace of what happens in the subprocess while it is runnning (and before
 202      * it terminates).
 203      *
 204      * @param serviceUrlStr string representing the JMX service Url to connect to.
 205      */
 206     private int runClientSide(String args[], String serviceUrlStr) throws Exception {
 207 
 208         // Building command-line
 209         List<String> opts = buildCommandLine(args);
 210         opts.add("-serviceUrl");
 211         opts.add(serviceUrlStr);
 212 
 213         // Launch separate JVM subprocess
 214         int exitCode = 0;
 215         String[] optsArray = opts.toArray(new String[0]);
 216         ProcessBuilder pb = new ProcessBuilder(optsArray);
 217         Process p = ProcessTools.startProcess("AuthorizationTest$ClientSide", pb);
 218 
 219         // Handling end of subprocess
 220         try {
 221             exitCode = p.waitFor();
 222             if (exitCode != 0) {
 223                 System.out.println(
 224                     "Subprocess unexpected exit value of [" + exitCode +
 225                     "]. Expected 0.\n");
 226             }
 227         } catch (InterruptedException e) {
 228             System.out.println("Parent process interrupted with exception : \n " + e + " :" );
 229 
 230             // Parent thread unknown state, killing subprocess.
 231             p.destroyForcibly();
 232 
 233             throw new RuntimeException(
 234                 "Parent process interrupted with exception : \n " + e + " :" );
 235 
 236         } finally {
 237             if (p.isAlive()) {
 238                 p.destroyForcibly();
 239             }
 240             return exitCode;
 241         }
 242 
 243      }
 244 
 245     public void run(Map<String, Object> serverArgs, String clientArgs[]) {
 246 
 247         System.out.println("AuthorizationTest::run: Start") ;
 248         int errorCount = 0;
 249 
 250         try {
 251             // Initialise the server side
 252             JMXServiceURL urlToUse = createServerSide(serverArgs);
 253 
 254             // Run client side
 255             errorCount = runClientSide(clientArgs, urlToUse.toString());
 256 
 257             if ( errorCount == 0 ) {
 258                 System.out.println("AuthorizationTest::run: Done without any error") ;
 259             } else {
 260                 System.out.println("AuthorizationTest::run: Done with "
 261                         + errorCount
 262                         + " error(s)") ;
 263                 throw new RuntimeException("errorCount = " + errorCount);
 264             }
 265 
 266             cs.stop();
 267 
 268         } catch(Exception e) {
 269             throw new RuntimeException(e);
 270         }
 271 
 272     }
 273 
 274     private static class ClientSide {
 275 
 276         private JMXConnector cc = null;
 277         private MBeanServerConnection mbsc = null;
 278 
 279         public static void main(String args[]) throws Exception {
 280 
 281             // Parses parameters
 282             Utils.parseDebugProperties();
 283 
 284             // Supported parameters list format is : "MainClass [-client <param-spec> ...]
 285             // with <param-spec> either "-parami valuei" or "-parami"
 286             HashMap<String, Object> clientMap = new HashMap<>() ;
 287             Utils.parseClientParameters(args, CLIENT_CLASS_NAME, clientMap);
 288 
 289             // Run test
 290             ClientSide test = new ClientSide();
 291             test.run(clientMap);
 292 
 293         }
 294 
 295         public void run(Map<String, Object> args) {
 296 
 297             int errorCount = 0 ;
 298 
 299             try {
 300                 boolean expectedCreateException =
 301                         (args.containsKey("-expectedCreateException")) ? true : false ;
 302                 boolean expectedGetException =
 303                         (args.containsKey("-expectedGetException")) ? true : false ;
 304                 boolean expectedSetException =
 305                         (args.containsKey("-expectedSetException")) ? true : false ;
 306                 boolean expectedInvokeException =
 307                         (args.containsKey("-expectedInvokeException")) ? true : false ;
 308                 // JSR262 (see bug 6440374)
 309                 // There is no special JSR262 protocol operation for connect.
 310                 // The first request sent initiate the connection.
 311                 // In the JSR262 current implementation, getDefaultDomain is sent to
 312                 // the server in order to get the server part of the connection ID.
 313                 // => the connection may fail if no access permission on get requests.
 314                 boolean expectedConnectException =
 315                         (args.containsKey("-expectedConnectException")) ? true : false ;
 316                 // Before connection,
 317                 // remove the element of the Map with null values (not supported by RMI)
 318                 // See bug 4982668
 319                 args.remove("-expectedCreateException");
 320                 args.remove("-expectedGetException");
 321                 args.remove("-expectedSetException");
 322                 args.remove("-expectedInvokeException");
 323                 args.remove("-expectedConnectException");
 324 
 325 
 326                 // Here do connect to the JMX Server
 327                 String username = System.getProperty("username");
 328                 Utils.debug(Utils.DEBUG_STANDARD,
 329                     "ClientSide::run: CONNECT on behalf of \"" + username + "\"");
 330                 doConnect(args, expectedConnectException);
 331 
 332                 // If the connection did not fail, perform some requests.
 333                 // At this stage the mbeanserver connection is up and running
 334                 if (mbsc != null) {
 335                     ObjectName on = new ObjectName("defaultDomain:class=Simple");
 336 
 337                     // Create request
 338                     Utils.debug(Utils.DEBUG_STANDARD,
 339                         "ClientSide::run: CREATE on behalf of \"" +
 340                         username + "\"");
 341                     errorCount += doCreateRequest(mbsc,
 342                         new ObjectName("defaultDomain:class=Simple,user=" + username),
 343                         expectedCreateException);
 344 
 345                     // Get request
 346                     Utils.debug(Utils.DEBUG_STANDARD,
 347                         "ClientSide::run: GET on behalf of \"" +
 348                         username + "\"");
 349                     errorCount += doGetRequest(mbsc, on, expectedGetException);
 350 
 351                     // Set request
 352                     Utils.debug(Utils.DEBUG_STANDARD,
 353                         "ClientSide::run: SET on behalf of \"" +
 354                         username + "\"");
 355                     errorCount += doSetRequest(mbsc, on, expectedSetException);
 356 
 357                     // Invoke request
 358                     Utils.debug(Utils.DEBUG_STANDARD,
 359                         "ClientSide::run: INVOKE on behalf of \"" +
 360                         username + "\"");
 361                     errorCount += doInvokeRequest(mbsc, on, expectedInvokeException);
 362                 }
 363 
 364             } catch(Exception e) {
 365                 Utils.printThrowable(e, true) ;
 366                 errorCount++;
 367             } finally {
 368                 // Terminate the JMX Client
 369                 try {
 370                     cc.close();
 371                 } catch (Exception e) {
 372                     Utils.printThrowable(e, true) ;
 373                     errorCount++;
 374                 }
 375             }
 376 
 377             System.out.println("ClientSide::run: Done") ;
 378 
 379             // Handle result
 380             if (errorCount == 0) {
 381                 System.out.println("ClientSide::run: (OK) authorization test succeeded.");
 382             } else {
 383                 String message = "AuthorizationTest$ClientSide::run: (ERROR) " +
 384                         " authorization test failed with " +
 385                         errorCount + " error(s)";
 386                 System.out.println(message);
 387                 throw new RuntimeException(message);
 388             }
 389         }
 390 
 391         protected void doConnect(Map<String, Object> args,
 392                                  boolean expectedException) {
 393 
 394             String msgTag = "ClientSide::doConnect";
 395             boolean throwRuntimeException = false;
 396             String message = "";
 397 
 398             try {
 399                 Utils.debug(Utils.DEBUG_STANDARD,
 400                     "ClientSide::doConnect: Connect the client");
 401 
 402                 // Collect connection environment
 403                 HashMap<String, Object> env = new HashMap<>();
 404 
 405                 Object value = args.get("-mapType");
 406                 if (value != null) {
 407                     String username = System.getProperty("username");
 408                     String password = System.getProperty("password");
 409                     Utils.debug(Utils.DEBUG_STANDARD,
 410                         msgTag + "add \"jmx.remote.credentials\" = \"" +
 411                         username + "\", \"" + password + "\"");
 412                     env.put("jmx.remote.credentials",
 413                         new String[] { username , password });
 414                 }
 415 
 416                 // Get a connection to remote mbean server
 417                 JMXServiceURL addr = new JMXServiceURL((String)args.get("-serviceUrl"));
 418                 cc = JMXConnectorFactory.connect(addr,env);
 419                 mbsc = cc.getMBeanServerConnection();
 420 
 421                 if (expectedException) {
 422                     message = "ClientSide::doConnect: (ERROR) " +
 423                         "Connect did not fail with expected SecurityException";
 424                     System.out.println(message);
 425                     throwRuntimeException = true;
 426                 } else {
 427                     System.out.println("ClientSide::doConnect: (OK) Connect succeed");
 428                 }
 429             } catch(Exception e) {
 430                 Utils.printThrowable(e, true);
 431                 if (expectedException) {
 432                     if (e instanceof java.lang.SecurityException) {
 433                         System.out.println("ClientSide::doConnect: (OK) " +
 434                             "Connect failed with expected SecurityException");
 435                     } else {
 436                         message = "ClientSide::doConnect: (ERROR) " +
 437                             "Create failed with " + e.getClass() +
 438                             " instead of expected SecurityException";
 439                         System.out.println(message);
 440                         throwRuntimeException = true;
 441                     }
 442                 } else {
 443                     message = "ClientSide::doConnect: (ERROR) " +
 444                         "Connect failed";
 445                     System.out.println(message);
 446                     throwRuntimeException = true;
 447                 }
 448             }
 449 
 450             // If the connection failed, or if the connection succeeded but should not,
 451             // no need to go further => throw RuntimeException and exit the test
 452             if (throwRuntimeException) {
 453                 throw new RuntimeException(message);
 454             }
 455         }
 456 
 457         protected int doCreateRequest(MBeanServerConnection mbsc,
 458                                       ObjectName on,
 459                                       boolean expectedException) {
 460             int errorCount = 0;
 461 
 462             try {
 463                 Utils.debug(Utils.DEBUG_STANDARD,
 464                     "ClientSide::doCreateRequest: Create and register the MBean") ;
 465 
 466                 mbsc.createMBean("Simple", on) ;
 467 
 468                 if (expectedException) {
 469                     System.out.println("ClientSide::doCreateRequest: " +
 470                         "(ERROR) Create did not fail with expected SecurityException");
 471                     errorCount++;
 472                 } else {
 473                     System.out.println("ClientSide::doCreateRequest: (OK) Create succeed") ;
 474                 }
 475             } catch(Exception e) {
 476                 Utils.printThrowable(e, true) ;
 477                 if (expectedException) {
 478                     if (e instanceof java.lang.SecurityException) {
 479                         System.out.println("ClientSide::doCreateRequest: " +
 480                             "(OK) Create failed with expected SecurityException") ;
 481                     } else {
 482                         System.out.println("ClientSide::doCreateRequest: " +
 483                             "(ERROR) Create failed with " +
 484                             e.getClass() + " instead of expected SecurityException");
 485                         errorCount++;
 486                     }
 487                 } else {
 488                     System.out.println("ClientSide::doCreateRequest: " +
 489                         "(ERROR) Create failed");
 490                     errorCount++;
 491                 }
 492             }
 493             return errorCount;
 494         }
 495 
 496         protected int doGetRequest(MBeanServerConnection mbsc,
 497                                    ObjectName on,
 498                                    boolean expectedException) {
 499             int errorCount = 0;
 500 
 501             try {
 502                 Utils.debug(Utils.DEBUG_STANDARD,
 503                     "ClientSide::doGetRequest: Get attributes of the MBean") ;
 504 
 505                 mbsc.getAttribute(on, "Attribute");
 506 
 507                 if (expectedException) {
 508                     System.out.println("ClientSide::doGetRequest: " +
 509                         "(ERROR) Get did not fail with expected SecurityException");
 510                     errorCount++;
 511                 } else {
 512                     System.out.println("ClientSide::doGetRequest: (OK) Get succeed") ;
 513                 }
 514             } catch(Exception e) {
 515                 Utils.printThrowable(e, true) ;
 516                 if (expectedException) {
 517                     if (e instanceof java.lang.SecurityException) {
 518                         System.out.println("ClientSide::doGetRequest: " +
 519                             "(OK) Get failed with expected SecurityException") ;
 520                     } else {
 521                         System.out.println("ClientSide::doGetRequest: " +
 522                             "(ERROR) Get failed with " +
 523                             e.getClass() + " instead of expected SecurityException");
 524                         errorCount++;
 525                     }
 526                 } else {
 527                     System.out.println("ClientSide::doGetRequest: (ERROR) Get failed");
 528                     errorCount++;
 529                 }
 530             }
 531 
 532             return errorCount;
 533         }
 534 
 535         protected int doSetRequest(MBeanServerConnection mbsc,
 536                                    ObjectName on,
 537                                    boolean expectedException) {
 538             int errorCount = 0;
 539 
 540             try {
 541                 Utils.debug(Utils.DEBUG_STANDARD,
 542                     "ClientSide::doSetRequest: Set attributes of the MBean") ;
 543 
 544                 Attribute attribute = new Attribute("Attribute", "My value") ;
 545                 mbsc.setAttribute(on, attribute) ;
 546 
 547                 if (expectedException) {
 548                     System.out.println("ClientSide::doSetRequest: " +
 549                         "(ERROR) Set did not fail with expected SecurityException");
 550                     errorCount++;
 551                 } else {
 552                     System.out.println("ClientSide::doSetRequest: (OK) Set succeed") ;
 553                 }
 554             } catch(Exception e) {
 555                 Utils.printThrowable(e, true) ;
 556                 if (expectedException) {
 557                     if (e instanceof java.lang.SecurityException) {
 558                         System.out.println("ClientSide::doSetRequest: " +
 559                             "(OK) Set failed with expected SecurityException") ;
 560                     } else {
 561                         System.out.println("ClientSide::doSetRequest: " +
 562                             "(ERROR) Set failed with " +
 563                             e.getClass() + " instead of expected SecurityException");
 564                         errorCount++;
 565                     }
 566                 } else {
 567                     System.out.println("ClientSide::doSetRequest: (ERROR) Set failed");
 568                     errorCount++;
 569                 }
 570             }
 571             return errorCount;
 572         }
 573 
 574         protected int doInvokeRequest(MBeanServerConnection mbsc,
 575                                       ObjectName on,
 576                                       boolean expectedException) {
 577             int errorCount = 0;
 578 
 579             try {
 580                 Utils.debug(Utils.DEBUG_STANDARD,
 581                     "ClientSide::doInvokeRequest: Invoke operations on the MBean") ;
 582 
 583                 mbsc.invoke(on, "operation", null, null) ;
 584 
 585                 if (expectedException) {
 586                     System.out.println("ClientSide::doInvokeRequest: " +
 587                         "(ERROR) Invoke did not fail with expected SecurityException");
 588                     errorCount++;
 589                 } else {
 590                     System.out.println("ClientSide::doInvokeRequest: (OK) Invoke succeed") ;
 591                 }
 592             } catch(Exception e) {
 593                 Utils.printThrowable(e, true) ;
 594                 if (expectedException) {
 595                     if (e instanceof java.lang.SecurityException) {
 596                         System.out.println("ClientSide::doInvokeRequest: " +
 597                             "(OK) Invoke failed with expected SecurityException") ;
 598                     } else {
 599                         System.out.println("ClientSide::doInvokeRequest: " +
 600                             " (ERROR) Invoke failed with " +
 601                             e.getClass() + " instead of expected SecurityException");
 602                         errorCount++;
 603                     }
 604                 } else {
 605                     System.out.println("ClientSide::doInvokeRequest: " +
 606                         "(ERROR) Invoke failed");
 607                     errorCount++;
 608                 }
 609             }
 610             return errorCount;
 611         }
 612 
 613     }
 614 }