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