1 /*
   2  * Copyright (c) 2005, 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.  Oracle designates this
   8  * particular file as subject to the "Classpath" exception as provided
   9  * by Oracle in the LICENSE file that accompanied this code.
  10  *
  11  * This code is distributed in the hope that it will be useful, but WITHOUT
  12  * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
  13  * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
  14  * version 2 for more details (a copy is included in the LICENSE file that
  15  * accompanied this code).
  16  *
  17  * You should have received a copy of the GNU General Public License version
  18  * 2 along with this work; if not, write to the Free Software Foundation,
  19  * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
  20  *
  21  * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
  22  * or visit www.oracle.com if you need additional information or have any
  23  * questions.
  24  */
  25 
  26 package sun.management;
  27 
  28 import java.lang.management.MonitorInfo;
  29 import java.util.HashMap;
  30 import java.util.Map;
  31 import javax.management.openmbean.CompositeType;
  32 import javax.management.openmbean.CompositeData;
  33 import javax.management.openmbean.CompositeDataSupport;
  34 import javax.management.openmbean.OpenDataException;
  35 import javax.management.openmbean.OpenType;
  36 
  37 /**
  38  * A CompositeData for MonitorInfo for the local management support.
  39  * This class avoids the performance penalty paid to the
  40  * construction of a CompositeData use in the local case.
  41  */
  42 public class MonitorInfoCompositeData extends LazyCompositeData {
  43     private final MonitorInfo lock;
  44 
  45     private MonitorInfoCompositeData(MonitorInfo mi) {
  46         this.lock = mi;
  47     }
  48 
  49     public MonitorInfo getMonitorInfo() {
  50         return lock;
  51     }
  52 
  53     public static CompositeData toCompositeData(MonitorInfo mi) {
  54         MonitorInfoCompositeData micd = new MonitorInfoCompositeData(mi);
  55         return micd.getCompositeData();
  56     }
  57 
  58     protected CompositeData getCompositeData() {
  59         StackTraceElement ste = lock.getLockedStackFrame();
  60         CompositeData steCData = ste != null ? StackTraceElementCompositeData.toCompositeData(ste)
  61                                              : null;
  62         // values may be null; can't use Map.of
  63         Map<String,Object> items = new HashMap<>();
  64         items.put(CLASS_NAME,         lock.getClassName());
  65         items.put(IDENTITY_HASH_CODE, lock.getIdentityHashCode());
  66         items.put(LOCKED_STACK_FRAME, steCData);
  67         items.put(LOCKED_STACK_DEPTH, lock.getLockedStackDepth());
  68 
  69         try {
  70             return new CompositeDataSupport(MONITOR_INFO_COMPOSITE_TYPE, items);
  71         } catch (OpenDataException e) {
  72             // Should never reach here
  73             throw new AssertionError(e);
  74         }
  75     }
  76 
  77     private static final String CLASS_NAME         = "className";
  78     private static final String IDENTITY_HASH_CODE = "identityHashCode";
  79     private static final String LOCKED_STACK_FRAME = "lockedStackFrame";
  80     private static final String LOCKED_STACK_DEPTH = "lockedStackDepth";
  81 
  82     private static final String[] MONITOR_INFO_ATTRIBUTES = {
  83         CLASS_NAME,
  84         IDENTITY_HASH_CODE,
  85         LOCKED_STACK_FRAME,
  86         LOCKED_STACK_DEPTH
  87     };
  88 
  89     private static final CompositeType MONITOR_INFO_COMPOSITE_TYPE;
  90     private static final CompositeType V6_COMPOSITE_TYPE;
  91     static {
  92         try {
  93             MONITOR_INFO_COMPOSITE_TYPE = (CompositeType)
  94                 MappedMXBeanType.toOpenType(MonitorInfo.class);
  95 
  96             OpenType<?>[] types = new OpenType<?>[MONITOR_INFO_ATTRIBUTES.length];
  97             for (int i = 0; i < MONITOR_INFO_ATTRIBUTES.length; i++) {
  98                 String name = MONITOR_INFO_ATTRIBUTES[i];
  99                 types[i] = name.equals(LOCKED_STACK_FRAME)
 100                             ? StackTraceElementCompositeData.v5CompositeType()
 101                             : MONITOR_INFO_COMPOSITE_TYPE.getType(name);
 102             }
 103             V6_COMPOSITE_TYPE = new CompositeType("MonitorInfo",
 104                                                   "JDK 6 MonitorInfo",
 105                                                   MONITOR_INFO_ATTRIBUTES,
 106                                                   MONITOR_INFO_ATTRIBUTES,
 107                                                   types);
 108         } catch (OpenDataException e) {
 109             // Should never reach here
 110             throw new AssertionError(e);
 111         }
 112     }
 113 
 114     static CompositeType v6CompositeType() {
 115         return V6_COMPOSITE_TYPE;
 116     }
 117 
 118     public static String getClassName(CompositeData cd) {
 119         return getString(cd, CLASS_NAME);
 120     }
 121 
 122     public static int getIdentityHashCode(CompositeData cd) {
 123         return getInt(cd, IDENTITY_HASH_CODE);
 124     }
 125 
 126     public static StackTraceElement getLockedStackFrame(CompositeData cd) {
 127         CompositeData ste = (CompositeData) cd.get(LOCKED_STACK_FRAME);
 128         if (ste != null) {
 129             return StackTraceElementCompositeData.from(ste);
 130         } else {
 131             return null;
 132         }
 133     }
 134 
 135     public static int getLockedStackDepth(CompositeData cd) {
 136         return getInt(cd, LOCKED_STACK_DEPTH);
 137     }
 138 
 139     /** Validate if the input CompositeData has the expected
 140      * CompositeType (i.e. contain all attributes with expected
 141      * names and types).
 142      */
 143     public static void validateCompositeData(CompositeData cd) {
 144         if (cd == null) {
 145             throw new NullPointerException("Null CompositeData");
 146         }
 147 
 148         if (!isTypeMatched(MONITOR_INFO_COMPOSITE_TYPE, cd.getCompositeType()) &&
 149             !isTypeMatched(V6_COMPOSITE_TYPE, cd.getCompositeType())) {
 150             throw new IllegalArgumentException(
 151                 "Unexpected composite type for MonitorInfo");
 152         }
 153     }
 154 
 155     private static final long serialVersionUID = -5825215591822908529L;
 156 }