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 6486655 27 * @summary Test that attributes and operations appear in the same order 28 * in MBeanInfo as they did in the Standard MBean or MXBean Interface. 29 * @author Eamonn McManus 30 */ 31 32/* 33 * For more background on this test, see: 34 * http://weblogs.java.net/blog/emcmanus/archive/2006/11/notes_on_unspec.html 35 */ 36 37import java.lang.management.ManagementFactory; 38import java.lang.reflect.Method; 39import java.math.BigInteger; 40import java.util.ArrayList; 41import java.util.Collections; 42import java.util.List; 43import javax.management.MBeanAttributeInfo; 44import javax.management.MBeanInfo; 45import javax.management.MBeanOperationInfo; 46import javax.management.MBeanServer; 47import javax.management.ObjectName; 48import javax.management.StandardMBean; 49 50public class FeatureOrderTest { 51 private static boolean failed; 52 53 public static interface OrderMXBean { 54 public int getMercury(); 55 56 public String getVenus(); 57 public void setVenus(String x); 58 59 public BigInteger getEarth(); 60 public void setEarth(BigInteger x); 61 62 public boolean isMars(); 63 64 public double getJupiter(); 65 66 public byte getSaturn(); 67 68 public short getUranus(); 69 public void setUranus(short x); 70 71 public long getNeptune(); 72 73 // No more Pluto! Yay! 74 75 public void neptune(); 76 public void uranus(int x); 77 public int saturn(int x, int y); 78 public short jupiter(int x, long y, double z); 79 public void mars(boolean x); 80 public BigInteger earth(); 81 public double earth(double x); // http://www.imdb.com/title/tt0064519/ 82 public String venus(); 83 public int mercury(); 84 } 85 86 public static interface OrderMBean extends OrderMXBean {} 87 88 public static class OrderImpl implements OrderMXBean { 89 public int getMercury() { 90 return 0; 91 } 92 93 public String getVenus() { 94 return null; 95 } 96 97 public void setVenus(String x) { 98 } 99 100 public BigInteger getEarth() { 101 return null; 102 } 103 104 public void setEarth(BigInteger x) { 105 } 106 107 public boolean isMars() { 108 return true; 109 } 110 111 public double getJupiter() { 112 return 0; 113 } 114 115 public byte getSaturn() { 116 return 0; 117 } 118 119 public short getUranus() { 120 return 0; 121 } 122 123 public void setUranus(short x) { 124 } 125 126 public long getNeptune() { 127 return 0; 128 } 129 130 public void neptune() { 131 } 132 133 public void uranus(int x) { 134 } 135 136 public int saturn(int x, int y) { 137 return 0; 138 } 139 140 public short jupiter(int x, long y, double z) { 141 return 0; 142 } 143 144 public void mars(boolean x) { 145 } 146 147 public BigInteger earth() { 148 return null; 149 } 150 151 public double earth(double x) { 152 return 0; 153 } 154 155 public String venus() { 156 return null; 157 } 158 159 public int mercury() { 160 return 0; 161 } 162 } 163 164 public static class Order extends OrderImpl implements OrderMBean {} 165 166 private static final boolean[] booleans = {false, true}; 167 168 public static void main(String[] args) throws Exception { 169 // Build the lists of attributes and operations that we would expect 170 // if they are derived by reflection and preserve the reflection order 171 List<String> expectedAttributeNames = new ArrayList<String>(); 172 List<String> expectedOperationNames = new ArrayList<String>(); 173 for (Method m : OrderMXBean.class.getMethods()) { 174 String name = m.getName(); 175 String attrName = null; 176 if (name.startsWith("get") && !name.equals("get") && 177 m.getParameterTypes().length == 0 && 178 m.getReturnType() != void.class) 179 attrName = name.substring(3); 180 else if (name.startsWith("is") && !name.equals("is") && 181 m.getParameterTypes().length == 0 && 182 m.getReturnType() == boolean.class) 183 attrName = name.substring(2); 184 else if (name.startsWith("set") && !name.equals("set") && 185 m.getReturnType() == void.class && 186 m.getParameterTypes().length == 1) 187 attrName = name.substring(3); 188 if (attrName != null) { 189 if (!expectedAttributeNames.contains(attrName)) 190 expectedAttributeNames.add(attrName); 191 } else 192 expectedOperationNames.add(name); 193 } 194 195 MBeanServer mbs = ManagementFactory.getPlatformMBeanServer(); 196 for (boolean mxbean : booleans) { 197 for (boolean withStandardMBean : booleans) { 198 String testName = "MXBean: " + mxbean + "; " + 199 "using javax.management.StandardMBean: " + 200 withStandardMBean; 201 System.out.println("Test case: " + testName); 202 Object mbean; 203 if (mxbean) { 204 if (withStandardMBean) { 205 mbean = new StandardMBean( 206 new OrderImpl(), OrderMXBean.class, true); 207 } else 208 mbean = new OrderImpl(); 209 } else { 210 if (withStandardMBean) 211 mbean = new StandardMBean(new Order(), OrderMBean.class); 212 else 213 mbean = new Order(); 214 } 215 ObjectName name = new ObjectName( 216 ":mxbean=" + mxbean + "," + "withStandardMBean=" + 217 withStandardMBean); 218 mbs.registerMBean(mbean, name); 219 220 /* Make sure we are testing what we think. */ 221 MBeanInfo mbi = mbs.getMBeanInfo(name); 222 boolean isWithStandardMBean = 223 mbs.isInstanceOf(name, StandardMBean.class.getName()); 224 System.out.println("classname " +mbi.getClassName()); 225 String mxbeanField = 226 (String) mbi.getDescriptor().getFieldValue("mxbean"); 227 boolean isMXBean = "true".equalsIgnoreCase(mxbeanField); 228 229 if (mxbean != isMXBean) 230 throw new Exception("Test error: MXBean mismatch"); 231 if (withStandardMBean != isWithStandardMBean) 232 throw new Exception("Test error: StandardMBean mismatch"); 233 234 // Check that order of attributes and operations matches 235 MBeanAttributeInfo[] mbais = mbi.getAttributes(); 236 checkEqual(expectedAttributeNames.size(), mbais.length, 237 "number of attributes"); 238 List<String> attributeNames = new ArrayList<String>(); 239 for (MBeanAttributeInfo mbai : mbais) 240 attributeNames.add(mbai.getName()); 241 checkEqual(expectedAttributeNames, attributeNames, 242 "order of attributes"); 243 244 MBeanOperationInfo[] mbois = mbi.getOperations(); 245 checkEqual(expectedOperationNames.size(), mbois.length, 246 "number of operations"); 247 List<String> operationNames = new ArrayList<String>(); 248 for (MBeanOperationInfo mboi : mbois) 249 operationNames.add(mboi.getName()); 250 checkEqual(expectedOperationNames, operationNames, 251 "order of operations"); 252 System.out.println(); 253 } 254 } 255 256 if (failed) 257 throw new Exception("TEST FAILED"); 258 System.out.println("TEST PASSED"); 259 } 260 261 private static void checkEqual(Object expected, Object actual, String what) { 262 if (expected.equals(actual)) 263 System.out.println("OK: " + what + " matches"); 264 else { 265 System.out.println("FAILED: " + what + " differs:"); 266 System.out.println(" expected: " + expected); 267 System.out.println(" actual: " + actual); 268 failed = true; 269 } 270 } 271} 272