0N/A/*
2362N/A * Copyright (c) 2006, Oracle and/or its affiliates. All rights reserved.
0N/A * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
0N/A *
0N/A * This code is free software; you can redistribute it and/or modify it
0N/A * under the terms of the GNU General Public License version 2 only, as
0N/A * published by the Free Software Foundation.
0N/A *
0N/A * This code is distributed in the hope that it will be useful, but WITHOUT
0N/A * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
0N/A * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
0N/A * version 2 for more details (a copy is included in the LICENSE file that
0N/A * accompanied this code).
0N/A *
0N/A * You should have received a copy of the GNU General Public License version
0N/A * 2 along with this work; if not, write to the Free Software Foundation,
0N/A * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
0N/A *
2362N/A * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
2362N/A * or visit www.oracle.com if you need additional information or have any
2362N/A * questions.
0N/A */
0N/A
0N/A/*
0N/A * @test
0N/A * @bug 6398884
0N/A * @summary Test that a method inherited from two different interfaces
0N/A * appears only once in MBeanInfo.
0N/A * @author dfuchs
0N/A * @run clean TooManyFooTest
0N/A * @run build TooManyFooTest
0N/A * @run main TooManyFooTest
0N/A */
0N/A
0N/Aimport java.lang.management.ManagementFactory;
0N/Aimport java.lang.reflect.Method;
0N/Aimport java.util.Arrays;
0N/Aimport java.util.HashMap;
0N/Aimport java.util.HashSet;
0N/Aimport java.util.Map;
0N/Aimport java.util.Set;
0N/Aimport java.util.logging.Logger;
0N/Aimport javax.management.Descriptor;
0N/Aimport javax.management.MBeanInfo;
0N/Aimport javax.management.MBeanOperationInfo;
0N/Aimport javax.management.MBeanServer;
0N/Aimport javax.management.ObjectName;
0N/Aimport javax.management.StandardMBean;
0N/Aimport javax.management.openmbean.OpenMBeanOperationInfo;
0N/A
0N/A/**
0N/A * Class TooManyFooTest
0N/A * @author Sun Microsystems, 2005 - All rights reserved.
0N/A */
0N/Apublic class TooManyFooTest {
0N/A
0N/A /**
0N/A * A logger for this class.
0N/A **/
0N/A private static final Logger LOG =
0N/A Logger.getLogger(TooManyFooTest.class.getName());
0N/A
0N/A public static class NumberHolder {
0N/A public Integer getNumber() { return 0;}
0N/A public void setNumber(Integer n) {};
0N/A }
0N/A public static class MyNumberHolder extends NumberHolder {
0N/A
0N/A }
0N/A public interface Parent1 {
0N/A public int foo(); // Both in Parent1 and Parent2
0N/A public Integer barfoo(); // Subtype in Parent1, Super type in Parent2
0N/A public Long foobar(); // Subtype in Parent1 & MBean, Super type in
0N/A // Parent2
0N/A public Number toofoo(); // Subtype in Parent1, Super type in Parent2
0N/A // Concrete type in MBean
0N/A public Object toofoofoo(); // Super type in Parent1, Subtype in Parent2,
0N/A public NumberHolder toobarbar(); // toofoofoo reversed
0N/A }
0N/A
0N/A public interface Parent2 {
0N/A public int foo(); // Both in Parent1 and Parent2
0N/A public Number barfoo();
0N/A public Number foobar();
0N/A public Object toofoo();
0N/A public NumberHolder toofoofoo();
0N/A public Object toobarbar();
0N/A }
0N/A
0N/A public interface ChildMBean extends Parent1, Parent2 {
0N/A public Long foobar();
0N/A public Long toofoo();
0N/A }
0N/A
0N/A public interface ChildMXBean extends Parent1, Parent2 {
0N/A public Long foobar();
0N/A public Long toofoo();
0N/A }
0N/A
0N/A public interface ChildMixMXBean extends ChildMBean, ChildMXBean {
0N/A }
0N/A
0N/A public static class Child implements ChildMBean {
0N/A public int foo() {return 0;}
0N/A public Long foobar() {return 0L;}
0N/A public Long toofoo() {return 0L;}
0N/A public Integer barfoo() {return 0;}
0N/A public MyNumberHolder toofoofoo() { return null;}
0N/A public MyNumberHolder toobarbar() { return null;}
0N/A }
0N/A
0N/A public static class ChildMix implements ChildMXBean {
0N/A public int foo() {return 0;}
0N/A public Long foobar() {return 0L;}
0N/A public Long toofoo() {return 0L;}
0N/A public Integer barfoo() {return 0;}
0N/A public MyNumberHolder toofoofoo() { return null;}
0N/A public MyNumberHolder toobarbar() { return null;}
0N/A }
0N/A
0N/A public static class ChildMixMix extends Child implements ChildMixMXBean {
0N/A }
0N/A
0N/A
0N/A /** Creates a new instance of TooManyFooTest */
0N/A public TooManyFooTest() {
0N/A }
0N/A
0N/A private static final int OPCOUNT;
0N/A private static final Map<String,String> EXPECTED_TYPES;
0N/A private static final String[][] type_array = {
0N/A { "foo", int.class.getName() },
0N/A { "foobar", Long.class.getName()},
0N/A { "toofoo", Long.class.getName()},
0N/A { "barfoo", Integer.class.getName()},
0N/A { "toofoofoo", NumberHolder.class.getName()},
0N/A { "toobarbar", NumberHolder.class.getName()},
0N/A };
0N/A static {
0N/A try {
0N/A final Set<String> declared = new HashSet<String>();
0N/A for (Method m:Child.class.getDeclaredMethods()) {
0N/A declared.add(m.getName()+Arrays.asList(m.getParameterTypes()));
0N/A }
0N/A final Set<String> exposed = new HashSet<String>();
0N/A for (Method m:ChildMBean.class.getMethods()) {
0N/A exposed.add(m.getName()+Arrays.asList(m.getParameterTypes()));
0N/A }
0N/A declared.retainAll(exposed);
0N/A OPCOUNT = declared.size();
0N/A EXPECTED_TYPES = new HashMap<String,String>();
0N/A for (String[] st:type_array) {
0N/A EXPECTED_TYPES.put(st[0],st[1]);
0N/A }
0N/A } catch (Exception x) {
0N/A throw new ExceptionInInitializerError(x);
0N/A }
0N/A }
0N/A
0N/A private static void test(Object child, String name, boolean mxbean)
0N/A throws Exception {
0N/A final ObjectName childName =
0N/A new ObjectName("test:type=Child,name="+name);
0N/A final MBeanServer server =
0N/A ManagementFactory.getPlatformMBeanServer();
0N/A server.registerMBean(child,childName);
0N/A try {
0N/A final MBeanInfo info = server.getMBeanInfo(childName);
0N/A System.out.println(name+": " + info.getDescriptor());
0N/A final int len = info.getOperations().length;
0N/A if (len == OPCOUNT) {
0N/A System.out.println(name+": OK, only "+OPCOUNT+
0N/A " operations here...");
0N/A } else {
0N/A final String qual = (len>OPCOUNT)?"many":"few";
0N/A System.err.println(name+": Too "+qual+" foos! Found "+
0N/A len+", expected "+OPCOUNT);
0N/A for (MBeanOperationInfo op : info.getOperations()) {
0N/A System.err.println("public "+op.getReturnType()+" "+
0N/A op.getName()+"();");
0N/A }
0N/A throw new RuntimeException("Too " + qual +
0N/A " foos for "+name);
0N/A }
0N/A
0N/A final Descriptor d = info.getDescriptor();
0N/A final String mxstr = String.valueOf(d.getFieldValue("mxbean"));
0N/A final boolean mxb =
0N/A (mxstr==null)?false:Boolean.valueOf(mxstr).booleanValue();
0N/A System.out.println(name+": mxbean="+mxb);
0N/A if (mxbean && !mxb)
0N/A throw new AssertionError("MXBean is not OpenMBean?");
0N/A
0N/A for (MBeanOperationInfo mboi : info.getOperations()) {
0N/A
0N/A // Sanity check
0N/A if (mxbean && !mboi.getName().equals("foo")) {
0N/A // The spec doesn't guarantee that the MBeanOperationInfo
0N/A // of an MXBean will be an OpenMBeanOperationInfo, and in
0N/A // some circumstances in our implementation it will not.
0N/A // However, in thsi tests, for all methods but foo(),
0N/A // it should.
0N/A //
0N/A if (!(mboi instanceof OpenMBeanOperationInfo))
0N/A throw new AssertionError("Operation "+mboi.getName()+
0N/A "() is not Open?");
0N/A }
0N/A
0N/A final String exp = EXPECTED_TYPES.get(mboi.getName());
0N/A
0N/A // For MXBeans, we need to compare 'exp' with the original
0N/A // type - because mboi.getReturnType() returns the OpenType
0N/A //
0N/A String type = (String)mboi.getDescriptor().
0N/A getFieldValue("originalType");
0N/A if (type == null) type = mboi.getReturnType();
0N/A if (type.equals(exp)) continue;
0N/A System.err.println("Bad return type for "+
0N/A mboi.getName()+"! Found "+type+
0N/A ", expected "+exp);
0N/A throw new RuntimeException("Bad return type for "+
0N/A mboi.getName());
0N/A }
0N/A } finally {
0N/A server.unregisterMBean(childName);
0N/A }
0N/A }
0N/A
0N/A public static void main(String[] args) throws Exception {
0N/A final Child child = new Child();
0N/A test(child,"Child[MBean]",false);
0N/A final ChildMix childx = new ChildMix();
0N/A test(childx,"ChildMix[MXBean]",true);
0N/A final ChildMixMix childmx = new ChildMixMix();
0N/A test(childmx,"ChildMixMix[MXBean]",false);
0N/A final StandardMBean schild = new StandardMBean(child,ChildMBean.class);
0N/A test(schild,"Child[StandarMBean(Child)]",false);
0N/A final StandardMBean schildx =
0N/A new StandardMBean(childx,ChildMXBean.class,true);
0N/A test(schildx,"ChildMix[StandarMXBean(ChildMix)]",true);
0N/A final StandardMBean schildmx =
0N/A new StandardMBean(childmx,ChildMixMXBean.class,true);
0N/A test(schildmx,"ChildMixMix[StandarMXBean(ChildMixMix)]",true);
0N/A }
0N/A
0N/A}