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