/*
* Copyright (c) 2006, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License version 2 only, as
* published by the Free Software Foundation.
*
* This code is distributed in the hope that it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
* version 2 for more details (a copy is included in the LICENSE file that
* accompanied this code).
*
* You should have received a copy of the GNU General Public License version
* 2 along with this work; if not, write to the Free Software Foundation,
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
*
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
* or visit www.oracle.com if you need additional information or have any
* questions.
*/
/*
* @test
* @bug 6486655
* @summary Test that attributes and operations appear in the same order
* in MBeanInfo as they did in the Standard MBean or MXBean Interface.
* @author Eamonn McManus
*/
/*
* For more background on this test, see:
* http://weblogs.java.net/blog/emcmanus/archive/2006/11/notes_on_unspec.html
*/
import java.lang.management.ManagementFactory;
import java.lang.reflect.Method;
import java.math.BigInteger;
import java.util.ArrayList;
import java.util.Collections;
import java.util.List;
import javax.management.MBeanAttributeInfo;
import javax.management.MBeanInfo;
import javax.management.MBeanOperationInfo;
import javax.management.MBeanServer;
import javax.management.ObjectName;
import javax.management.StandardMBean;
public class FeatureOrderTest {
private static boolean failed;
public static interface OrderMXBean {
public int getMercury();
public String getVenus();
public void setVenus(String x);
public BigInteger getEarth();
public void setEarth(BigInteger x);
public boolean isMars();
public double getJupiter();
public byte getSaturn();
public short getUranus();
public void setUranus(short x);
public long getNeptune();
// No more Pluto! Yay!
public void neptune();
public void uranus(int x);
public int saturn(int x, int y);
public short jupiter(int x, long y, double z);
public void mars(boolean x);
public BigInteger earth();
public double earth(double x); // http://www.imdb.com/title/tt0064519/
public String venus();
public int mercury();
}
public static interface OrderMBean extends OrderMXBean {}
public static class OrderImpl implements OrderMXBean {
public int getMercury() {
return 0;
}
public String getVenus() {
return null;
}
public void setVenus(String x) {
}
public BigInteger getEarth() {
return null;
}
public void setEarth(BigInteger x) {
}
public boolean isMars() {
return true;
}
public double getJupiter() {
return 0;
}
public byte getSaturn() {
return 0;
}
public short getUranus() {
return 0;
}
public void setUranus(short x) {
}
public long getNeptune() {
return 0;
}
public void neptune() {
}
public void uranus(int x) {
}
public int saturn(int x, int y) {
return 0;
}
public short jupiter(int x, long y, double z) {
return 0;
}
public void mars(boolean x) {
}
public BigInteger earth() {
return null;
}
public double earth(double x) {
return 0;
}
public String venus() {
return null;
}
public int mercury() {
return 0;
}
}
public static class Order extends OrderImpl implements OrderMBean {}
private static final boolean[] booleans = {false, true};
public static void main(String[] args) throws Exception {
// Build the lists of attributes and operations that we would expect
// if they are derived by reflection and preserve the reflection order
List<String> expectedAttributeNames = new ArrayList<String>();
List<String> expectedOperationNames = new ArrayList<String>();
for (Method m : OrderMXBean.class.getMethods()) {
String name = m.getName();
String attrName = null;
if (name.startsWith("get") && !name.equals("get") &&
m.getParameterTypes().length == 0 &&
m.getReturnType() != void.class)
attrName = name.substring(3);
else if (name.startsWith("is") && !name.equals("is") &&
m.getParameterTypes().length == 0 &&
m.getReturnType() == boolean.class)
attrName = name.substring(2);
else if (name.startsWith("set") && !name.equals("set") &&
m.getReturnType() == void.class &&
m.getParameterTypes().length == 1)
attrName = name.substring(3);
if (attrName != null) {
if (!expectedAttributeNames.contains(attrName))
expectedAttributeNames.add(attrName);
} else
expectedOperationNames.add(name);
}
MBeanServer mbs = ManagementFactory.getPlatformMBeanServer();
for (boolean mxbean : booleans) {
for (boolean withStandardMBean : booleans) {
String testName = "MXBean: " + mxbean + "; " +
"using javax.management.StandardMBean: " +
withStandardMBean;
System.out.println("Test case: " + testName);
Object mbean;
if (mxbean) {
if (withStandardMBean) {
mbean = new StandardMBean(
new OrderImpl(), OrderMXBean.class, true);
} else
mbean = new OrderImpl();
} else {
if (withStandardMBean)
mbean = new StandardMBean(new Order(), OrderMBean.class);
else
mbean = new Order();
}
ObjectName name = new ObjectName(
":mxbean=" + mxbean + "," + "withStandardMBean=" +
withStandardMBean);
mbs.registerMBean(mbean, name);
/* Make sure we are testing what we think. */
MBeanInfo mbi = mbs.getMBeanInfo(name);
boolean isWithStandardMBean =
mbs.isInstanceOf(name, StandardMBean.class.getName());
System.out.println("classname " +mbi.getClassName());
String mxbeanField =
(String) mbi.getDescriptor().getFieldValue("mxbean");
boolean isMXBean = "true".equalsIgnoreCase(mxbeanField);
if (mxbean != isMXBean)
throw new Exception("Test error: MXBean mismatch");
if (withStandardMBean != isWithStandardMBean)
throw new Exception("Test error: StandardMBean mismatch");
// Check that order of attributes and operations matches
MBeanAttributeInfo[] mbais = mbi.getAttributes();
checkEqual(expectedAttributeNames.size(), mbais.length,
"number of attributes");
List<String> attributeNames = new ArrayList<String>();
for (MBeanAttributeInfo mbai : mbais)
attributeNames.add(mbai.getName());
checkEqual(expectedAttributeNames, attributeNames,
"order of attributes");
MBeanOperationInfo[] mbois = mbi.getOperations();
checkEqual(expectedOperationNames.size(), mbois.length,
"number of operations");
List<String> operationNames = new ArrayList<String>();
for (MBeanOperationInfo mboi : mbois)
operationNames.add(mboi.getName());
checkEqual(expectedOperationNames, operationNames,
"order of operations");
System.out.println();
}
}
if (failed)
throw new Exception("TEST FAILED");
System.out.println("TEST PASSED");
}
private static void checkEqual(Object expected, Object actual, String what) {
if (expected.equals(actual))
System.out.println("OK: " + what + " matches");
else {
System.out.println("FAILED: " + what + " differs:");
System.out.println(" expected: " + expected);
System.out.println(" actual: " + actual);
failed = true;
}
}
}