jdk/src/share/classes/com/sun/jmx/namespace/RoutingProxy.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 java.io.IOException;
       
    30 import java.util.logging.Level;
       
    31 import java.util.logging.Logger;
       
    32 
       
    33 import javax.management.AttributeNotFoundException;
       
    34 import javax.management.InstanceNotFoundException;
       
    35 import javax.management.MBeanException;
       
    36 import javax.management.MBeanRegistrationException;
       
    37 
       
    38 import javax.management.MBeanServerConnection;
       
    39 import javax.management.MalformedObjectNameException;
       
    40 import javax.management.ObjectName;
       
    41 import javax.management.ReflectionException;
       
    42 import javax.management.namespace.JMXNamespaces;
       
    43 
       
    44 
       
    45 /**
       
    46  * An RoutingProxy narrows on a given name space in a
       
    47  * source object implementing MBeanServerConnection.
       
    48  * It is used to implement
       
    49  * {@code JMXNamespaces.narrowToNamespace(...)}.
       
    50  * This abstract class has two concrete subclasses:
       
    51  * <p>{@link RoutingConnectionProxy}: to cd in an MBeanServerConnection.</p>
       
    52  * <p>{@link RoutingServerProxy}: to cd in an MBeanServer.</p>
       
    53  * <p><b>
       
    54  * This API is a Sun internal API and is subject to changes without notice.
       
    55  * </b></p>
       
    56  * @since 1.7
       
    57  */
       
    58 public abstract class RoutingProxy<T extends MBeanServerConnection>
       
    59         extends RoutingMBeanServerConnection<T> {
       
    60 
       
    61     /**
       
    62      * A logger for this class.
       
    63      **/
       
    64     private static final Logger LOG = JmxProperties.NAMESPACE_LOGGER;
       
    65 
       
    66     // The source MBeanServerConnection
       
    67     private final T source;
       
    68 
       
    69     // The name space we're narrowing to (usually some name space in
       
    70     // the source MBeanServerConnection
       
    71     private final String                sourceNs;
       
    72 
       
    73     // The name space we pretend to be mounted in (usually "")
       
    74     private final String                targetNs;
       
    75 
       
    76     // The name of the JMXNamespace that handles the source name space
       
    77     private final ObjectName            handlerName;
       
    78     private final ObjectNameRouter      router;
       
    79     final boolean forwardsContext;
       
    80     private volatile String             defaultDomain = null;
       
    81 
       
    82     /**
       
    83      * Creates a new instance of RoutingProxy
       
    84      */
       
    85     protected RoutingProxy(T source,
       
    86                           String sourceNs,
       
    87                           String targetNs,
       
    88                           boolean forwardsContext) {
       
    89         if (source == null) throw new IllegalArgumentException("null");
       
    90         this.sourceNs = JMXNamespaces.normalizeNamespaceName(sourceNs);
       
    91 
       
    92         // Usually sourceNs is not null, except when implementing
       
    93         // Client Contexts
       
    94         //
       
    95         if (sourceNs.equals("")) {
       
    96             this.handlerName = null;
       
    97         } else {
       
    98             // System.err.println("sourceNs: "+sourceNs);
       
    99             this.handlerName =
       
   100                 JMXNamespaces.getNamespaceObjectName(this.sourceNs);
       
   101             try {
       
   102                 // System.err.println("handlerName: "+handlerName);
       
   103                 if (!source.isRegistered(handlerName))
       
   104                     throw new IllegalArgumentException(sourceNs +
       
   105                             ": no such name space");
       
   106             } catch (IOException x) {
       
   107                 throw new IllegalArgumentException("source stale: "+x,x);
       
   108             }
       
   109         }
       
   110         this.source = source;
       
   111         this.targetNs = (targetNs==null?"":
       
   112             JMXNamespaces.normalizeNamespaceName(targetNs));
       
   113         this.router =
       
   114                 new ObjectNameRouter(this.targetNs,this.sourceNs);
       
   115         this.forwardsContext = forwardsContext;
       
   116 
       
   117         if (LOG.isLoggable(Level.FINER))
       
   118             LOG.finer("RoutingProxy for " + this.sourceNs + " created");
       
   119     }
       
   120 
       
   121     @Override
       
   122     public T source() { return source; }
       
   123 
       
   124     ObjectNameRouter getObjectNameRouter() {
       
   125 // TODO: uncomment this when contexts are added
       
   126 //        if (forwardsContext)
       
   127 //            return ObjectNameRouter.wrapWithContext(router);
       
   128 //        else
       
   129             return router;
       
   130     }
       
   131 
       
   132     @Override
       
   133     public ObjectName toSource(ObjectName targetName)
       
   134         throws MalformedObjectNameException {
       
   135         if (targetName == null) return null;
       
   136         if (targetName.getDomain().equals("") && targetNs.equals("")) {
       
   137             try {
       
   138                 if (defaultDomain == null)
       
   139                     defaultDomain = getDefaultDomain();
       
   140             } catch(Exception x) {
       
   141                 LOG.log(Level.FINEST,"Failed to get default domain",x);
       
   142             }
       
   143             if (defaultDomain != null)
       
   144                 targetName = targetName.withDomain(defaultDomain);
       
   145         }
       
   146         final ObjectNameRouter r = getObjectNameRouter();
       
   147         return r.toSourceContext(targetName,true);
       
   148     }
       
   149 
       
   150     @Override
       
   151     protected ObjectName newSourceMBeanName(ObjectName targetName)
       
   152         throws MBeanRegistrationException {
       
   153         if (targetName != null) return super.newSourceMBeanName(targetName);
       
   154 
       
   155         // OK => we can accept null if sourceNs is empty.
       
   156         if (sourceNs.equals("")) return null;
       
   157 
       
   158         throw new MBeanRegistrationException(
       
   159                 new IllegalArgumentException(
       
   160                 "Can't use null ObjectName with namespaces"));
       
   161     }
       
   162 
       
   163     @Override
       
   164     public ObjectName toTarget(ObjectName sourceName)
       
   165         throws MalformedObjectNameException {
       
   166         if (sourceName == null) return null;
       
   167         final ObjectNameRouter r = getObjectNameRouter();
       
   168         return r.toTargetContext(sourceName,false);
       
   169     }
       
   170 
       
   171     private Object getAttributeFromHandler(String attributeName)
       
   172             throws IOException {
       
   173 
       
   174         try {
       
   175             return source().getAttribute(handlerName,attributeName);
       
   176          } catch (RuntimeException ex) {
       
   177             throw makeCompliantRuntimeException(ex);
       
   178          } catch (IOException x) {
       
   179              throw x;
       
   180          } catch (MBeanException ex) {
       
   181              throw new IOException("Failed to get "+attributeName+": "+
       
   182                      ex.getMessage(),
       
   183                      ex.getTargetException());
       
   184          } catch (AttributeNotFoundException ex) {
       
   185              throw new IOException("Failed to get "+attributeName+": "+
       
   186                      ex.getMessage(),ex);
       
   187          } catch (InstanceNotFoundException ex) {
       
   188              throw new IOException("Failed to get "+attributeName+": "+
       
   189                      ex.getMessage(),ex);
       
   190          } catch (ReflectionException ex) {
       
   191              throw new IOException("Failed to get "+attributeName+": "+
       
   192                      ex.getMessage(),ex);
       
   193          }
       
   194     }
       
   195 
       
   196     // We cannot call getMBeanCount() on the underlying
       
   197     // MBeanServerConnection, because it would return the number of
       
   198     // 'top-level' MBeans, not the number of MBeans in the name space
       
   199     // we are narrowing to. Instead we're calling getMBeanCount() on
       
   200     // the JMXNamespace that handles the source name space.
       
   201     //
       
   202     // There is however one particular case when the sourceNs is empty.
       
   203     // In that case, there's no handler - and the 'source' is the top
       
   204     // level namespace. In that particular case, handlerName will be null,
       
   205     // and we directly invoke the top level source().
       
   206     // This later complex case is only used when implementing ClientContexts.
       
   207     //
       
   208     @Override
       
   209     public Integer getMBeanCount() throws IOException {
       
   210         try {
       
   211             if (handlerName == null) return source().getMBeanCount();
       
   212             return (Integer) getAttributeFromHandler("MBeanCount");
       
   213          } catch (RuntimeException ex) {
       
   214             throw makeCompliantRuntimeException(ex);
       
   215          }
       
   216     }
       
   217 
       
   218     // We cannot call getDomains() on the underlying
       
   219     // MBeanServerConnection, because it would return the domains of
       
   220     // 'top-level' MBeans, not the domains of MBeans in the name space
       
   221     // we are narrowing to. Instead we're calling getDomains() on
       
   222     // the JMXNamespace that handles the source name space.
       
   223     //
       
   224     // There is however one particular case when the sourceNs is empty.
       
   225     // In that case, there's no handler - and the 'source' is the top
       
   226     // level namespace. In that particular case, handlerName will be null,
       
   227     // and we directly invoke the top level source().
       
   228     // This later complex case is only used when implementing ClientContexts.
       
   229     //
       
   230     @Override
       
   231     public String[] getDomains() throws IOException {
       
   232         try {
       
   233             if (handlerName == null) return source().getDomains();
       
   234             return (String[]) getAttributeFromHandler("Domains");
       
   235         } catch (RuntimeException ex) {
       
   236             throw makeCompliantRuntimeException(ex);
       
   237         }
       
   238     }
       
   239 
       
   240     // We cannot call getDefaultDomain() on the underlying
       
   241     // MBeanServerConnection, because it would return the default domain of
       
   242     // 'top-level' namespace, not the default domain in the name space
       
   243     // we are narrowing to. Instead we're calling getDefaultDomain() on
       
   244     // the JMXNamespace that handles the source name space.
       
   245     //
       
   246     // There is however one particular case when the sourceNs is empty.
       
   247     // In that case, there's no handler - and the 'source' is the top
       
   248     // level namespace. In that particular case, handlerName will be null,
       
   249     // and we directly invoke the top level source().
       
   250     // This later complex case is only used when implementing ClientContexts.
       
   251     //
       
   252     @Override
       
   253     public String getDefaultDomain() throws IOException {
       
   254         try {
       
   255             if (handlerName == null) {
       
   256                 defaultDomain = source().getDefaultDomain();
       
   257             } else {
       
   258                 defaultDomain =(String)
       
   259                         getAttributeFromHandler("DefaultDomain");
       
   260             }
       
   261             return defaultDomain;
       
   262         } catch (RuntimeException ex) {
       
   263             throw makeCompliantRuntimeException(ex);
       
   264         }
       
   265     }
       
   266 
       
   267     public String getSourceNamespace() {
       
   268         return sourceNs;
       
   269     }
       
   270 
       
   271     public String getTargetNamespace() {
       
   272         return targetNs;
       
   273     }
       
   274 
       
   275     @Override
       
   276     public String toString() {
       
   277         return super.toString()+", sourceNs="+
       
   278                 sourceNs + (targetNs.equals("")?"":
       
   279                     (" mounted on targetNs="+targetNs));
       
   280     }
       
   281 
       
   282 }