001/* 002 * Copyright 2002-2018 the original author or authors. 003 * 004 * Licensed under the Apache License, Version 2.0 (the "License"); 005 * you may not use this file except in compliance with the License. 006 * You may obtain a copy of the License at 007 * 008 * https://www.apache.org/licenses/LICENSE-2.0 009 * 010 * Unless required by applicable law or agreed to in writing, software 011 * distributed under the License is distributed on an "AS IS" BASIS, 012 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 013 * See the License for the specific language governing permissions and 014 * limitations under the License. 015 */ 016 017package org.springframework.jmx.export.notification; 018 019import javax.management.AttributeChangeNotification; 020import javax.management.MBeanException; 021import javax.management.Notification; 022import javax.management.ObjectName; 023import javax.management.modelmbean.ModelMBean; 024import javax.management.modelmbean.ModelMBeanNotificationBroadcaster; 025 026import org.springframework.util.Assert; 027 028/** 029 * {@link NotificationPublisher} implementation that uses the infrastructure 030 * provided by the {@link ModelMBean} interface to track 031 * {@link javax.management.NotificationListener javax.management.NotificationListeners} 032 * and send {@link Notification Notifications} to those listeners. 033 * 034 * @author Rob Harrop 035 * @author Juergen Hoeller 036 * @author Rick Evans 037 * @since 2.0 038 * @see javax.management.modelmbean.ModelMBeanNotificationBroadcaster 039 * @see NotificationPublisherAware 040 */ 041public class ModelMBeanNotificationPublisher implements NotificationPublisher { 042 043 /** 044 * The {@link ModelMBean} instance wrapping the managed resource into which this 045 * {@code NotificationPublisher} will be injected. 046 */ 047 private final ModelMBeanNotificationBroadcaster modelMBean; 048 049 /** 050 * The {@link ObjectName} associated with the {@link ModelMBean modelMBean}. 051 */ 052 private final ObjectName objectName; 053 054 /** 055 * The managed resource associated with the {@link ModelMBean modelMBean}. 056 */ 057 private final Object managedResource; 058 059 060 /** 061 * Create a new instance of the {@link ModelMBeanNotificationPublisher} class 062 * that will publish all {@link javax.management.Notification Notifications} 063 * to the supplied {@link ModelMBean}. 064 * @param modelMBean the target {@link ModelMBean}; must not be {@code null} 065 * @param objectName the {@link ObjectName} of the source {@link ModelMBean} 066 * @param managedResource the managed resource exposed by the supplied {@link ModelMBean} 067 * @throws IllegalArgumentException if any of the parameters is {@code null} 068 */ 069 public ModelMBeanNotificationPublisher( 070 ModelMBeanNotificationBroadcaster modelMBean, ObjectName objectName, Object managedResource) { 071 072 Assert.notNull(modelMBean, "'modelMBean' must not be null"); 073 Assert.notNull(objectName, "'objectName' must not be null"); 074 Assert.notNull(managedResource, "'managedResource' must not be null"); 075 this.modelMBean = modelMBean; 076 this.objectName = objectName; 077 this.managedResource = managedResource; 078 } 079 080 081 /** 082 * Send the supplied {@link Notification} using the wrapped 083 * {@link ModelMBean} instance. 084 * @param notification the {@link Notification} to be sent 085 * @throws IllegalArgumentException if the supplied {@code notification} is {@code null} 086 * @throws UnableToSendNotificationException if the supplied {@code notification} could not be sent 087 */ 088 @Override 089 public void sendNotification(Notification notification) { 090 Assert.notNull(notification, "Notification must not be null"); 091 replaceNotificationSourceIfNecessary(notification); 092 try { 093 if (notification instanceof AttributeChangeNotification) { 094 this.modelMBean.sendAttributeChangeNotification((AttributeChangeNotification) notification); 095 } 096 else { 097 this.modelMBean.sendNotification(notification); 098 } 099 } 100 catch (MBeanException ex) { 101 throw new UnableToSendNotificationException("Unable to send notification [" + notification + "]", ex); 102 } 103 } 104 105 /** 106 * Replaces the notification source if necessary to do so. 107 * From the {@link Notification javadoc}: 108 * <i>"It is strongly recommended that notification senders use the object name 109 * rather than a reference to the MBean object as the source."</i> 110 * @param notification the {@link Notification} whose 111 * {@link javax.management.Notification#getSource()} might need massaging 112 */ 113 private void replaceNotificationSourceIfNecessary(Notification notification) { 114 if (notification.getSource() == null || notification.getSource().equals(this.managedResource)) { 115 notification.setSource(this.objectName); 116 } 117 } 118 119}