All Downloads are FREE. Search and download functionalities are using the official Maven repository.

org.glassfish.admin.amx.util.jmx.NotificationListenerBase Maven / Gradle / Ivy

/*
 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS HEADER.
 *
 * Copyright (c) 1997-2012 Oracle and/or its affiliates. All rights reserved.
 *
 * The contents of this file are subject to the terms of either the GNU
 * General Public License Version 2 only ("GPL") or the Common Development
 * and Distribution License("CDDL") (collectively, the "License").  You
 * may not use this file except in compliance with the License.  You can
 * obtain a copy of the License at
 * https://glassfish.dev.java.net/public/CDDL+GPL_1_1.html
 * or packager/legal/LICENSE.txt.  See the License for the specific
 * language governing permissions and limitations under the License.
 *
 * When distributing the software, include this License Header Notice in each
 * file and include the License file at packager/legal/LICENSE.txt.
 *
 * GPL Classpath Exception:
 * Oracle designates this particular file as subject to the "Classpath"
 * exception as provided by Oracle in the GPL Version 2 section of the License
 * file that accompanied this code.
 *
 * Modifications:
 * If applicable, add the following below the License Header, with the fields
 * enclosed by brackets [] replaced by your own identifying information:
 * "Portions Copyright [year] [name of copyright owner]"
 *
 * Contributor(s):
 * If you wish your version of this file to be governed by only the CDDL or
 * only the GPL Version 2, indicate your decision by adding "[Contributor]
 * elects to include this software in this distribution under the [CDDL or GPL
 * Version 2] license."  If you don't indicate a single choice of license, a
 * recipient has the option to distribute your version of this file under
 * either the CDDL, the GPL Version 2 or to extend the choice of license to
 * its licensees as provided above.  However, if you add GPL Version 2 code
 * and therefore, elected the GPL Version 2 license, then the option applies
 * only if the new code is made subject to such option by the copyright
 * holder.
 */
// Portions Copyright [2019] Payara Foundation and/or affiliates

package org.glassfish.admin.amx.util.jmx;

import java.io.IOException;
import java.util.Collections;

import java.util.HashSet;
import java.util.Set;
import javax.management.InstanceNotFoundException;
import javax.management.JMException;
import javax.management.MBeanServer;
import javax.management.MBeanServerConnection;
import javax.management.MBeanServerNotification;
import javax.management.Notification;
import javax.management.NotificationFilter;
import javax.management.NotificationListener;
import javax.management.ObjectName;
import org.glassfish.admin.amx.util.SetUtil;

/**
Convenience base class for listening for Notifications
from one or more MBeans, which may be specified as
a specific MBean ObjectName, or an ObjectName pattern.
If the ObjectName is a pattern, the list of listenees
is dynamically maintained.

Caller should call {@link #cleanup} when done, because a listener is maintained on the MBeanServer delegate. */ public abstract class NotificationListenerBase implements NotificationListener { private final MBeanServerConnection mConn; /** actual MBean ObjectNames, not patterns */ private final Set mListenees; /** targets as specified by caller, may be a pattern or fixed ObjectName */ private final ObjectName mPattern; private final NotificationFilter mFilter; private RegistrationListener mDelegateListener; private volatile boolean mSetupListening; /** Calls this( conn, listenTo, null, null ).

Instantiating code must call setupListening() in order to initiate listening */ protected NotificationListenerBase(final String name, final MBeanServerConnection conn, final ObjectName pattern) throws IOException { this(name, conn, pattern, null); } /** Listen to all MBean(s) which match the pattern 'listenTo'.

Instantiating code must call setupListening() in order to initiate listening @param name arbitrary name of this listener @param conn the MBeanServerConnection or MBeanServer @param pattern an MBean ObjectName, or an ObjectName pattern @param filter optional NotificationFilter */ protected NotificationListenerBase( final String name, final MBeanServerConnection conn, final ObjectName pattern, final NotificationFilter filter) throws IOException { mConn = conn; mPattern = pattern; mFilter = filter; mDelegateListener = null; mSetupListening = false; mListenees = Collections.synchronizedSet(new HashSet()); // test connection for validity if (!conn.isRegistered(JMXUtil.getMBeanServerDelegateObjectName())) { throw new IllegalArgumentException(); } } protected synchronized void listenToMBean(final ObjectName objectName) throws InstanceNotFoundException, IOException { if (!mListenees.contains(objectName)) { mListenees.add(objectName); getMBeanServerConnection().addNotificationListener( objectName, this, mFilter, null); } } public synchronized void startListening() throws InstanceNotFoundException, IOException { if (mSetupListening) { throw new IllegalStateException("setupListening() must be called exactly once"); } if (mPattern.isPattern()) { // it's crucial we listen for registration/unregistration events // so that any patterns are maintained. // do this BEFORE the code below, of we could // miss a registration. mDelegateListener = new RegistrationListener(); JMXUtil.listenToMBeanServerDelegate(mConn, mDelegateListener, null, null); } Set s; if (mPattern.isPattern()) { s = JMXUtil.queryNames(getConn(), mPattern, null); } else { s = SetUtil.newSet(mPattern); } for (final ObjectName objectName : s) { listenToMBean(objectName); } mSetupListening = true; } /** Get the filter originally specified when constructing this object. */ public final NotificationFilter getNotificationFilter(final ObjectName objectName) { return mFilter; } protected synchronized void listenToIfMatch(final ObjectName objectName) throws IOException, InstanceNotFoundException { if (!mListenees.contains(objectName)) { final String defaultDomain = getConn().getDefaultDomain(); if (JMXUtil.matchesPattern(defaultDomain, mPattern, objectName)) { listenToMBean(objectName); } } } /** tracks coming and going of MBeans being listened to which match our patterns. */ private final class RegistrationListener implements NotificationListener { @Override public void handleNotification( final Notification notifIn, final Object handback) { if (notifIn instanceof MBeanServerNotification) { final MBeanServerNotification notif = (MBeanServerNotification) notifIn; final ObjectName objectName = notif.getMBeanName(); final String type = notif.getType(); try { if (type.equals(MBeanServerNotification.REGISTRATION_NOTIFICATION)) { listenToIfMatch(objectName); } else if (type.equals(MBeanServerNotification.UNREGISTRATION_NOTIFICATION)) { mListenees.remove(objectName); } } catch (Exception e) { // nothing can be done... } } } } /** Reset everything so that no listening is occuring and all lists are empty. */ public synchronized void cleanup() { try { if (mDelegateListener != null) { // it's crucial we listen for registration/unregistration events // so that any patterns are maintained. getConn().removeNotificationListener( JMXUtil.getMBeanServerDelegateObjectName(), mDelegateListener, null, null); mDelegateListener = null; } for (final ObjectName objectName : mListenees) { getConn().removeNotificationListener( objectName, this, mFilter, null); } } catch (JMException e) { } catch (IOException e) { } mListenees.clear(); } /** @return a copy of the MBean currently being listened to. */ public synchronized Set getListenees() { final Set objectNames = new HashSet(); synchronized (mListenees) { objectNames.addAll(mListenees); } return (objectNames); } /** @return the MBeanServerConnection in use. @throws an Exception if no longer alive ( isAlive() returns false). */ public final MBeanServerConnection getMBeanServerConnection() { return getConn(); } protected final MBeanServerConnection getConn() { return mConn; } protected final void checkAlive() throws IOException { if (!isAlive()) { throw new IOException("MBeanServerConnection failed"); } } /** @return true if still listening and the connection is still alive */ public boolean isAlive() { boolean isAlive = true; if (!(mConn instanceof MBeanServer)) { // remote, check if it is alive try { mConn.isRegistered(JMXUtil.getMBeanServerDelegateObjectName()); } catch (Exception e) { isAlive = false; } } return isAlive; } }





© 2015 - 2024 Weber Informatics LLC | Privacy Policy