/* * #%L * Nazgul Project: nazgul-core-jmx-api * %% * Copyright (C) 2010 - 2017 jGuru Europe AB * %% * Licensed under the jGuru Europe AB license (the "License"), based * on Apache License, Version 2.0; you may not use this file except * in compliance with the License. * * You may obtain a copy of the License at * * http://www.jguru.se/licenses/jguruCorporateSourceLicense-2.0.txt * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. * #L% * */ package se.jguru.nazgul.core.jmx.api.event; import org.slf4j.Logger; import org.slf4j.LoggerFactory; import se.jguru.nazgul.core.algorithms.api.Validate; import javax.management.AttributeChangeNotification; import javax.management.MBeanNotificationInfo; import javax.management.Notification; import javax.management.NotificationBroadcasterSupport; import javax.management.NotificationListener; import java.io.Serializable; import java.util.concurrent.Executor; /** * Abstract NotificationEmitter implementation, sporting functionality for adding and removing listeners. * * @author <a href="mailto:lj@jguru.se">Lennart Jörelid, jGuru Europe AB</a> */ public class DefaultNotificationEmitter extends NotificationBroadcasterSupport implements Serializable { // Our log private static final Logger log = LoggerFactory.getLogger(DefaultNotificationEmitter.class); // Internal state private String id; /** * <p>Constructs a NotificationBroadcasterSupport with information about the notifications that may be sent. Each * listener is invoked by the thread sending the notification. This constructor is equivalent to * {@link javax.management.NotificationBroadcasterSupport#NotificationBroadcasterSupport(java.util.concurrent.Executor, javax.management.MBeanNotificationInfo[] info)}.</p> * <p>If the <code>info</code> array is not empty, then it is * cloned by the constructor as if by {@code info.clone()}, and * each call to {@link #getNotificationInfo()} returns a new clone.</p> * * @param id a (unique) id of this DefaultNotificationEmitter. * @param info an array indicating, for each notification this MBean may send, the name of the Java class of the * notification and the notification type. Can be null, which is equivalent to an empty array. */ public DefaultNotificationEmitter(final String id, final MBeanNotificationInfo... info) { super(info); // Check sanity Validate.notEmpty(id, "id"); // Assign internal state this.id = id; } /** * <p>Constructs a NotificationBroadcasterSupport with information about the notifications that may be sent, * and where each listener is invoked using the given {@link java.util.concurrent.Executor}.</p> * <p>When {@link #sendNotification sendNotification} is called, a * listener is selected if it was added with a null {@link javax.management.NotificationFilter}, or if * {@link javax.management.NotificationFilter#isNotificationEnabled(Notification)} returns true for the * notification being sent. The call to <code>NotificationFilter.isNotificationEnabled</code> takes place in the * thread that called <code>sendNotification</code>. Then, for each selected listener, * {@link java.util.concurrent.Executor#execute executor.execute} is called with a command that calls the * <code>handleNotification</code> method.</p> * <p>If the <code>info</code> array is not empty, then it is cloned by the constructor as if by * {@code info.clone()}, and each call to {@link #getNotificationInfo()} returns a new clone.</p> * * @param id a (unique) id of this DefaultNotificationEmitter. * @param executor an executor used by the method <code>sendNotification</code> to send each notification. If it * is null, the thread calling <code>sendNotification</code> will invoke the * <code>handleNotification</code> method itself. * @param info an array indicating, for each notification this MBean may send, the name of the Java class of * the notification and the notification type. Can be null, which is equivalent to an empty array. */ public DefaultNotificationEmitter(final String id, final Executor executor, final MBeanNotificationInfo... info) { super(executor, info); // Check sanity Validate.notEmpty(id, "id"); // Assign internal state this.id = id; } /** * {@inheritDoc} */ @Override public void handleNotification(final NotificationListener listener, final Notification notification, final Object handback) { // Log somewhat if (log.isDebugEnabled() && listener != null) { log.debug("Notifying listener of type [" + listener.getClass().getName() + "]"); } // Delegate. super.handleNotification(listener, notification, handback); } /** * @return a debug String representation of the AbstractNotificationEmitter, printing its ID and its * corresponding list of MBeanNotificationInfo string-information. */ @Override public String toString() { final StringBuilder builder = new StringBuilder(); final MBeanNotificationInfo[] notificationInfo = getNotificationInfo(); final int size = notificationInfo == null ? 0 : notificationInfo.length; for (int i = 0; i < size; i++) { builder.append(" [").append(i).append("]: ").append(notificationInfo[i].toString()).append("\n"); } // All done. return "[" + getClass().getName() + " :: " + id + "] with " + size + " " + "registered MBeanNotificationInfo elements ... " + builder + "\n.... End [" + getClass().getName() + " :: " + id + "]"; } /** * Factory method to generate a StateChange DefaultNotificationEmitter instance with the supplied id. * * @param id The id of the returned DefaultNotificationEmitter. Cannot be null or empty. * @return a StateChange DefaultNotificationEmitter instance which emits events for * {@code AttributeChangeNotification.ATTRIBUTE_CHANGE} with the attribute name {@code state}. */ public static DefaultNotificationEmitter getDefaultStateChangeNotificationEmitter(final String id) { // Check sanity Validate.notEmpty(id, "id"); // All done. return new DefaultNotificationEmitter(id, new MBeanNotificationInfo( new String[]{AttributeChangeNotification.ATTRIBUTE_CHANGE}, "state", "LifecycleState changed") ); } }