Path: blob/master/test/jdk/javax/management/MBeanInfo/TooManyFooTest.java
41152 views
/*1* Copyright (c) 2006, 2015, Oracle and/or its affiliates. All rights reserved.2* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.3*4* This code is free software; you can redistribute it and/or modify it5* under the terms of the GNU General Public License version 2 only, as6* published by the Free Software Foundation.7*8* This code is distributed in the hope that it will be useful, but WITHOUT9* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or10* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License11* version 2 for more details (a copy is included in the LICENSE file that12* accompanied this code).13*14* You should have received a copy of the GNU General Public License version15* 2 along with this work; if not, write to the Free Software Foundation,16* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.17*18* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA19* or visit www.oracle.com if you need additional information or have any20* questions.21*/2223/*24* @test25* @bug 639888426* @summary Test that a method inherited from two different interfaces27* appears only once in MBeanInfo.28* @author dfuchs29*30* @run clean TooManyFooTest31* @run build TooManyFooTest32* @run main TooManyFooTest33*/3435import java.lang.management.ManagementFactory;36import java.lang.reflect.Method;37import java.util.Arrays;38import java.util.HashMap;39import java.util.HashSet;40import java.util.Map;41import java.util.Set;42import java.util.logging.Logger;43import javax.management.Descriptor;44import javax.management.MBeanInfo;45import javax.management.MBeanOperationInfo;46import javax.management.MBeanServer;47import javax.management.ObjectName;48import javax.management.StandardMBean;49import javax.management.openmbean.OpenMBeanOperationInfo;5051/**52* Class TooManyFooTest53* @author Sun Microsystems, 2005 - All rights reserved.54*/55public class TooManyFooTest {5657public static class NumberHolder {58public Integer getNumber() { return 0;}59public void setNumber(Integer n) {};60}61public static class MyNumberHolder extends NumberHolder {6263}64public interface Parent1 {65public int foo(); // Both in Parent1 and Parent266public Integer barfoo(); // Subtype in Parent1, Super type in Parent267public Long foobar(); // Subtype in Parent1 & MBean, Super type in68// Parent269public Number toofoo(); // Subtype in Parent1, Super type in Parent270// Concrete type in MBean71public Object toofoofoo(); // Super type in Parent1, Subtype in Parent2,72public NumberHolder toobarbar(); // toofoofoo reversed73}7475public interface Parent2 {76public int foo(); // Both in Parent1 and Parent277public Number barfoo();78public Number foobar();79public Object toofoo();80public NumberHolder toofoofoo();81public Object toobarbar();82}8384public interface ChildMBean extends Parent1, Parent2 {85public Long foobar();86public Long toofoo();87}8889public interface ChildMXBean extends Parent1, Parent2 {90public Long foobar();91public Long toofoo();92}9394public interface ChildMixMXBean extends ChildMBean, ChildMXBean {95}9697public static class Child implements ChildMBean {98public int foo() {return 0;}99public Long foobar() {return 0L;}100public Long toofoo() {return 0L;}101public Integer barfoo() {return 0;}102public MyNumberHolder toofoofoo() { return null;}103public MyNumberHolder toobarbar() { return null;}104}105106public static class ChildMix implements ChildMXBean {107public int foo() {return 0;}108public Long foobar() {return 0L;}109public Long toofoo() {return 0L;}110public Integer barfoo() {return 0;}111public MyNumberHolder toofoofoo() { return null;}112public MyNumberHolder toobarbar() { return null;}113}114115public static class ChildMixMix extends Child implements ChildMixMXBean {116}117118119/** Creates a new instance of TooManyFooTest */120public TooManyFooTest() {121}122123private static final int OPCOUNT;124private static final Map<String,String> EXPECTED_TYPES;125private static final String[][] type_array = {126{ "foo", int.class.getName() },127{ "foobar", Long.class.getName()},128{ "toofoo", Long.class.getName()},129{ "barfoo", Integer.class.getName()},130{ "toofoofoo", NumberHolder.class.getName()},131{ "toobarbar", NumberHolder.class.getName()},132};133static {134try {135final Set<String> declared = new HashSet<String>();136for (Method m:Child.class.getDeclaredMethods()) {137declared.add(m.getName()+Arrays.asList(m.getParameterTypes()));138}139final Set<String> exposed = new HashSet<String>();140for (Method m:ChildMBean.class.getMethods()) {141exposed.add(m.getName()+Arrays.asList(m.getParameterTypes()));142}143declared.retainAll(exposed);144OPCOUNT = declared.size();145EXPECTED_TYPES = new HashMap<String,String>();146for (String[] st:type_array) {147EXPECTED_TYPES.put(st[0],st[1]);148}149} catch (Exception x) {150throw new ExceptionInInitializerError(x);151}152}153154private static void test(Object child, String name, boolean mxbean)155throws Exception {156final ObjectName childName =157new ObjectName("test:type=Child,name="+name);158final MBeanServer server =159ManagementFactory.getPlatformMBeanServer();160server.registerMBean(child,childName);161try {162final MBeanInfo info = server.getMBeanInfo(childName);163System.out.println(name+": " + info.getDescriptor());164final int len = info.getOperations().length;165if (len == OPCOUNT) {166System.out.println(name+": OK, only "+OPCOUNT+167" operations here...");168} else {169final String qual = (len>OPCOUNT)?"many":"few";170System.err.println(name+": Too "+qual+" foos! Found "+171len+", expected "+OPCOUNT);172for (MBeanOperationInfo op : info.getOperations()) {173System.err.println("public "+op.getReturnType()+" "+174op.getName()+"();");175}176throw new RuntimeException("Too " + qual +177" foos for "+name);178}179180final Descriptor d = info.getDescriptor();181final String mxstr = String.valueOf(d.getFieldValue("mxbean"));182final boolean mxb =183(mxstr==null)?false:Boolean.valueOf(mxstr).booleanValue();184System.out.println(name+": mxbean="+mxb);185if (mxbean && !mxb)186throw new AssertionError("MXBean is not OpenMBean?");187188for (MBeanOperationInfo mboi : info.getOperations()) {189190// Sanity check191if (mxbean && !mboi.getName().equals("foo")) {192// The spec doesn't guarantee that the MBeanOperationInfo193// of an MXBean will be an OpenMBeanOperationInfo, and in194// some circumstances in our implementation it will not.195// However, in thsi tests, for all methods but foo(),196// it should.197//198if (!(mboi instanceof OpenMBeanOperationInfo))199throw new AssertionError("Operation "+mboi.getName()+200"() is not Open?");201}202203final String exp = EXPECTED_TYPES.get(mboi.getName());204205// For MXBeans, we need to compare 'exp' with the original206// type - because mboi.getReturnType() returns the OpenType207//208String type = (String)mboi.getDescriptor().209getFieldValue("originalType");210if (type == null) type = mboi.getReturnType();211if (type.equals(exp)) continue;212System.err.println("Bad return type for "+213mboi.getName()+"! Found "+type+214", expected "+exp);215throw new RuntimeException("Bad return type for "+216mboi.getName());217}218} finally {219server.unregisterMBean(childName);220}221}222223public static void main(String[] args) throws Exception {224final Child child = new Child();225test(child,"Child[MBean]",false);226final ChildMix childx = new ChildMix();227test(childx,"ChildMix[MXBean]",true);228final ChildMixMix childmx = new ChildMixMix();229test(childmx,"ChildMixMix[MXBean]",false);230final StandardMBean schild = new StandardMBean(child,ChildMBean.class);231test(schild,"Child[StandarMBean(Child)]",false);232final StandardMBean schildx =233new StandardMBean(childx,ChildMXBean.class,true);234test(schildx,"ChildMix[StandarMXBean(ChildMix)]",true);235final StandardMBean schildmx =236new StandardMBean(childmx,ChildMixMXBean.class,true);237test(schildmx,"ChildMixMix[StandarMXBean(ChildMixMix)]",true);238}239240}241242243