From ca1683b0bc47b9d1cb40f54c0466c21188297d90 Mon Sep 17 00:00:00 2001 From: dfuchs Date: Fri, 12 Sep 2008 19:06:38 +0200 Subject: [PATCH] 6747983: jmx namespace: unspecified self-link detection logic Reviewed-by: emcmanus --- .../jmx/namespace/NamespaceInterceptor.java | 226 +------------- .../namespace/JMXRemoteNamespace.java | 112 +------ .../namespace/JMXNamespaceTest.java | 278 +++--------------- 3 files changed, 42 insertions(+), 574 deletions(-) diff --git a/src/share/classes/com/sun/jmx/namespace/NamespaceInterceptor.java b/src/share/classes/com/sun/jmx/namespace/NamespaceInterceptor.java index 11afeb2af..6862066d2 100644 --- a/src/share/classes/com/sun/jmx/namespace/NamespaceInterceptor.java +++ b/src/share/classes/com/sun/jmx/namespace/NamespaceInterceptor.java @@ -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 @@ import javax.management.namespace.JMXNamespacePermission; */ public class NamespaceInterceptor extends HandlerInterceptor { - 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; @@ -64,21 +55,6 @@ public class NamespaceInterceptor extends HandlerInterceptor { 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 */ @@ -100,164 +76,6 @@ public class NamespaceInterceptor extends HandlerInterceptor { ", 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 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 @@ public class NamespaceInterceptor extends HandlerInterceptor { * (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 @@ public class NamespaceInterceptor extends HandlerInterceptor { return super.source(); } - /** - * Calls {@link MBeanServerConnection#queryNames queryNames} - * on the underlying - * {@link #getMBeanServerConnection MBeanServerConnection}. - **/ - @Override - public final Set 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 { diff --git a/src/share/classes/javax/management/namespace/JMXRemoteNamespace.java b/src/share/classes/javax/management/namespace/JMXRemoteNamespace.java index 1e877e0ce..6958f57f2 100644 --- a/src/share/classes/javax/management/namespace/JMXRemoteNamespace.java +++ b/src/share/classes/javax/management/namespace/JMXRemoteNamespace.java @@ -28,11 +28,9 @@ package javax.management.namespace; 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.AttributeChangeNotification; 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 @@ public class JMXRemoteNamespace */ 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 @@ public class JMXRemoteNamespace // 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 class JMXRemoteNamespace } - public boolean isProbeRequested() { - return this.parent.isProbeRequested(); - } } private static final MBeanNotificationInfo connectNotification = @@ -201,7 +190,6 @@ public class JMXRemoteNamespace 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 @@ public class JMXRemoteNamespace // handles (dis)connection events this.listener = new ConnectionListener(); - - // XXX TODO: remove the probe, or simplify it. - this.probed = false; } /** @@ -274,10 +259,6 @@ public class JMXRemoteNamespace 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 class JMXRemoteNamespace } 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 env = new HashMap(getEnvMap()); try { @@ -652,79 +614,9 @@ public class JMXRemoteNamespace 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 { diff --git a/test/javax/management/namespace/JMXNamespaceTest.java b/test/javax/management/namespace/JMXNamespaceTest.java index 1c2ffac9d..a35377112 100644 --- a/test/javax/management/namespace/JMXNamespaceTest.java +++ b/test/javax/management/namespace/JMXNamespaceTest.java @@ -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.InvalidAttributeValueException; 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 @@ public class JMXNamespaceTest { } } - private static class SimpleTestConf { + public static class SimpleTestConf { public final Wombat wombat; public final StandardMBean mbean; public final String dirname; @@ -457,259 +456,56 @@ public class JMXNamespaceTest { } } - /** - * 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 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 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 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); } } -- GitLab