3789983e89
Reviewed-by: darcy, ihse
242 lines
9.3 KiB
Java
242 lines
9.3 KiB
Java
/*
|
|
* Copyright (c) 2006, 2015, 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 6398884
|
|
* @summary Test that a method inherited from two different interfaces
|
|
* appears only once in MBeanInfo.
|
|
* @author dfuchs
|
|
*
|
|
* @run clean TooManyFooTest
|
|
* @run build TooManyFooTest
|
|
* @run main TooManyFooTest
|
|
*/
|
|
|
|
import java.lang.management.ManagementFactory;
|
|
import java.lang.reflect.Method;
|
|
import java.util.Arrays;
|
|
import java.util.HashMap;
|
|
import java.util.HashSet;
|
|
import java.util.Map;
|
|
import java.util.Set;
|
|
import java.util.logging.Logger;
|
|
import javax.management.Descriptor;
|
|
import javax.management.MBeanInfo;
|
|
import javax.management.MBeanOperationInfo;
|
|
import javax.management.MBeanServer;
|
|
import javax.management.ObjectName;
|
|
import javax.management.StandardMBean;
|
|
import javax.management.openmbean.OpenMBeanOperationInfo;
|
|
|
|
/**
|
|
* Class TooManyFooTest
|
|
* @author Sun Microsystems, 2005 - All rights reserved.
|
|
*/
|
|
public class TooManyFooTest {
|
|
|
|
public static class NumberHolder {
|
|
public Integer getNumber() { return 0;}
|
|
public void setNumber(Integer n) {};
|
|
}
|
|
public static class MyNumberHolder extends NumberHolder {
|
|
|
|
}
|
|
public interface Parent1 {
|
|
public int foo(); // Both in Parent1 and Parent2
|
|
public Integer barfoo(); // Subtype in Parent1, Super type in Parent2
|
|
public Long foobar(); // Subtype in Parent1 & MBean, Super type in
|
|
// Parent2
|
|
public Number toofoo(); // Subtype in Parent1, Super type in Parent2
|
|
// Concrete type in MBean
|
|
public Object toofoofoo(); // Super type in Parent1, Subtype in Parent2,
|
|
public NumberHolder toobarbar(); // toofoofoo reversed
|
|
}
|
|
|
|
public interface Parent2 {
|
|
public int foo(); // Both in Parent1 and Parent2
|
|
public Number barfoo();
|
|
public Number foobar();
|
|
public Object toofoo();
|
|
public NumberHolder toofoofoo();
|
|
public Object toobarbar();
|
|
}
|
|
|
|
public interface ChildMBean extends Parent1, Parent2 {
|
|
public Long foobar();
|
|
public Long toofoo();
|
|
}
|
|
|
|
public interface ChildMXBean extends Parent1, Parent2 {
|
|
public Long foobar();
|
|
public Long toofoo();
|
|
}
|
|
|
|
public interface ChildMixMXBean extends ChildMBean, ChildMXBean {
|
|
}
|
|
|
|
public static class Child implements ChildMBean {
|
|
public int foo() {return 0;}
|
|
public Long foobar() {return 0L;}
|
|
public Long toofoo() {return 0L;}
|
|
public Integer barfoo() {return 0;}
|
|
public MyNumberHolder toofoofoo() { return null;}
|
|
public MyNumberHolder toobarbar() { return null;}
|
|
}
|
|
|
|
public static class ChildMix implements ChildMXBean {
|
|
public int foo() {return 0;}
|
|
public Long foobar() {return 0L;}
|
|
public Long toofoo() {return 0L;}
|
|
public Integer barfoo() {return 0;}
|
|
public MyNumberHolder toofoofoo() { return null;}
|
|
public MyNumberHolder toobarbar() { return null;}
|
|
}
|
|
|
|
public static class ChildMixMix extends Child implements ChildMixMXBean {
|
|
}
|
|
|
|
|
|
/** Creates a new instance of TooManyFooTest */
|
|
public TooManyFooTest() {
|
|
}
|
|
|
|
private static final int OPCOUNT;
|
|
private static final Map<String,String> EXPECTED_TYPES;
|
|
private static final String[][] type_array = {
|
|
{ "foo", int.class.getName() },
|
|
{ "foobar", Long.class.getName()},
|
|
{ "toofoo", Long.class.getName()},
|
|
{ "barfoo", Integer.class.getName()},
|
|
{ "toofoofoo", NumberHolder.class.getName()},
|
|
{ "toobarbar", NumberHolder.class.getName()},
|
|
};
|
|
static {
|
|
try {
|
|
final Set<String> declared = new HashSet<String>();
|
|
for (Method m:Child.class.getDeclaredMethods()) {
|
|
declared.add(m.getName()+Arrays.asList(m.getParameterTypes()));
|
|
}
|
|
final Set<String> exposed = new HashSet<String>();
|
|
for (Method m:ChildMBean.class.getMethods()) {
|
|
exposed.add(m.getName()+Arrays.asList(m.getParameterTypes()));
|
|
}
|
|
declared.retainAll(exposed);
|
|
OPCOUNT = declared.size();
|
|
EXPECTED_TYPES = new HashMap<String,String>();
|
|
for (String[] st:type_array) {
|
|
EXPECTED_TYPES.put(st[0],st[1]);
|
|
}
|
|
} catch (Exception x) {
|
|
throw new ExceptionInInitializerError(x);
|
|
}
|
|
}
|
|
|
|
private static void test(Object child, String name, boolean mxbean)
|
|
throws Exception {
|
|
final ObjectName childName =
|
|
new ObjectName("test:type=Child,name="+name);
|
|
final MBeanServer server =
|
|
ManagementFactory.getPlatformMBeanServer();
|
|
server.registerMBean(child,childName);
|
|
try {
|
|
final MBeanInfo info = server.getMBeanInfo(childName);
|
|
System.out.println(name+": " + info.getDescriptor());
|
|
final int len = info.getOperations().length;
|
|
if (len == OPCOUNT) {
|
|
System.out.println(name+": OK, only "+OPCOUNT+
|
|
" operations here...");
|
|
} else {
|
|
final String qual = (len>OPCOUNT)?"many":"few";
|
|
System.err.println(name+": Too "+qual+" foos! Found "+
|
|
len+", expected "+OPCOUNT);
|
|
for (MBeanOperationInfo op : info.getOperations()) {
|
|
System.err.println("public "+op.getReturnType()+" "+
|
|
op.getName()+"();");
|
|
}
|
|
throw new RuntimeException("Too " + qual +
|
|
" foos for "+name);
|
|
}
|
|
|
|
final Descriptor d = info.getDescriptor();
|
|
final String mxstr = String.valueOf(d.getFieldValue("mxbean"));
|
|
final boolean mxb =
|
|
(mxstr==null)?false:Boolean.valueOf(mxstr).booleanValue();
|
|
System.out.println(name+": mxbean="+mxb);
|
|
if (mxbean && !mxb)
|
|
throw new AssertionError("MXBean is not OpenMBean?");
|
|
|
|
for (MBeanOperationInfo mboi : info.getOperations()) {
|
|
|
|
// Sanity check
|
|
if (mxbean && !mboi.getName().equals("foo")) {
|
|
// The spec doesn't guarantee that the MBeanOperationInfo
|
|
// of an MXBean will be an OpenMBeanOperationInfo, and in
|
|
// some circumstances in our implementation it will not.
|
|
// However, in thsi tests, for all methods but foo(),
|
|
// it should.
|
|
//
|
|
if (!(mboi instanceof OpenMBeanOperationInfo))
|
|
throw new AssertionError("Operation "+mboi.getName()+
|
|
"() is not Open?");
|
|
}
|
|
|
|
final String exp = EXPECTED_TYPES.get(mboi.getName());
|
|
|
|
// For MXBeans, we need to compare 'exp' with the original
|
|
// type - because mboi.getReturnType() returns the OpenType
|
|
//
|
|
String type = (String)mboi.getDescriptor().
|
|
getFieldValue("originalType");
|
|
if (type == null) type = mboi.getReturnType();
|
|
if (type.equals(exp)) continue;
|
|
System.err.println("Bad return type for "+
|
|
mboi.getName()+"! Found "+type+
|
|
", expected "+exp);
|
|
throw new RuntimeException("Bad return type for "+
|
|
mboi.getName());
|
|
}
|
|
} finally {
|
|
server.unregisterMBean(childName);
|
|
}
|
|
}
|
|
|
|
public static void main(String[] args) throws Exception {
|
|
final Child child = new Child();
|
|
test(child,"Child[MBean]",false);
|
|
final ChildMix childx = new ChildMix();
|
|
test(childx,"ChildMix[MXBean]",true);
|
|
final ChildMixMix childmx = new ChildMixMix();
|
|
test(childmx,"ChildMixMix[MXBean]",false);
|
|
final StandardMBean schild = new StandardMBean(child,ChildMBean.class);
|
|
test(schild,"Child[StandarMBean(Child)]",false);
|
|
final StandardMBean schildx =
|
|
new StandardMBean(childx,ChildMXBean.class,true);
|
|
test(schildx,"ChildMix[StandarMXBean(ChildMix)]",true);
|
|
final StandardMBean schildmx =
|
|
new StandardMBean(childmx,ChildMixMXBean.class,true);
|
|
test(schildmx,"ChildMixMix[StandarMXBean(ChildMixMix)]",true);
|
|
}
|
|
|
|
}
|