OpenJDK / jdk / jdk
changeset 1711:d9d3b0002726
Merge
author | sjiang |
---|---|
date | Tue, 09 Dec 2008 20:51:59 +0100 |
parents | 0bdf9295cab1 392dd6db361a |
children | 8664f15a755b |
files | |
diffstat | 21 files changed, 441 insertions(+), 211 deletions(-) [+] |
line wrap: on
line diff
--- a/jdk/src/share/classes/com/sun/jmx/interceptor/DispatchInterceptor.java Tue Dec 09 20:50:45 2008 +0100 +++ b/jdk/src/share/classes/com/sun/jmx/interceptor/DispatchInterceptor.java Tue Dec 09 20:51:59 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 20:50:45 2008 +0100 +++ b/jdk/src/share/classes/com/sun/jmx/interceptor/DomainDispatchInterceptor.java Tue Dec 09 20:51:59 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 20:50:45 2008 +0100 +++ b/jdk/src/share/classes/com/sun/jmx/interceptor/NamespaceDispatchInterceptor.java Tue Dec 09 20:51:59 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 20:50:45 2008 +0100 +++ b/jdk/src/share/classes/com/sun/jmx/mbeanserver/MXBeanLookup.java Tue Dec 09 20:51:59 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 20:50:45 2008 +0100 +++ b/jdk/src/share/classes/com/sun/jmx/mbeanserver/Util.java Tue Dec 09 20:51:59 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 20:50:45 2008 +0100 +++ b/jdk/src/share/classes/com/sun/jmx/namespace/DomainInterceptor.java Tue Dec 09 20:51:59 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 20:50:45 2008 +0100 +++ b/jdk/src/share/classes/com/sun/jmx/namespace/NamespaceInterceptor.java Tue Dec 09 20:51:59 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 20:50:45 2008 +0100 +++ b/jdk/src/share/classes/com/sun/jmx/namespace/ObjectNameRouter.java Tue Dec 09 20:51:59 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 20:50:45 2008 +0100 +++ b/jdk/src/share/classes/com/sun/jmx/namespace/RoutingMBeanServerConnection.java Tue Dec 09 20:51:59 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 20:50:45 2008 +0100 +++ b/jdk/src/share/classes/com/sun/jmx/namespace/RoutingProxy.java Tue Dec 09 20:51:59 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 20:50:45 2008 +0100 +++ b/jdk/src/share/classes/javax/management/MBeanServer.java Tue Dec 09 20:51:59 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 20:50:45 2008 +0100 +++ b/jdk/src/share/classes/javax/management/MBeanServerConnection.java Tue Dec 09 20:51:59 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 20:50:45 2008 +0100 +++ b/jdk/src/share/classes/javax/management/ObjectName.java Tue Dec 09 20:51:59 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>**//b//c//D:k=v</code> or <code>a//**//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>**//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//**//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//**//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**//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**</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 20:50:45 2008 +0100 +++ b/jdk/src/share/classes/javax/management/namespace/JMXDomain.java Tue Dec 09 20:51:59 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 20:50:45 2008 +0100 +++ b/jdk/src/share/classes/javax/management/namespace/JMXNamespacePermission.java Tue Dec 09 20:51:59 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>**//b//c//D:k=v</code> or <code>a//**//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>**//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//**//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//**//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**//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**</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 20:50:45 2008 +0100 +++ b/jdk/src/share/classes/javax/management/namespace/JMXNamespaces.java Tue Dec 09 20:51:59 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 20:50:45 2008 +0100 +++ b/jdk/src/share/classes/javax/management/namespace/package-info.java Tue Dec 09 20:51:59 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 20:50:45 2008 +0100 +++ b/jdk/test/javax/management/namespace/LeadingSeparatorsTest.java Tue Dec 09 20:51:59 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 20:50:45 2008 +0100 +++ b/jdk/test/javax/management/namespace/NullDomainObjectNameTest.java Tue Dec 09 20:51:59 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 20:50:45 2008 +0100 +++ b/jdk/test/javax/management/namespace/NullObjectNameTest.java Tue Dec 09 20:51:59 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 20:50:45 2008 +0100 +++ b/jdk/test/javax/management/namespace/QueryNamesTest.java Tue Dec 09 20:51:59 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);