src/share/jaxws_classes/com/sun/org/glassfish/external/amx/MBeanListener.java

Thu, 31 Aug 2017 15:18:52 +0800

author
aoqi
date
Thu, 31 Aug 2017 15:18:52 +0800
changeset 637
9c07ef4934dd
parent 368
0989ad8c0860
parent 0
373ffda63c9a
permissions
-rw-r--r--

merge

     1 /*
     2  * Copyright (c) 2009, 2010, Oracle and/or its affiliates. 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.  Oracle designates this
     8  * particular file as subject to the "Classpath" exception as provided
     9  * by Oracle 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 Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
    22  * or visit www.oracle.com if you need additional information or have any
    23  * questions.
    24  */
    27 package com.sun.org.glassfish.external.amx;
    29 import java.util.Set;
    30 import javax.management.MBeanServer;
    31 import javax.management.MBeanServerConnection;
    32 import javax.management.MBeanServerNotification;
    33 import javax.management.Notification;
    34 import javax.management.NotificationListener;
    35 import javax.management.ObjectName;
    36 import java.util.concurrent.CountDownLatch;
    38 import static com.sun.org.glassfish.external.amx.AMX.*;
    40 /**
    41  * Listens for registration of MBeans of various types.
    42  * Intended usage is for subsystems to lazy-load only when the Parent
    43  * MBean is registered.
    44  */
    45 @com.sun.org.glassfish.external.arc.Taxonomy(stability = com.sun.org.glassfish.external.arc.Stability.UNCOMMITTED)
    46 public class MBeanListener<T extends MBeanListener.Callback> implements NotificationListener
    47 {
    48     private static void debug(final Object o) { System.out.println( "" + o ); }
    50     /** listen for MBeans in a given domain of a given type[name]
    51         OR an ObjectName (below) */
    52     private final String mJMXDomain;
    53     private final String mType;
    54     private final String mName;
    56     /** mType and mName should be null if mObjectName is non-null, and vice versa */
    57     private final ObjectName mObjectName;
    59     private final MBeanServerConnection mMBeanServer;
    61     private final T mCallback;
    63     public String toString()
    64     {
    65         return "MBeanListener: ObjectName=" + mObjectName + ", type=" + mType + ", name=" + mName;
    66     }
    68     public String getType()
    69     {
    70         return mType;
    71     }
    73     public String getName()
    74     {
    75         return mName;
    76     }
    78     public MBeanServerConnection getMBeanServer()
    79     {
    80         return mMBeanServer;
    81     }
    83     /** Callback interface.  */
    84     public interface Callback
    85     {
    86         public void mbeanRegistered(final ObjectName objectName, final MBeanListener listener);
    87         public void mbeanUnregistered(final ObjectName objectName, final MBeanListener listener);
    88     }
    90     /**
    91         Default callback implementation, can be subclassed if needed
    92         Remembers only the last MBean that was seen.
    93      */
    94     public static class CallbackImpl implements MBeanListener.Callback
    95     {
    96         private volatile ObjectName mRegistered = null;
    97         private volatile ObjectName mUnregistered = null;
    98         private final boolean mStopAtFirst;
   100         public CallbackImpl() {
   101             this(true);
   102         }
   104         public CallbackImpl(final boolean stopAtFirst)
   105         {
   106             mStopAtFirst = stopAtFirst;
   107         }
   109         public ObjectName getRegistered()   { return mRegistered; }
   110         public ObjectName getUnregistered() { return mUnregistered; }
   112         protected final CountDownLatch mLatch = new CountDownLatch(1);
   114         /** Optional: wait for the CountDownLatch to fire
   115             If used, the subclass should countDown() the latch when the
   116             appropriate event happens
   117         */
   118         public void await()
   119         {
   120             try
   121             {
   122                 mLatch.await(); // wait until BootAMXMBean is ready
   123             }
   124             catch (InterruptedException e)
   125             {
   126                 throw new RuntimeException(e);
   127             }
   128         }
   130         public void mbeanRegistered(final ObjectName objectName, final MBeanListener listener)
   131         {
   132             mRegistered = objectName;
   133             if ( mStopAtFirst )
   134             {
   135                 listener.stopListening();
   136             }
   137         }
   138         public void mbeanUnregistered(final ObjectName objectName, final MBeanListener listener)
   139         {
   140             mUnregistered = objectName;
   141             if ( mStopAtFirst )
   142             {
   143                 listener.stopListening();
   144             }
   145         }
   146     }
   148     public T getCallback()
   149     {
   150         return mCallback;
   151     }
   153     /**
   154      * Listener for a specific MBean.
   155      * Caller must call {@link #start} to start listening.
   156      * @param server
   157      * @param objectName
   158      * @param callback
   159      */
   160     public MBeanListener(
   161             final MBeanServerConnection server,
   162             final ObjectName objectName,
   163             final T callback)
   164     {
   165         mMBeanServer = server;
   166         mObjectName = objectName;
   167         mJMXDomain = null;
   168         mType = null;
   169         mName = null;
   170         mCallback = callback;
   171     }
   173     /**
   174      * Listener for all MBeans of specified type, with or without a name.
   175      * Caller must call {@link #start} to start listening.
   176      * @param server
   177      * @param type type of the MBean (as found in the ObjectName)
   178      * @param callback
   179      */
   180     public MBeanListener(
   181             final MBeanServerConnection server,
   182             final String domain,
   183             final String type,
   184             final T callback)
   185     {
   186         this(server, domain, type, null, callback);
   187     }
   189     /**
   190      * Listener for MBeans of specified type, with specified name (or any name
   191      * if null is passed for the name).
   192      * Caller must call {@link #start} to start listening.
   193      * @param server
   194      * @param type type of the MBean (as found in the ObjectName)
   195      * @param name name of the MBean, or null if none
   196      * @param callback
   197      */
   198     public MBeanListener(
   199             final MBeanServerConnection server,
   200             final String domain,
   201             final String type,
   202             final String name,
   203             final T callback)
   204     {
   205         mMBeanServer = server;
   206         mJMXDomain = domain;
   207         mType = type;
   208         mName = name;
   209         mObjectName = null;
   210         mCallback = callback;
   211     }
   214     private boolean isRegistered( final MBeanServerConnection conn, final ObjectName objectName )
   215     {
   216         try
   217         {
   218             return conn.isRegistered(objectName);
   219         }
   220         catch (final Exception e)
   221         {
   222             throw new RuntimeException(e);
   223         }
   224     }
   226     /**
   227     Start listening.  If the required MBean(s) are already present, the callback
   228     will be synchronously made before returning.  It is also possible that the
   229     callback could happen twice for the same MBean.
   230      */
   231     public void startListening()
   232     {
   233         // race condition: must listen *before* looking for existing MBeans
   234         try
   235         {
   236             mMBeanServer.addNotificationListener( AMXUtil.getMBeanServerDelegateObjectName(), this, null, this);
   237         }
   238         catch (final Exception e)
   239         {
   240             throw new RuntimeException("Can't add NotificationListener", e);
   241         }
   243         if ( mObjectName != null )
   244         {
   245             if ( isRegistered(mMBeanServer, mObjectName) )
   246             {
   247                 mCallback.mbeanRegistered(mObjectName, this);
   248             }
   249         }
   250         else
   251         {
   252             // query for AMX MBeans of the requisite type
   253             String props = TYPE_KEY + "=" + mType;
   254             if (mName != null)
   255             {
   256                 props = props + "," + NAME_KEY + mName;
   257             }
   259             final ObjectName pattern = AMXUtil.newObjectName(mJMXDomain + ":" +props);
   260             try
   261             {
   262                 final Set<ObjectName> matched = mMBeanServer.queryNames(pattern, null);
   263                 for (final ObjectName objectName : matched)
   264                 {
   265                     mCallback.mbeanRegistered(objectName, this);
   266                 }
   267             }
   268             catch( final Exception e )
   269             {
   270                 throw new RuntimeException(e);
   271             }
   272         }
   273     }
   276     /** unregister the listener */
   277     public void stopListening()
   278     {
   279         try
   280         {
   281             mMBeanServer.removeNotificationListener( AMXUtil.getMBeanServerDelegateObjectName(), this);
   282         }
   283         catch (final Exception e)
   284         {
   285             throw new RuntimeException("Can't remove NotificationListener " + this, e);
   286         }
   287     }
   289     public void handleNotification(
   290             final Notification notifIn,
   291             final Object handback)
   292     {
   293         if (notifIn instanceof MBeanServerNotification)
   294         {
   295             final MBeanServerNotification notif = (MBeanServerNotification) notifIn;
   296             final ObjectName objectName = notif.getMBeanName();
   298             boolean match = false;
   299             if ( mObjectName != null && mObjectName.equals(objectName) )
   300             {
   301                 match = true;
   302             }
   303             else if ( objectName.getDomain().equals( mJMXDomain ) )
   304             {
   305                 if ( mType != null && mType.equals(objectName.getKeyProperty(TYPE_KEY)) )
   306                 {
   307                     final String mbeanName = objectName.getKeyProperty(NAME_KEY);
   308                     if (mName != null && mName.equals(mbeanName))
   309                     {
   310                         match = true;
   311                     }
   312                 }
   313             }
   315             if ( match )
   316             {
   317                 final String notifType = notif.getType();
   318                 if (MBeanServerNotification.REGISTRATION_NOTIFICATION.equals(notifType))
   319                 {
   320                     mCallback.mbeanRegistered(objectName, this);
   321                 }
   322                 else if (MBeanServerNotification.UNREGISTRATION_NOTIFICATION.equals(notifType))
   323                 {
   324                     mCallback.mbeanUnregistered(objectName, this);
   325                 }
   326             }
   327         }
   328     }
   330 }

mercurial