1 /* 2 * Copyright (c) 2004, 2019, 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.io.Serializable; 29 import java.util.*; 30 import javax.management.openmbean.ArrayType; 31 import javax.management.openmbean.CompositeData; 32 import javax.management.openmbean.CompositeType; 33 import javax.management.openmbean.OpenType; 34 import javax.management.openmbean.TabularType; 35 36 /** 37 * This abstract class provides the implementation of the CompositeData 38 * interface. A CompositeData object will be lazily created only when 39 * the CompositeData interface is used. 40 * 41 * Classes that extends this abstract class will implement the 42 * getCompositeData() method. The object returned by the 43 * getCompositeData() is an instance of CompositeData such that 44 * the instance serializes itself as the type CompositeDataSupport. 45 */ 46 public abstract class LazyCompositeData 47 implements CompositeData, Serializable { 48 49 @SuppressWarnings("serial") // Not statically typed as Serializable 50 private CompositeData compositeData; 51 52 // Implementation of the CompositeData interface 53 @Override 54 public boolean containsKey(String key) { 55 return compositeData().containsKey(key); 56 } 57 58 @Override 59 public boolean containsValue(Object value) { 60 return compositeData().containsValue(value); 61 } 62 63 @Override 64 public boolean equals(Object obj) { 65 return compositeData().equals(obj); 66 } 67 68 @Override 69 public Object get(String key) { 70 return compositeData().get(key); 71 } 72 73 @Override 74 public Object[] getAll(String[] keys) { 75 return compositeData().getAll(keys); 76 } 77 78 @Override 79 public CompositeType getCompositeType() { 80 return compositeData().getCompositeType(); 81 } 82 83 @Override 84 public int hashCode() { 85 return compositeData().hashCode(); 86 } 87 88 @Override 89 public String toString() { 90 /** FIXME: What should this be?? */ 91 return compositeData().toString(); 92 } 93 94 @Override 95 public Collection<?> values() { 96 return compositeData().values(); 97 } 98 99 /* Lazy creation of a CompositeData object 100 * only when the CompositeData interface is used. 101 */ 102 private synchronized CompositeData compositeData() { 103 if (compositeData != null) 104 return compositeData; 105 compositeData = getCompositeData(); 106 return compositeData; 107 } 108 109 /** 110 * Designate to a CompositeData object when writing to an 111 * output stream during serialization so that the receiver 112 * only requires JMX 1.2 classes but not any implementation 113 * specific class. 114 */ 115 protected Object writeReplace() throws java.io.ObjectStreamException { 116 return compositeData(); 117 } 118 119 /** 120 * Returns the CompositeData representing this object. 121 * The returned CompositeData object must be an instance 122 * of javax.management.openmbean.CompositeDataSupport class 123 * so that no implementation specific class is required 124 * for unmarshalling besides JMX 1.2 classes. 125 */ 126 protected abstract CompositeData getCompositeData(); 127 128 // Helper methods 129 public static String getString(CompositeData cd, String itemName) { 130 if (cd == null) 131 throw new IllegalArgumentException("Null CompositeData"); 132 133 return (String) cd.get(itemName); 134 } 135 136 public static boolean getBoolean(CompositeData cd, String itemName) { 137 if (cd == null) 138 throw new IllegalArgumentException("Null CompositeData"); 139 140 return ((Boolean) cd.get(itemName)); 141 } 142 143 public static long getLong(CompositeData cd, String itemName) { 144 if (cd == null) 145 throw new IllegalArgumentException("Null CompositeData"); 146 147 return ((Long) cd.get(itemName)); 148 } 149 150 public static int getInt(CompositeData cd, String itemName) { 151 if (cd == null) 152 throw new IllegalArgumentException("Null CompositeData"); 153 154 return ((Integer) cd.get(itemName)); 155 } 156 157 /** 158 * Compares two CompositeTypes and returns true if 159 * all items in type1 exist in type2 and their item types 160 * are the same. 161 * @param type1 the base composite type 162 * @param type2 the checked composite type 163 * @return {@code true} if all items in type1 exist in type2 and their item 164 * types are the same. 165 */ 166 protected static boolean isTypeMatched(CompositeType type1, CompositeType type2) { 167 if (type1 == type2) return true; 168 169 // We can't use CompositeType.isValue() since it returns false 170 // if the type name doesn't match. 171 Set<String> allItems = type1.keySet(); 172 173 // Check all items in the type1 exist in type2 174 if (!type2.keySet().containsAll(allItems)) 175 return false; 176 177 return allItems.stream().allMatch( 178 item -> isTypeMatched(type1.getType(item), type2.getType(item)) 179 ); 180 } 181 182 protected static boolean isTypeMatched(TabularType type1, TabularType type2) { 183 if (type1 == type2) return true; 184 185 List<String> list1 = type1.getIndexNames(); 186 List<String> list2 = type2.getIndexNames(); 187 188 // check if the list of index names are the same 189 if (!list1.equals(list2)) 190 return false; 191 192 return isTypeMatched(type1.getRowType(), type2.getRowType()); 193 } 194 195 protected static boolean isTypeMatched(ArrayType<?> type1, ArrayType<?> type2) { 196 if (type1 == type2) return true; 197 198 int dim1 = type1.getDimension(); 199 int dim2 = type2.getDimension(); 200 201 // check if the array dimensions are the same 202 if (dim1 != dim2) 203 return false; 204 205 return isTypeMatched(type1.getElementOpenType(), type2.getElementOpenType()); 206 } 207 208 private static boolean isTypeMatched(OpenType<?> ot1, OpenType<?> ot2) { 209 if (ot1 instanceof CompositeType) { 210 if (! (ot2 instanceof CompositeType)) 211 return false; 212 if (!isTypeMatched((CompositeType) ot1, (CompositeType) ot2)) 213 return false; 214 } else if (ot1 instanceof TabularType) { 215 if (! (ot2 instanceof TabularType)) 216 return false; 217 if (!isTypeMatched((TabularType) ot1, (TabularType) ot2)) 218 return false; 219 } else if (ot1 instanceof ArrayType) { 220 if (! (ot2 instanceof ArrayType)) 221 return false; 222 if (!isTypeMatched((ArrayType<?>) ot1, (ArrayType<?>) ot2)) { 223 return false; 224 } 225 } else if (!ot1.equals(ot2)) { 226 return false; 227 } 228 return true; 229 } 230 231 private static final long serialVersionUID = -2190411934472666714L; 232 }