/*
 * Copyright (c) 2005, 2008, 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 6175517 6278707 6318827 6305746 6392303 6600709
 * @summary General MXBean test.
 * @author Eamonn McManus
 * @run clean MXBeanTest MerlinMXBean TigerMXBean
 * @run build MXBeanTest MerlinMXBean TigerMXBean
 * @run main MXBeanTest
 */

import java.lang.reflect.Array;
import java.lang.reflect.Field;
import java.lang.reflect.InvocationHandler;
import java.lang.reflect.Method;
import java.lang.reflect.Proxy;
import java.util.Arrays;
import java.util.Collection;
import java.util.HashMap;
import java.util.Iterator;
import java.util.Map;
import java.util.SortedMap;
import javax.management.JMX;
import javax.management.MBeanAttributeInfo;
import javax.management.MBeanInfo;
import javax.management.MBeanOperationInfo;
import javax.management.MBeanParameterInfo;
import javax.management.MBeanServer;
import javax.management.MBeanServerConnection;
import javax.management.MBeanServerFactory;
import javax.management.MBeanServerInvocationHandler;
import javax.management.ObjectName;
import javax.management.StandardMBean;
import javax.management.openmbean.ArrayType;
import javax.management.openmbean.CompositeData;
import javax.management.openmbean.CompositeDataInvocationHandler;
import javax.management.openmbean.OpenType;
import javax.management.openmbean.SimpleType;
import javax.management.openmbean.TabularData;
import javax.management.openmbean.TabularType;
import javax.management.remote.JMXConnector;
import javax.management.remote.JMXConnectorFactory;
import javax.management.remote.JMXConnectorServer;
import javax.management.remote.JMXConnectorServerFactory;
import javax.management.remote.JMXServiceURL;

public class MXBeanTest {
    public static void main(String[] args) throws Exception {
        testInterface(MerlinMXBean.class, false);
        testInterface(TigerMXBean.class, false);
        testInterface(MerlinMXBean.class, true);
        testInterface(TigerMXBean.class, true);
        testExplicitMXBean();
        testSubclassMXBean();
        testIndirectMXBean();

        if (failures == 0)
            System.out.println("Test passed");
        else
            throw new Exception("TEST FAILURES: " + failures);
    }

    private static int failures = 0;

    public static interface ExplicitMXBean {
        public int[] getInts();
    }
    public static class Explicit implements ExplicitMXBean {
        public int[] getInts() {
            return new int[] {1, 2, 3};
        }
    }
    public static class Subclass
        extends StandardMBean
        implements ExplicitMXBean {
        public Subclass() {
            super(ExplicitMXBean.class, true);
        }

        public int[] getInts() {
            return new int[] {1, 2, 3};
        }
    }
    public static interface IndirectInterface extends ExplicitMXBean {}
    public static class Indirect implements IndirectInterface {
        public int[] getInts() {
            return new int[] {1, 2, 3};
        }
    }

    private static void testExplicitMXBean() throws Exception {
        System.out.println("Explicit MXBean test...");
        MBeanServer mbs = MBeanServerFactory.newMBeanServer();
        ObjectName on = new ObjectName("test:type=Explicit");
        Explicit explicit = new Explicit();
        mbs.registerMBean(explicit, on);
        testMXBean(mbs, on);
    }

    private static void testSubclassMXBean() throws Exception {
        System.out.println("Subclass MXBean test...");
        MBeanServer mbs = MBeanServerFactory.newMBeanServer();
        ObjectName on = new ObjectName("test:type=Subclass");
        Subclass subclass = new Subclass();
        mbs.registerMBean(subclass, on);
        testMXBean(mbs, on);
    }

    private static void testIndirectMXBean() throws Exception {
        System.out.println("Indirect MXBean test...");
        MBeanServer mbs = MBeanServerFactory.newMBeanServer();
        ObjectName on = new ObjectName("test:type=Indirect");
        Indirect indirect = new Indirect();
        mbs.registerMBean(indirect, on);
        testMXBean(mbs, on);
    }

    private static void testMXBean(MBeanServer mbs, ObjectName on)
            throws Exception {
        MBeanInfo mbi = mbs.getMBeanInfo(on);
        MBeanAttributeInfo[] attrs = mbi.getAttributes();
        int nattrs = attrs.length;
        if (mbi.getAttributes().length != 1)
            failure("wrong number of attributes: " + attrs);
        else {
            MBeanAttributeInfo mbai = attrs[0];
            if (mbai.getName().equals("Ints")
                && mbai.isReadable() && !mbai.isWritable()
                && mbai.getDescriptor().getFieldValue("openType")
                    .equals(new ArrayType<int[]>(SimpleType.INTEGER, true))
                && attrs[0].getType().equals("[I"))
                success("MBeanAttributeInfo");
            else
                failure("MBeanAttributeInfo: " + mbai);
        }

        int[] ints = (int[]) mbs.getAttribute(on, "Ints");
        if (equal(ints, new int[] {1, 2, 3}, null))
            success("getAttribute");
        else
            failure("getAttribute: " + Arrays.toString(ints));

        ExplicitMXBean proxy =
            JMX.newMXBeanProxy(mbs, on, ExplicitMXBean.class);
        int[] pints = proxy.getInts();
        if (equal(pints, new int[] {1, 2, 3}, null))
            success("getAttribute through proxy");
        else
            failure("getAttribute through proxy: " + Arrays.toString(pints));
    }

    private static class NamedMXBeans extends HashMap<ObjectName, Object> {
        private static final long serialVersionUID = 0;

        NamedMXBeans(MBeanServerConnection mbsc) {
            this.mbsc = mbsc;
        }

        MBeanServerConnection getMBeanServerConnection() {
            return mbsc;
        }

        private final MBeanServerConnection mbsc;
    }

    /* This is the core of the test.  Given the MXBean interface c, we
       make an MXBean object that implements that interface by
       constructing a dynamic proxy.  If the interface defines an
       attribute Foo (with getFoo and setFoo methods), then it must
       also contain a field (constant) Foo of the same type, and a
       field (constant) FooType that is an OpenType.  The field Foo is
       a reference value for this case.  We check that the attribute
       does indeed have the given OpenType.  The dynamically-created
       MXBean will return the reference value from the getFoo()
       method, and we check that that value survives the mapping to
       open values and back when the attribute is accessed through an
       MXBean proxy.  The MXBean will also check in its setFoo method
       that the value being set is equal to the reference value, which
       tests that the mapping and unmapping also works in the other
       direction.  The interface should define an operation opFoo with
       two parameters and a return value all of the same type as the
       attribute.  The MXBean will check that the two parameters are
       equal to the reference value, and will return that value.  The
       test checks that calling the operation through an MXBean proxy
       returns the reference value, again after mapping to and back
       from open values.

       If any field (constant) in the MXBean interface has a name that
       ends with ObjectName, say FooObjectName, then its value must be
       a String containing an ObjectName value.  There must be a field
       (constant) called Foo that is a valid MXBean, and that MXBean
       will be registered in the MBean Server with the given name before
       the test starts.  This enables us to test that inter-MXBean
       references are correctly converted to ObjectNames and back.
     */
    private static <T> void testInterface(Class<T> c, boolean nullTest)
            throws Exception {

        System.out.println("Testing " + c.getName() +
                           (nullTest ? " for null values" : "") + "...");

        MBeanServer mbs = MBeanServerFactory.newMBeanServer();

        JMXServiceURL url = new JMXServiceURL("rmi", null, 0);
        JMXConnectorServer cs =
            JMXConnectorServerFactory.newJMXConnectorServer(url, null, mbs);
        cs.start();
        JMXServiceURL addr = cs.getAddress();
        JMXConnector cc = JMXConnectorFactory.connect(addr);
        MBeanServerConnection mbsc = cc.getMBeanServerConnection();

        NamedMXBeans namedMXBeans = new NamedMXBeans(mbsc);
        InvocationHandler ih =
            nullTest ? new MXBeanNullImplInvocationHandler(c, namedMXBeans) :
                       new MXBeanImplInvocationHandler(c, namedMXBeans);
        T impl = c.cast(Proxy.newProxyInstance(c.getClassLoader(),
                                               new Class[] {c},
                                               ih));
        ObjectName on = new ObjectName("test:type=" + c.getName());
        mbs.registerMBean(impl, on);

        System.out.println("Register any MXBeans...");

        Field[] fields = c.getFields();
        for (Field field : fields) {
            String n = field.getName();
            if (n.endsWith("ObjectName")) {
                String objectNameString = (String) field.get(null);
                String base = n.substring(0, n.length() - 10);
                Field f = c.getField(base);
                Object mxbean = f.get(null);
                ObjectName objectName =
                    ObjectName.getInstance(objectNameString);
                mbs.registerMBean(mxbean, objectName);
                namedMXBeans.put(objectName, mxbean);
            }
        }

        try {
            testInterface(c, mbsc, on, namedMXBeans, nullTest);
        } finally {
            try {
                cc.close();
            } finally {
                cs.stop();
            }
        }
    }

    private static <T> void testInterface(Class<T> c,
                                          MBeanServerConnection mbsc,
                                          ObjectName on,
                                          NamedMXBeans namedMXBeans,
                                          boolean nullTest)
            throws Exception {

        System.out.println("Type check...");

        MBeanInfo mbi = mbsc.getMBeanInfo(on);
        MBeanAttributeInfo[] mbais = mbi.getAttributes();
        for (int i = 0; i < mbais.length; i++) {
            MBeanAttributeInfo mbai = mbais[i];
            String name = mbai.getName();
            Field typeField = c.getField(name + "Type");
            OpenType typeValue = (OpenType) typeField.get(null);
            OpenType openType =
                (OpenType) mbai.getDescriptor().getFieldValue("openType");
            if (typeValue.equals(openType))
                success("attribute " + name);
            else {
                final String msg =
                    "Wrong type attribute " + name + ": " +
                    openType + " should be " + typeValue;
                failure(msg);
            }
        }

        MBeanOperationInfo[] mbois = mbi.getOperations();
        for (int i = 0; i < mbois.length; i++) {
            MBeanOperationInfo mboi = mbois[i];
            String oname = mboi.getName();
            if (!oname.startsWith("op"))
                throw new Error();
            OpenType retType =
                (OpenType) mboi.getDescriptor().getFieldValue("openType");
            MBeanParameterInfo[] params = mboi.getSignature();
            MBeanParameterInfo p1i = params[0];
            MBeanParameterInfo p2i = params[1];
            OpenType p1Type =
                (OpenType) p1i.getDescriptor().getFieldValue("openType");
            OpenType p2Type =
                (OpenType) p2i.getDescriptor().getFieldValue("openType");
            if (!retType.equals(p1Type) || !p1Type.equals(p2Type)) {
                final String msg =
                    "Parameter and return open types should all be same " +
                    "but are not: " + retType + " " + oname + "(" + p1Type +
                    ", " + p2Type + ")";
                failure(msg);
                continue;
            }
            String name = oname.substring(2);
            Field typeField = c.getField(name + "Type");
            OpenType typeValue = (OpenType) typeField.get(null);
            if (typeValue.equals(retType))
                success("operation " + oname);
            else {
                final String msg =
                    "Wrong type operation " + oname + ": " +
                    retType + " should be " + typeValue;
                failure(msg);
            }
        }


        System.out.println("Mapping check...");

        Object proxy =
            JMX.newMXBeanProxy(mbsc, on, c);

        Method[] methods = c.getMethods();
        for (int i = 0; i < methods.length; i++) {
            final Method method = methods[i];
            if (method.getDeclaringClass() != c)
                continue; // skip hashCode() etc inherited from Object
            final String mname = method.getName();
            final int what = getType(method);
            final String name = getName(method);
            final Field refField = c.getField(name);
            if (nullTest && refField.getType().isPrimitive())
                continue;
            final Field openTypeField = c.getField(name + "Type");
            final OpenType openType = (OpenType) openTypeField.get(null);
            final Object refValue = nullTest ? null : refField.get(null);
            Object setValue = refValue;
            try {
                Field onField = c.getField(name + "ObjectName");
                String refName = (String) onField.get(null);
                ObjectName refObjName = ObjectName.getInstance(refName);
                Class<?> mxbeanInterface = refField.getType();
                setValue = nullTest ? null :
                    JMX.newMXBeanProxy(mbsc, refObjName, mxbeanInterface);
            } catch (Exception e) {
                // no xObjectName field, setValue == refValue
            }
            boolean ok = true;
            try {
                switch (what) {
                case GET:
                    final Object gotOpen = mbsc.getAttribute(on, name);
                    if (nullTest) {
                        if (gotOpen != null) {
                            failure(mname + " got non-null value " +
                                    gotOpen);
                            ok = false;
                        }
                    } else if (!openType.isValue(gotOpen)) {
                        if (gotOpen instanceof TabularData) {
                            // detail the mismatch
                            TabularData gotTabular = (TabularData) gotOpen;
                            compareTabularType((TabularType) openType,
                                               gotTabular.getTabularType());
                        }
                        failure(mname + " got open data " + gotOpen +
                                " not valid for open type " + openType);
                        ok = false;
                    }
                    final Object got = method.invoke(proxy, (Object[]) null);
                    if (!equal(refValue, got, namedMXBeans)) {
                        failure(mname + " got " + string(got) +
                                ", should be " + string(refValue));
                        ok = false;
                    }
                    break;

                case SET:
                    method.invoke(proxy, new Object[] {setValue});
                    break;

                case OP:
                    final Object opped =
                        method.invoke(proxy, new Object[] {setValue, setValue});
                    if (!equal(refValue, opped, namedMXBeans)) {
                        failure(
                                mname + " got " + string(opped) +
                                ", should be " + string(refValue)
                                );
                        ok = false;
                    }
                    break;

                default:
                    throw new Error();
                }

                if (ok)
                    success(mname);

            } catch (Exception e) {
                failure(mname, e);
            }
        }
    }


    private static void success(String what) {
        System.out.println("OK: " + what);
    }

    private static void failure(String what) {
        System.out.println("FAILED: " + what);
        failures++;
    }

    private static void failure(String what, Exception e) {
        System.out.println("FAILED WITH EXCEPTION: " + what);
        e.printStackTrace(System.out);
        failures++;
    }

    private static class MXBeanImplInvocationHandler
            implements InvocationHandler {
        MXBeanImplInvocationHandler(Class intf, NamedMXBeans namedMXBeans) {
            this.intf = intf;
            this.namedMXBeans = namedMXBeans;
        }

        public Object invoke(Object proxy, Method method, Object[] args)
                throws Throwable {
            final String mname = method.getName();
            final int what = getType(method);
            final String name = getName(method);
            final Field refField = intf.getField(name);
            final Object refValue = getRefValue(refField);

            switch (what) {
            case GET:
                assert args == null;
                return refValue;

            case SET:
                assert args.length == 1;
                Object setValue = args[0];
                if (!equal(refValue, setValue, namedMXBeans)) {
                    final String msg =
                        mname + "(" + string(setValue) +
                        ") does not match ref: " + string(refValue);
                    throw new IllegalArgumentException(msg);
                }
                return null;

            case OP:
                assert args.length == 2;
                Object arg1 = args[0];
                Object arg2 = args[1];
                if (!equal(arg1, arg2, namedMXBeans)) {
                    final String msg =
                        mname + "(" + string(arg1) + ", " + string(arg2) +
                        "): args not equal";
                    throw new IllegalArgumentException(msg);
                }
                if (!equal(refValue, arg1, namedMXBeans)) {
                    final String msg =
                        mname + "(" + string(arg1) + ", " + string(arg2) +
                        "): args do not match ref: " + string(refValue);
                    throw new IllegalArgumentException(msg);
                }
                return refValue;
            default:
                throw new Error();
            }
        }

        Object getRefValue(Field refField) throws Exception {
            return refField.get(null);
        }

        private final Class intf;
        private final NamedMXBeans namedMXBeans;
    }

    private static class MXBeanNullImplInvocationHandler
            extends MXBeanImplInvocationHandler {
        MXBeanNullImplInvocationHandler(Class intf, NamedMXBeans namedMXBeans) {
            super(intf, namedMXBeans);
        }

        @Override
        Object getRefValue(Field refField) throws Exception {
            Class<?> type = refField.getType();
            if (type.isPrimitive())
                return super.getRefValue(refField);
            else
                return null;
        }
    }


    private static final String[] prefixes = {
        "get", "set", "op",
    };
    private static final int GET = 0, SET = 1, OP = 2;

    private static String getName(Method m) {
        return getName(m.getName());
    }

    private static String getName(String n) {
        for (int i = 0; i < prefixes.length; i++) {
            if (n.startsWith(prefixes[i]))
                return n.substring(prefixes[i].length());
        }
        throw new Error();
    }

    private static int getType(Method m) {
        return getType(m.getName());
    }

    private static int getType(String n) {
        for (int i = 0; i < prefixes.length; i++) {
            if (n.startsWith(prefixes[i]))
                return i;
        }
        throw new Error();
    }

    static boolean equal(Object o1, Object o2, NamedMXBeans namedMXBeans) {
        if (o1 == o2)
            return true;
        if (o1 == null || o2 == null)
            return false;
        if (o1.getClass().isArray()) {
            if (!o2.getClass().isArray())
                return false;
            return deepEqual(o1, o2, namedMXBeans);
        }
        if (o1 instanceof Map) {
            if (!(o2 instanceof Map))
                return false;
            return equalMap((Map) o1, (Map) o2, namedMXBeans);
        }
        if (o1 instanceof CompositeData && o2 instanceof CompositeData) {
            return compositeDataEqual((CompositeData) o1, (CompositeData) o2,
                                      namedMXBeans);
        }
        if (Proxy.isProxyClass(o1.getClass())) {
            if (Proxy.isProxyClass(o2.getClass()))
                return proxyEqual(o1, o2, namedMXBeans);
            InvocationHandler ih = Proxy.getInvocationHandler(o1);
//            if (ih instanceof MXBeanInvocationHandler) {
//                return proxyEqualsObject((MXBeanInvocationHandler) ih,
//                                         o2, namedMXBeans);
            if (ih instanceof MBeanServerInvocationHandler) {
                return true;
            } else if (ih instanceof CompositeDataInvocationHandler) {
                return o2.equals(o1);
                // We assume the other object has a reasonable equals method
            }
        } else if (Proxy.isProxyClass(o2.getClass()))
            return equal(o2, o1, namedMXBeans);
        return o1.equals(o2);
    }

    // We'd use Arrays.deepEquals except we want the test to work on 1.4
    // Note this code assumes no selfreferential arrays
    // (as does Arrays.deepEquals)
    private static boolean deepEqual(Object a1, Object a2,
                                     NamedMXBeans namedMXBeans) {
        int len = Array.getLength(a1);
        if (len != Array.getLength(a2))
            return false;
        for (int i = 0; i < len; i++) {
            Object e1 = Array.get(a1, i);
            Object e2 = Array.get(a2, i);
            if (!equal(e1, e2, namedMXBeans))
                return false;
        }
        return true;
    }

    private static boolean equalMap(Map<?,?> m1, Map<?,?> m2,
                                    NamedMXBeans namedMXBeans) {
        if (m1.size() != m2.size())
            return false;
        if ((m1 instanceof SortedMap) != (m2 instanceof SortedMap))
            return false;
        for (Object k1 : m1.keySet()) {
            if (!m2.containsKey(k1))
                return false;
            if (!equal(m1.get(k1), m2.get(k1), namedMXBeans))
                return false;
        }
        return true;
    }

    // This is needed to work around a bug (5095277)
    // in CompositeDataSupport.equals
    private static boolean compositeDataEqual(CompositeData cd1,
                                              CompositeData cd2,
                                              NamedMXBeans namedMXBeans) {
        if (cd1 == cd2)
            return true;
        if (!cd1.getCompositeType().equals(cd2.getCompositeType()))
            return false;
        Collection v1 = cd1.values();
        Collection v2 = cd2.values();
        if (v1.size() != v2.size())
            return false; // should not happen
        for (Iterator i1 = v1.iterator(), i2 = v2.iterator();
             i1.hasNext(); ) {
            if (!equal(i1.next(), i2.next(), namedMXBeans))
                return false;
        }
        return true;
    }

    // Also needed for 5095277
    private static boolean proxyEqual(Object proxy1, Object proxy2,
                                      NamedMXBeans namedMXBeans) {
        if (proxy1.getClass() != proxy2.getClass())
            return proxy1.equals(proxy2);
        InvocationHandler ih1 = Proxy.getInvocationHandler(proxy1);
        InvocationHandler ih2 = Proxy.getInvocationHandler(proxy2);
        if (!(ih1 instanceof CompositeDataInvocationHandler)
            || !(ih2 instanceof CompositeDataInvocationHandler))
            return proxy1.equals(proxy2);
        CompositeData cd1 =
            ((CompositeDataInvocationHandler) ih1).getCompositeData();
        CompositeData cd2 =
            ((CompositeDataInvocationHandler) ih2).getCompositeData();
        return compositeDataEqual(cd1, cd2, namedMXBeans);
    }

//    private static boolean proxyEqualsObject(MXBeanInvocationHandler ih,
//                                             Object o,
//                                             NamedMXBeans namedMXBeans) {
//        if (namedMXBeans.getMBeanServerConnection() !=
//            ih.getMBeanServerConnection())
//            return false;
//
//        ObjectName on = ih.getObjectName();
//        Object named = namedMXBeans.get(on);
//        if (named == null)
//            return false;
//        return (o == named && ih.getMXBeanInterface().isInstance(named));
//    }

    /* I wanted to call this method toString(Object), but oddly enough
       this meant that I couldn't call it from the inner class
       MXBeanImplInvocationHandler, because the inherited Object.toString()
       prevented that.  */
    static String string(Object o) {
        if (o == null)
            return "null";
        if (o instanceof String)
            return '"' + (String) o + '"';
        if (o instanceof Collection)
            return deepToString((Collection) o);
        if (o.getClass().isArray())
            return deepToString(o);
        return o.toString();
    }

    private static String deepToString(Object o) {
        StringBuffer buf = new StringBuffer();
        buf.append("[");
        int len = Array.getLength(o);
        for (int i = 0; i < len; i++) {
            if (i > 0)
                buf.append(", ");
            Object e = Array.get(o, i);
            buf.append(string(e));
        }
        buf.append("]");
        return buf.toString();
    }

    private static String deepToString(Collection c) {
        return deepToString(c.toArray());
    }

    private static void compareTabularType(TabularType t1, TabularType t2) {
        if (t1.equals(t2)) {
            System.out.println("same tabular type");
            return;
        }
        if (t1.getClassName().equals(t2.getClassName()))
            System.out.println("same class name");
        if (t1.getDescription().equals(t2.getDescription()))
            System.out.println("same description");
        else {
            System.out.println("t1 description: " + t1.getDescription());
            System.out.println("t2 description: " + t2.getDescription());
        }
        if (t1.getIndexNames().equals(t2.getIndexNames()))
            System.out.println("same index names");
        if (t1.getRowType().equals(t2.getRowType()))
            System.out.println("same row type");
    }
}
