KickJava   Java API By Example, From Geeks To Geeks.

Java > Open Source Codes > com > sun > enterprise > admin > jmx > remote > server > notification > ServerNotificationManager


1 /*
2  * The contents of this file are subject to the terms
3  * of the Common Development and Distribution License
4  * (the License). You may not use this file except in
5  * compliance with the License.
6  *
7  * You can obtain a copy of the license at
8  * https://glassfish.dev.java.net/public/CDDLv1.0.html or
9  * glassfish/bootstrap/legal/CDDLv1.0.txt.
10  * See the License for the specific language governing
11  * permissions and limitations under the License.
12  *
13  * When distributing Covered Code, include this CDDL
14  * Header Notice in each file and include the License file
15  * at glassfish/bootstrap/legal/CDDLv1.0.txt.
16  * If applicable, add the following below the CDDL Header,
17  * with the fields enclosed by brackets [] replaced by
18  * you own identifying information:
19  * "Portions Copyrighted [year] [name of copyright owner]"
20  *
21  * Copyright 2006 Sun Microsystems, Inc. All rights reserved.
22  */

23
24 package com.sun.enterprise.admin.jmx.remote.server.notification;
25
26 import java.io.IOException JavaDoc;
27 import java.io.OutputStream JavaDoc;
28
29 import java.util.logging.Logger JavaDoc;
30 import java.util.ArrayList JavaDoc;
31 import java.util.HashMap JavaDoc;
32 import java.util.Iterator JavaDoc;
33
34 import javax.servlet.*;
35 import javax.servlet.http.*;
36
37 import javax.management.*;
38
39 import com.sun.enterprise.admin.jmx.remote.DefaultConfiguration;
40 import com.sun.enterprise.admin.jmx.remote.notification.NotificationWrapper;
41 import com.sun.enterprise.admin.jmx.remote.notification.ListenerInfo;
42
43
44 /**
45  * This is the NotificationManager on the server-side responsible for
46  * dipatching notifications to the clients.
47  * The ServerNotificationManager maintains a list of NotificationConnection objects
48  * for each client.
49  */

50 public class ServerNotificationManager implements Runnable JavaDoc {
51     private HashMap JavaDoc connections = null;
52     private HashMap JavaDoc listenerMap = null;
53     private boolean exiting = false;
54     private Thread JavaDoc keepAliveThr = null;
55     private MBeanServerConnection mbsc = null;
56     private int bufsiz = DefaultConfiguration.NOTIF_MAX_BUFSIZ;
57
58     private static final Logger JavaDoc logger = Logger.getLogger(
59         DefaultConfiguration.JMXCONNECTOR_LOGGER);/*,
60         DefaultConfiguration.LOGGER_RESOURCE_BUNDLE_NAME );*/

61
62     public ServerNotificationManager(MBeanServerConnection mbsc) {
63         this.mbsc = mbsc;
64         connections = new HashMap JavaDoc();
65         listenerMap = new HashMap JavaDoc();
66         keepAliveThr = new Thread JavaDoc(this);
67         keepAliveThr.start();
68     }
69
70     /**
71      * Initializes the notification buffer size for new NotificationConnection objects.
72      * The buffer size can be set via the property com.sun.jmx.remote.http.notification.bufsize
73      * The property can be set as an init-param for the server-side connector servlet.
74      */

75     public void setBufSiz(ServletConfig cfg) {
76         String JavaDoc bsiz = cfg.getInitParameter(DefaultConfiguration.NOTIF_BUFSIZ_PROPERTY_NAME);
77         if (bsiz == null || bsiz.trim().length() == 0)
78             bsiz = System.getProperty("com.sun.web.jmx.connector.notification.bufsiz");
79         try {
80             bufsiz = Integer.parseInt(bsiz);
81         } catch (NumberFormatException JavaDoc nume) {
82             bufsiz = DefaultConfiguration.NOTIF_MAX_BUFSIZ;
83         }
84         if (bufsiz <= DefaultConfiguration.NOTIF_MIN_BUFSIZ)
85             bufsiz = DefaultConfiguration.NOTIF_MAX_BUFSIZ;
86     }
87
88     private void closeConnection(String JavaDoc id, boolean unregisterNotifications) {
89         NotificationConnection conn =
90                     (NotificationConnection) connections.get(id);
91         if (conn != null) {
92             if (unregisterNotifications) {
93                 unregisterNotifications(id);
94             }
95             connections.remove(id);
96             conn.close();
97             synchronized (conn) {
98                 conn.notify();
99             }
100         }
101     }
102
103     private void unregisterNotifications(String JavaDoc id) {
104         synchronized (listenerMap) {
105             Iterator JavaDoc itr = listenerMap.keySet().iterator();
106             while (itr.hasNext()) {
107                 ObjectName mbean = (ObjectName) itr.next();
108                 ArrayList JavaDoc list = (ArrayList JavaDoc) listenerMap.get(mbean);
109                 for (int i=0, len=list.size(); i < len; i++) {
110                     ListenerInfo info = (ListenerInfo) list.get(i);
111                     if (info.proxy != null &&
112                         ((NotificationListenerProxy)info.proxy).getId() == id) {
113                         list.remove(i);
114                         try {
115                             mbsc.removeNotificationListener(
116                                 mbean, ((NotificationListener)info.proxy));
117                         } catch (Exception JavaDoc ex) {
118                             // XXX: Log it
119
}
120                     }
121                 }
122                 listenerMap.put(mbean, list);
123             }
124         }
125     }
126
127     /**
128      * getNotifications() is called a client connects to the server or is sending a close message.
129      * This method will create a new NotificationConnection object to represent the client.
130      * This method will block until the connection needs to be closed or if the
131      * connection drops.
132      * In case the client is reconnecting (because the connection had dropped),
133      * then a NotificationConnection object is created, only if a connection object
134      * for the client is not already found.
135      */

136     public void getNotifications(HttpServletRequest req, HttpServletResponse res) {
137         String JavaDoc id = req.getParameter(DefaultConfiguration.NOTIF_ID_PARAM);
138         String JavaDoc cmd = req.getParameter(DefaultConfiguration.NOTIF_CMD_PARAM);
139         res.setStatus(res.SC_OK);
140         res.setHeader("Content-Type", "application/octet-stream");
141         res.setHeader("Connection", "Keep-Alive");
142         if (cmd != null && cmd.trim().equals(DefaultConfiguration.NOTIF_CMD_CLOSE)) {
143             synchronized (connections) {
144                 closeConnection(id, true);
145             }
146             return;
147         }
148         NotificationConnection connection = null;
149         try {
150             OutputStream JavaDoc out = res.getOutputStream();
151             synchronized (connections) {
152                 connection = (NotificationConnection) connections.get(id);
153                 if (connection == null) {
154                     connection = new NotificationConnection(out, bufsiz);
155                     connections.put(id, connection);
156                 } else {
157                     connection.reinit(out);
158                 }
159             }
160             out.flush();
161         } catch (IOException JavaDoc ioex) {
162             // TODO: Log it
163
try {
164                 res.sendError(res.SC_SERVICE_UNAVAILABLE, "Unable to send notifications, since OutputStream could not be opened");
165             } catch (IOException JavaDoc ioe) {
166                 // TODO: Log it
167
}
168             return;
169         }
170         synchronized (connection) {
171             while (!connection.hasIOExceptionOccurred()) {
172                 try {
173                     connection.wait();
174                     break; // somebody notified
175
} catch (InterruptedException JavaDoc intre) {
176                     // continue
177
}
178             }
179         }
180     }
181
182     /**
183      * Called whenever the webapp is being shutdown by the servlet container
184      */

185     public void close() {
186         exiting = true;
187         while (true) {
188             try {
189                 keepAliveThr.join();
190                 break;
191             } catch (InterruptedException JavaDoc intr) {
192             }
193         }
194         NotificationConnection conn = null;
195         synchronized (connections) {
196             HashMap JavaDoc conns = (HashMap JavaDoc) connections.clone();
197             Iterator JavaDoc itr = conns.keySet().iterator();
198             while (itr.hasNext()) {
199                 String JavaDoc id = (String JavaDoc) itr.next();
200                 closeConnection(id, false);
201             }
202         }
203     }
204
205     public boolean isExiting() {
206         return exiting;
207     }
208
209     /**
210      * The keepalive thread that sends an empty notification to every client every 10 seconds.
211      */

212     public void run() {
213         while (!isExiting()) {
214             try {
215                 Thread.sleep(DefaultConfiguration.NOTIF_WAIT_INTERVAL);
216             } catch (InterruptedException JavaDoc intrEx) {
217                 // Ignore any interrupts
218
}
219             if (isExiting())
220                 break;
221             Iterator JavaDoc itr = getConnectionsIterator();
222             NotificationConnection conn = null;
223             synchronized (connections) {
224                 while (itr.hasNext() && !isExiting()) {
225                     String JavaDoc id = (String JavaDoc) itr.next();
226                     conn = (NotificationConnection) connections.get(id);
227                     conn.fireWaitNotif();
228                 }
229             }
230         }
231     }
232
233     private Iterator JavaDoc getConnectionsIterator() {
234         Iterator JavaDoc itr = null;
235         synchronized (connections) {
236             itr = connections.keySet().iterator();
237         }
238         return itr;
239     }
240
241     /**
242      * fireNotification() is invoked by NotificationListenerProxy, whenever a notification
243      * is sent by any NotificationBroadcaster.
244      */

245     public void fireNotification(NotificationListenerProxy proxy) {
246         String JavaDoc id = proxy.getId();
247         if (id == null || id.trim().length() == 0)
248             return; // Drop this notification; Nobody is listening for this notification
249
NotificationConnection conn = null;
250         synchronized (connections) {
251             conn = (NotificationConnection) connections.get(id);
252         }
253         if (conn == null)
254             return; // Drop this notification; Nobody is listening for this notification
255

256         conn.fireNotification(proxy.getNotificationWrapper());
257     }
258
259     private synchronized void addListenerInfo(ObjectName mbean,
260                                               ListenerInfo info) {
261         ArrayList JavaDoc list = (ArrayList JavaDoc) listenerMap.get(mbean);
262         if (list == null)
263             list = new ArrayList JavaDoc();
264         list.add(info);
265         listenerMap.put(mbean, list);
266     }
267
268     /**
269      * Registers a notification listener for proper removal, for all registrations
270      * done by a call to addNotificationListener(ObjectName, ObjectName, ...).
271      * Since, the reference of the filter and handback objects is matched by
272      * the NotificationBroadcaster, the ServerNotificationManager would register
273      * the actual filter and handback object registered, with the NotificationBroadcaster,
274      * and is bound to an id, refering this registration, sent by the client.
275      */

276     public String JavaDoc addObjNameNotificationListener(ObjectName mbean,
277                                                  NotificationFilter filter,
278                                                  Object JavaDoc handback,
279                                                  String JavaDoc id) {
280         ListenerInfo info = new ListenerInfo();
281         info.filter = filter;
282         info.handback = handback;
283         info.id = id;
284         addListenerInfo(mbean, info);
285         return info.id;
286    }
287
288     /**
289      * Registers a notification listener for proper removal, for all registrations
290      * done by a call to addNotificationListener(ObjectName, NotificationListener, ...).
291      * Since, the reference of the filter and handback objects is matched by
292      * the NotificationBroadcaster, the ServerNotificationManager would register
293      * the actual filter and handback object registered, with the NotificationBroadcaster,
294      * and is bound to an id, refering this registration, sent by the client.
295      */

296     public String JavaDoc addNotificationListener(ObjectName mbean,
297                                           String JavaDoc id,
298                                           Object JavaDoc proxy) {
299         ListenerInfo info = new ListenerInfo();
300         info.id = id;
301         info.proxy = proxy;
302         addListenerInfo(mbean, info);
303
304         return info.id;
305     }
306
307     private synchronized Object JavaDoc removeListenerInfo(
308                 ObjectName mbean, String JavaDoc id, boolean getProxy) {
309         ArrayList JavaDoc list = (ArrayList JavaDoc) listenerMap.get(mbean);
310         Iterator JavaDoc itr = null;
311         if (list == null)
312             return null;
313         itr = list.iterator();
314         while (itr.hasNext()) {
315             ListenerInfo info = (ListenerInfo) itr.next();
316             if (info.id.equals(id)) {
317                 list.remove(list.indexOf(info));
318                 Object JavaDoc retObj = null;
319                 if (getProxy)
320                     retObj = info.proxy;
321                 else
322                     retObj = info;
323                 return retObj;
324             }
325         }
326
327         return null;
328     }
329
330     /**
331      * Removes a registered NotificationListener, when
332      * removeNotificationListener(ObjectName, ObjectName, ...) is called.
333      */

334     public ListenerInfo removeObjNameNotificationListener(ObjectName mbean,
335                                                           String JavaDoc id) {
336         return (ListenerInfo) removeListenerInfo(mbean, id, false);
337     }
338
339     /**
340      * Removes a registered NotificationListener, when
341      * removeNotificationListener(ObjectName, NotificationListener, ...) is called.
342      */

343     public Object JavaDoc removeNotificationListener( ObjectName mbean,
344                                                 String JavaDoc id) {
345         return removeListenerInfo(mbean, id, true);
346     }
347 }
348
349
Popular Tags