1 /* 2 * Copyright (c) 2011, 2012, 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 com.sun.management.GarbageCollectionNotificationInfo; 29 import com.sun.management.GcInfo; 30 import java.lang.reflect.Method; 31 import javax.management.openmbean.CompositeData; 32 import javax.management.openmbean.CompositeType; 33 import javax.management.openmbean.CompositeDataSupport; 34 import javax.management.openmbean.OpenDataException; 35 import javax.management.openmbean.OpenType; 36 import javax.management.openmbean.SimpleType; 37 import java.security.AccessController; 38 import java.security.PrivilegedAction; 39 import java.lang.reflect.Field; 40 import java.util.HashMap; 41 42 /** 43 * A CompositeData for GarbageCollectionNotificationInfo for the local management support. 44 * This class avoids the performance penalty paid to the 45 * construction of a CompositeData use in the local case. 46 */ 47 public class GarbageCollectionNotifInfoCompositeData extends LazyCompositeData { 48 private final GarbageCollectionNotificationInfo gcNotifInfo; 49 50 public GarbageCollectionNotifInfoCompositeData(GarbageCollectionNotificationInfo info) { 51 this.gcNotifInfo = info; 52 } 53 54 public GarbageCollectionNotificationInfo getGarbageCollectionNotifInfo() { 55 return gcNotifInfo; 56 } 57 58 public static CompositeData toCompositeData(GarbageCollectionNotificationInfo info) { 59 GarbageCollectionNotifInfoCompositeData gcnicd = 60 new GarbageCollectionNotifInfoCompositeData(info); 61 return gcnicd.getCompositeData(); 62 } 63 64 private CompositeType getCompositeTypeByBuilder() { 65 final GcInfoBuilder builder = AccessController.doPrivileged (new PrivilegedAction<GcInfoBuilder>() { 66 public GcInfoBuilder run() { 67 try { 68 Class cl = Class.forName("com.sun.management.GcInfo"); 69 Field f = cl.getDeclaredField("builder"); 70 f.setAccessible(true); 71 return (GcInfoBuilder)f.get(gcNotifInfo.getGcInfo()); 72 } catch(ClassNotFoundException | NoSuchFieldException | IllegalAccessException e) { 73 return null; 74 } 75 } 76 }); 77 CompositeType gict = null; 78 synchronized(compositeTypeByBuilder) { 79 gict = compositeTypeByBuilder.get(builder); 80 if(gict == null) { 81 OpenType<?>[] gcNotifInfoItemTypes = new OpenType<?>[] { 82 SimpleType.STRING, 83 SimpleType.STRING, 84 SimpleType.STRING, 85 builder.getGcInfoCompositeType(), 86 }; 87 try { 88 final String typeName = 89 "sun.management.GarbageCollectionNotifInfoCompositeType"; 90 gict = new CompositeType(typeName, 91 "CompositeType for GC notification info", 92 gcNotifInfoItemNames, 93 gcNotifInfoItemNames, 94 gcNotifInfoItemTypes); 95 compositeTypeByBuilder.put(builder,gict); 96 } catch (OpenDataException e) { 97 // shouldn't reach here 98 throw Util.newException(e); 99 } 100 } 101 } 102 return gict; 103 } 104 105 protected CompositeData getCompositeData() { 106 // CONTENTS OF THIS ARRAY MUST BE SYNCHRONIZED WITH 107 // gcNotifInfoItemNames! 108 final Object[] gcNotifInfoItemValues; 109 gcNotifInfoItemValues = new Object[] { 110 gcNotifInfo.getGcName(), 111 gcNotifInfo.getGcAction(), 112 gcNotifInfo.getGcCause(), 113 GcInfoCompositeData.toCompositeData(gcNotifInfo.getGcInfo()) 114 }; 115 116 CompositeType gict = getCompositeTypeByBuilder(); 117 118 try { 119 return new CompositeDataSupport(gict, 120 gcNotifInfoItemNames, 121 gcNotifInfoItemValues); 122 } catch (OpenDataException e) { 123 // Should never reach here 124 throw new AssertionError(e); 125 } 126 } 127 128 // private static MappedMXBeanType gcInfoMapType; 129 private static final String GC_NAME = "gcName"; 130 private static final String GC_ACTION = "gcAction"; 131 private static final String GC_CAUSE = "gcCause"; 132 private static final String GC_INFO = "gcInfo"; 133 private static final String[] gcNotifInfoItemNames = { 134 GC_NAME, 135 GC_ACTION, 136 GC_CAUSE, 137 GC_INFO 138 }; 139 private static HashMap<GcInfoBuilder,CompositeType> compositeTypeByBuilder = 140 new HashMap<>(); 141 142 public static String getGcName(CompositeData cd) { 143 String gcname = getString(cd, GC_NAME); 144 if (gcname == null) { 145 throw new IllegalArgumentException("Invalid composite data: " + 146 "Attribute " + GC_NAME + " has null value"); 147 } 148 return gcname; 149 } 150 151 public static String getGcAction(CompositeData cd) { 152 String gcaction = getString(cd, GC_ACTION); 153 if (gcaction == null) { 154 throw new IllegalArgumentException("Invalid composite data: " + 155 "Attribute " + GC_ACTION + " has null value"); 156 } 157 return gcaction; 158 } 159 160 public static String getGcCause(CompositeData cd) { 161 String gccause = getString(cd, GC_CAUSE); 162 if (gccause == null) { 163 throw new IllegalArgumentException("Invalid composite data: " + 164 "Attribute " + GC_CAUSE + " has null value"); 165 } 166 return gccause; 167 } 168 169 public static GcInfo getGcInfo(CompositeData cd) { 170 CompositeData gcInfoData = (CompositeData) cd.get(GC_INFO); 171 return GcInfo.from(gcInfoData); 172 } 173 174 /** Validate if the input CompositeData has the expected 175 * CompositeType (i.e. contain all attributes with expected 176 * names and types). 177 */ 178 public static void validateCompositeData(CompositeData cd) { 179 if (cd == null) { 180 throw new NullPointerException("Null CompositeData"); 181 } 182 183 if (!isTypeMatched( getBaseGcNotifInfoCompositeType(), cd.getCompositeType())) { 184 throw new IllegalArgumentException( 185 "Unexpected composite type for GarbageCollectionNotificationInfo"); 186 } 187 } 188 189 // This is only used for validation. 190 private static CompositeType baseGcNotifInfoCompositeType = null; 191 private static synchronized CompositeType getBaseGcNotifInfoCompositeType() { 192 if (baseGcNotifInfoCompositeType == null) { 193 try { 194 OpenType<?>[] baseGcNotifInfoItemTypes = new OpenType<?>[] { 195 SimpleType.STRING, 196 SimpleType.STRING, 197 SimpleType.STRING, 198 GcInfoCompositeData.getBaseGcInfoCompositeType() 199 }; 200 baseGcNotifInfoCompositeType = 201 new CompositeType("sun.management.BaseGarbageCollectionNotifInfoCompositeType", 202 "CompositeType for Base GarbageCollectionNotificationInfo", 203 gcNotifInfoItemNames, 204 gcNotifInfoItemNames, 205 baseGcNotifInfoItemTypes); 206 } catch (OpenDataException e) { 207 // shouldn't reach here 208 throw Util.newException(e); 209 } 210 } 211 return baseGcNotifInfoCompositeType; 212 } 213 214 private static final long serialVersionUID = -1805123446483771292L; 215 }