1 /*
   2  * Copyright (c) 2004, 2005, 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     4982289
  27  * @summary Test ThreadInfo.from to return a valid
  28  *          ThreadInfo object. Or throw exception if
  29  *          the input CompositeData is invalid.
  30  * @author  Mandy Chung
  31  *
  32  * @compile OpenTypeConverter.java
  33  * @build ThreadInfoCompositeData
  34  * @run main ThreadInfoCompositeData
  35  */
  36 
  37 import javax.management.openmbean.*;
  38 import java.lang.management.LockInfo;
  39 import java.lang.management.MonitorInfo;
  40 import java.lang.management.ThreadInfo;
  41 
  42 public class ThreadInfoCompositeData {
  43     private static StackTraceElement[] ste = new StackTraceElement[1];
  44     private static CompositeData[] steCD = new CompositeData[1];
  45     private static String lockClassName = "myClass";
  46     private static int lockIdentityHashCode = 123456;
  47     private static String lockName = lockClassName + '@' +
  48         Integer.toHexString(lockIdentityHashCode);
  49     private static LockInfo lockInfo =
  50         new LockInfo(lockClassName, lockIdentityHashCode);
  51 
  52     public static void main(String[] argv) throws Exception {
  53         // A valid CompositeData is passed to ThreadInfo
  54         createGoodCompositeData();
  55         // A valid CompositeData for JDK 5.0 ThreadInfo
  56         // is passed to ThreadInfo
  57         createV5ThreadInfo();
  58         // An invalid CompositeData is passed to ThreadInfo.from()
  59         badNameCompositeData();
  60         badTypeCompositeData();
  61         System.out.println("Test passed");
  62     }
  63 
  64     public static void createGoodCompositeData() throws Exception {
  65         CompositeType ct =
  66             new CompositeType("MyCompositeType",
  67                               "CompositeType for ThreadInfo",
  68                               validItemNames,
  69                               validItemNames,
  70                               validItemTypes);
  71         CompositeData cd =
  72             new CompositeDataSupport(ct,
  73                                      validItemNames,
  74                                      values);
  75         ThreadInfo info = ThreadInfo.from(cd);
  76         checkThreadInfo(info);
  77    }
  78 
  79     public static void createV5ThreadInfo() throws Exception {
  80         String[] v5ItemNames = new String[NUM_V5_ATTS];
  81         OpenType[] v5ItemTypes = new OpenType[NUM_V5_ATTS];
  82         Object[] v5ItemValues = new Object[NUM_V5_ATTS];
  83         for (int i = 0; i < NUM_V5_ATTS; i++) {
  84             v5ItemNames[i] = validItemNames[i];
  85             v5ItemTypes[i] = validItemTypes[i];
  86             v5ItemValues[i] = values[i];
  87         }
  88         CompositeType ct =
  89             new CompositeType("MyCompositeType",
  90                               "CompositeType for JDK 5.0 ThreadInfo",
  91                               v5ItemNames,
  92                               v5ItemNames,
  93                               v5ItemTypes);
  94         CompositeData cd =
  95             new CompositeDataSupport(ct,
  96                                      v5ItemNames,
  97                                      v5ItemValues);
  98         ThreadInfo info = ThreadInfo.from(cd);
  99         checkThreadInfo(info);
 100    }
 101 
 102    static void checkThreadInfo(ThreadInfo info) throws Exception {
 103         if (info.getThreadId() != ((Long) values[THREAD_ID]).longValue()) {
 104             throw new RuntimeException("Thread Id = " + info.getThreadId() +
 105                " expected = " + values[THREAD_ID]);
 106         }
 107         if (!info.getThreadName().equals(values[THREAD_NAME])) {
 108             throw new RuntimeException("Thread Name = " +
 109                info.getThreadName() + " expected = " + values[THREAD_NAME]);
 110         }
 111         if (info.getThreadState() != Thread.State.RUNNABLE) {
 112             throw new RuntimeException("Thread Name = " +
 113                info.getThreadName() + " expected = " + Thread.State.RUNNABLE);
 114         }
 115         if (info.getBlockedTime() != ((Long) values[BLOCKED_TIME]).longValue()) {
 116             throw new RuntimeException("blocked time = " +
 117                info.getBlockedTime() +
 118                " expected = " + values[BLOCKED_TIME]);
 119         }
 120         if (info.getBlockedCount() != ((Long) values[BLOCKED_COUNT]).longValue()) {
 121             throw new RuntimeException("blocked count = " +
 122                info.getBlockedCount() +
 123                " expected = " + values[BLOCKED_COUNT]);
 124         }
 125         if (info.getWaitedTime() != ((Long) values[WAITED_TIME]).longValue()) {
 126             throw new RuntimeException("waited time = " +
 127                info.getWaitedTime() +
 128                " expected = " + values[WAITED_TIME]);
 129         }
 130         if (info.getWaitedCount() != ((Long) values[WAITED_COUNT]).longValue()) {
 131             throw new RuntimeException("waited count = " +
 132                info.getWaitedCount() +
 133                " expected = " + values[WAITED_COUNT]);
 134         }
 135         if (!info.getLockName().equals(values[LOCK_NAME])) {
 136             throw new RuntimeException("Lock Name = " +
 137                info.getLockName() + " expected = " + values[LOCK_NAME]);
 138         }
 139         if (info.getLockOwnerId() !=
 140                 ((Long) values[LOCK_OWNER_ID]).longValue()) {
 141             throw new RuntimeException(
 142                "LockOwner Id = " + info.getLockOwnerId() +
 143                " expected = " + values[LOCK_OWNER_ID]);
 144         }
 145         if (!info.getLockOwnerName().equals(values[LOCK_OWNER_NAME])) {
 146             throw new RuntimeException("LockOwner Name = " +
 147                info.getLockOwnerName() + " expected = " +
 148                values[LOCK_OWNER_NAME]);
 149         }
 150         if (!values[DAEMON].equals(info.isDaemon())) {
 151             throw new RuntimeException("Daemon = " +
 152                info.isDaemon() + " expected = " +
 153                values[DAEMON]);
 154         }
 155 
 156         checkStackTrace(info.getStackTrace());
 157 
 158         checkLockInfo(info.getLockInfo());
 159     }
 160 
 161     private static void checkStackTrace(StackTraceElement[] s)
 162         throws Exception {
 163         if (ste.length != s.length) {
 164             throw new RuntimeException("Stack Trace length = " +
 165                 s.length + " expected = " + ste.length);
 166         }
 167 
 168         StackTraceElement s1 = ste[0];
 169         StackTraceElement s2 = s[0];
 170 
 171         if (!s1.getClassName().equals(s2.getClassName())) {
 172             throw new RuntimeException("Class name = " +
 173                 s2.getClassName() + " expected = " + s1.getClassName());
 174         }
 175         if (!s1.getMethodName().equals(s2.getMethodName())) {
 176             throw new RuntimeException("Method name = " +
 177                 s2.getMethodName() + " expected = " + s1.getMethodName());
 178         }
 179         if (!s1.getFileName().equals(s2.getFileName())) {
 180             throw new RuntimeException("File name = " +
 181                 s2.getFileName() + " expected = " + s1.getFileName());
 182         }
 183         if (s1.getLineNumber() != s2.getLineNumber()) {
 184             throw new RuntimeException("Line number = " +
 185                 s2.getLineNumber() + " expected = " + s1.getLineNumber());
 186         }
 187     }
 188 
 189     private static void checkLockInfo(LockInfo li)
 190         throws Exception {
 191         if (!li.getClassName().equals(lockInfo.getClassName())) {
 192             throw new RuntimeException("Class Name = " +
 193                 li.getClassName() + " expected = " + lockInfo.getClassName());
 194         }
 195         if (li.getIdentityHashCode() != lockInfo.getIdentityHashCode()) {
 196             throw new RuntimeException("Class Name = " +
 197                 li.getIdentityHashCode() + " expected = " +
 198                 lockInfo.getIdentityHashCode());
 199         }
 200     }
 201 
 202     public static void badNameCompositeData() throws Exception {
 203         CompositeType ct =
 204             new CompositeType("MyCompositeType",
 205                               "CompositeType for ThreadInfo",
 206                               badItemNames,
 207                               badItemNames,
 208                               validItemTypes);
 209         CompositeData cd =
 210             new CompositeDataSupport(ct,
 211                                      badItemNames,
 212                                      values);
 213 
 214         try {
 215             ThreadInfo info = ThreadInfo.from(cd);
 216         } catch (IllegalArgumentException e) {
 217             System.out.println("Expected exception: " +
 218                 e.getMessage());
 219             return;
 220         }
 221         throw new RuntimeException(
 222             "IllegalArgumentException not thrown");
 223     }
 224 
 225     public static void badTypeCompositeData() throws Exception {
 226         CompositeType ct =
 227             new CompositeType("MyCompositeType",
 228                               "CompositeType for ThreadInfo",
 229                               validItemNames,
 230                               validItemNames,
 231                               badItemTypes);
 232 
 233         // patch values[STACK_TRACE] to Long
 234         values[STACK_TRACE] = new Long(1000);
 235         values[LOCK_INFO] = new Long(1000);
 236         CompositeData cd =
 237             new CompositeDataSupport(ct,
 238                                      validItemNames,
 239                                      values);
 240 
 241         try {
 242             ThreadInfo info = ThreadInfo.from(cd);
 243         } catch (IllegalArgumentException e) {
 244             System.out.println("Expected exception: " +
 245                 e.getMessage());
 246             return;
 247         }
 248         throw new RuntimeException(
 249             "IllegalArgumentException not thrown");
 250     }
 251 
 252     private static final int THREAD_ID       = 0;
 253     private static final int THREAD_NAME     = 1;
 254     private static final int THREAD_STATE    = 2;
 255     private static final int BLOCKED_TIME    = 3;
 256     private static final int BLOCKED_COUNT   = 4;
 257     private static final int WAITED_TIME     = 5;
 258     private static final int WAITED_COUNT    = 6;
 259     private static final int LOCK_NAME       = 7;
 260     private static final int LOCK_OWNER_ID   = 8;
 261     private static final int LOCK_OWNER_NAME = 9;
 262     private static final int STACK_TRACE     = 10;
 263     private static final int SUSPENDED       = 11;
 264     private static final int IN_NATIVE       = 12;
 265     private static final int NUM_V5_ATTS     = 13;
 266     // JDK 6.0 ThreadInfo attributes
 267     private static final int LOCK_INFO       = 13;
 268     // JDK 9.0 ThreadInfo attributes
 269     private static final int DAEMON          = 14;
 270     private static final int PRIORITY        = 15;
 271 
 272     private static final String[] validItemNames = {
 273         "threadId",
 274         "threadName",
 275         "threadState",
 276         "blockedTime",
 277         "blockedCount",
 278         "waitedTime",
 279         "waitedCount",
 280         "lockName",
 281         "lockOwnerId",
 282         "lockOwnerName",
 283         "stackTrace",
 284         "suspended",
 285         "inNative",
 286         "lockInfo",
 287         "daemon",
 288         "priority",
 289     };
 290 
 291     private static OpenType[] validItemTypes = {
 292         SimpleType.LONG,
 293         SimpleType.STRING,
 294         SimpleType.STRING,
 295         SimpleType.LONG,
 296         SimpleType.LONG,
 297         SimpleType.LONG,
 298         SimpleType.LONG,
 299         SimpleType.STRING,
 300         SimpleType.LONG,
 301         SimpleType.STRING,
 302         null,  // ArrayType for StackTraceElement[]
 303         SimpleType.BOOLEAN,
 304         SimpleType.BOOLEAN,
 305         null,  // CompositeType for LockInfo
 306         SimpleType.BOOLEAN,
 307         SimpleType.INTEGER,
 308     };
 309 
 310     private static Object[] values = {
 311         new Long(100),
 312         "FooThread",
 313         "RUNNABLE",
 314         new Long(200),
 315         new Long(10),
 316         new Long(300),
 317         new Long(20),
 318         lockName,
 319         new Long(99),
 320         "BarThread",
 321         steCD,
 322         new Boolean(false),
 323         new Boolean(false),
 324         null, // To be initialized to lockInfoCD
 325         new Boolean(false),
 326         Thread.NORM_PRIORITY,
 327     };
 328 
 329     private static final String[] steItemNames = {
 330         "className",
 331         "methodName",
 332         "fileName",
 333         "lineNumber",
 334         "nativeMethod",
 335     };
 336 
 337     private static final String[] lockInfoItemNames = {
 338         "className",
 339         "identityHashCode",
 340     };
 341 
 342     static {
 343         // create stack trace element
 344         ste[0] = new StackTraceElement("FooClass", "getFoo", "Foo.java", 100);
 345 
 346         // initialize the ste[0] and values and validItemTypes
 347         try {
 348             CompositeType steCType = (CompositeType)
 349                 OpenTypeConverter.toOpenType(StackTraceElement.class);
 350             validItemTypes[STACK_TRACE] = new ArrayType(1, steCType);
 351 
 352             final Object[] steValue = {
 353                 ste[0].getClassName(),
 354                 ste[0].getMethodName(),
 355                 ste[0].getFileName(),
 356                 new Integer(ste[0].getLineNumber()),
 357                 new Boolean(ste[0].isNativeMethod()),
 358             };
 359 
 360             steCD[0] =
 361                 new CompositeDataSupport(steCType,
 362                                          steItemNames,
 363                                          steValue);
 364 
 365             CompositeType lockInfoCType = (CompositeType)
 366                 OpenTypeConverter.toOpenType(LockInfo.class);
 367             validItemTypes[LOCK_INFO] = lockInfoCType;
 368 
 369             final Object[] lockInfoValue = {
 370                 lockInfo.getClassName(),
 371                 lockInfo.getIdentityHashCode(),
 372             };
 373 
 374             values[LOCK_INFO] =
 375                 new CompositeDataSupport(lockInfoCType,
 376                                          lockInfoItemNames,
 377                                          lockInfoValue);
 378         } catch (Exception e) {
 379             throw new RuntimeException(e);
 380         }
 381     }
 382 
 383     private static final String[] badItemNames = {
 384         "threadId",
 385         "threadName",
 386         "threadState",
 387         "blockedTime",
 388         "blockedCount",
 389         "waitedTime",
 390         "waitedCount",
 391         "lockName",
 392         "lockOwnerId",
 393         "lockOwnerName",
 394         "BadStackTrace", // bad item name
 395         "suspended",
 396         "inNative",
 397         "lockInfo",
 398         "daemon",
 399         "priority",
 400     };
 401     private static final OpenType[] badItemTypes = {
 402         SimpleType.LONG,
 403         SimpleType.STRING,
 404         SimpleType.STRING,
 405         SimpleType.LONG,
 406         SimpleType.LONG,
 407         SimpleType.LONG,
 408         SimpleType.LONG,
 409         SimpleType.STRING,
 410         SimpleType.LONG,
 411         SimpleType.STRING,
 412         SimpleType.LONG,  // bad type
 413         SimpleType.BOOLEAN,
 414         SimpleType.BOOLEAN,
 415         SimpleType.LONG,  // bad type
 416         SimpleType.BOOLEAN,
 417         SimpleType.INTEGER,
 418     };
 419 
 420 }