1 /* 2 * Copyright (c) 2006, 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 Tests most of the existing query types. 28 * @author Olivier Lagneau 29 * 30 * @modules java.management.rmi 31 * 32 * @compile TestQuery.java 33 * @run main/othervm/timeout=300 -DDEBUG_STANDARD SupportedQueryTypesTest -mbeanClassName TestQuery 34 */ 35 36 import java.util.Map ; 37 import java.util.HashMap; 38 import java.util.Set; 39 import java.util.HashSet; 40 import java.util.Iterator; 41 import java.util.Properties; 42 import java.lang.reflect.Method; 43 44 import java.lang.management.ManagementFactory; 45 import javax.management.MBeanServer; 46 import javax.management.MBeanServerFactory; 47 import javax.management.MBeanServerConnection; 48 import javax.management.ObjectInstance; 49 import javax.management.ObjectName ; 50 import javax.management.QueryExp; 51 52 import javax.management.remote.JMXConnector; 53 import javax.management.remote.JMXConnectorFactory; 54 import javax.management.remote.JMXConnectorServer; 55 import javax.management.remote.JMXConnectorServerFactory; 56 import javax.management.remote.JMXServiceURL; 57 58 public class SupportedQueryTypesTest { 59 60 protected String mbeanClassName = null; 61 62 private MBeanServerConnection mbsc = null; 63 64 65 /* 66 * First Debug properties and arguments are collect in expected 67 * map (argName, value) format, then calls original test's run method. 68 */ 69 public static void main(String args[]) throws Exception { 70 71 System.out.println("================================================="); 72 73 // Parses parameters 74 Utils.parseDebugProperties(); 75 Map<String, Object> map = Utils.parseParameters(args) ; 76 77 // Run test 78 SupportedQueryTypesTest test = new SupportedQueryTypesTest(); 79 test.run(map); 80 81 } 82 83 public void run(Map<String, Object> args) { 84 int errorCount = 0; 85 86 ObjectName on = null; 87 ObjectName serverDelegateObjectName = null; 88 89 JMXConnectorServer cs = null; 90 JMXConnector cc = null; 91 92 System.out.println("SupportedQueryTypesTest::run: Start") ; 93 try { 94 // JMX MbeanServer used inside single VM as if remote. 95 MBeanServer mbs = ManagementFactory.getPlatformMBeanServer(); 96 97 JMXServiceURL url = new JMXServiceURL("rmi", null, 0); 98 cs = JMXConnectorServerFactory.newJMXConnectorServer(url, null, mbs); 99 cs.start(); 100 101 JMXServiceURL addr = cs.getAddress(); 102 cc = JMXConnectorFactory.connect(addr); 103 mbsc = cc.getMBeanServerConnection(); 104 105 106 // Create and register the ServerDelegate MBean on the remote MBeanServer 107 String serverDelegateClassName = ServerDelegate.class.getName(); 108 serverDelegateObjectName = 109 new ObjectName("defaultDomain:class=" + serverDelegateClassName); 110 mbsc.createMBean(serverDelegateClassName, serverDelegateObjectName); 111 112 // Retrieve the MBean class name 113 mbeanClassName = (String) args.get("-mbeanClassName") ; 114 on = new ObjectName("defaultDomain:class=" + mbeanClassName); 115 116 // Create and register the MBean on the remote MBeanServer 117 System.out.println("SupportedQueryTypesTest::run: CREATE " + 118 mbeanClassName + " on the remote MBeanServer with name " 119 + on); 120 mbsc.createMBean(mbeanClassName, on); 121 122 // Create a QueryFactory and setup which query we'll use. 123 QueryFactory queries = new QueryFactory(mbeanClassName); 124 queries.buildQueries(); 125 int maxIndex = queries.getSize(); 126 int minIndex = 1; 127 128 // Create a reference Set<ObjectName> to check later on 129 // the queryNames() results 130 Set<ObjectName> referenceNameSet = new HashSet<ObjectName>(); 131 referenceNameSet.add(on); 132 133 // Create a reference Set<ObjectInstance> to check later on 134 // the queryMBeans() results 135 ObjectInstance oi = new ObjectInstance(on, mbeanClassName); 136 Set<ObjectInstance> referenceInstanceSet = 137 new HashSet<ObjectInstance>(); 138 referenceInstanceSet.add(oi); 139 140 // Perform the queryNames and queryMBeans requests 141 for (int i = minIndex; i <= maxIndex; i++ ) { 142 QueryExp query = queries.getQuery(i); 143 System.out.println("----"); 144 System.out.println("SupportedQueryTypesTest::run: Query # " + i); 145 System.out.println("query " + query); 146 errorCount += 147 doQueryNames(query, referenceNameSet); 148 errorCount += 149 doQueryMBeans(query, referenceInstanceSet); 150 } 151 152 } catch(Exception e) { 153 Utils.printThrowable(e, true); 154 errorCount++; 155 156 } finally { 157 // Do unregister the MBean 158 try { 159 if (mbsc.isRegistered(on)) { 160 mbsc.unregisterMBean(on); 161 } 162 if (mbsc.isRegistered(serverDelegateObjectName)) { 163 mbsc.unregisterMBean(serverDelegateObjectName); 164 } 165 } catch (Exception e) { 166 Utils.printThrowable(e, true) ; 167 errorCount++; 168 } 169 170 try { 171 // Close JMX Connector Client 172 cc.close(); 173 // Stop connertor server 174 cs.stop(); 175 176 } catch (Exception e) { 177 Utils.printThrowable(e, true) ; 178 errorCount++; 179 } 180 } 181 182 System.out.println(""); 183 System.out.println("SupportedQueryTypesTest::run: Done") ; 184 185 // Handle result 186 if (errorCount == 0) { 187 System.out.println("SupportedQueryTypesTest::run: (OK)"); 188 } else { 189 String message = "SupportedQueryTypesTest::run: (ERROR) Got " + 190 + errorCount + " error(s)"; 191 System.out.println(message); 192 throw new RuntimeException(message); 193 } 194 } 195 196 197 private int doQueryNames(QueryExp query, Set<ObjectName> referenceSet) { 198 int errorCount = 0; 199 System.out.println(" <*> Perform queryNames call "); 200 201 try { 202 // Call queryNames on the remote MBeanServer 203 Set<ObjectName> remoteSet = mbsc.queryNames(null, query); 204 205 // Compare the 2 Set<ObjectName> 206 errorCount += checkSet(remoteSet, referenceSet); 207 208 // Cleaning 209 remoteSet.clear(); 210 211 } catch (Exception e) { 212 Utils.printThrowable(e, true); 213 errorCount++; 214 } 215 216 if ( errorCount == 0 ) { 217 System.out.println("\t(OK)"); 218 } else { 219 System.out.println("\t(ERROR) Query failed"); 220 } 221 222 return errorCount; 223 } 224 225 226 private int doQueryMBeans(QueryExp query, Set<ObjectInstance> referenceSet) { 227 int errorCount = 0; 228 System.out.println(" <*> Perform queryMBeans call "); 229 230 try { 231 // Call queryMBeans on the remote MBeanServer 232 Set<ObjectInstance> remoteSet = mbsc.queryMBeans(null, query); 233 234 // Compare the 2 Set<ObjectInstance> 235 errorCount += checkSet(remoteSet, referenceSet); 236 237 // Cleaning 238 remoteSet.clear(); 239 240 } catch (Exception e) { 241 Utils.printThrowable(e, true); 242 errorCount++; 243 } 244 245 if ( errorCount == 0 ) { 246 System.out.println("\t(OK)"); 247 } else { 248 System.out.println("\t(ERROR) Query failed"); 249 } 250 251 return errorCount; 252 } 253 254 /** 255 * Pretty print of a Set content. 256 * When the Set isn't empty, toString() is called on each element. 257 * <br>The variable's name used to hold that Set is given via the setName 258 * parameter and used in the output. 259 */ 260 private static void printSet(Set<?> printableSet, String setName) { 261 if ( printableSet.size() == 0 ) { 262 System.out.println("The Set " + setName + " is empty"); 263 } else { 264 System.out.println("The Set " + setName + " contains :"); 265 266 for (Iterator<?> it = printableSet.iterator(); it.hasNext();) { 267 Object elem = it.next(); 268 System.out.println("\t" + elem.toString()); 269 } 270 } 271 } 272 273 274 /** 275 * This method check the Set remoteSet is equal to 276 * the reference Set referenceSet, 277 * which means same size and content (order doesn't matter). 278 * <br>It returns 0 when the check is fine, otherwise 1. 279 */ 280 private int checkSet(Set<?> remoteSet, Set<?> referenceSet) { 281 if ( ! remoteSet.equals(referenceSet) ) { 282 System.out.println("SupportedQueryTypesTest::checkSet:" 283 + " (ERROR) Set aren't as expected"); 284 printSet(remoteSet, "remoteSet"); 285 printSet(referenceSet, "referenceSet"); 286 return 1; 287 } else { 288 return 0; 289 } 290 } 291 292 // Utility inner class coming from JMX Tonga test suite. 293 private static class Utils { 294 295 // DEBUG is printed depending on the DEBUG and DEBUG_LEVEL JAVA property 296 static final String DEBUG_HEADER = "[debug] "; 297 298 // DEBUG levels 299 static int selectedDebugLevel = 0; 300 static final int DEBUG_STANDARD = 1; 301 static final int DEBUG_VERBOSE = 2; // Mainly used for stress tests 302 static final int DEBUG_ALL = DEBUG_STANDARD | DEBUG_VERBOSE; 303 304 static void parseDebugProperties() { 305 int level = 0; 306 Properties p = System.getProperties(); 307 308 // get selected levels 309 if (p.getProperty("DEBUG_STANDARD") != null) { 310 level |= DEBUG_STANDARD; 311 } 312 313 if (p.getProperty("DEBUG_VERBOSE") != null) { 314 level |= DEBUG_VERBOSE; 315 } 316 317 if (p.getProperty("DEBUG_ALL") != null) { 318 level |= DEBUG_ALL; 319 } 320 321 selectedDebugLevel = level; 322 } 323 324 /** 325 * Reproduces the original parsing and collection of test parameters 326 * from the DTonga JMX test suite. 327 * 328 * Collects passed args and returns them in a map(argname, value) structure, 329 * which will be then propagated as necessary to various called methods. 330 */ 331 static Map<String, Object> parseParameters(String args[]) 332 throws Exception { 333 debug(DEBUG_STANDARD, "TestRoot::parseParameters: Start"); 334 HashMap<String, Object> map = new HashMap<>(); 335 336 for ( int i = 0; i < args.length; i++ ) { 337 if ( args[i].trim().startsWith("-") ) { 338 if ((i+1) < args.length && !args[i+1].startsWith("-") ) { 339 debug(DEBUG_STANDARD, 340 "TestRoot::parseParameters: added in map = " + 341 args[i] + 342 " with value " + 343 args[i+1]) ; 344 map.put(args[i].trim(), args[i+1].trim()) ; 345 } else if ((i+1) < args.length && args[i+1].startsWith("-") || 346 (i+1) == args.length ) { 347 debug(DEBUG_STANDARD, 348 "TestRoot::parseParameters: added in map = " + 349 args[i] + 350 " with null value") ; 351 map.put(args[i].trim(), null) ; 352 } else { 353 System.out.println( 354 "TestRoot::parseParameters: (WARNING) not added in map = " + 355 args[i]) ; 356 } 357 } 358 } 359 360 debug(DEBUG_STANDARD, "TestRoot::parseParameters: Done") ; 361 return map ; 362 } 363 364 /** 365 * This method is to be used in all tests to print anything 366 * that is temporary. 367 * Printing is done only when debug is activated by the property DEBUG. 368 * Printing depends also on the DEBUG_LEVEL property. 369 * Here it encapsulates a System.out.println. 370 */ 371 static void debug(int level, String line) { 372 if ((selectedDebugLevel & level) != 0) { 373 System.out.println(DEBUG_HEADER + line); 374 } 375 } 376 377 /** 378 * Do print stack trace when withStack is true. 379 * Does try to call getTargetException() and getTargetError() then 380 * print embedded stacks in the case of an Exception wrapping 381 * another Exception or an Error. Recurse until no more wrapping 382 * is found. 383 */ 384 static void printThrowable(Throwable theThro, boolean withStack) { 385 try { 386 if (withStack) { 387 theThro.printStackTrace(System.out); 388 } 389 if (theThro instanceof Exception) { 390 Exception t = (Exception) theThro; 391 Method target = null; 392 String blank = " "; 393 try { 394 target = t.getClass().getMethod("getTargetException", 395 (java.lang.Class<?>[]) null); 396 } catch (Exception ee) { 397 // OK: getTargetException method could be there or not 398 } 399 System.out.println(blank + t.getClass() + "==>" + t.getMessage()); 400 while (target != null) { 401 try { 402 t = (Exception) target.invoke(t, 403 (java.lang.Object[]) null); 404 } catch (Exception ee) { 405 t = null; 406 } 407 try { 408 if (t != null) { 409 blank = blank + " "; 410 System.out.println(blank + t.getClass() + "==>" + 411 t.getMessage()); 412 try { 413 target = 414 t.getClass().getMethod("getTargetException", 415 (java.lang.Class<?>[]) null); 416 } catch (Exception ee) { 417 // OK: getTargetException method could be there or not } 418 } 419 } else { 420 target = null; 421 } 422 } catch (Exception ee) { 423 target = null; 424 } 425 } 426 427 // We may have exceptions wrapping an Error then it is 428 // getTargetError that is likely to be called 429 try { 430 target = ((Exception) theThro).getClass().getMethod("getTargetError", 431 (java.lang.Class<?>[]) null); 432 } catch (Exception ee) { 433 // OK: getTargetError method could be there or not 434 } 435 Throwable err = theThro; 436 while (target != null) { 437 try { 438 err = (Error) target.invoke(err, 439 (java.lang.Object[]) null); 440 } catch (Exception ee) { 441 err = null; 442 } 443 try { 444 if (err != null) { 445 blank = blank + " "; 446 System.out.println(blank + err.getClass() + "==>" + 447 err.getMessage()); 448 if (withStack) { 449 err.printStackTrace(System.out); 450 } 451 try { 452 target = err.getClass().getMethod("getTargetError", 453 (java.lang.Class<?>[]) null); 454 } catch (Exception ee) { 455 // OK: getTargetError method could be there or not 456 } 457 } else { 458 target = null; 459 } 460 } catch (Exception ee) { 461 target = null; 462 } 463 } 464 } else { 465 System.out.println("Throwable is : " + theThro); 466 } 467 } catch (Throwable x) { 468 System.out.println("Exception : raised in printException : " + x); 469 } 470 } 471 } 472 473 }