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

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

mercurial