jdk/test/javax/management/namespace/NullObjectNameTest.java
author dfuchs
Tue, 09 Dec 2008 20:20:48 +0100
changeset 1709 392dd6db361a
parent 1570 4165709c91e3
permissions -rw-r--r--
6768935: Clarify the behaviour of ObjectName pattern matching with regards to namespaces Reviewed-by: emcmanus

/*
 * Copyright 2008 Sun Microsystems, Inc.  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 Sun Microsystems, Inc., 4150 Network Circle, Santa Clara,
 * CA 95054 USA or visit www.sun.com if you need additional information or
 * have any questions.
 */
/*
 * @test NullObjectNameTest.java
 * @summary Test that null ObjectName are correctly handled in namespaces.
 * @author Daniel Fuchs
 * @bug 5072476
 * @run clean NullObjectNameTest Wombat WombatMBean
 * @compile -XDignore.symbol.file=true  NullObjectNameTest.java
 * @run build NullObjectNameTest Wombat WombatMBean
 * @run main NullObjectNameTest
 */

import com.sun.jmx.namespace.RoutingServerProxy;
import java.lang.management.ManagementFactory;
import java.util.Arrays;
import java.util.logging.Logger;
import javax.management.MBeanRegistrationException;
import javax.management.MBeanServer;
import javax.management.MBeanServerFactory;
import javax.management.NotCompliantMBeanException;
import javax.management.ObjectInstance;
import javax.management.ObjectName;
import javax.management.RuntimeOperationsException;
import javax.management.namespace.JMXNamespaces;
import javax.management.namespace.JMXRemoteNamespace;
import javax.management.namespace.JMXNamespace;
import javax.management.remote.JMXConnectorServer;
import javax.management.remote.JMXConnectorServerFactory;
import javax.management.remote.JMXServiceURL;

/**
 * Class NullObjectNameTest
 * @author Sun Microsystems, 2005 - All rights reserved.
 */
public class NullObjectNameTest {

    /**
     * A logger for this class.
     **/
    private static final Logger LOG =
            Logger.getLogger(NullObjectNameTest.class.getName());

    /** Creates a new instance of NullObjectNameTest */
    public NullObjectNameTest() {
    }

    public static class MyWombat
            extends Wombat {
        public MyWombat() throws NotCompliantMBeanException {
            super();
        }
        @Override
        public ObjectName preRegister(MBeanServer server, ObjectName name)
        throws Exception {

            if (name == null)
                name = new ObjectName(":type=Wombat");

            return super.preRegister(server, name);
        }

    }

    static String failure=null;

    public static void testRegister() throws Exception {
        final MBeanServer top = ManagementFactory.getPlatformMBeanServer();
        final MBeanServer sub = MBeanServerFactory.createMBeanServer();
        final JMXServiceURL url = new JMXServiceURL("rmi",null,0);
        final JMXConnectorServer srv =
                JMXConnectorServerFactory.newJMXConnectorServer(url,null,sub);
        srv.start();

        try {

            // Create a namespace rmi// that points to 'sub' and flows through
            // a JMXRemoteNamespace connected to 'srv'
            // The namespace rmi// will accept createMBean, but not registerMBean.
            //
            final JMXRemoteNamespace rmiHandler = JMXRemoteNamespace.
                    newJMXRemoteNamespace(srv.getAddress(),null);
            top.registerMBean(rmiHandler,JMXNamespaces.getNamespaceObjectName("rmi"));
            top.invoke(JMXNamespaces.getNamespaceObjectName("rmi"),
                    "connect", null, null);

            // Create a namespace direct// that points to 'sub' and flows
            // through a direct reference to 'sub'.
            // The namespace direct// will accept createMBean, and registerMBean.
            //
            final JMXNamespace directHandler = new JMXNamespace(sub);
            top.registerMBean(directHandler,
                    JMXNamespaces.getNamespaceObjectName("direct"));

            // Now cd to each of the created namespace.
            //
            MBeanServer cdrmi = JMXNamespaces.narrowToNamespace(top,"rmi");
            MBeanServer cddirect = JMXNamespaces.narrowToNamespace(top,"direct");
            boolean ok = false;

            // Check that calling createMBean with a null ObjectName fails
            // gracefully for namespace rmi// (we can't add rmi// to a null
            // ObjectName.
            //
            // TODO: do this test for all createMBean flavors!
            try {
                final ObjectInstance moi1 =
                        cdrmi.createMBean(MyWombat.class.getName(),null);
                System.out.println(moi1.getObjectName().toString()+
                        ": created through rmi//");
                cddirect.unregisterMBean(moi1.getObjectName());
                failed("expected MBeanRegistrationException");
            } catch (MBeanRegistrationException x) {
                System.out.println("Received expected exception: " + x);
                if (!(x.getCause() instanceof IllegalArgumentException)) {
                    System.err.println("Bad wrapped exception: "+ x.getCause());
                    failed("expected IllegalArgumentException");
                }
            }

            // Check that calling refgisterMBean with a null ObjectName fails
            // gracefully for namespace direct// (we can't add direct// to a null
            // ObjectName.
            //
            try {
                final ObjectInstance moi2 =
                        cddirect.registerMBean(new MyWombat(), (ObjectName)null);
                System.out.println(moi2.getObjectName().toString()+
                        ": created through direct//");
                cdrmi.unregisterMBean(moi2.getObjectName());
                failed("expected MBeanRegistrationException");
            } catch (MBeanRegistrationException x) {
                System.out.println("Received expected exception: " + x);
                if (!(x.getCause() instanceof IllegalArgumentException)) {
                    System.err.println("Bad wrapped exception: "+ x.getCause());
                    failed("expected IllegalArgumentException");
                }
            }

            // Now artificially pretend that 'sub' is contained in a faked//
            // namespace.
            // We should be able to use 'null' in registerMBean/createMBean in
            // this case.
            //
            RoutingServerProxy proxy =
                    new RoutingServerProxy(sub, "", "faked", true);
            final ObjectInstance moi3 =
                    proxy.registerMBean(new MyWombat(),null);
            System.out.println(moi3.getObjectName().toString()+
                    ": created through faked//");

            // Now check that null is correctly handled (accepted or rejected)
            // in queries for each of the above configs.
            //
            ObjectName wombat = moi3.getObjectName().withDomain(
                    moi3.getObjectName().getDomain().substring("faked//".length()));
            ObjectInstance moi = new ObjectInstance(wombat,moi3.getClassName());

            System.out.println("Checking queryNames(null,null) with rmi//");
            assertEquals(cdrmi.queryNames(null,null).contains(wombat),true);
            System.out.println("Checking queryNames(null,null) with direct//");
            assertEquals(cddirect.queryNames(null,null).contains(wombat),true);
            System.out.println("Checking queryMBeans(null,null) with rmi//");
            assertEquals(cdrmi.queryMBeans(null,null).contains(moi),true);
            System.out.println("Checking queryMBeans(null,null) with direct//");
            assertEquals(cddirect.queryMBeans(null,null).contains(moi),true);

            try {
                System.out.println("Checking queryNames(null,null) with faked//");
                assertEquals(proxy.queryNames(null,null).
                        contains(moi3.getObjectName()),true);
                failed("queryNames(null,null) should have failed for faked//");
            } catch (RuntimeOperationsException x) {
                if (x.getCause() instanceof IllegalArgumentException)
                    System.out.println(
                            "Received expected exception for faked//: "+x);
                else {
                    System.err.println(
                            "Expected exception has unexpected cause " +
                            "for faked//: "+x.getCause());
                    x.printStackTrace();
                    failed("queryNames(null,null) failed with unexpected " +
                            "cause for faked//");
                }
            }
            try {
                System.out.println("Checking queryMBeans(null,null) with faked//");
                assertEquals(proxy.queryMBeans(null,null).contains(moi3),true);
                failed("queryMBeans(null,null) should have failed for faked//");
            } catch (RuntimeOperationsException x) {
                if (x.getCause() instanceof IllegalArgumentException)
                    System.out.println(
                            "Received expected exception for faked//: "+x);
                else {
                    System.err.println(
                            "Expected exception has unexpected cause " +
                            "for faked//: "+x.getCause());
                    x.printStackTrace();
                    failed("queryMBeans(null,null) failed with unexpected " +
                            "cause for faked//");
                }
            }
            System.out.println("Checking queryNames(faked//*:*,null)");
            assertEquals(proxy.queryNames(new ObjectName("faked//*:*"),null).
                    contains(moi3.getObjectName()),true);

            System.out.println("Checking queryMBeans(faked//*:*,null)");
            assertEquals(proxy.queryMBeans(new ObjectName("faked//*:*"),null).
                    contains(moi3),true);

            proxy.unregisterMBean(moi3.getObjectName());

            // ADD NEW TESTS HERE ^^^

        } finally {
            srv.stop();
        }

        if (failure != null)
            throw new Exception(failure);


    }
    private static void assertEquals(Object x, Object y) {
        if (!equal(x, y))
            failed("expected " + string(x) + "; got " + string(y));
    }

    private static boolean equal(Object x, Object y) {
        if (x == y)
            return true;
        if (x == null || y == null)
            return false;
        if (x.getClass().isArray())
            return Arrays.deepEquals(new Object[] {x}, new Object[] {y});
        return x.equals(y);
    }

    private static String string(Object x) {
        String s = Arrays.deepToString(new Object[] {x});
        return s.substring(1, s.length() - 1);
    }


    private static void failed(String why) {
        failure = why;
        new Throwable("FAILED: " + why).printStackTrace(System.out);
    }

    public static void main(String[] args) throws Exception {
        testRegister();
    }
}