FileDocCategorySizeDatePackage
ServerNotificationManager.javaAPI DocGlassfish v2 API14225Fri May 04 22:36:30 BST 2007com.sun.enterprise.admin.jmx.remote.server.notification

ServerNotificationManager

public class ServerNotificationManager extends Object implements Runnable
This is the NotificationManager on the server-side responsible for dipatching notifications to the clients. The ServerNotificationManager maintains a list of NotificationConnection objects for each client.

Fields Summary
private HashMap
connections
private HashMap
listenerMap
private boolean
exiting
private Thread
keepAliveThr
private MBeanServerConnection
mbsc
private int
bufsiz
private static final Logger
logger
Constructors Summary
public ServerNotificationManager(MBeanServerConnection mbsc)

/*, 
        DefaultConfiguration.LOGGER_RESOURCE_BUNDLE_NAME );*/

       
        this.mbsc = mbsc;
        connections = new HashMap();
        listenerMap = new HashMap();
        keepAliveThr = new Thread(this);
        keepAliveThr.start();
    
Methods Summary
private synchronized voidaddListenerInfo(javax.management.ObjectName mbean, com.sun.enterprise.admin.jmx.remote.notification.ListenerInfo info)

        ArrayList list = (ArrayList) listenerMap.get(mbean);
        if (list == null)
            list = new ArrayList();
        list.add(info);
        listenerMap.put(mbean, list);
    
public java.lang.StringaddNotificationListener(javax.management.ObjectName mbean, java.lang.String id, java.lang.Object proxy)
Registers a notification listener for proper removal, for all registrations done by a call to addNotificationListener(ObjectName, NotificationListener, ...). Since, the reference of the filter and handback objects is matched by the NotificationBroadcaster, the ServerNotificationManager would register the actual filter and handback object registered, with the NotificationBroadcaster, and is bound to an id, refering this registration, sent by the client.

        ListenerInfo info = new ListenerInfo();
        info.id = id;
        info.proxy = proxy;
        addListenerInfo(mbean, info);

        return info.id;
    
public java.lang.StringaddObjNameNotificationListener(javax.management.ObjectName mbean, javax.management.NotificationFilter filter, java.lang.Object handback, java.lang.String id)
Registers a notification listener for proper removal, for all registrations done by a call to addNotificationListener(ObjectName, ObjectName, ...). Since, the reference of the filter and handback objects is matched by the NotificationBroadcaster, the ServerNotificationManager would register the actual filter and handback object registered, with the NotificationBroadcaster, and is bound to an id, refering this registration, sent by the client.

        ListenerInfo info = new ListenerInfo();
        info.filter = filter;
        info.handback = handback;
        info.id = id;
        addListenerInfo(mbean, info);
        return info.id;
   
public voidclose()
Called whenever the webapp is being shutdown by the servlet container

        exiting = true;
        while (true) {
            try {
                keepAliveThr.join();
                break;
            } catch (InterruptedException intr) {
            }
        }
        NotificationConnection conn = null;
        synchronized (connections) {
            HashMap conns = (HashMap) connections.clone();
            Iterator itr = conns.keySet().iterator();
            while (itr.hasNext()) {
                String id = (String) itr.next();
                closeConnection(id, false);
            }
        }
    
private voidcloseConnection(java.lang.String id, boolean unregisterNotifications)

        NotificationConnection conn =
                    (NotificationConnection) connections.get(id);
        if (conn != null) {
            if (unregisterNotifications) {
                unregisterNotifications(id);
            }
            connections.remove(id);
            conn.close();
            synchronized (conn) {
                conn.notify();
            }
        }
    
public voidfireNotification(NotificationListenerProxy proxy)
fireNotification() is invoked by NotificationListenerProxy, whenever a notification is sent by any NotificationBroadcaster.

        String id = proxy.getId();
        if (id == null || id.trim().length() == 0)
            return; // Drop this notification; Nobody is listening for this notification
        NotificationConnection conn = null;
        synchronized (connections) {
            conn = (NotificationConnection) connections.get(id);
        }
        if (conn == null)
            return; // Drop this notification; Nobody is listening for this notification

        conn.fireNotification(proxy.getNotificationWrapper());
    
private java.util.IteratorgetConnectionsIterator()

        Iterator itr = null;
        synchronized (connections) {
            itr = connections.keySet().iterator();
        }
        return itr;
    
public voidgetNotifications(javax.servlet.http.HttpServletRequest req, javax.servlet.http.HttpServletResponse res)
getNotifications() is called a client connects to the server or is sending a close message. This method will create a new NotificationConnection object to represent the client. This method will block until the connection needs to be closed or if the connection drops. In case the client is reconnecting (because the connection had dropped), then a NotificationConnection object is created, only if a connection object for the client is not already found.

        String id = req.getParameter(DefaultConfiguration.NOTIF_ID_PARAM);
        String cmd = req.getParameter(DefaultConfiguration.NOTIF_CMD_PARAM);
        res.setStatus(res.SC_OK);
        res.setHeader("Content-Type", "application/octet-stream");
        res.setHeader("Connection", "Keep-Alive");
        if (cmd != null && cmd.trim().equals(DefaultConfiguration.NOTIF_CMD_CLOSE)) {
            synchronized (connections) {
                closeConnection(id, true);
            }
            return;
        }
        NotificationConnection connection = null;
        try {
            OutputStream out = res.getOutputStream();
            synchronized (connections) {
                connection = (NotificationConnection) connections.get(id);
                if (connection == null) {
                    connection = new NotificationConnection(out, bufsiz);
                    connections.put(id, connection);
                } else {
                    connection.reinit(out);
                }
            }
            out.flush();
        } catch (IOException ioex) {
            // TODO: Log it
            try {
                res.sendError(res.SC_SERVICE_UNAVAILABLE, "Unable to send notifications, since OutputStream could not be opened");
            } catch (IOException ioe) {
                // TODO: Log it
            }
            return;
        }
        synchronized (connection) {
            while (!connection.hasIOExceptionOccurred()) {
                try {
                    connection.wait();
                    break; // somebody notified
                } catch (InterruptedException intre) {
                    // continue
                }
            }
        }
    
public booleanisExiting()

        return exiting;
    
private synchronized java.lang.ObjectremoveListenerInfo(javax.management.ObjectName mbean, java.lang.String id, boolean getProxy)

        ArrayList list = (ArrayList) listenerMap.get(mbean);
        Iterator itr = null;
        if (list == null)
            return null;
        itr = list.iterator();
        while (itr.hasNext()) {
            ListenerInfo info = (ListenerInfo) itr.next();
            if (info.id.equals(id)) {
                list.remove(list.indexOf(info));
                Object retObj = null;
                if (getProxy)
                    retObj = info.proxy;
                else
                    retObj = info;
                return retObj;
            }
        }

        return null;
    
public java.lang.ObjectremoveNotificationListener(javax.management.ObjectName mbean, java.lang.String id)
Removes a registered NotificationListener, when removeNotificationListener(ObjectName, NotificationListener, ...) is called.

        return removeListenerInfo(mbean, id, true);
    
public com.sun.enterprise.admin.jmx.remote.notification.ListenerInforemoveObjNameNotificationListener(javax.management.ObjectName mbean, java.lang.String id)
Removes a registered NotificationListener, when removeNotificationListener(ObjectName, ObjectName, ...) is called.

        return (ListenerInfo) removeListenerInfo(mbean, id, false);
    
public voidrun()
The keepalive thread that sends an empty notification to every client every 10 seconds.

        while (!isExiting()) {
            try {
                Thread.sleep(DefaultConfiguration.NOTIF_WAIT_INTERVAL);
            } catch (InterruptedException intrEx) {
                // Ignore any interrupts
            }
            if (isExiting())
                break;
            Iterator itr = getConnectionsIterator();
            NotificationConnection conn = null;
            synchronized (connections) {
                while (itr.hasNext() && !isExiting()) {
                    String id = (String) itr.next();
                    conn = (NotificationConnection) connections.get(id);
                    conn.fireWaitNotif();
                }
            }
        }
    
public voidsetBufSiz(javax.servlet.ServletConfig cfg)
Initializes the notification buffer size for new NotificationConnection objects. The buffer size can be set via the property com.sun.jmx.remote.http.notification.bufsize The property can be set as an init-param for the server-side connector servlet.

        String bsiz = cfg.getInitParameter(DefaultConfiguration.NOTIF_BUFSIZ_PROPERTY_NAME);
        if (bsiz == null || bsiz.trim().length() == 0)
            bsiz = System.getProperty("com.sun.web.jmx.connector.notification.bufsiz");
        try {
            bufsiz = Integer.parseInt(bsiz);
        } catch (NumberFormatException nume) {
            bufsiz = DefaultConfiguration.NOTIF_MAX_BUFSIZ;
        }
        if (bufsiz <= DefaultConfiguration.NOTIF_MIN_BUFSIZ)
            bufsiz = DefaultConfiguration.NOTIF_MAX_BUFSIZ;
    
private voidunregisterNotifications(java.lang.String id)

        synchronized (listenerMap) {
            Iterator itr = listenerMap.keySet().iterator();
            while (itr.hasNext()) {
                ObjectName mbean = (ObjectName) itr.next();
                ArrayList list = (ArrayList) listenerMap.get(mbean);
                for (int i=0, len=list.size(); i < len; i++) {
                    ListenerInfo info = (ListenerInfo) list.get(i);
                    if (info.proxy != null &&
                        ((NotificationListenerProxy)info.proxy).getId() == id) {
                        list.remove(i);
                        try {
                            mbsc.removeNotificationListener(
                                mbean, ((NotificationListener)info.proxy));
                        } catch (Exception ex) {
                            // XXX: Log it
                        }
                    }
                }
                listenerMap.put(mbean, list);
            }
        }