001: /*
002: * Licensed to the Apache Software Foundation (ASF) under one or more
003: * contributor license agreements. See the NOTICE file distributed with
004: * this work for additional information regarding copyright ownership.
005: * The ASF licenses this file to You under the Apache License, Version 2.0
006: * (the "License"); you may not use this file except in compliance with
007: * the License. You may obtain a copy of the License at
008: *
009: * http://www.apache.org/licenses/LICENSE-2.0
010: *
011: * Unless required by applicable law or agreed to in writing, software
012: * distributed under the License is distributed on an "AS IS" BASIS,
013: * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
014: * See the License for the specific language governing permissions and
015: * limitations under the License.
016: */
017:
018: package org.apache.tomcat.util.modeler;
019:
020: import java.util.ArrayList;
021: import java.util.Iterator;
022:
023: import javax.management.ListenerNotFoundException;
024: import javax.management.MBeanNotificationInfo;
025: import javax.management.Notification;
026: import javax.management.NotificationBroadcaster;
027: import javax.management.NotificationFilter;
028: import javax.management.NotificationListener;
029:
030: /**
031: * <p>Implementation of <code>NotificationBroadcaster</code> for attribute
032: * change notifications. This class is used by <code>BaseModelMBean</code> to
033: * handle notifications of attribute change events to interested listeners.
034: *</p>
035: *
036: * @author Craig R. McClanahan
037: * @author Costin Manolache
038: */
039:
040: public class BaseNotificationBroadcaster implements
041: NotificationBroadcaster {
042:
043: // ----------------------------------------------------------- Constructors
044:
045: // ----------------------------------------------------- Instance Variables
046:
047: /**
048: * The set of registered <code>BaseNotificationBroadcasterEntry</code>
049: * entries.
050: */
051: protected ArrayList entries = new ArrayList();
052:
053: // --------------------------------------------------------- Public Methods
054:
055: /**
056: * Add a notification event listener to this MBean.
057: *
058: * @param listener Listener that will receive event notifications
059: * @param filter Filter object used to filter event notifications
060: * actually delivered, or <code>null</code> for no filtering
061: * @param handback Handback object to be sent along with event
062: * notifications
063: *
064: * @exception IllegalArgumentException if the listener parameter is null
065: */
066: public void addNotificationListener(NotificationListener listener,
067: NotificationFilter filter, Object handback)
068: throws IllegalArgumentException {
069:
070: synchronized (entries) {
071:
072: // Optimization to coalesce attribute name filters
073: if (filter instanceof BaseAttributeFilter) {
074: BaseAttributeFilter newFilter = (BaseAttributeFilter) filter;
075: Iterator items = entries.iterator();
076: while (items.hasNext()) {
077: BaseNotificationBroadcasterEntry item = (BaseNotificationBroadcasterEntry) items
078: .next();
079: if ((item.listener == listener)
080: && (item.filter != null)
081: && (item.filter instanceof BaseAttributeFilter)
082: && (item.handback == handback)) {
083: BaseAttributeFilter oldFilter = (BaseAttributeFilter) item.filter;
084: String newNames[] = newFilter.getNames();
085: String oldNames[] = oldFilter.getNames();
086: if (newNames.length == 0) {
087: oldFilter.clear();
088: } else {
089: if (oldNames.length != 0) {
090: for (int i = 0; i < newNames.length; i++)
091: oldFilter.addAttribute(newNames[i]);
092: }
093: }
094: return;
095: }
096: }
097: }
098:
099: // General purpose addition of a new entry
100: entries.add(new BaseNotificationBroadcasterEntry(listener,
101: filter, handback));
102: }
103:
104: }
105:
106: /**
107: * Return an <code>MBeanNotificationInfo</code> object describing the
108: * notifications sent by this MBean.
109: */
110: public MBeanNotificationInfo[] getNotificationInfo() {
111:
112: return (new MBeanNotificationInfo[0]);
113:
114: }
115:
116: /**
117: * Remove a notification event listener from this MBean.
118: *
119: * @param listener The listener to be removed (any and all registrations
120: * for this listener will be eliminated)
121: *
122: * @exception ListenerNotFoundException if this listener is not
123: * registered in the MBean
124: */
125: public void removeNotificationListener(NotificationListener listener)
126: throws ListenerNotFoundException {
127:
128: synchronized (entries) {
129: Iterator items = entries.iterator();
130: while (items.hasNext()) {
131: BaseNotificationBroadcasterEntry item = (BaseNotificationBroadcasterEntry) items
132: .next();
133: if (item.listener == listener)
134: items.remove();
135: }
136: }
137:
138: }
139:
140: /**
141: * Remove a notification event listener from this MBean.
142: *
143: * @param listener The listener to be removed (any and all registrations
144: * for this listener will be eliminated)
145: * @param handback Handback object to be sent along with event
146: * notifications
147: *
148: * @exception ListenerNotFoundException if this listener is not
149: * registered in the MBean
150: */
151: public void removeNotificationListener(
152: NotificationListener listener, Object handback)
153: throws ListenerNotFoundException {
154:
155: removeNotificationListener(listener);
156:
157: }
158:
159: /**
160: * Remove a notification event listener from this MBean.
161: *
162: * @param listener The listener to be removed (any and all registrations
163: * for this listener will be eliminated)
164: * @param filter Filter object used to filter event notifications
165: * actually delivered, or <code>null</code> for no filtering
166: * @param handback Handback object to be sent along with event
167: * notifications
168: *
169: * @exception ListenerNotFoundException if this listener is not
170: * registered in the MBean
171: */
172: public void removeNotificationListener(
173: NotificationListener listener, NotificationFilter filter,
174: Object handback) throws ListenerNotFoundException {
175:
176: removeNotificationListener(listener);
177:
178: }
179:
180: /**
181: * Send the specified notification to all interested listeners.
182: *
183: * @param notification The notification to be sent
184: */
185: public void sendNotification(Notification notification) {
186:
187: synchronized (entries) {
188: Iterator items = entries.iterator();
189: while (items.hasNext()) {
190: BaseNotificationBroadcasterEntry item = (BaseNotificationBroadcasterEntry) items
191: .next();
192: if ((item.filter != null)
193: && (!item.filter
194: .isNotificationEnabled(notification)))
195: continue;
196: item.listener.handleNotification(notification,
197: item.handback);
198: }
199: }
200:
201: }
202:
203: // -------------------- Internal Extensions --------------------
204:
205: // Fast access. First index is the hook type
206: // ( FixedNotificationFilter.getType() ).
207: NotificationListener hooks[][] = new NotificationListener[20][];
208: int hookCount[] = new int[20];
209:
210: private synchronized void registerNotifications(
211: FixedNotificationFilter filter) {
212: String names[] = filter.getNames();
213: Registry reg = Registry.getRegistry();
214: for (int i = 0; i < names.length; i++) {
215: int code = reg.getId(null, names[i]);
216: if (hooks.length < code) {
217: // XXX reallocate
218: throw new RuntimeException("Too many hooks " + code);
219: }
220: NotificationListener listeners[] = hooks[code];
221: if (listeners == null) {
222:
223: }
224:
225: }
226: }
227:
228: }
229:
230: /**
231: * Utility class representing a particular registered listener entry.
232: */
233:
234: class BaseNotificationBroadcasterEntry {
235:
236: public BaseNotificationBroadcasterEntry(
237: NotificationListener listener, NotificationFilter filter,
238: Object handback) {
239: this .listener = listener;
240: this .filter = filter;
241: this .handback = handback;
242: }
243:
244: public NotificationFilter filter = null;
245:
246: public Object handback = null;
247:
248: public NotificationListener listener = null;
249:
250: }
|