FileDocCategorySizeDatePackage
CometConnectionManagerValve.javaAPI DocApache Tomcat 6.0.1413886Fri Jul 20 04:20:34 BST 2007org.apache.catalina.valves

CometConnectionManagerValve

public class CometConnectionManagerValve extends ValveBase implements HttpSessionListener, org.apache.catalina.Lifecycle, org.apache.catalina.LifecycleListener

Implementation of a Valve that tracks Comet connections, and closes them when the associated session expires or the webapp is reloaded.

This Valve should be attached to a Context.

author
Remy Maucherat
version
$Revision: 467222 $ $Date: 2006-10-24 05:17:11 +0200 (mar., 24 oct. 2006) $

Fields Summary
protected static final String
info
The descriptive information related to this implementation.
protected org.apache.catalina.util.StringManager
sm
The string manager for this package.
protected org.apache.catalina.util.LifecycleSupport
lifecycle
The lifecycle event support for this component.
protected boolean
started
Has this component been started yet?
protected ConcurrentHashMap
connections
Connection list.
Constructors Summary
Methods Summary
public voidaddLifecycleListener(org.apache.catalina.LifecycleListener listener)
Add a lifecycle event listener to this component.

param
listener The listener to add

    

    // ------------------------------------------------------------- Properties

    
    // ------------------------------------------------------ Lifecycle Methods


                       
        

        lifecycle.addLifecycleListener(listener);

    
public voidevent(org.apache.catalina.connector.Request request, org.apache.catalina.connector.Response response, org.apache.catalina.CometEvent event)
Use events to update the connection state.

param
request The servlet request to be processed
param
response The servlet response to be created
exception
IOException if an input/output error occurs
exception
ServletException if a servlet error occurs

        
        // Perform the request
        boolean ok = false;
        try {
            getNext().event(request, response, event);
            ok = true;
        } finally {
            if (!ok || response.isClosed() 
                    || (event.getEventType() == CometEvent.EventType.END)
                    || (event.getEventType() == CometEvent.EventType.ERROR
                            && !(event.getEventSubType() == CometEvent.EventSubType.TIMEOUT))) {
                // Remove from tracked list, the connection is done
                HttpSession session = request.getSession(true);
                synchronized (session) {
                    ConnectionInfo[] connectionInfos = connections.get(session.getId());
                    if (connectionInfos != null) {
                        boolean found = false;
                        for (int i = 0; !found && (i < connectionInfos.length); i++) {
                            found = (connectionInfos[i].request == request);
                        }
                        if (found) {
                            ConnectionInfo[] newConnectionInfos = 
                                new ConnectionInfo[connectionInfos.length - 1];
                            int pos = 0;
                            for (int i = 0; i < connectionInfos.length; i++) {
                                if (connectionInfos[i].request != request) {
                                    newConnectionInfos[pos++] = connectionInfos[i];
                                }
                            }
                            connections.put(session.getId(), newConnectionInfos);
                        }
                    }
                }                
            }
        }
        
    
public org.apache.catalina.LifecycleListener[]findLifecycleListeners()
Get the lifecycle listeners associated with this lifecycle. If this Lifecycle has no listeners registered, a zero-length array is returned.


        return lifecycle.findLifecycleListeners();

    
public java.lang.StringgetInfo()
Return descriptive information about this Valve implementation.

        return (info);
    
public voidinvoke(org.apache.catalina.connector.Request request, org.apache.catalina.connector.Response response)
Register requests for tracking, whenever needed.

param
request The servlet request to be processed
param
response The servlet response to be created
exception
IOException if an input/output error occurs
exception
ServletException if a servlet error occurs

        // Perform the request
        getNext().invoke(request, response);
        
        if (request.isComet() && !response.isClosed()) {
            // Start tracking this connection, since this is a 
            // begin event, and Comet mode is on
            HttpSession session = request.getSession(true);
            ConnectionInfo newConnectionInfo = new ConnectionInfo();
            newConnectionInfo.request = request;
            newConnectionInfo.response = response;
            newConnectionInfo.event = request.getEvent();
            synchronized (session) {
                String id = session.getId();
                ConnectionInfo[] connectionInfos = connections.get(id);
                if (connectionInfos == null) {
                    connectionInfos = new ConnectionInfo[1];
                    connectionInfos[0] = newConnectionInfo;
                    connections.put(id, connectionInfos);
                } else {
                    ConnectionInfo[] newConnectionInfos = 
                        new ConnectionInfo[connectionInfos.length + 1];
                    for (int i = 0; i < connectionInfos.length; i++) {
                        newConnectionInfos[i] = connectionInfos[i];
                    }
                    newConnectionInfos[connectionInfos.length] = newConnectionInfo;
                    connections.put(id, newConnectionInfos);
                }
            }
        }
        
    
public voidlifecycleEvent(org.apache.catalina.LifecycleEvent event)

        if (event.getType() == Lifecycle.BEFORE_STOP_EVENT) {
            // The webapp is getting stopped, so all current connections 
            // should be closed
            // Close all Comet connections associated with this session
            Iterator<ConnectionInfo[]> iterator = connections.values().iterator();
            while (iterator.hasNext()) {
                ConnectionInfo[] connectionInfos = iterator.next();
                if (connectionInfos != null) {
                    for (int i = 0; i < connectionInfos.length; i++) {
                        ConnectionInfo connectionInfo = connectionInfos[i];
                        try {
                            ((CometEventImpl) connectionInfo.event).setEventType(CometEvent.EventType.END);
                            ((CometEventImpl) connectionInfo.event).setEventSubType(CometEvent.EventSubType.WEBAPP_RELOAD);
                            getNext().event(connectionInfo.request, connectionInfo.response, connectionInfo.event);
                            connectionInfo.event.close();
                        } catch (Exception e) {
                            container.getLogger().warn(sm.getString("cometConnectionManagerValve.event"), e);
                        }
                    }
                }
            }
            connections.clear();
        }
    
public voidremoveLifecycleListener(org.apache.catalina.LifecycleListener listener)
Remove a lifecycle event listener from this component.

param
listener The listener to add


        lifecycle.removeLifecycleListener(listener);

    
public voidsessionCreated(javax.servlet.http.HttpSessionEvent se)

    
public voidsessionDestroyed(javax.servlet.http.HttpSessionEvent se)

        // Close all Comet connections associated with this session
        ConnectionInfo[] connectionInfos = connections.remove(se.getSession().getId());
        if (connectionInfos != null) {
            for (int i = 0; i < connectionInfos.length; i++) {
                ConnectionInfo connectionInfo = connectionInfos[i];
                try {
                    ((CometEventImpl) connectionInfo.event).setEventType(CometEvent.EventType.END);
                    ((CometEventImpl) connectionInfo.event).setEventSubType(CometEvent.EventSubType.SESSION_END);
                    getNext().event(connectionInfo.request, connectionInfo.response, connectionInfo.event);
                    connectionInfo.event.close();
                } catch (Exception e) {
                    container.getLogger().warn(sm.getString("cometConnectionManagerValve.event"), e);
                }
            }
        }
    
public voidstart()
Prepare for the beginning of active use of the public methods of this component. This method should be called after configure(), and before any of the public methods of the component are utilized.

exception
LifecycleException if this component detects a fatal error that prevents this component from being used


        // Validate and update our current component state
        if (started)
            throw new LifecycleException
                (sm.getString("semaphoreValve.alreadyStarted"));
        lifecycle.fireLifecycleEvent(START_EVENT, null);
        started = true;

        if (container instanceof Context) {
            ((Lifecycle) container).addLifecycleListener(this);
        }
        
    
public voidstop()
Gracefully terminate the active use of the public methods of this component. This method should be the last one called on a given instance of this component.

exception
LifecycleException if this component detects a fatal error that needs to be reported


        // Validate and update our current component state
        if (!started)
            throw new LifecycleException
                (sm.getString("semaphoreValve.notStarted"));
        lifecycle.fireLifecycleEvent(STOP_EVENT, null);
        started = false;

        if (container instanceof Context) {
            ((Lifecycle) container).removeLifecycleListener(this);
        }

        // The webapp is getting stopped, so all current connections 
        // should be closed
        // Close all Comet connections associated with this session
        // Note: this will only be done if the container was not a Context
        // (otherwise, this needs to be done before stop, as the servlet would
        // be deallocated already)
        Iterator<ConnectionInfo[]> iterator = connections.values().iterator();
        while (iterator.hasNext()) {
            ConnectionInfo[] connectionInfos = iterator.next();
            if (connectionInfos != null) {
                for (int i = 0; i < connectionInfos.length; i++) {
                    ConnectionInfo connectionInfo = connectionInfos[i];
                    try {
                        connectionInfo.event.close();
                    } catch (Exception e) {
                        container.getLogger().warn(sm.getString("cometConnectionManagerValve.event"), e);
                    }
                }
            }
        }
        connections.clear();