1 /*
2  * Copyright (c) 2003, 2018, 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 /test/lib
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.test.lib.JDKToolFinder;
68 import jdk.test.lib.process.ProcessTools;
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      */
main(String args[])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      */
createServerSide(Map<String, Object> serverMap)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      */
buildCommandLine(String args[])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.test.lib.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      */
runClientSide(String args[], String serviceUrlStr)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 
run(Map<String, Object> serverArgs, String clientArgs[])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 
main(String args[])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 
run(Map<String, Object> args)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 
doConnect(Map<String, Object> args, boolean expectedException)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 
doCreateRequest(MBeanServerConnection mbsc, ObjectName on, boolean expectedException)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 
doGetRequest(MBeanServerConnection mbsc, ObjectName on, boolean expectedException)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 
doSetRequest(MBeanServerConnection mbsc, ObjectName on, boolean expectedException)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 
doInvokeRequest(MBeanServerConnection mbsc, ObjectName on, boolean expectedException)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 }
614