jdk/src/share/classes/com/sun/jmx/namespace/RoutingMBeanServerConnection.java
changeset 1156 bbc2d15aaf7a
child 1222 78e3d021d528
equal deleted inserted replaced
1155:a9a142fcf1b5 1156:bbc2d15aaf7a
       
     1 /*
       
     2  * Copyright 2008 Sun Microsystems, Inc.  All Rights Reserved.
       
     3  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
       
     4  *
       
     5  * This code is free software; you can redistribute it and/or modify it
       
     6  * under the terms of the GNU General Public License version 2 only, as
       
     7  * published by the Free Software Foundation.  Sun designates this
       
     8  * particular file as subject to the "Classpath" exception as provided
       
     9  * by Sun in the LICENSE file that accompanied this code.
       
    10  *
       
    11  * This code is distributed in the hope that it will be useful, but WITHOUT
       
    12  * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
       
    13  * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
       
    14  * version 2 for more details (a copy is included in the LICENSE file that
       
    15  * accompanied this code).
       
    16  *
       
    17  * You should have received a copy of the GNU General Public License version
       
    18  * 2 along with this work; if not, write to the Free Software Foundation,
       
    19  * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
       
    20  *
       
    21  * Please contact Sun Microsystems, Inc., 4150 Network Circle, Santa Clara,
       
    22  * CA 95054 USA or visit www.sun.com if you need additional information or
       
    23  * have any questions.
       
    24  */
       
    25 
       
    26 package com.sun.jmx.namespace;
       
    27 
       
    28 import com.sun.jmx.defaults.JmxProperties;
       
    29 import com.sun.jmx.mbeanserver.Util;
       
    30 import java.io.IOException;
       
    31 import java.lang.reflect.UndeclaredThrowableException;
       
    32 import java.util.Set;
       
    33 import java.util.logging.Level;
       
    34 import java.util.logging.Logger;
       
    35 
       
    36 import javax.management.Attribute;
       
    37 import javax.management.AttributeList;
       
    38 import javax.management.AttributeNotFoundException;
       
    39 import javax.management.InstanceAlreadyExistsException;
       
    40 import javax.management.InstanceNotFoundException;
       
    41 import javax.management.IntrospectionException;
       
    42 import javax.management.InvalidAttributeValueException;
       
    43 import javax.management.JMRuntimeException;
       
    44 import javax.management.ListenerNotFoundException;
       
    45 import javax.management.MBeanException;
       
    46 import javax.management.MBeanInfo;
       
    47 import javax.management.MBeanRegistrationException;
       
    48 import javax.management.MBeanServerConnection;
       
    49 import javax.management.MalformedObjectNameException;
       
    50 import javax.management.NotCompliantMBeanException;
       
    51 import javax.management.NotificationFilter;
       
    52 import javax.management.NotificationListener;
       
    53 import javax.management.ObjectInstance;
       
    54 import javax.management.ObjectName;
       
    55 import javax.management.QueryExp;
       
    56 import javax.management.ReflectionException;
       
    57 import javax.management.RuntimeMBeanException;
       
    58 import javax.management.RuntimeOperationsException;
       
    59 
       
    60 /**
       
    61  * A RoutingMBeanServerConnection wraps a MBeanServerConnection, defining
       
    62  * abstract methods that can be implemented by subclasses to rewrite
       
    63  * routing ObjectNames. It is used to implement
       
    64  * HandlerInterceptors (wrapping JMXNamespace instances) and routing
       
    65  * proxies (used to implement cd operations).
       
    66  * <p><b>
       
    67  * This API is a Sun internal API and is subject to changes without notice.
       
    68  * </b></p>
       
    69  * @since 1.7
       
    70  */
       
    71 public abstract class RoutingMBeanServerConnection<T extends MBeanServerConnection>
       
    72         implements MBeanServerConnection {
       
    73 
       
    74     /**
       
    75      * A logger for this class.
       
    76      **/
       
    77     private static final Logger LOG = JmxProperties.NAMESPACE_LOGGER;
       
    78 
       
    79     /**
       
    80      * Creates a new instance of RoutingMBeanServerConnection
       
    81      */
       
    82     public RoutingMBeanServerConnection() {
       
    83     }
       
    84 
       
    85     /**
       
    86      * Returns the wrapped source connection.
       
    87      **/
       
    88     protected abstract T source() throws IOException;
       
    89 
       
    90     /**
       
    91      * Converts a target ObjectName to a source ObjectName.
       
    92      **/
       
    93     protected abstract ObjectName toSource(ObjectName targetName)
       
    94         throws MalformedObjectNameException;
       
    95 
       
    96     /**
       
    97      * Converts a source ObjectName to a target ObjectName.
       
    98      **/
       
    99     protected abstract ObjectName toTarget(ObjectName sourceName)
       
   100         throws MalformedObjectNameException;
       
   101 
       
   102     /**
       
   103      * Can be overridden by subclasses to check the validity of a new
       
   104      * ObjectName used in createMBean or registerMBean.
       
   105      * This method is typically used by subclasses which might require
       
   106      * special handling for "null";
       
   107      **/
       
   108     protected ObjectName newSourceMBeanName(ObjectName targetName)
       
   109         throws MBeanRegistrationException {
       
   110         try {
       
   111             return toSource(targetName);
       
   112         } catch (Exception x) {
       
   113             throw new MBeanRegistrationException(x,"Illegal MBean Name");
       
   114         }
       
   115     }
       
   116 
       
   117     // Calls toSource(), Wraps MalformedObjectNameException.
       
   118     ObjectName toSourceOrRuntime(ObjectName targetName)
       
   119         throws RuntimeOperationsException {
       
   120         try {
       
   121             return toSource(targetName);
       
   122         } catch (MalformedObjectNameException x) {
       
   123             final IllegalArgumentException x2 =
       
   124                     new IllegalArgumentException(String.valueOf(targetName),x);
       
   125             final RuntimeOperationsException x3 =
       
   126                     new RuntimeOperationsException(x2);
       
   127             throw x3;
       
   128         }
       
   129     }
       
   130 
       
   131 
       
   132     // Wraps given exception if needed.
       
   133     RuntimeException makeCompliantRuntimeException(Exception x) {
       
   134         if (x instanceof SecurityException)  return (SecurityException)x;
       
   135         if (x instanceof JMRuntimeException) return (JMRuntimeException)x;
       
   136         if (x instanceof RuntimeException)
       
   137             return new RuntimeOperationsException((RuntimeException)x);
       
   138         if (x instanceof IOException)
       
   139             return Util.newRuntimeIOException((IOException)x);
       
   140         // shouldn't come here...
       
   141         final RuntimeException x2 = new UndeclaredThrowableException(x);
       
   142         return new RuntimeOperationsException(x2);
       
   143     }
       
   144 
       
   145     /**
       
   146      * This method is a hook to implement permission checking in subclasses.
       
   147      * By default, this method does nothing and simply returns
       
   148      * {@code attribute}.
       
   149      *
       
   150      * @param routingName The name of the MBean in the enclosing context.
       
   151      *        This is of the form {@code <namespace>//<ObjectName>}.
       
   152      * @param attributes  The list of attributes to check permission for.
       
   153      * @param action one of "getAttribute" or "setAttribute"
       
   154      * @return The list of attributes for which the callers has the
       
   155      *         appropriate {@link
       
   156      *         javax.management.namespace.JMXNamespacePermission}.
       
   157      */
       
   158     String[] checkAttributes(ObjectName routingName,
       
   159             String[] attributes, String action) {
       
   160         check(routingName,null,action);
       
   161         return attributes;
       
   162     }
       
   163 
       
   164     /**
       
   165      * This method is a hook to implement permission checking in subclasses.
       
   166      * By default, this method does nothing and simply returns
       
   167      * {@code attribute}.
       
   168      *
       
   169      * @param routingName The name of the MBean in the enclosing context.
       
   170      *        This is of the form {@code <namespace>//<ObjectName>}.
       
   171      * @param attributes The list of attributes to check permission for.
       
   172      * @param action one of "getAttribute" or "setAttribute"
       
   173      * @return The list of attributes for which the callers has the
       
   174      *         appropriate {@link
       
   175      *         javax.management.namespace.JMXNamespacePermission}.
       
   176      */
       
   177     AttributeList checkAttributes(ObjectName routingName,
       
   178             AttributeList attributes, String action) {
       
   179         check(routingName,null,action);
       
   180         return attributes;
       
   181     }
       
   182 
       
   183     // from MBeanServerConnection
       
   184     public AttributeList getAttributes(ObjectName name, String[] attributes)
       
   185         throws InstanceNotFoundException, ReflectionException, IOException {
       
   186         final ObjectName sourceName = toSourceOrRuntime(name);
       
   187         try {
       
   188             final String[] authorized =
       
   189                     checkAttributes(name,attributes,"getAttribute");
       
   190             final AttributeList attrList =
       
   191                     source().getAttributes(sourceName,authorized);
       
   192             return attrList;
       
   193         } catch (RuntimeException ex) {
       
   194             throw makeCompliantRuntimeException(ex);
       
   195         }
       
   196     }
       
   197 
       
   198    /**
       
   199      * This method is a hook to implement permission checking in subclasses.
       
   200      * By default, this method does nothing.
       
   201      * A subclass may override this method and throw a {@link
       
   202      * SecurityException} if the permission is denied.
       
   203      *
       
   204      * @param routingName The name of the MBean in the enclosing context.
       
   205      *        This is of the form {@code <namespace>//<ObjectName>}.
       
   206      * @param member The {@link
       
   207      *  javax.management.namespace.JMXNamespacePermission#getMember member}
       
   208      *  name.
       
   209      * @param action The {@link
       
   210      *  javax.management.namespace.JMXNamespacePermission#getActions action}
       
   211      *  name.
       
   212      */
       
   213     void check(ObjectName routingName,
       
   214                String member, String action) {
       
   215     }
       
   216 
       
   217     void checkPattern(ObjectName routingPattern,
       
   218                String member, String action) {
       
   219         // pattern is checked only at posteriori by checkQuery.
       
   220         // checking it a priori usually doesn't work, because ObjectName.apply
       
   221         // does not work between two patterns.
       
   222         check(null,null,action);
       
   223     }
       
   224 
       
   225     void checkCreate(ObjectName routingName, String className,
       
   226                      String action) {
       
   227     }
       
   228 
       
   229     // from MBeanServerConnection
       
   230     public Object invoke(ObjectName name, String operationName, Object[] params,
       
   231                          String[] signature)
       
   232         throws InstanceNotFoundException, MBeanException, ReflectionException,
       
   233             IOException {
       
   234         final ObjectName sourceName = toSourceOrRuntime(name);
       
   235         try {
       
   236             check(name, operationName, "invoke");
       
   237             final Object result =
       
   238                     source().invoke(sourceName,operationName,params,
       
   239                                    signature);
       
   240             return result;
       
   241         } catch (RuntimeException ex) {
       
   242             throw makeCompliantRuntimeException(ex);
       
   243         }
       
   244     }
       
   245 
       
   246     // from MBeanServerConnection
       
   247     public void unregisterMBean(ObjectName name)
       
   248         throws InstanceNotFoundException, MBeanRegistrationException,
       
   249             IOException {
       
   250         final ObjectName sourceName = toSourceOrRuntime(name);
       
   251         try {
       
   252             check(name, null, "unregisterMBean");
       
   253             source().unregisterMBean(sourceName);
       
   254         } catch (RuntimeException ex) {
       
   255             throw makeCompliantRuntimeException(ex);
       
   256         }
       
   257     }
       
   258 
       
   259     // from MBeanServerConnection
       
   260     public MBeanInfo getMBeanInfo(ObjectName name)
       
   261         throws InstanceNotFoundException, IntrospectionException,
       
   262             ReflectionException, IOException {
       
   263         final ObjectName sourceName = toSourceOrRuntime(name);
       
   264         try {
       
   265             check(name, null, "getMBeanInfo");
       
   266             return source().getMBeanInfo(sourceName);
       
   267         } catch (RuntimeException ex) {
       
   268             throw makeCompliantRuntimeException(ex);
       
   269         }
       
   270     }
       
   271 
       
   272     // from MBeanServerConnection
       
   273     public ObjectInstance getObjectInstance(ObjectName name)
       
   274         throws InstanceNotFoundException, IOException {
       
   275         final ObjectName sourceName = toSourceOrRuntime(name);
       
   276         try {
       
   277             check(name, null, "getObjectInstance");
       
   278             return processOutputInstance(
       
   279                     source().getObjectInstance(sourceName));
       
   280         } catch (RuntimeException ex) {
       
   281             throw makeCompliantRuntimeException(ex);
       
   282         }
       
   283     }
       
   284 
       
   285     // from MBeanServerConnection
       
   286     public boolean isRegistered(ObjectName name) throws IOException {
       
   287         final ObjectName sourceName = toSourceOrRuntime(name);
       
   288         try {
       
   289             return source().isRegistered(sourceName);
       
   290         } catch (RuntimeMBeanException x) {
       
   291             throw new RuntimeOperationsException(x.getTargetException());
       
   292         } catch (RuntimeException x) {
       
   293             throw makeCompliantRuntimeException(x);
       
   294         }
       
   295     }
       
   296 
       
   297     // from MBeanServerConnection
       
   298     public void setAttribute(ObjectName name, Attribute attribute)
       
   299         throws InstanceNotFoundException, AttributeNotFoundException,
       
   300             InvalidAttributeValueException, MBeanException,
       
   301             ReflectionException, IOException {
       
   302         final ObjectName sourceName = toSourceOrRuntime(name);
       
   303         try {
       
   304             check(name,
       
   305                   (attribute==null?null:attribute.getName()),
       
   306                   "setAttribute");
       
   307             source().setAttribute(sourceName,attribute);
       
   308         } catch (RuntimeException ex) {
       
   309             throw makeCompliantRuntimeException(ex);
       
   310         }
       
   311     }
       
   312 
       
   313     // from MBeanServerConnection
       
   314     public ObjectInstance createMBean(String className,
       
   315             ObjectName name, ObjectName loaderName,
       
   316             Object[] params, String[] signature)
       
   317         throws ReflectionException, InstanceAlreadyExistsException,
       
   318             MBeanRegistrationException, MBeanException,
       
   319             NotCompliantMBeanException, InstanceNotFoundException, IOException {
       
   320         final ObjectName sourceName = newSourceMBeanName(name);
       
   321         // Loader Name is already a sourceLoaderName.
       
   322         final ObjectName sourceLoaderName = loaderName;
       
   323         try {
       
   324             checkCreate(name, className, "instantiate");
       
   325             checkCreate(name, className, "registerMBean");
       
   326             final ObjectInstance instance =
       
   327                     source().createMBean(className,sourceName,
       
   328                                          sourceLoaderName,
       
   329                                          params,signature);
       
   330             return processOutputInstance(instance);
       
   331         } catch (RuntimeException ex) {
       
   332             throw makeCompliantRuntimeException(ex);
       
   333         }
       
   334     }
       
   335 
       
   336     // from MBeanServerConnection
       
   337     public ObjectInstance createMBean(String className, ObjectName name,
       
   338             Object[] params, String[] signature)
       
   339             throws ReflectionException, InstanceAlreadyExistsException,
       
   340             MBeanRegistrationException, MBeanException,
       
   341             NotCompliantMBeanException, IOException {
       
   342         final ObjectName sourceName = newSourceMBeanName(name);
       
   343         try {
       
   344             checkCreate(name, className, "instantiate");
       
   345             checkCreate(name, className, "registerMBean");
       
   346             return processOutputInstance(source().createMBean(className,
       
   347                     sourceName,params,signature));
       
   348         } catch (RuntimeException ex) {
       
   349             throw makeCompliantRuntimeException(ex);
       
   350         }
       
   351     }
       
   352 
       
   353     // from MBeanServerConnection
       
   354     public ObjectInstance createMBean(String className, ObjectName name,
       
   355             ObjectName loaderName)
       
   356             throws ReflectionException, InstanceAlreadyExistsException,
       
   357             MBeanRegistrationException, MBeanException,
       
   358             NotCompliantMBeanException, InstanceNotFoundException, IOException {
       
   359         final ObjectName sourceName = newSourceMBeanName(name);
       
   360         // Loader Name is already a source Loader Name.
       
   361         final ObjectName sourceLoaderName = loaderName;
       
   362         try {
       
   363             checkCreate(name, className, "instantiate");
       
   364             checkCreate(name, className, "registerMBean");
       
   365             return processOutputInstance(source().createMBean(className,
       
   366                     sourceName,sourceLoaderName));
       
   367         } catch (RuntimeException ex) {
       
   368             throw makeCompliantRuntimeException(ex);
       
   369         }
       
   370     }
       
   371 
       
   372     // from MBeanServerConnection
       
   373     public ObjectInstance createMBean(String className, ObjectName name)
       
   374         throws ReflectionException, InstanceAlreadyExistsException,
       
   375             MBeanRegistrationException, MBeanException,
       
   376             NotCompliantMBeanException, IOException {
       
   377         final ObjectName sourceName = newSourceMBeanName(name);
       
   378         try {
       
   379             checkCreate(name, className, "instantiate");
       
   380             checkCreate(name, className, "registerMBean");
       
   381             return processOutputInstance(source().
       
   382                     createMBean(className,sourceName));
       
   383         } catch (RuntimeException ex) {
       
   384             throw makeCompliantRuntimeException(ex);
       
   385         }
       
   386      }
       
   387 
       
   388     // from MBeanServerConnection
       
   389     public Object getAttribute(ObjectName name, String attribute)
       
   390         throws MBeanException, AttributeNotFoundException,
       
   391             InstanceNotFoundException, ReflectionException, IOException {
       
   392         final ObjectName sourceName = toSourceOrRuntime(name);
       
   393         try {
       
   394             check(name, attribute, "getAttribute");
       
   395             return source().getAttribute(sourceName,attribute);
       
   396         } catch (RuntimeException ex) {
       
   397             throw makeCompliantRuntimeException(ex);
       
   398         }
       
   399     }
       
   400 
       
   401     // from MBeanServerConnection
       
   402     public boolean isInstanceOf(ObjectName name, String className)
       
   403         throws InstanceNotFoundException, IOException {
       
   404         final ObjectName sourceName = toSourceOrRuntime(name);
       
   405         try {
       
   406             check(name, null, "isInstanceOf");
       
   407             return source().isInstanceOf(sourceName,className);
       
   408         } catch (RuntimeException ex) {
       
   409             throw makeCompliantRuntimeException(ex);
       
   410         }
       
   411     }
       
   412 
       
   413     // from MBeanServerConnection
       
   414     public AttributeList setAttributes(ObjectName name, AttributeList attributes)
       
   415         throws InstanceNotFoundException, ReflectionException, IOException {
       
   416         final ObjectName sourceName = toSourceOrRuntime(name);
       
   417         try {
       
   418             final AttributeList authorized =
       
   419                     checkAttributes(name, attributes, "setAttribute");
       
   420             return source().
       
   421                     setAttributes(sourceName,authorized);
       
   422         } catch (RuntimeException ex) {
       
   423             throw makeCompliantRuntimeException(ex);
       
   424         }
       
   425     }
       
   426 
       
   427     // Return names in the target's context.
       
   428     Set<ObjectInstance> processOutputInstances(Set<ObjectInstance> sources) {
       
   429 
       
   430         final Set<ObjectInstance> result = Util.equivalentEmptySet(sources);
       
   431         for (ObjectInstance i : sources) {
       
   432             try {
       
   433                 final ObjectInstance target = processOutputInstance(i);
       
   434                 if (!checkQuery(target.getObjectName(), "queryMBeans"))
       
   435                     continue;
       
   436                 result.add(target);
       
   437             } catch (Exception x) {
       
   438                 if (LOG.isLoggable(Level.FINE)) {
       
   439                     LOG.fine("Skiping returned item: " +
       
   440                              "Unexpected exception while processing " +
       
   441                              "ObjectInstance: " + x);
       
   442                 }
       
   443                 continue;
       
   444             }
       
   445         }
       
   446         return result;
       
   447     }
       
   448 
       
   449     /**
       
   450      * This is a hook to implement permission checking in subclasses.
       
   451      *
       
   452      * Checks that the caller has sufficient permission for returning
       
   453      * information about {@code sourceName} in {@code action}.
       
   454      *
       
   455      * By default always return true. Subclass may override this method
       
   456      * and return false if the caller doesn't have sufficient permissions.
       
   457      *
       
   458      * @param routingName The name of the MBean to include or exclude from
       
   459      *        the query, expressed in the enclosing context.
       
   460      *        This is of the form {@code <namespace>//<ObjectName>}.
       
   461      * @param action one of "queryNames" or "queryMBeans"
       
   462      * @return true if {@code sourceName} can be returned.
       
   463      */
       
   464     boolean checkQuery(ObjectName routingName, String action) {
       
   465         return true;
       
   466     }
       
   467 
       
   468     // Return names in the target's context.
       
   469     ObjectInstance processOutputInstance(ObjectInstance source) {
       
   470         if (source == null) return null;
       
   471         final ObjectName sourceName = source.getObjectName();
       
   472         try {
       
   473             final ObjectName targetName = toTarget(sourceName);
       
   474             return new ObjectInstance(targetName,source.getClassName());
       
   475         } catch (MalformedObjectNameException x) {
       
   476             final IllegalArgumentException x2 =
       
   477                     new IllegalArgumentException(String.valueOf(sourceName),x);
       
   478             final RuntimeOperationsException x3 =
       
   479                     new RuntimeOperationsException(x2);
       
   480             throw x3;
       
   481         }
       
   482     }
       
   483 
       
   484     // Returns names in the target's context.
       
   485     Set<ObjectName> processOutputNames(Set<ObjectName> sourceNames) {
       
   486 
       
   487         final Set<ObjectName> names = Util.equivalentEmptySet(sourceNames);
       
   488         for (ObjectName n : sourceNames) {
       
   489             try {
       
   490                 final ObjectName targetName = toTarget(n);
       
   491                 if (!checkQuery(targetName, "queryNames")) continue;
       
   492                 names.add(targetName);
       
   493             } catch (Exception x) {
       
   494                 if (LOG.isLoggable(Level.FINE)) {
       
   495                     LOG.fine("Skiping returned item: " +
       
   496                              "Unexpected exception while processing " +
       
   497                              "ObjectInstance: " + x);
       
   498                 }
       
   499                 continue;
       
   500             }
       
   501         }
       
   502         return names;
       
   503     }
       
   504 
       
   505     // from MBeanServerConnection
       
   506     public Set<ObjectInstance> queryMBeans(ObjectName name,
       
   507             QueryExp query) throws IOException {
       
   508         if (name == null) name=ObjectName.WILDCARD;
       
   509         final ObjectName sourceName = toSourceOrRuntime(name);
       
   510         try {
       
   511             checkPattern(name,null,"queryMBeans");
       
   512             return processOutputInstances(
       
   513                     source().queryMBeans(sourceName,query));
       
   514         } catch (RuntimeException ex) {
       
   515             throw makeCompliantRuntimeException(ex);
       
   516         }
       
   517     }
       
   518 
       
   519     // from MBeanServerConnection
       
   520 
       
   521     public Set<ObjectName> queryNames(ObjectName name, QueryExp query)
       
   522         throws IOException {
       
   523         if (name == null) name=ObjectName.WILDCARD;
       
   524         final ObjectName sourceName = toSourceOrRuntime(name);
       
   525         try {
       
   526             checkPattern(name,null,"queryNames");
       
   527             final Set<ObjectName> tmp = source().queryNames(sourceName,query);
       
   528             final Set<ObjectName> out = processOutputNames(tmp);
       
   529             //System.err.println("queryNames: out: "+out);
       
   530             return out;
       
   531         } catch (RuntimeException ex) {
       
   532             throw makeCompliantRuntimeException(ex);
       
   533         }
       
   534     }
       
   535 
       
   536     // from MBeanServerConnection
       
   537     public void removeNotificationListener(ObjectName name,
       
   538             NotificationListener listener)
       
   539         throws InstanceNotFoundException,
       
   540         ListenerNotFoundException, IOException {
       
   541         final ObjectName sourceName = toSourceOrRuntime(name);
       
   542         try {
       
   543             check(name,null,"removeNotificationListener");
       
   544             source().removeNotificationListener(sourceName,listener);
       
   545         } catch (RuntimeException ex) {
       
   546             throw makeCompliantRuntimeException(ex);
       
   547         }
       
   548     }
       
   549 
       
   550     // from MBeanServerConnection
       
   551     public void addNotificationListener(ObjectName name, ObjectName listener,
       
   552             NotificationFilter filter, Object handback)
       
   553             throws InstanceNotFoundException, IOException {
       
   554         final ObjectName sourceName = toSourceOrRuntime(name);
       
   555         // Listener name is already a source listener name.
       
   556         try {
       
   557             check(name,null,"addNotificationListener");
       
   558             source().addNotificationListener(sourceName,listener,
       
   559                     filter,handback);
       
   560         } catch (RuntimeException ex) {
       
   561             throw makeCompliantRuntimeException(ex);
       
   562         }
       
   563     }
       
   564 
       
   565     // from MBeanServerConnection
       
   566     public void addNotificationListener(ObjectName name,
       
   567                 NotificationListener listener, NotificationFilter filter,
       
   568                 Object handback) throws InstanceNotFoundException, IOException {
       
   569         final ObjectName sourceName = toSourceOrRuntime(name);
       
   570         try {
       
   571             check(name,null,"addNotificationListener");
       
   572             source().addNotificationListener(sourceName, listener, filter,
       
   573                     handback);
       
   574         } catch (RuntimeException ex) {
       
   575             throw makeCompliantRuntimeException(ex);
       
   576         }
       
   577     }
       
   578 
       
   579 
       
   580     // from MBeanServerConnection
       
   581     public void removeNotificationListener(ObjectName name,
       
   582             NotificationListener listener, NotificationFilter filter,
       
   583             Object handback)
       
   584             throws InstanceNotFoundException, ListenerNotFoundException,
       
   585                 IOException {
       
   586         final ObjectName sourceName = toSourceOrRuntime(name);
       
   587         try {
       
   588             check(name,null,"removeNotificationListener");
       
   589             source().removeNotificationListener(sourceName,listener,filter,
       
   590                     handback);
       
   591         } catch (RuntimeException ex) {
       
   592             throw makeCompliantRuntimeException(ex);
       
   593         }
       
   594     }
       
   595 
       
   596     // from MBeanServerConnection
       
   597     public void removeNotificationListener(ObjectName name, ObjectName listener,
       
   598             NotificationFilter filter, Object handback)
       
   599             throws InstanceNotFoundException, ListenerNotFoundException,
       
   600             IOException {
       
   601         final ObjectName sourceName = toSourceOrRuntime(name);
       
   602         try {
       
   603             check(name,null,"removeNotificationListener");
       
   604             source().removeNotificationListener(sourceName,listener,
       
   605                     filter,handback);
       
   606         } catch (RuntimeException ex) {
       
   607             throw makeCompliantRuntimeException(ex);
       
   608         }
       
   609     }
       
   610 
       
   611     // from MBeanServerConnection
       
   612     public void removeNotificationListener(ObjectName name, ObjectName listener)
       
   613         throws InstanceNotFoundException, ListenerNotFoundException,
       
   614                IOException {
       
   615         final ObjectName sourceName = toSourceOrRuntime(name);
       
   616         // listener name is already a source name...
       
   617         final ObjectName sourceListener = listener;
       
   618         try {
       
   619             check(name,null,"removeNotificationListener");
       
   620             source().removeNotificationListener(sourceName,sourceListener);
       
   621         } catch (RuntimeException ex) {
       
   622             throw makeCompliantRuntimeException(ex);
       
   623         }
       
   624     }
       
   625 
       
   626     // from MBeanServerConnection
       
   627     public Integer getMBeanCount() throws IOException {
       
   628         try {
       
   629             return source().getMBeanCount();
       
   630         } catch (RuntimeException ex) {
       
   631             throw makeCompliantRuntimeException(ex);
       
   632         }
       
   633     }
       
   634 
       
   635     // from MBeanServerConnection
       
   636     public String[] getDomains() throws IOException {
       
   637         try {
       
   638             check(null,null,"getDomains");
       
   639             final String[] domains = source().getDomains();
       
   640             return checkDomains(domains,"getDomains");
       
   641         } catch (RuntimeException ex) {
       
   642             throw makeCompliantRuntimeException(ex);
       
   643         }
       
   644     }
       
   645 
       
   646     /**
       
   647      * This method is a hook to implement permission checking in subclasses.
       
   648      * Checks that the caller as the necessary permissions to view the
       
   649      * given domain. If not remove the domains for which the caller doesn't
       
   650      * have permission from the list.
       
   651      * <p>
       
   652      * By default, this method always returns {@code domains}
       
   653      *
       
   654      * @param domains The domains to return.
       
   655      * @param action  "getDomains"
       
   656      * @return a filtered list of domains.
       
   657      */
       
   658     String[] checkDomains(String[] domains, String action) {
       
   659         return domains;
       
   660     }
       
   661 
       
   662     // from MBeanServerConnection
       
   663     public String getDefaultDomain() throws IOException {
       
   664         try {
       
   665             return source().getDefaultDomain();
       
   666         } catch (RuntimeException ex) {
       
   667             throw makeCompliantRuntimeException(ex);
       
   668         }
       
   669     }
       
   670 
       
   671 }