6768935: Clarify the behaviour of ObjectName pattern matching with regards to namespaces
authordfuchs
Tue, 09 Dec 2008 20:20:48 +0100
changeset 1709 392dd6db361a
parent 1708 4e1939e6e6b5
child 1711 d9d3b0002726
6768935: Clarify the behaviour of ObjectName pattern matching with regards to namespaces Reviewed-by: emcmanus
jdk/src/share/classes/com/sun/jmx/interceptor/DispatchInterceptor.java
jdk/src/share/classes/com/sun/jmx/interceptor/DomainDispatchInterceptor.java
jdk/src/share/classes/com/sun/jmx/interceptor/NamespaceDispatchInterceptor.java
jdk/src/share/classes/com/sun/jmx/mbeanserver/MXBeanLookup.java
jdk/src/share/classes/com/sun/jmx/mbeanserver/Util.java
jdk/src/share/classes/com/sun/jmx/namespace/DomainInterceptor.java
jdk/src/share/classes/com/sun/jmx/namespace/NamespaceInterceptor.java
jdk/src/share/classes/com/sun/jmx/namespace/ObjectNameRouter.java
jdk/src/share/classes/com/sun/jmx/namespace/RoutingMBeanServerConnection.java
jdk/src/share/classes/com/sun/jmx/namespace/RoutingProxy.java
jdk/src/share/classes/javax/management/MBeanServer.java
jdk/src/share/classes/javax/management/MBeanServerConnection.java
jdk/src/share/classes/javax/management/ObjectName.java
jdk/src/share/classes/javax/management/namespace/JMXDomain.java
jdk/src/share/classes/javax/management/namespace/JMXNamespacePermission.java
jdk/src/share/classes/javax/management/namespace/JMXNamespaces.java
jdk/src/share/classes/javax/management/namespace/package-info.java
jdk/test/javax/management/namespace/LeadingSeparatorsTest.java
jdk/test/javax/management/namespace/NullDomainObjectNameTest.java
jdk/test/javax/management/namespace/NullObjectNameTest.java
jdk/test/javax/management/namespace/QueryNamesTest.java
--- a/jdk/src/share/classes/com/sun/jmx/interceptor/DispatchInterceptor.java	Tue Dec 09 19:44:22 2008 +0100
+++ b/jdk/src/share/classes/com/sun/jmx/interceptor/DispatchInterceptor.java	Tue Dec 09 20:20:48 2008 +0100
@@ -44,7 +44,6 @@
 import javax.management.MBeanInfo;
 import javax.management.MBeanRegistrationException;
 import javax.management.MBeanServer;
-import javax.management.MalformedObjectNameException;
 import javax.management.NotCompliantMBeanException;
 import javax.management.NotificationFilter;
 import javax.management.NotificationListener;
@@ -205,8 +204,7 @@
 
     // Returns the ObjectName of the JMXNamespace (or JMXDomain) for that
     // key (a namespace or a domain name).
-    abstract ObjectName getHandlerNameFor(String key)
-        throws MalformedObjectNameException;
+    abstract ObjectName getHandlerNameFor(String key);
 
     // Creates an interceptor for the given key, name, JMXNamespace (or
     // JMXDomain). Note: this will be either a NamespaceInterceptor
@@ -263,14 +261,10 @@
     void validateHandlerNameFor(String key, ObjectName name) {
         if (key == null || key.equals(""))
             throw new IllegalArgumentException("invalid key for "+name+": "+key);
-        try {
-            final ObjectName handlerName = getHandlerNameFor(key);
-            if (!name.equals(handlerName))
-                throw new IllegalArgumentException("bad handler name: "+name+
-                        ". Should be: "+handlerName);
-        } catch (MalformedObjectNameException x) {
-            throw new IllegalArgumentException(name.toString(),x);
-        }
+        final ObjectName handlerName = getHandlerNameFor(key);
+        if (!name.equals(handlerName))
+            throw new IllegalArgumentException("bad handler name: "+name+
+                    ". Should be: "+handlerName);
     }
 
     // Called by the DefaultMBeanServerInterceptor when an instance
--- a/jdk/src/share/classes/com/sun/jmx/interceptor/DomainDispatchInterceptor.java	Tue Dec 09 19:44:22 2008 +0100
+++ b/jdk/src/share/classes/com/sun/jmx/interceptor/DomainDispatchInterceptor.java	Tue Dec 09 20:20:48 2008 +0100
@@ -38,7 +38,6 @@
 
 import javax.management.MBeanServer;
 import javax.management.MBeanServerDelegate;
-import javax.management.MalformedObjectNameException;
 import javax.management.ObjectName;
 import javax.management.QueryExp;
 import javax.management.namespace.JMXDomain;
@@ -248,21 +247,17 @@
         if (pattern == null) return true;
         if (pattern.isDomainPattern()) return true;
 
-        try {
-            // case b) above.
-            //
-            // This is a bit of a hack. If there's any chance that a JMXDomain
-            // MBean name is selected by the given pattern then we must include
-            // the local namespace in our search.
-            //
-            // Returning true will have this effect. see 2. above.
-            //
-            if (pattern.apply(ALL_DOMAINS.withDomain(pattern.getDomain())))
-                return true;
-        } catch (MalformedObjectNameException x) {
-            // should not happen
-            throw new IllegalArgumentException(String.valueOf(pattern), x);
-        }
+        // case b) above.
+        //
+        // This is a bit of a hack. If there's any chance that a JMXDomain
+        // MBean name is selected by the given pattern then we must include
+        // the local namespace in our search.
+        //
+        // Returning true will have this effect. see 2. above.
+        //
+        if (pattern.apply(ALL_DOMAINS.withDomain(pattern.getDomain())))
+            return true;
+
         return false;
     }
 
@@ -291,8 +286,7 @@
     }
 
     @Override
-    final ObjectName getHandlerNameFor(String key)
-        throws MalformedObjectNameException {
+    final ObjectName getHandlerNameFor(String key) {
         return JMXDomain.getDomainObjectName(key);
     }
 
--- a/jdk/src/share/classes/com/sun/jmx/interceptor/NamespaceDispatchInterceptor.java	Tue Dec 09 19:44:22 2008 +0100
+++ b/jdk/src/share/classes/com/sun/jmx/interceptor/NamespaceDispatchInterceptor.java	Tue Dec 09 20:20:48 2008 +0100
@@ -37,8 +37,8 @@
 
 import javax.management.MBeanServer;
 import javax.management.MBeanServerDelegate;
-import javax.management.MalformedObjectNameException;
 import javax.management.ObjectName;
+import javax.management.RuntimeOperationsException;
 import javax.management.namespace.JMXDomain;
 import javax.management.namespace.JMXNamespace;
 import static javax.management.namespace.JMXNamespaces.NAMESPACE_SEPARATOR;
@@ -60,6 +60,7 @@
 
     private static final int NAMESPACE_SEPARATOR_LENGTH =
             NAMESPACE_SEPARATOR.length();
+    private static final ObjectName X3 = ObjectName.valueOf("x:x=x");
 
     private final DomainDispatchInterceptor nextInterceptor;
     private final String           serverName;
@@ -89,27 +90,38 @@
            serverName = Util.getMBeanServerSecurityName(delegate);
     }
 
-    // TODO: Should move that to JMXNamespace? or to ObjectName?
     /**
      * Get first name space in ObjectName path. Ignore leading namespace
-     * separators.
+     * separators. Includes the trailing //.
+     *
+     * Examples:
+     * <pre>
+     *  For ObjectName:                   Returns:
+     *  foo//bar//baz:x=x         ->      "foo//"
+     *  foo//:type=JMXNamespace   ->      "foo//"
+     *  foo//:x=x                 ->      "foo//"
+     *  foo////:x=x               ->      "foo//"
+     *  //foo//bar//baz:x=x       ->      "//"
+     *  ////foo//bar//baz:x=x     ->      "//"
+     *  //:x=x                    ->      "//"
+     *  foo:x=x                   ->      ""
+     *  (null)                    ->      ""
+     *  :x=x                      ->      ""
+     *
+     * </pre>
      **/
-    static String getFirstNamespace(ObjectName name) {
+    static String getFirstNamespaceWithSlash(ObjectName name) {
         if (name == null) return "";
         final String domain = name.getDomain();
         if (domain.equals("")) return "";
 
-        // skip leading separators
-        int first = 0;
-        while (domain.startsWith(NAMESPACE_SEPARATOR,first))
-            first += NAMESPACE_SEPARATOR_LENGTH;
-
         // go to next separator
-        final int end = domain.indexOf(NAMESPACE_SEPARATOR,first);
+        final int end = domain.indexOf(NAMESPACE_SEPARATOR);
         if (end == -1) return ""; // no namespace
 
         // This is the first element in the namespace path.
-        final String namespace = domain.substring(first,end);
+        final String namespace =
+                domain.substring(0,end+NAMESPACE_SEPARATOR_LENGTH);
 
         return namespace;
     }
@@ -130,27 +142,49 @@
                     resource.getClass().getName());
     }
 
-    final boolean isLocalHandlerNameFor(String namespace,
-            ObjectName handlerName) {
-        return handlerName.getDomain().equals(namespace+NAMESPACE_SEPARATOR) &&
-               JMXNamespace.TYPE_ASSIGNMENT.equals(
-               handlerName.getKeyPropertyListString());
+    // Removes the trailing //. namespaceWithSlash should be either
+    // "" or a namespace path ending with //.
+    //
+    private final String getKeyFor(String namespaceWithSlash) {
+        final int end = namespaceWithSlash.length() -
+                NAMESPACE_SEPARATOR_LENGTH;
+        if (end <= 0) return "";
+        final String key = namespaceWithSlash.substring(0,end);
+        return key;
     }
 
     @Override
     final MBeanServer getInterceptorOrNullFor(ObjectName name) {
-        final String namespace = getFirstNamespace(name);
-        if (namespace.equals("") || isLocalHandlerNameFor(namespace,name) ||
-            name.getDomain().equals(namespace+NAMESPACE_SEPARATOR)) {
+        final String namespace = getFirstNamespaceWithSlash(name);
+
+        // Leading separators should trigger instance not found exception.
+        // returning null here has this effect.
+        //
+        if (namespace.equals(NAMESPACE_SEPARATOR)) {
+            LOG.finer("ObjectName starts with: "+namespace);
+            return null;
+        }
+
+        // namespace="" means that there was no namespace path in the
+        //   ObjectName. => delegate to the next interceptor (local MBS)
+        // name.getDomain()=namespace means that we have an ObjectName of
+        //   the form blah//:x=x. This is either a JMXNamespace or a non
+        //   existent MBean. => delegate to the next interceptor (local MBS)
+        if (namespace.equals("") || name.getDomain().equals(namespace)) {
             LOG.finer("dispatching to local name space");
             return nextInterceptor;
         }
-        final NamespaceInterceptor ns = getInterceptor(namespace);
+
+        // There was a namespace path in the ObjectName. Returns the
+        // interceptor that handles it, or null if there is no such
+        // interceptor.
+        final String key = getKeyFor(namespace);
+        final NamespaceInterceptor ns = getInterceptor(key);
         if (LOG.isLoggable(Level.FINER)) {
             if (ns != null) {
-                LOG.finer("dispatching to name space: " + namespace);
+                LOG.finer("dispatching to name space: " + key);
             } else {
-                LOG.finer("no handler for: " + namespace);
+                LOG.finer("no handler for: " + key);
             }
         }
         return ns;
@@ -158,18 +192,44 @@
 
     @Override
     final QueryInterceptor getInterceptorForQuery(ObjectName pattern) {
-        final String namespace = getFirstNamespace(pattern);
-        if (namespace.equals("") || isLocalHandlerNameFor(namespace,pattern) ||
-            pattern.getDomain().equals(namespace+NAMESPACE_SEPARATOR)) {
+        final String namespace = getFirstNamespaceWithSlash(pattern);
+
+        // Leading separators should trigger instance not found exception.
+        // returning null here has this effect.
+        //
+        if (namespace.equals(NAMESPACE_SEPARATOR)) {
+            LOG.finer("ObjectName starts with: "+namespace);
+            return null;
+        }
+
+        // namespace="" means that there was no namespace path in the
+        //   ObjectName. => delegate to the next interceptor (local MBS)
+        // name.getDomain()=namespace means that we have an ObjectName of
+        //   the form blah//:x=x. This is either a JMXNamespace or a non
+        //   existent MBean. => delegate to the next interceptor (local MBS)
+        if (namespace.equals("") || pattern.getDomain().equals(namespace)) {
             LOG.finer("dispatching to local name space");
             return new QueryInterceptor(nextInterceptor);
         }
-        final NamespaceInterceptor ns = getInterceptor(namespace);
+
+        // This is a 'hack' to check whether the first namespace is a pattern.
+        // We wan to throw RTOE wrapping IAE in that case
+        if (X3.withDomain(namespace).isDomainPattern()) {
+            throw new RuntimeOperationsException(
+                new IllegalArgumentException("Pattern not allowed in namespace path"));
+        }
+
+        // There was a namespace path in the ObjectName. Returns the
+        // interceptor that handles it, or null if there is no such
+        // interceptor.
+        //
+        final String key = getKeyFor(namespace);
+        final NamespaceInterceptor ns = getInterceptor(key);
         if (LOG.isLoggable(Level.FINER)) {
             if (ns != null) {
-                LOG.finer("dispatching to name space: " + namespace);
+                LOG.finer("dispatching to name space: " + key);
             } else {
-                LOG.finer("no handler for: " + namespace);
+                LOG.finer("no handler for: " + key);
             }
         }
         if (ns == null) return null;
@@ -177,15 +237,16 @@
     }
 
     @Override
-    final ObjectName getHandlerNameFor(String key)
-        throws MalformedObjectNameException {
-        return ObjectName.getInstance(key+NAMESPACE_SEPARATOR,
+    final ObjectName getHandlerNameFor(String key) {
+        return ObjectName.valueOf(key+NAMESPACE_SEPARATOR,
                     "type", JMXNamespace.TYPE);
     }
 
     @Override
     final public String getHandlerKey(ObjectName name) {
-        return getFirstNamespace(name);
+        final String namespace = getFirstNamespaceWithSlash(name);
+        // namespace is either "" or a namespace ending with //
+        return getKeyFor(namespace);
     }
 
     @Override
--- a/jdk/src/share/classes/com/sun/jmx/mbeanserver/MXBeanLookup.java	Tue Dec 09 19:44:22 2008 +0100
+++ b/jdk/src/share/classes/com/sun/jmx/mbeanserver/MXBeanLookup.java	Tue Dec 09 20:20:48 2008 +0100
@@ -37,7 +37,6 @@
 import javax.management.JMX;
 import javax.management.MBeanServerConnection;
 import javax.management.MBeanServerInvocationHandler;
-import javax.management.MalformedObjectNameException;
 import javax.management.ObjectName;
 import javax.management.openmbean.OpenDataException;
 
@@ -225,7 +224,7 @@
             String domain = prefix + name.getDomain();
             try {
                 name = name.withDomain(domain);
-            } catch (MalformedObjectNameException e) {
+            } catch (IllegalArgumentException e) {
                 throw EnvHelp.initCause(
                         new InvalidObjectException(e.getMessage()), e);
             }
@@ -239,12 +238,14 @@
             String domain = name.getDomain();
             if (!domain.startsWith(prefix)) {
                 throw new OpenDataException(
-                        "Proxy's name does not start with " + prefix + ": " + name);
+                        "Proxy's name does not start with " +
+                        prefix + ": " + name);
             }
             try {
                 name = name.withDomain(domain.substring(prefix.length()));
-            } catch (MalformedObjectNameException e) {
-                throw EnvHelp.initCause(new OpenDataException(e.getMessage()), e);
+            } catch (IllegalArgumentException e) {
+                throw EnvHelp.initCause(
+                        new OpenDataException(e.getMessage()), e);
             }
             return name;
         }
--- a/jdk/src/share/classes/com/sun/jmx/mbeanserver/Util.java	Tue Dec 09 19:44:22 2008 +0100
+++ b/jdk/src/share/classes/com/sun/jmx/mbeanserver/Util.java	Tue Dec 09 20:20:48 2008 +0100
@@ -48,7 +48,6 @@
 import javax.management.MBeanServer;
 import javax.management.MBeanServerDelegate;
 import javax.management.MBeanServerFactory;
-import javax.management.MalformedObjectNameException;
 import javax.management.ObjectInstance;
 import javax.management.ObjectName;
 import javax.management.loading.ClassLoaderRepository;
--- a/jdk/src/share/classes/com/sun/jmx/namespace/DomainInterceptor.java	Tue Dec 09 19:44:22 2008 +0100
+++ b/jdk/src/share/classes/com/sun/jmx/namespace/DomainInterceptor.java	Tue Dec 09 20:20:48 2008 +0100
@@ -42,7 +42,6 @@
 import javax.management.MBeanPermission;
 import javax.management.MBeanServerDelegate;
 import javax.management.MBeanServerNotification;
-import javax.management.MalformedObjectNameException;
 import javax.management.Notification;
 import javax.management.NotificationFilter;
 import javax.management.NotificationListener;
@@ -268,13 +267,9 @@
     // When we reach here, it has been verified that 'name' matches our domain
     // name (done by DomainDispatchInterceptor)
     private ObjectName getPatternFor(final ObjectName name) {
-        try {
-            if (name == null) return ALL;
-            if (name.getDomain().equals(domainName)) return name;
-            return name.withDomain(domainName);
-        } catch (MalformedObjectNameException x) {
-            throw new IllegalArgumentException(String.valueOf(name),x);
-        }
+        if (name == null) return ALL;
+        if (name.getDomain().equals(domainName)) return name;
+        return name.withDomain(domainName);
    }
 
     @Override
--- a/jdk/src/share/classes/com/sun/jmx/namespace/NamespaceInterceptor.java	Tue Dec 09 19:44:22 2008 +0100
+++ b/jdk/src/share/classes/com/sun/jmx/namespace/NamespaceInterceptor.java	Tue Dec 09 20:20:48 2008 +0100
@@ -24,15 +24,12 @@
  */
 package com.sun.jmx.namespace;
 
-import com.sun.jmx.defaults.JmxProperties;
 import java.util.ArrayList;
 import java.util.List;
-import java.util.logging.Logger;
 
 import javax.management.Attribute;
 import javax.management.AttributeList;
 import javax.management.MBeanServer;
-import javax.management.MalformedObjectNameException;
 import javax.management.ObjectName;
 import javax.management.namespace.JMXNamespace;
 import javax.management.namespace.JMXNamespacePermission;
@@ -114,14 +111,12 @@
     }
 
     @Override
-    protected ObjectName toSource(ObjectName targetName)
-            throws MalformedObjectNameException {
+    protected ObjectName toSource(ObjectName targetName) {
         return proc.toSourceContext(targetName, true);
     }
 
     @Override
-    protected ObjectName toTarget(ObjectName sourceName)
-            throws MalformedObjectNameException {
+    protected ObjectName toTarget(ObjectName sourceName) {
         return proc.toTargetContext(sourceName, false);
     }
 
--- a/jdk/src/share/classes/com/sun/jmx/namespace/ObjectNameRouter.java	Tue Dec 09 19:44:22 2008 +0100
+++ b/jdk/src/share/classes/com/sun/jmx/namespace/ObjectNameRouter.java	Tue Dec 09 20:20:48 2008 +0100
@@ -27,7 +27,6 @@
 
 import static javax.management.namespace.JMXNamespaces.NAMESPACE_SEPARATOR;
 
-import javax.management.MalformedObjectNameException;
 import javax.management.ObjectInstance;
 import javax.management.ObjectName;
 
@@ -83,11 +82,7 @@
         }
         final String targetDomain =
                 (tlen>0?targetPrefix+NAMESPACE_SEPARATOR+srcDomain:srcDomain);
-        try {
-            return sourceName.withDomain(targetDomain);
-        } catch (MalformedObjectNameException x) {
-            throw new IllegalArgumentException(String.valueOf(sourceName),x);
-        }
+        return sourceName.withDomain(targetDomain);
     }
 
     public final ObjectName toSourceContext(ObjectName targetName,
@@ -113,11 +108,7 @@
         final String sourceDomain =
                 (slen>0?sourcePrefix+NAMESPACE_SEPARATOR+targetDomain:
                     targetDomain);
-        try {
-            return targetName.withDomain(sourceDomain);
-        } catch (MalformedObjectNameException x) {
-            throw new IllegalArgumentException(String.valueOf(targetName),x);
-        }
+        return targetName.withDomain(sourceDomain);
     }
 
     public final ObjectInstance toTargetContext(ObjectInstance sourceMoi,
--- a/jdk/src/share/classes/com/sun/jmx/namespace/RoutingMBeanServerConnection.java	Tue Dec 09 19:44:22 2008 +0100
+++ b/jdk/src/share/classes/com/sun/jmx/namespace/RoutingMBeanServerConnection.java	Tue Dec 09 20:20:48 2008 +0100
@@ -46,7 +46,6 @@
 import javax.management.MBeanInfo;
 import javax.management.MBeanRegistrationException;
 import javax.management.MBeanServerConnection;
-import javax.management.MalformedObjectNameException;
 import javax.management.NotCompliantMBeanException;
 import javax.management.NotificationFilter;
 import javax.management.NotificationListener;
@@ -100,18 +99,17 @@
      * the target name is "foo//X".
      * In the case of cascading - such as in NamespaceInterceptor, this method
      * will convert "foo//X" (the targetName) into "X", the source name.
+     * @throws IllegalArgumentException if the name cannot be converted.
      **/
-    protected abstract ObjectName toSource(ObjectName targetName)
-        throws MalformedObjectNameException;
-
+    protected abstract ObjectName toSource(ObjectName targetName);
     /**
      * Converts a source ObjectName to a target ObjectName.
      * (see description of toSource above for explanations)
      * In the case of cascading - such as in NamespaceInterceptor, this method
      * will convert "X" (the sourceName) into "foo//X", the target name.
+     * @throws IllegalArgumentException if the name cannot be converted.
      **/
-    protected abstract ObjectName toTarget(ObjectName sourceName)
-        throws MalformedObjectNameException;
+    protected abstract ObjectName toTarget(ObjectName sourceName);
 
     /**
      * Can be overridden by subclasses to check the validity of a new
@@ -128,17 +126,12 @@
         }
     }
 
-    // Calls toSource(), Wraps MalformedObjectNameException.
-    ObjectName toSourceOrRuntime(ObjectName targetName)
-        throws RuntimeOperationsException {
+    // Calls toSource(), Wraps IllegalArgumentException.
+    ObjectName toSourceOrRuntime(ObjectName targetName) {
         try {
             return toSource(targetName);
-        } catch (MalformedObjectNameException x) {
-            final IllegalArgumentException x2 =
-                    new IllegalArgumentException(String.valueOf(targetName),x);
-            final RuntimeOperationsException x3 =
-                    new RuntimeOperationsException(x2);
-            throw x3;
+        } catch (RuntimeException x) {
+            throw makeCompliantRuntimeException(x);
         }
     }
 
@@ -376,12 +369,8 @@
         try {
             final ObjectName targetName = toTarget(sourceName);
             return new ObjectInstance(targetName,source.getClassName());
-        } catch (MalformedObjectNameException x) {
-            final IllegalArgumentException x2 =
-                    new IllegalArgumentException(String.valueOf(sourceName),x);
-            final RuntimeOperationsException x3 =
-                    new RuntimeOperationsException(x2);
-            throw x3;
+        } catch (RuntimeException x) {
+            throw makeCompliantRuntimeException(x);
         }
     }
 
--- a/jdk/src/share/classes/com/sun/jmx/namespace/RoutingProxy.java	Tue Dec 09 19:44:22 2008 +0100
+++ b/jdk/src/share/classes/com/sun/jmx/namespace/RoutingProxy.java	Tue Dec 09 20:20:48 2008 +0100
@@ -199,8 +199,7 @@
     public T source() { return source; }
 
     @Override
-    public ObjectName toSource(ObjectName targetName)
-        throws MalformedObjectNameException {
+    public ObjectName toSource(ObjectName targetName) {
         if (targetName == null) return null;
         if (targetName.getDomain().equals("") && targetNs.equals("")) {
             try {
@@ -229,8 +228,7 @@
     }
 
     @Override
-    public ObjectName toTarget(ObjectName sourceName)
-        throws MalformedObjectNameException {
+    public ObjectName toTarget(ObjectName sourceName) {
         if (sourceName == null) return null;
         return router.toTargetContext(sourceName,false);
     }
--- a/jdk/src/share/classes/javax/management/MBeanServer.java	Tue Dec 09 19:44:22 2008 +0100
+++ b/jdk/src/share/classes/javax/management/MBeanServer.java	Tue Dec 09 20:20:48 2008 +0100
@@ -424,10 +424,16 @@
     public ObjectInstance getObjectInstance(ObjectName name)
             throws InstanceNotFoundException;
 
-    // doc comment inherited from MBeanServerConnection
+    /**
+     * {@inheritDoc}
+      * @throws RuntimeOperationsException {@inheritDoc}
+     */
     public Set<ObjectInstance> queryMBeans(ObjectName name, QueryExp query);
 
-    // doc comment inherited from MBeanServerConnection
+    /**
+     * {@inheritDoc}
+      * @throws RuntimeOperationsException {@inheritDoc}
+    */
     public Set<ObjectName> queryNames(ObjectName name, QueryExp query);
 
     // doc comment inherited from MBeanServerConnection
--- a/jdk/src/share/classes/javax/management/MBeanServerConnection.java	Tue Dec 09 19:44:22 2008 +0100
+++ b/jdk/src/share/classes/javax/management/MBeanServerConnection.java	Tue Dec 09 20:20:48 2008 +0100
@@ -436,7 +436,17 @@
      * specified, all the MBeans registered will be retrieved.
      * @param query The query expression to be applied for selecting
      * MBeans. If null no query expression will be applied for
-     * selecting MBeans.
+     * selecting MBeans.  ObjectName patterns that may be contained in the
+     * query expression will be
+     * <a href="namespace/package-summary.html#NamespaceAndQueries"><!--
+     * -->evaluated</a> in the context of the
+     * {@link javax.management.namespace namespace}
+     * in which the MBeans selected by {@code name} are registered.
+     * Thus, in the {@code query} parameter, no ObjectName pattern containing a
+     * namespace path can match any of the MBean names selected by {@code name}.
+     * See the
+     * <a href="namespace/package-summary.html#RejectedNamespacePatterns"><!--
+     * -->namespaces documentation</a> for more details.
      *
      * @return A set containing the <CODE>ObjectInstance</CODE>
      * objects for the selected MBeans.  If no MBean satisfies the
@@ -444,6 +454,11 @@
      *
      * @exception IOException A communication problem occurred when
      * talking to the MBean server.
+     * @exception RuntimeOperationsException Wraps a
+     * <CODE>java.lang.IllegalArgumentException</CODE>: The <em>name</em>
+     * parameter contains an invalid pattern. See the
+     * <a href="namespace/package-summary.html#RejectedNamespacePatterns"><!--
+     * -->namespaces documentation</a> for more details.
      */
     public Set<ObjectInstance> queryMBeans(ObjectName name, QueryExp query)
             throws IOException;
@@ -464,7 +479,17 @@
      * specified, the name of all registered MBeans will be retrieved.
      * @param query The query expression to be applied for selecting
      * MBeans. If null no query expression will be applied for
-     * selecting MBeans.
+     * selecting MBeans. ObjectName patterns that may be contained in the
+     * query expression will be
+     * <a href="namespace/package-summary.html#NamespaceAndQueries"><!--
+     * -->evaluated</a> in the context of the
+     * {@link javax.management.namespace namespace}
+     * in which the MBeans slected by {@code name} are registered.
+     * Thus, in the {@code query} parameter, no ObjectName pattern containing a
+     * namespace path can match any of the MBean names selected by {@code name}.
+     * See the
+     * <a href="namespace/package-summary.html#RejectedNamespacePatterns"><!--
+     * -->namespaces documentation</a> for more details.
      *
      * @return A set containing the ObjectNames for the MBeans
      * selected.  If no MBean satisfies the query, an empty list is
@@ -472,6 +497,11 @@
      *
      * @exception IOException A communication problem occurred when
      * talking to the MBean server.
+     * @exception RuntimeOperationsException Wraps a
+     * <CODE>java.lang.IllegalArgumentException</CODE>: The <em>name</em>
+     * parameter contains an invalid pattern. See the
+     * <a href="namespace/package-summary.html#RejectedNamespacePatterns"><!--
+     * -->namespaces documentation</a> for more details.
      */
     public Set<ObjectName> queryNames(ObjectName name, QueryExp query)
             throws IOException;
--- a/jdk/src/share/classes/javax/management/ObjectName.java	Tue Dec 09 19:44:22 2008 +0100
+++ b/jdk/src/share/classes/javax/management/ObjectName.java	Tue Dec 09 20:20:48 2008 +0100
@@ -56,14 +56,38 @@
  * properties.</p>
  *
  * <p>The <em>domain</em> is a string of characters not including
- * the character colon (<code>:</code>).  It is recommended that the domain
- * should not contain the string "{@code //}", which is reserved for future use.
+ * the character colon (<code>:</code>).</p>
+ * <p>Starting with the version 2.0 of the JMX specification, the
+ * <em>domain</em> can also start with a {@linkplain
+ * javax.management.namespace#NamespacePrefix namespace prefix} identifying
+ * the {@linkplain javax.management.namespace namespace} in which the
+ * MBean is registered. A namespace prefix is a path string where
+ * elements are separated by a double slash (<code>//</code>).
+ * It identifies the {@linkplain  javax.management.namespace namespace} in
+ * which the MBean so named is registered.</p>
+ *
+ * <p>For instance the ObjectName <em>bar//baz:k=v</em> identifiies an MBean
+ * named <em>baz:k=v</em> in the namespace <em>bar</em>. Similarly the
+ * ObjectName <em>foo//bar//baz:k=v</em> identifiies an MBean named
+ * <em>baz:k=v</em> in the namespace <em>foo//bar</em>. See the {@linkplain
+ * javax.management.namespace namespace} documentation for more details.</p>
  *
  * <p>If the domain includes at least one occurrence of the wildcard
  * characters asterisk (<code>*</code>) or question mark
  * (<code>?</code>), then the object name is a pattern.  The asterisk
  * matches any sequence of zero or more characters, while the question
- * mark matches any single character.</p>
+ * mark matches any single character. <br>
+ * A namespace separator <code>//</code> does not match wildcard
+ * characters unless it is at the very end of the domain string.
+ * So <em>foo*bar*:*</em> does not match <em>foo//bar:k=v</em> but it
+ * does match <em>fooxbar//:k=v</em>.
+ * </p>
+ *
+ * <p>When included in a namespace path the special path element
+ * <code>**</code> matches any number of sub namespaces
+ * recursively, but only if used as a complete namespace path element,
+ * as in <code>*&#42;//b//c//D:k=v</code> or <code>a//*&#42;//c//D:k=v</code>
+ * - see <a href="#metawildcard">below</a>.
  *
  * <p>If the domain is empty, it will be replaced in certain contexts
  * by the <em>default domain</em> of the MBean server in which the
@@ -171,6 +195,51 @@
  *     with {@code \}.</li>
  * </ul>
  *
+ * <p id="metawildcard"><b>Pattern and namespaces:</b></p>
+ * <p>In an object name pattern, a path element
+ *    of exactly <code>**</code> corresponds to a meta
+ *    wildcard that will match any number of sub namespaces.<br>Hence:</p>
+ * <table border="0" cellpadding="5">
+ * <thead><th>pattern</th><th>matches</th><th>doesn't match</th></thead>
+ * <tbody>
+ * <tr><td><ul><li><code>*&#42;//D:k=v</code></li></ul></td>
+ *     <td><code>a//D:k=v</code><br>
+ *         <code>a//b//D:k=v</code><br>
+ *         <code>a//b//c//D:k=v</code></td>
+ *     <td><code>D:k=v</code></td></tr>
+ * <tr><td><ul><li><code>a//*&#42;//D:k=v</code></li></ul></td>
+ *     <td><code>a//b//D:k=v</code><br>
+ *         <code>a//b//c//D:k=v</code></td>
+ *     <td><code>b//b//c//D:k=v</code><br>
+ *         <code>a//D:k=v</code><br>
+ *         <code>D:k=v</code></td></tr>
+ * <tr><td><ul><li><code>a//*&#42;//e//D:k=v</code></li></ul></td>
+ *     <td><code>a//b//e//D:k=v</code><br>
+ *         <code>a//b//c//e//D:k=v</code></td>
+ *     <td><code>a//b//c//c//D:k=v</code><br>
+ *         <code>b//b//c//e//D:k=v</code><br>
+ *         <code>a//e//D:k=v</code><br>
+ *         <code>e//D:k=v</code></td></tr>
+ * <tr><td><ul><li><code>a//b*&#42;//e//D:k=v</code></li></ul></td>
+ *      <td><code>a//b//e//D:k=v</code></td>
+ *      <td><code>a//b//c//e//D:k=v</code><br>
+ *          because in that case <code>b*&#42;</code><br>
+ *         is not a meta-wildcard - and <code>b**</code><br>
+ *         is thus equivalent to <code>b*</code>.</td></tr>
+ * </tbody>
+ * </table>
+ *</ul>
+ * </p>
+ * <p>
+ * <b>Note:</b> Although ObjectName patterns where the characters
+ * <code>*</code> and <code>?</code> appear in the namespace path are legal,
+ * they are not valid in the {@code name} parameter of the MBean Server's
+ * {@link MBeanServer#queryNames queryNames} and {@link MBeanServer#queryMBeans
+ * queryMBeans} methods. See the
+ * <a href="namespace/package-summary.html#RejectedNamespacePatterns"><!--
+ * -->namespaces documentation</a> for more details.
+ * </p>
+ *
  * <p>An ObjectName can be written as a String with the following
  * elements in order:</p>
  *
@@ -439,11 +508,6 @@
         _propertyList = aname._propertyList;
         _property_list_pattern = aname._property_list_pattern;
         _property_value_pattern = aname._property_value_pattern;
-        // TODO remove this hack
-        // if (toString().endsWith("//javax.management.service:type1=event_client_delegeate_mbean,type2=default")) {
-        //    Thread.currentThread().dumpStack();
-        //    throw new Error("************************ Gotcha!");
-        //}
     }
 
     // Instance private fields <=======================================
@@ -1096,11 +1160,10 @@
      */
     private boolean isDomain(String domain) {
         if (domain == null) return true;
-        final char[] d=domain.toCharArray();
-        final int len = d.length;
+        final int len = domain.length();
         int next = 0;
         while (next < len) {
-            final char c = d[next++];
+            final char c = domain.charAt(next++);
             switch (c) {
                 case ':' :
                 case '\n' :
@@ -1234,12 +1297,6 @@
         if (!nw.equals("")) {
             nameString = nw + NAMESPACE_SEPARATOR + nameString;
         }
-        // TODO remove this hack
-        // if (nameString.endsWith("//javax.management.service:type1=event_client_delegeate_mbean,type2=default")) {
-        //    System.err.println("old="+old+", nw="+nw);
-        //    Thread.currentThread().dumpStack();
-        //    throw new Error("************************ Gotcha!");
-        // }
         return nameString;
     }
 
@@ -1584,13 +1641,18 @@
      * @return A new {@code ObjectName} that is the same as {@code this}
      *         except the domain is {@code newDomain}.
      * @throws NullPointerException if {@code newDomain} is null.
-     * @throws MalformedObjectNameException if the new domain is syntactically
-     *         illegal.
+     * @exception IllegalArgumentException The {@code newDomain} passed as a
+     * parameter does not have the right format.  The {@linkplain
+     * Throwable#getCause() cause} of this exception will be a
+     * {@link MalformedObjectNameException}.
      * @since 1.7
      **/
-    public final ObjectName withDomain(String newDomain)
-            throws MalformedObjectNameException {
-        return new ObjectName(newDomain, this);
+    public final ObjectName withDomain(String newDomain) {
+        try {
+            return new ObjectName(newDomain, this);
+        } catch (MalformedObjectNameException x) {
+            throw new IllegalArgumentException(x.getMessage(),x);
+        }
     }
 
     /**
--- a/jdk/src/share/classes/javax/management/namespace/JMXDomain.java	Tue Dec 09 19:44:22 2008 +0100
+++ b/jdk/src/share/classes/javax/management/namespace/JMXDomain.java	Tue Dec 09 20:20:48 2008 +0100
@@ -35,7 +35,6 @@
 import javax.management.InstanceNotFoundException;
 import javax.management.MBeanServer;
 import javax.management.MBeanServerDelegate;
-import javax.management.MalformedObjectNameException;
 import javax.management.ObjectName;
 
 /**
@@ -291,12 +290,9 @@
     public static ObjectName getDomainObjectName(String domain) {
         if (domain == null) return null;
         if (domain.contains(NAMESPACE_SEPARATOR))
-            throw new IllegalArgumentException(domain);
-        try {
-            return ObjectName.getInstance(domain, "type", TYPE);
-        } catch (MalformedObjectNameException x) {
-            throw new IllegalArgumentException(domain,x);
-        }
+            throw new IllegalArgumentException("domain contains " +
+                    NAMESPACE_SEPARATOR+": "+domain);
+        return ObjectName.valueOf(domain, "type", TYPE);
     }
 
 
--- a/jdk/src/share/classes/javax/management/namespace/JMXNamespacePermission.java	Tue Dec 09 19:44:22 2008 +0100
+++ b/jdk/src/share/classes/javax/management/namespace/JMXNamespacePermission.java	Tue Dec 09 20:20:48 2008 +0100
@@ -136,7 +136,8 @@
  * <code>**</code> matches any number of sub namespaces
  * recursively, but only if used as a complete namespace path element,
  * as in <code>*&#42;//b//c//D:k=v</code> or <code>a//*&#42;//c//D:k=v</code>
- * - see <a href="#metawildcard">below</a>.
+ * - see ObjectName <a href="../ObjectName.html#metawildcard">documentation</a>
+ * for more details.
  * </p>
  *
  *
@@ -270,38 +271,9 @@
  * </pre>
  * <p><b>Note on wildcards:</b> In an object name pattern, a path element
  *    of exactly <code>**</code> corresponds to a meta
- *    wildcard that will match any number of sub namespaces. Hence:</p>
- * <ul>
- * <table border="1">
- * <thead><th>pattern</th><th>matches</th><th>doesn't match</th></thead>
- * <tbody>
- * <tr><td><code>*&#42;//D:k=v</code></td>
- *     <td><code>a//D:k=v</code><br>
- *         <code>a//b//D:k=v</code><br>
- *         <code>a//b//c//D:k=v</code></td>
- *     <td><code>D:k=v</code></td></tr>
- * <tr><td><code>a//*&#42;//D:k=v</code></td>
- *     <td><code>a//b//D:k=v</code><br>
- *         <code>a//b//c//D:k=v</code></td>
- *     <td><code>b//b//c//D:k=v</code><br>
- *         <code>a//D:k=v</code><br>
- *         <code>D:k=v</code></td></tr>
- * <tr><td><code>a//*&#42;//e//D:k=v</code></td>
- *     <td><code>a//b//e//D:k=v</code><br>
- *         <code>a//b//c//e//D:k=v</code></td>
- *     <td><code>a//b//c//c//D:k=v</code><br>
- *         <code>b//b//c//e//D:k=v</code><br>
- *         <code>a//e//D:k=v</code><br>
- *         <code>e//D:k=v</code></td></tr>
- * <tr><td><code>a//b*&#42;//e//D:k=v</code></td>
- *      <td><code>a//b//e//D:k=v</code></td>
- *      <td><code>a//b//c//e//D:k=v</code><br>
- *          because in that case <code>b*&#42;</code><br>
- *         is not a meta-wildcard - and <code>b**</code><br>
- *         is thus equivalent to <code>b*</code>.</td></tr>
- * </tbody>
- * </table>
- *</ul>
+ *    wildcard that will match any number of sub namespaces.
+ *    See ObjectName <a href="../ObjectName.html#metawildcard">documentation</a>
+ *    for more details.</p>
  *
  * <p>If {@code <mbean server name>::} is omitted, then one of
  * <code>member</code> or <code>object name</code> may be omitted.
--- a/jdk/src/share/classes/javax/management/namespace/JMXNamespaces.java	Tue Dec 09 19:44:22 2008 +0100
+++ b/jdk/src/share/classes/javax/management/namespace/JMXNamespaces.java	Tue Dec 09 20:20:48 2008 +0100
@@ -292,17 +292,13 @@
         if (path == null || to == null)
             throw new IllegalArgumentException("Null argument");
         checkTrailingSlashes(path);
-        try {
-            String prefix = path;
-            if (!prefix.equals("")) prefix =
-                    ObjectNameRouter.normalizeNamespacePath(
+        String prefix = path;
+        if (!prefix.equals(""))
+            prefix = ObjectNameRouter.normalizeNamespacePath(
                         prefix + NAMESPACE_SEPARATOR,false,false,false);
-            return to.withDomain(
+         return to.withDomain(
                     ObjectNameRouter.normalizeDomain(
                         prefix+to.getDomain(),false));
-        } catch (MalformedObjectNameException x) {
-            throw new IllegalArgumentException(path+": "+x,x);
-        }
     }
 
     /**
--- a/jdk/src/share/classes/javax/management/namespace/package-info.java	Tue Dec 09 19:44:22 2008 +0100
+++ b/jdk/src/share/classes/javax/management/namespace/package-info.java	Tue Dec 09 20:20:48 2008 +0100
@@ -204,7 +204,38 @@
  *      </pre>
  *      An easier way to access MBeans contained in a name space is to
  *      <i>cd</i> inside the name space, as shown in the following paragraph.
- *  </p>
+ *  </p><p id="RejectedNamespacePatterns">
+ *      Although ObjectName patterns where the characters
+ *      <code>*</code> and <code>?</code> appear in the namespace path are
+ *      legal, they are not valid in the {@code name} parameter of the
+ *      MBean Server {@link
+ *      javax.management.MBeanServer#queryNames queryNames} and {@link
+ *      javax.management.MBeanServer#queryMBeans queryMBeans} methods.<br>
+ *      When invoking <code>queryNames</code> or  <code>queryMBeans</code>,
+ *      only ObjectNames of the form:<br>
+ *      [<em>namespace-without-pattern</em>//]*[<em>pattern-without-namespace</em>]:<em>key-properties-with-or-without-pattern</em>
+ *      are valid.<br>
+ *      In other words: in the case of {@link
+ *      javax.management.MBeanServer#queryNames queryNames} and {@link
+ *      javax.management.MBeanServer#queryMBeans queryMBeans}, if a
+ *      namespace path is present, it must not contain any pattern.
+ *  </p><p id="NamespaceAndQueries">
+ *      There is no such restriction for the {@code query} parameter of these
+ *      methods. However, it must be noted that the {@code query} parameter
+ *      will be evaluated in the context of the namespace where the MBeans
+ *      selected by the pattern specified in {@code name} are located.
+ *      This means that if {@code query} parameter is an ObjectName pattern that
+ *      contains a namespace path, no MBean name will match and the result of
+ *      the query will be empty.<br>
+ *      In other words:</p>
+ * <ul><li>{@code queryNames("foo//bar//?a?:*","b?z:type=Monitor,*")} will select
+ *         all MBeans in namespace <em>foo//bar</em> whose names match both
+ *         <em>?a?:*</em> and <em>b?z:type=Monitor,*</em>, but</li>
+ *     <li>{@code queryNames("foo//bar//?a?:*","foo//bar//b?z:type=Monitor,*")}
+ *         will select nothing because no name matching <em>?a?:*</em> will
+ *         also match <em>foo//bar//b?z:type=Monitor,*</em>.
+ *     </li>
+ *  </ul>
  *
  *  <h3 id="ChangeTo">Narrowing Down Into a Name Spaces</h3>
  *  <p>
@@ -228,7 +259,8 @@
  *      to name space {@code "foo"} behaves just like a regular MBean server.
  *      However, it may sometimes throw an {@link
  *      java.lang.UnsupportedOperationException UnsupportedOperationException}
- *      wrapped in a JMX exception if you try to call an operation which is not
+ *      wrapped in a {@link javax.management.RuntimeOperationsException
+ *      RuntimeOperationsException} if you try to call an operation which is not
  *      supported by the underlying name space handler.
  *      <br>For instance, {@link javax.management.MBeanServer#registerMBean
  *      registerMBean} is not supported for name spaces mounted from remote
--- a/jdk/test/javax/management/namespace/LeadingSeparatorsTest.java	Tue Dec 09 19:44:22 2008 +0100
+++ b/jdk/test/javax/management/namespace/LeadingSeparatorsTest.java	Tue Dec 09 20:20:48 2008 +0100
@@ -24,7 +24,7 @@
  * @test LeadingSeparatorsTest.java
  * @summary Test that the semantics of a leading // in ObjectName is respected.
  * @author Daniel Fuchs
- * @bug 5072476
+ * @bug 5072476 6768935
  * @run clean LeadingSeparatorsTest Wombat WombatMBean
  * @compile -XDignore.symbol.file=true  LeadingSeparatorsTest.java
  * @run build LeadingSeparatorsTest Wombat WombatMBean
@@ -36,6 +36,7 @@
 import java.util.Set;
 import java.util.HashSet;
 import java.util.logging.Logger;
+import javax.management.InstanceNotFoundException;
 import javax.management.MBeanServer;
 import javax.management.MBeanServerFactory;
 import javax.management.NotCompliantMBeanException;
@@ -121,19 +122,29 @@
             // register wombat using an object name with a leading //
             final Object     obj = new MyWombat();
             // check that returned object name doesn't have the leading //
-            assertEquals(n2,top.registerMBean(obj, n1).getObjectName());
+            assertEquals(n2,top.registerMBean(obj, n2).getObjectName());
             System.out.println(n1+" registered");
 
             // check that the registered Wombat can be accessed with all its
             // names.
             System.out.println(n2+" mood is: "+top.getAttribute(n2, "Mood"));
-            System.out.println(n1+" mood is: "+top.getAttribute(n1, "Mood"));
+            try {
+                System.out.println(n1+" mood is: "+top.getAttribute(n1, "Mood"));
+                throw new Exception("Excepected exception not thrown for "+n1);
+            } catch (InstanceNotFoundException x) {
+                System.out.println("OK: "+x);
+            }
             System.out.println(n4+" mood is: "+top.getAttribute(n4, "Mood"));
-            System.out.println(n3+" mood is: "+top.getAttribute(n3, "Mood"));
+            try {
+                System.out.println(n3+" mood is: "+top.getAttribute(n3, "Mood"));
+                throw new Exception("Excepected exception not thrown for "+n3);
+            } catch (InstanceNotFoundException x) {
+                System.out.println("OK: "+x);
+            }
 
             // call listMatching. The result should not contain any prefix.
             final Set<ObjectName> res = (Set<ObjectName>)
-                    top.invoke(n3, "listMatching",
+                    top.invoke(n4, "listMatching",
                     // remove rmi// from rmi//*:*
                     JMXNamespaces.deepReplaceHeadNamespace(
                     new Object[] {ObjectName.WILDCARD.withDomain("rmi//*")},
@@ -158,7 +169,7 @@
             // //niark//niark//
             //
             final Set<ObjectName> res4 = (Set<ObjectName>)
-                    top.invoke(n3, "untrue",
+                    top.invoke(n4, "untrue",
                     // remove niark//niark : should remove nothing since
                     // our ObjectName begins with a leading //
                     JMXNamespaces.deepReplaceHeadNamespace(
--- a/jdk/test/javax/management/namespace/NullDomainObjectNameTest.java	Tue Dec 09 19:44:22 2008 +0100
+++ b/jdk/test/javax/management/namespace/NullDomainObjectNameTest.java	Tue Dec 09 20:20:48 2008 +0100
@@ -40,6 +40,7 @@
 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;
@@ -215,9 +216,20 @@
                 assertEquals(proxy.queryNames(
                         new ObjectName(":*"),null).
                         contains(moi3.getObjectName()),true);
-                failed("queryNames(null,null) should have failed for faked//");
-            } catch (IllegalArgumentException x) {
-                System.out.println("Received expected exception for faked//: "+x);
+                failed("queryNames(new ObjectName(\":*\"),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(new ObjectName(\":*\"),null)" +
+                            " failed with unexpected cause for faked//");
+                }
             }
             // These should fail because the ObjectName doesn't start
             // with "faked//"
@@ -226,9 +238,20 @@
                     "new ObjectName(\":*\"),null) with faked//");
                 assertEquals(proxy.queryMBeans(
                         new ObjectName(":*"),null).contains(moi3),true);
-                failed("queryMBeans(null,null) should have failed for faked//");
-            } catch (IllegalArgumentException x) {
-                System.out.println("Received expected exception for faked//: "+x);
+                failed("queryMBeans(new ObjectName(\":*\"),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(new ObjectName(\":*\"),null) " +
+                            "failed with unexpected cause for faked//");
+                }
             }
 
             System.out.println("Checking queryNames(faked//*:*,null)");
--- a/jdk/test/javax/management/namespace/NullObjectNameTest.java	Tue Dec 09 19:44:22 2008 +0100
+++ b/jdk/test/javax/management/namespace/NullObjectNameTest.java	Tue Dec 09 20:20:48 2008 +0100
@@ -41,6 +41,7 @@
 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;
@@ -189,15 +190,35 @@
                 assertEquals(proxy.queryNames(null,null).
                         contains(moi3.getObjectName()),true);
                 failed("queryNames(null,null) should have failed for faked//");
-            } catch (IllegalArgumentException x) {
-                System.out.println("Received expected exception for faked//: "+x);
+            } 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 (IllegalArgumentException x) {
-                System.out.println("Received expected exception for faked//: "+x);
+            } 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).
--- a/jdk/test/javax/management/namespace/QueryNamesTest.java	Tue Dec 09 19:44:22 2008 +0100
+++ b/jdk/test/javax/management/namespace/QueryNamesTest.java	Tue Dec 09 20:20:48 2008 +0100
@@ -25,7 +25,7 @@
  * @test QueryNamesTest.java 1.4
  * @summary Test how queryNames works with Namespaces.
  * @author Daniel Fuchs
- * @bug 5072476
+ * @bug 5072476 6768935
  * @run clean QueryNamesTest Wombat WombatMBean
  * @run build QueryNamesTest Wombat WombatMBean
  * @run main QueryNamesTest
@@ -34,6 +34,7 @@
 
 import java.io.IOException;
 import java.lang.management.ManagementFactory;
+import java.util.ArrayList;
 import java.util.Arrays;
 import java.util.Collections;
 import java.util.HashMap;
@@ -52,7 +53,9 @@
 import javax.management.MBeanServerConnection;
 import javax.management.MBeanServerFactory;
 import javax.management.MalformedObjectNameException;
+import javax.management.ObjectInstance;
 import javax.management.ObjectName;
+import javax.management.RuntimeOperationsException;
 import javax.management.namespace.JMXNamespace;
 import javax.management.namespace.JMXNamespaces;
 
@@ -366,6 +369,66 @@
         return res;
     }
 
+    private static void checkNsPattern(MBeanServer server) throws Exception {
+        final List<String> list = new ArrayList<String>();
+        for (String s : namespaces) {
+            final String[] cmpnt = s.split("//");
+            for (int i=0;i<cmpnt.length;i++) {
+                final String[] clone = cmpnt.clone();
+                if (clone[i].length() < 3) {
+                    clone[i] = "*";
+                } else {
+                    clone[i] = "?"+cmpnt[i].substring(1, cmpnt[i].length()-2)+"*";
+                }
+                final StringBuilder sb = new StringBuilder();
+                for (int j=0;j<cmpnt.length;j++) {
+                    sb.append(clone[j]).append("//");
+                }
+                list.add(sb.toString()+"*:*");
+            }
+        }
+        for (String s : list) {
+            final Set<ObjectName> res = new HashSet<ObjectName>();
+
+            try {
+                res.addAll(server.queryNames(ObjectName.valueOf(s),null));
+            } catch (RuntimeOperationsException x) {
+                if (x.getCause() instanceof IllegalArgumentException) {
+                    System.out.println("queryNames("+s+"): OK - received "+x.getCause());
+                    continue;
+                }
+                System.err.println("queryNames("+s+"): Bad cause: "+x.getCause());
+                throw x;
+            } catch (Exception x) {
+                System.err.println("queryNames("+s+"): Bad exception: "+x);
+                throw x;
+            }
+            System.err.println("queryNames("+s+"): Bad result: "+res);
+            System.err.println("queryNames("+s+"): Excpected exception not thrown.");
+            throw new Exception("queryNames("+s+"): Excpected exception not thrown.");
+        }
+        for (String s : list) {
+            final Set<ObjectInstance> res = new HashSet<ObjectInstance>();
+
+            try {
+                res.addAll(server.queryMBeans(ObjectName.valueOf(s),null));
+            } catch (RuntimeOperationsException x) {
+                if (x.getCause() instanceof IllegalArgumentException) {
+                    System.out.println("queryMBeans("+s+"): OK - received "+x.getCause());
+                    continue;
+                }
+                System.err.println("queryMBeans("+s+"): Bad cause: "+x.getCause());
+                throw x;
+            } catch (Exception x) {
+                System.err.println("queryMBeans("+s+"): Bad exception: "+x);
+                throw x;
+            }
+            System.err.println("queryMBeans("+s+"): Bad result: "+res);
+            System.err.println("queryMBeans("+s+"): Excpected exception not thrown.");
+            throw new Exception("queryMBeans("+s+"): Excpected exception not thrown.");
+        }
+    }
+
     public static void main(String[] args)
         throws Exception {
         final MBeanServer server = ManagementFactory.getPlatformMBeanServer();
@@ -378,6 +441,7 @@
             System.out.println("Domains: " +Arrays.asList(server.getDomains()));
             checkRegistration(server);
             checkNsQuery(server);
+            checkNsPattern(server);
         } finally {
             boolean res = true;
             res = res && removeWombats(server, wombats);