6747983: jmx namespace: unspecified self-link detection logic
authordfuchs
Fri, 12 Sep 2008 19:06:38 +0200
changeset 1231 9b3e98cca850
parent 1230 18db753e5986
child 1232 7128121645f7
child 1240 7567f0847c37
6747983: jmx namespace: unspecified self-link detection logic Reviewed-by: emcmanus
jdk/src/share/classes/com/sun/jmx/namespace/NamespaceInterceptor.java
jdk/src/share/classes/javax/management/namespace/JMXRemoteNamespace.java
jdk/test/javax/management/namespace/JMXNamespaceTest.java
--- a/jdk/src/share/classes/com/sun/jmx/namespace/NamespaceInterceptor.java	Fri Sep 12 17:58:15 2008 +0200
+++ b/jdk/src/share/classes/com/sun/jmx/namespace/NamespaceInterceptor.java	Fri Sep 12 19:06:38 2008 +0200
@@ -25,22 +25,15 @@
 package com.sun.jmx.namespace;
 
 import com.sun.jmx.defaults.JmxProperties;
-import java.io.IOException;
 import java.util.ArrayList;
-import java.util.Collections;
 import java.util.List;
-import java.util.Set;
-import java.util.UUID;
 import java.util.logging.Logger;
 
 import javax.management.Attribute;
 import javax.management.AttributeList;
 import javax.management.MBeanServer;
-import javax.management.MBeanServerConnection;
 import javax.management.MalformedObjectNameException;
 import javax.management.ObjectName;
-import javax.management.QueryExp;
-import javax.management.namespace.JMXNamespaces;
 import javax.management.namespace.JMXNamespace;
 import javax.management.namespace.JMXNamespacePermission;
 
@@ -54,8 +47,6 @@
  */
 public class NamespaceInterceptor extends HandlerInterceptor<JMXNamespace> {
 
-    private static final Logger PROBE_LOG = Logger.getLogger(
-            JmxProperties.NAMESPACE_LOGGER+".probe");
 
     // The target name space in which the NamepsaceHandler is mounted.
     private final String           targetNs;
@@ -65,21 +56,6 @@
     private final ObjectNameRouter proc;
 
     /**
-     * Internal hack. The JMXRemoteNamespace can be closed and reconnected.
-     * Each time the JMXRemoteNamespace connects, a probe should be sent
-     * to detect cycle. The MBeanServer exposed by JMXRemoteNamespace thus
-     * implements the DynamicProbe interface, which makes it possible for
-     * this handler to know that it should send a new probe.
-     *
-     * XXX: TODO this probe thing is way too complex and fragile.
-     *      This *must* go away or be replaced by something simpler.
-     *      ideas are welcomed.
-     **/
-    public static interface DynamicProbe {
-        public boolean isProbeRequested();
-    }
-
-    /**
      * Creates a new instance of NamespaceInterceptor
      */
     public NamespaceInterceptor(
@@ -100,164 +76,6 @@
                 ", namespace="+this.targetNs+")";
     }
 
-    /*
-     * XXX: TODO this probe thing is way too complex and fragile.
-     *      This *must* go away or be replaced by something simpler.
-     *      ideas are welcomed.
-     */
-    private volatile boolean probed = false;
-    private volatile ObjectName probe;
-
-    // Query Pattern that we will send through the source server in order
-    // to detect self-linking namespaces.
-    //
-    // XXX: TODO this probe thing is way too complex and fragile.
-    //      This *must* go away or be replaced by something simpler.
-    //      ideas are welcomed.
-    final ObjectName makeProbePattern(ObjectName probe)
-            throws MalformedObjectNameException {
-
-        // we could probably link the probe pattern with the probe - e.g.
-        // using the UUID as key in the pattern - but is it worth it? it
-        // also has some side effects on the context namespace - because
-        // such a probe may get rejected by the jmx.context// namespace.
-        //
-        // The trick here is to devise a pattern that is not likely to
-        // be blocked by intermediate levels. Querying for all namespace
-        // handlers in the source (or source namespace) is more likely to
-        // achieve this goal.
-        //
-        return ObjectName.getInstance("*" +
-                JMXNamespaces.NAMESPACE_SEPARATOR + ":" +
-                JMXNamespace.TYPE_ASSIGNMENT);
-    }
-
-    // tell whether the name pattern corresponds to what might have been
-    // sent as a probe.
-    // XXX: TODO this probe thing is way too complex and fragile.
-    //      This *must* go away or be replaced by something simpler.
-    //      ideas are welcomed.
-    final boolean isProbePattern(ObjectName name) {
-        final ObjectName p = probe;
-        if (p == null) return false;
-        try {
-            return String.valueOf(name).endsWith(targetNs+
-                JMXNamespaces.NAMESPACE_SEPARATOR + "*" +
-                JMXNamespaces.NAMESPACE_SEPARATOR + ":" +
-                JMXNamespace.TYPE_ASSIGNMENT);
-        } catch (RuntimeException x) {
-            // should not happen.
-            PROBE_LOG.finest("Ignoring unexpected exception in self link detection: "+
-                    x);
-            return false;
-        }
-    }
-
-    // The first time a request reaches this NamespaceInterceptor, the
-    // interceptor will send a probe to detect whether the underlying
-    // JMXNamespace links to itslef.
-    //
-    // One way to create such self-linking namespace would be for instance
-    // to create a JMXNamespace whose getSourceServer() method would return:
-    // JMXNamespaces.narrowToNamespace(getMBeanServer(),
-    //                                 getObjectName().getDomain())
-    //
-    // If such an MBeanServer is returned, then any call to that MBeanServer
-    // will trigger an infinite loop.
-    // There can be even trickier configurations if remote connections are
-    // involved.
-    //
-    // In order to prevent this from happening, the NamespaceInterceptor will
-    // send a probe, in an attempt to detect whether it will receive it at
-    // the other end. If the probe is received, an exception will be thrown
-    // in order to break the recursion. The probe is only sent once - when
-    // the first request to the namespace occurs. The DynamicProbe interface
-    // can also be used by a Sun JMXNamespace implementation to request the
-    // emission of a probe at any time (see JMXRemoteNamespace
-    // implementation).
-    //
-    // Probes work this way: the NamespaceInterceptor sets a flag and sends
-    // a queryNames() request. If a queryNames() request comes in when the flag
-    // is on, then it deduces that there is a self-linking loop - and instead
-    // of calling queryNames() on the source MBeanServer of the JMXNamespace
-    // handler (which would cause the loop to go on) it breaks the recursion
-    // by returning the probe ObjectName.
-    // If the NamespaceInterceptor receives the probe ObjectName as result of
-    // its original sendProbe() request it knows that it has been looping
-    // back on itslef and throws an IOException...
-    //
-    //
-    // XXX: TODO this probe thing is way too complex and fragile.
-    //      This *must* go away or be replaced by something simpler.
-    //      ideas are welcomed.
-    //
-    final void sendProbe(MBeanServerConnection msc)
-            throws IOException {
-        try {
-            PROBE_LOG.fine("Sending probe");
-
-            // This is just to prevent any other thread to modify
-            // the probe while the detection cycle is in progress.
-            //
-            final ObjectName probePattern;
-            // we don't want to synchronize on this - we use targetNs
-            // because it's non null and final.
-            synchronized (targetNs) {
-                probed = false;
-                if (probe != null) {
-                    throw new IOException("concurent connection in progress");
-                }
-                final String uuid = UUID.randomUUID().toString();
-                final String endprobe =
-                        JMXNamespaces.NAMESPACE_SEPARATOR + uuid +
-                        ":type=Probe,key="+uuid;
-                final ObjectName newprobe =
-                        ObjectName.getInstance(endprobe);
-                probePattern = makeProbePattern(newprobe);
-                probe = newprobe;
-            }
-
-            try {
-                PROBE_LOG.finer("Probe query: "+probePattern+" expecting: "+probe);
-                final Set<ObjectName> res = msc.queryNames(probePattern, null);
-                final ObjectName expected = probe;
-                PROBE_LOG.finer("Probe res: "+res);
-                if (res.contains(expected)) {
-                    throw new IOException("namespace " +
-                            targetNs + " is linking to itself: " +
-                            "cycle detected by probe");
-                }
-            } catch (SecurityException x) {
-                PROBE_LOG.finer("Can't check for cycles: " + x);
-                // can't do anything....
-            } catch (RuntimeException x) {
-                PROBE_LOG.finer("Exception raised by queryNames: " + x);
-                throw x;
-            } finally {
-                probe = null;
-            }
-        } catch (MalformedObjectNameException x) {
-            final IOException io =
-                    new IOException("invalid name space: probe failed");
-            io.initCause(x);
-            throw io;
-        }
-        PROBE_LOG.fine("Probe returned - no cycles");
-        probed = true;
-    }
-
-    // allows a Sun implementation JMX Namespace, such as the
-    // JMXRemoteNamespace, to control when a probe should be sent.
-    //
-    // XXX: TODO this probe thing is way too complex and fragile.
-    //      This *must* go away or be replaced by something simpler.
-    //      ideas are welcomed.
-    private boolean isProbeRequested(Object o) {
-        if (o instanceof DynamicProbe)
-            return ((DynamicProbe)o).isProbeRequested();
-        return false;
-    }
-
     /**
      * This method will send a probe to detect self-linking name spaces.
      * A self linking namespace is a namespace that links back directly
@@ -277,29 +95,9 @@
      * (see JMXRemoteNamespace implementation).
      */
     private MBeanServer connection() {
-        try {
-            final MBeanServer c = super.source();
-            if (probe != null) // should not happen
-                throw new RuntimeException("connection is being probed");
-
-            if (probed == false || isProbeRequested(c)) {
-                try {
-                    // Should not happen if class well behaved.
-                    // Never probed. Force it.
-                    //System.err.println("sending probe for " +
-                    //        "target="+targetNs+", source="+srcNs);
-                    sendProbe(c);
-                } catch (IOException io) {
-                    throw new RuntimeException(io.getMessage(), io);
-                }
-            }
-
-            if (c != null) {
-                return c;
-            }
-        } catch (RuntimeException x) {
-            throw x;
-        }
+        final MBeanServer c = super.source();
+        if (c != null) return c;
+        // should not come here
         throw new NullPointerException("getMBeanServerConnection");
     }
 
@@ -315,24 +113,6 @@
         return super.source();
     }
 
-    /**
-     * Calls {@link MBeanServerConnection#queryNames queryNames}
-     * on the underlying
-     * {@link #getMBeanServerConnection MBeanServerConnection}.
-     **/
-    @Override
-    public final Set<ObjectName> queryNames(ObjectName name, QueryExp query) {
-        // XXX: TODO this probe thing is way too complex and fragile.
-        //      This *must* go away or be replaced by something simpler.
-        //      ideas are welcomed.
-        PROBE_LOG.finer("probe is: "+probe+" pattern is: "+name);
-        if (probe != null && isProbePattern(name)) {
-            PROBE_LOG.finer("Return probe: "+probe);
-            return Collections.singleton(probe);
-        }
-        return super.queryNames(name, query);
-    }
-
     @Override
     protected ObjectName toSource(ObjectName targetName)
             throws MalformedObjectNameException {
--- a/jdk/src/share/classes/javax/management/namespace/JMXRemoteNamespace.java	Fri Sep 12 17:58:15 2008 +0200
+++ b/jdk/src/share/classes/javax/management/namespace/JMXRemoteNamespace.java	Fri Sep 12 19:06:38 2008 +0200
@@ -28,11 +28,9 @@
 import com.sun.jmx.defaults.JmxProperties;
 import com.sun.jmx.mbeanserver.Util;
 import com.sun.jmx.namespace.JMXNamespaceUtils;
-import com.sun.jmx.namespace.NamespaceInterceptor.DynamicProbe;
 import com.sun.jmx.remote.util.EnvHelp;
 
 import java.io.IOException;
-import java.security.AccessControlException;
 import java.util.HashMap;
 import java.util.Map;
 import java.util.concurrent.atomic.AtomicLong;
@@ -44,9 +42,7 @@
 import javax.management.InstanceNotFoundException;
 import javax.management.ListenerNotFoundException;
 import javax.management.MBeanNotificationInfo;
-import javax.management.MBeanPermission;
 import javax.management.MBeanServerConnection;
-import javax.management.MalformedObjectNameException;
 import javax.management.Notification;
 import javax.management.NotificationBroadcasterSupport;
 import javax.management.NotificationEmitter;
@@ -118,9 +114,6 @@
      */
     private static final Logger LOG = JmxProperties.NAMESPACE_LOGGER;
 
-    private static final Logger PROBE_LOG = Logger.getLogger(
-            JmxProperties.NAMESPACE_LOGGER_NAME+".probe");
-
 
     // This connection listener is used to listen for connection events from
     // the underlying JMXConnector. It is used in particular to maintain the
@@ -153,8 +146,7 @@
     // because the one that is actually used is the one supplied by the
     // override of getMBeanServerConnection().
     private static class JMXRemoteNamespaceDelegate
-            extends MBeanServerConnectionWrapper
-            implements DynamicProbe {
+            extends MBeanServerConnectionWrapper {
         private volatile JMXRemoteNamespace parent=null;
 
         JMXRemoteNamespaceDelegate() {
@@ -180,9 +172,6 @@
 
         }
 
-        public boolean isProbeRequested() {
-            return this.parent.isProbeRequested();
-        }
     }
 
     private static final MBeanNotificationInfo connectNotification =
@@ -201,7 +190,6 @@
     private volatile MBeanServerConnection server = null;
     private volatile JMXConnector conn = null;
     private volatile ClassLoader defaultClassLoader = null;
-    private volatile boolean probed;
 
     /**
      * Creates a new instance of {@code JMXRemoteNamespace}.
@@ -241,9 +229,6 @@
 
         // handles (dis)connection events
         this.listener = new ConnectionListener();
-
-        // XXX TODO: remove the probe, or simplify it.
-        this.probed = false;
     }
 
    /**
@@ -274,10 +259,6 @@
         return optionsMap;
     }
 
-    boolean isProbeRequested() {
-        return probed==false;
-    }
-
     public void addNotificationListener(NotificationListener listener,
             NotificationFilter filter, Object handback) {
         broadcaster.addNotificationListener(listener, filter, handback);
@@ -603,26 +584,7 @@
     }
 
     public void connect() throws IOException {
-        if (conn != null) {
-            try {
-               // This is much too fragile. It must go away!
-               PROBE_LOG.finest("Probing again...");
-               triggerProbe(getMBeanServerConnection());
-            } catch(Exception x) {
-                close();
-                Throwable cause = x;
-                // if the cause is a security exception - rethrows it...
-                while (cause != null) {
-                    if (cause instanceof SecurityException)
-                        throw (SecurityException) cause;
-                    cause = cause.getCause();
-                }
-                throw new IOException("connection failed: cycle?",x);
-            }
-        }
         LOG.fine("connecting...");
-        // TODO remove these traces
-        // System.err.println(getInitParameter()+" connecting");
         final Map<String,Object> env =
                 new HashMap<String,Object>(getEnvMap());
         try {
@@ -652,79 +614,9 @@
             throw x;
         }
 
-
-        // XXX Revisit here
-        // Note from the author: This business of switching connection is
-        // incredibly complex. Isn't there any means to simplify it?
-        //
         switchConnection(conn,aconn,msc);
-        try {
-           triggerProbe(msc);
-        } catch(Exception x) {
-            close();
-            Throwable cause = x;
-            // if the cause is a security exception - rethrows it...
-            while (cause != null) {
-                if (cause instanceof SecurityException)
-                    throw (SecurityException) cause;
-                cause = cause.getCause();
-            }
-            throw new IOException("connection failed: cycle?",x);
-        }
-        LOG.fine("connected.");
-    }
 
-    // If this is a self-linking namespace, this method should trigger
-    // the emission of a probe in the wrapping NamespaceInterceptor.
-    // The first call to source() in the wrapping NamespaceInterceptor
-    // causes the emission of the probe.
-    //
-    // Note: the MBeanServer returned by getSourceServer
-    //       (our private JMXRemoteNamespaceDelegate inner class)
-    //       implements a sun private interface (DynamicProbe) which is
-    //       used by the NamespaceInterceptor to determine whether it should
-    //       send a probe or not.
-    //       We needed this interface here because the NamespaceInterceptor
-    //       has otherwise no means to knows that this object has just
-    //       connected, and that a new probe should be sent.
-    //
-    // Probes work this way: the NamespaceInterceptor sets a flag and sends
-    // a queryNames() request. If a queryNames() request comes in when the flag
-    // is on, then it deduces that there is a self-linking loop - and instead
-    // of calling queryNames() on the JMXNamespace (which would cause the
-    // loop to go on) it breaks the recursion by returning the probe ObjectName.
-    // If the NamespaceInterceptor receives the probe ObjectName as result of
-    // its original queryNames() it knows that it has been looping back on
-    // itslef and throws an Exception - which will be raised through this
-    // method, thus preventing the connection to be established...
-    //
-    // More info in the com.sun.jmx.namespace.NamespaceInterceptor class
-    //
-    // XXX: TODO this probe thing is way too complex and fragile.
-    //      This *must* go away or be replaced by something simpler.
-    //      ideas are welcomed.
-    //
-    private void triggerProbe(final MBeanServerConnection msc)
-            throws MalformedObjectNameException, IOException {
-        // Query Pattern that we will send through the source server in order
-        // to detect self-linking namespaces.
-        //
-        //
-        final ObjectName pattern;
-        pattern = ObjectName.getInstance("*" +
-                JMXNamespaces.NAMESPACE_SEPARATOR + ":" +
-                JMXNamespace.TYPE_ASSIGNMENT);
-        probed = false;
-        try {
-            msc.queryNames(pattern, null);
-            probed = true;
-        } catch (AccessControlException x) {
-            // if we have an MBeanPermission missing then do nothing...
-            if (!(x.getPermission() instanceof MBeanPermission))
-                throw x;
-            PROBE_LOG.finer("Can't check for cycles: " + x);
-            probed = false; // no need to do it again...
-        }
+        LOG.fine("connected.");
     }
 
     public void close() throws IOException {
--- a/jdk/test/javax/management/namespace/JMXNamespaceTest.java	Fri Sep 12 17:58:15 2008 +0200
+++ b/jdk/test/javax/management/namespace/JMXNamespaceTest.java	Fri Sep 12 19:06:38 2008 +0200
@@ -35,7 +35,6 @@
  *            NamespaceController.java NamespaceControllerMBean.java
  * @run main/othervm JMXNamespaceTest
  */
-import java.io.IOException;
 import java.lang.management.ManagementFactory;
 import java.lang.management.MemoryMXBean;
 import java.lang.reflect.InvocationTargetException;
@@ -52,10 +51,10 @@
 import javax.management.JMX;
 import javax.management.MBeanServer;
 import javax.management.MBeanServerConnection;
+import javax.management.MBeanServerFactory;
 import javax.management.NotificationEmitter;
 import javax.management.ObjectInstance;
 import javax.management.ObjectName;
-import javax.management.RuntimeOperationsException;
 import javax.management.StandardMBean;
 import javax.management.namespace.JMXNamespaces;
 import javax.management.namespace.JMXNamespace;
@@ -155,7 +154,7 @@
             }
     }
 
-    private static class SimpleTestConf {
+    public static class SimpleTestConf {
         public final  Wombat wombat;
         public final  StandardMBean mbean;
         public final  String dirname;
@@ -457,259 +456,56 @@
         }
     }
 
-    /**
-     * Test cycle detection.
-     * mkdir test ; cd test ; ln -s . kanga ; ln -s kanga/kanga/roo/kanga roo
-     * touch kanga/roo/wombat
-     **/
-    public static void probeKangaRooTest(String[] args) {
-        final SimpleTestConf conf;
+    public static void verySimpleTest(String[] args) {
+        System.err.println("verySimpleTest: starting");
         try {
-            conf = new SimpleTestConf(args);
-            try {
-                final JMXServiceURL url =
-                        new JMXServiceURL("rmi","localHost",0);
-                final Map<String,Object> empty = Collections.emptyMap();
-                final JMXConnectorServer server =
-                        JMXConnectorServerFactory.newJMXConnectorServer(url,
-                        empty,conf.server);
-                server.start();
-                final JMXServiceURL address = server.getAddress();
-                final JMXConnector client =
-                        JMXConnectorFactory.connect(address,
-                        empty);
-                final String[] signature = {
-                    JMXServiceURL.class.getName(),
-                    Map.class.getName(),
-                };
-
-                final Object[] params = {
-                    address,
-                    null,
-                };
-                final MBeanServerConnection c =
-                        client.getMBeanServerConnection();
-
-                // ln -s . kanga
-                final ObjectName dirName1 =
-                        new ObjectName("kanga//:type=JMXNamespace");
-                c.createMBean(JMXRemoteTargetNamespace.class.getName(),
-                              dirName1, params,signature);
-                c.invoke(dirName1, "connect", null, null);
-                try {
-                    // ln -s kanga//kanga//roo//kanga roo
-                    final JMXNamespace local = new JMXNamespace(
-                            new MBeanServerConnectionWrapper(null,
-                            JMXNamespaceTest.class.getClassLoader()){
-
-                        @Override
-                        protected MBeanServerConnection getMBeanServerConnection() {
-                            return JMXNamespaces.narrowToNamespace(c,
-                                    "kanga//kanga//roo//kanga"
-                                    );
-                        }
-
-                    });
-                    final ObjectName dirName2 =
-                            new ObjectName("roo//:type=JMXNamespace");
-                    conf.server.registerMBean(local,dirName2);
-                    System.out.println(dirName2 + " created!");
-                    try {
-                        // touch kanga/roo/wombat
-                        final ObjectName wombatName1 =
-                                new ObjectName("kanga//roo//"+conf.wombatName);
-                        final WombatMBean wombat1 =
-                                JMX.newMBeanProxy(c,wombatName1,WombatMBean.class);
-                        final String newCaption="I am still the same old wombat";
-                        Exception x = null;
-                        try {
-                            wombat1.setCaption(newCaption);
-                        } catch (RuntimeOperationsException r) {
-                            x=r.getTargetException();
-                            System.out.println("Got expected exception: " + x);
-                            // r.printStackTrace();
-                        }
-                        if (x == null)
-                            throw new RuntimeException("cycle not detected!");
-                    } finally {
-                        c.unregisterMBean(dirName2);
-                    }
-                } finally {
-                    c.unregisterMBean(dirName1);
-                    client.close();
-                    server.stop();
-                }
-            } finally {
-                conf.close();
-            }
-            System.err.println("probeKangaRooTest PASSED");
+            final MBeanServer srv = MBeanServerFactory.createMBeanServer();
+            srv.registerMBean(new JMXNamespace(
+                    JMXNamespaces.narrowToNamespace(srv, "foo")),
+                    JMXNamespaces.getNamespaceObjectName("foo"));
+            throw new Exception("Excpected IllegalArgumentException not raised.");
+        } catch (IllegalArgumentException x) {
+            System.err.println("verySimpleTest: got expected exception: "+x);
         } catch (Exception x) {
-            System.err.println("probeKangaRooTest FAILED: " +x);
+            System.err.println("verySimpleTest FAILED: " +x);
             x.printStackTrace();
             throw new RuntimeException(x);
         }
+        System.err.println("verySimpleTest: PASSED");
     }
-    /**
-     * Test cycle detection 2.
-     * mkdir test ; cd test ; ln -s . roo ; ln -s roo/roo kanga
-     * touch kanga/roo/wombat ; rm roo ; ln -s kanga roo ;
-     * touch kanga/roo/wombat
-     *
-     **/
-    public static void probeKangaRooCycleTest(String[] args) {
-        final SimpleTestConf conf;
-        try {
-            conf = new SimpleTestConf(args);
-            Exception failed = null;
-            try {
-                final JMXServiceURL url =
-                        new JMXServiceURL("rmi","localHost",0);
-                final Map<String,Object> empty = Collections.emptyMap();
-                final JMXConnectorServer server =
-                        JMXConnectorServerFactory.newJMXConnectorServer(url,
-                        empty,conf.server);
-                server.start();
-                final JMXServiceURL address = server.getAddress();
-                final JMXConnector client =
-                        JMXConnectorFactory.connect(address,
-                        empty);
-                final String[] signature = {
-                    JMXServiceURL.class.getName(),
-                    Map.class.getName(),
-                };
-                final String[] signature2 = {
-                    JMXServiceURL.class.getName(),
-                    Map.class.getName(),
-                    String.class.getName()
-                };
-                final Object[] params = {
-                    address,
-                    Collections.emptyMap(),
-                };
-                final Object[] params2 = {
-                    address,
-                    null,
-                    "kanga",
-                };
-                final MBeanServerConnection c =
-                        client.getMBeanServerConnection();
 
-                // ln -s . roo
-                final ObjectName dirName1 =
-                        new ObjectName("roo//:type=JMXNamespace");
-                c.createMBean(JMXRemoteTargetNamespace.class.getName(),
-                              dirName1, params,signature);
-                c.invoke(dirName1, "connect",null,null);
-                try {
-                    final Map<String,Object> emptyMap =
-                            Collections.emptyMap();
-                    final JMXNamespace local = new JMXNamespace(
-                            new MBeanServerConnectionWrapper(
-                            JMXNamespaces.narrowToNamespace(c,
-                            "roo//roo//"),
-                            JMXNamespaceTest.class.getClassLoader())) {
-                    };
-                    // ln -s roo/roo kanga
-                    final ObjectName dirName2 =
-                            new ObjectName("kanga//:type=JMXNamespace");
-                    conf.server.registerMBean(local,dirName2);
-                    System.out.println(dirName2 + " created!");
-                    try {
-                        // touch kanga/roo/wombat
-                        final ObjectName wombatName1 =
-                                new ObjectName("kanga//roo//"+conf.wombatName);
-                        final WombatMBean wombat1 =
-                                JMX.newMBeanProxy(c,wombatName1,WombatMBean.class);
-                        final String newCaption="I am still the same old wombat";
-                        wombat1.setCaption(newCaption);
-                        // rm roo
-                        c.unregisterMBean(dirName1);
-                        // ln -s kanga roo
-                        System.err.println("**** Creating " + dirName1 +
-                                " ****");
-                        c.createMBean(JMXRemoteTargetNamespace.class.getName(),
-                              dirName1, params2,signature2);
-                        System.err.println("**** Created " + dirName1 +
-                                " ****");
-                        Exception x = null;
-                        try {
-                            // touch kanga/roo/wombat
-                            wombat1.setCaption(newCaption+" I hope");
-                        } catch (RuntimeOperationsException r) {
-                            x=(Exception)r.getCause();
-                            System.out.println("Got expected exception: " + x);
-                            //r.printStackTrace();
-                        }
-                        if (x == null)
-                            throw new RuntimeException("should have failed!");
-                        x = null;
-                        try {
-                            // ls kanga/roo/wombat
-                            System.err.println("**** Connecting " + dirName1 +
-                                    " ****");
-                            JMX.newMBeanProxy(c,dirName1,
-                                    JMXRemoteNamespaceMBean.class).connect();
-                            System.err.println("**** Connected " + dirName1 +
-                                    " ****");
-                        } catch (IOException r) {
-                            x=r;
-                            System.out.println("Got expected exception: " + x);
-                            //r.printStackTrace();
-                        }
-                        System.err.println("**** Expected Exception Not Raised ****");
-                        if (x == null) {
-                            System.out.println(dirName1+" contains: "+
-                                    c.queryNames(new ObjectName(
-                                    dirName1.getDomain()+"*:*"),null));
-                            throw new RuntimeException("cycle not detected!");
-                        }
-                    } catch (Exception t) {
-                        if (failed == null) failed = t;
-                    } finally {
-                            c.unregisterMBean(dirName2);
-                    }
-                } finally {
-                    try {
-                        c.unregisterMBean(dirName1);
-                    } catch (Exception t) {
-                        if (failed == null) failed = t;
-                        System.err.println("Failed to unregister "+dirName1+
-                                ": "+t);
-                    }
-                    try {
-                        client.close();
-                    } catch (Exception t) {
-                        if (failed == null) failed = t;
-                        System.err.println("Failed to close client: "+t);
-                    }
-                    try {
-                        server.stop();
-                    } catch (Exception t) {
-                        if (failed == null) failed = t;
-                        System.err.println("Failed to stop server: "+t);
-                    }
-                }
-            } finally {
-                try {
-                    conf.close();
-                } catch (Exception t) {
-                    if (failed == null) failed = t;
-                    System.err.println("Failed to stop server: "+t);
-                }
-            }
-            if (failed != null) throw failed;
-            System.err.println("probeKangaRooCycleTest PASSED");
+    public static void verySimpleTest2(String[] args) {
+        System.err.println("verySimpleTest2: starting");
+        try {
+            final MBeanServer srv = MBeanServerFactory.createMBeanServer();
+            final JMXConnectorServer cs = JMXConnectorServerFactory.
+                    newJMXConnectorServer(new JMXServiceURL("rmi",null,0),
+                    null, srv);
+            cs.start();
+            final JMXConnector cc = JMXConnectorFactory.connect(cs.getAddress());
+
+            srv.registerMBean(new JMXNamespace(
+                    new MBeanServerConnectionWrapper(
+                            JMXNamespaces.narrowToNamespace(
+                                cc.getMBeanServerConnection(),
+                                "foo"))),
+                    JMXNamespaces.getNamespaceObjectName("foo"));
+            throw new Exception("Excpected IllegalArgumentException not raised.");
+        } catch (IllegalArgumentException x) {
+            System.err.println("verySimpleTest2: got expected exception: "+x);
         } catch (Exception x) {
-            System.err.println("probeKangaRooCycleTest FAILED: " +x);
+            System.err.println("verySimpleTest2 FAILED: " +x);
             x.printStackTrace();
             throw new RuntimeException(x);
         }
+        System.err.println("verySimpleTest2: PASSED");
     }
+
     public static void main(String[] args) {
         simpleTest(args);
         recursiveTest(args);
-        probeKangaRooTest(args);
-        probeKangaRooCycleTest(args);
+        verySimpleTest(args);
+        verySimpleTest2(args);
     }
 
 }