All Downloads are FREE. Search and download functionalities are using the official Maven repository.

org.apache.catalina.valves.CometConnectionManagerValve Maven / Gradle / Ivy

There is a newer version: 7.0.39.2
Show newest version
/*
 * Licensed to the Apache Software Foundation (ASF) under one or more
 * contributor license agreements.  See the NOTICE file distributed with
 * this work for additional information regarding copyright ownership.
 * The ASF licenses this file to You under the Apache License, Version 2.0
 * (the "License"); you may not use this file except in compliance with
 * the License.  You may obtain a copy of the License at
 * 
 *      http://www.apache.org/licenses/LICENSE-2.0
 * 
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */


package org.apache.catalina.valves;


import java.io.IOException;
import java.util.ArrayList;
import java.util.Collections;
import java.util.Iterator;
import java.util.List;

import javax.servlet.ServletException;
import javax.servlet.http.HttpSession;
import javax.servlet.http.HttpSessionEvent;
import javax.servlet.http.HttpSessionListener;

import org.apache.catalina.CometEvent;
import org.apache.catalina.CometProcessor;
import org.apache.catalina.Context;
import org.apache.catalina.Lifecycle;
import org.apache.catalina.LifecycleEvent;
import org.apache.catalina.LifecycleException;
import org.apache.catalina.LifecycleListener;
import org.apache.catalina.connector.CometEventImpl;
import org.apache.catalina.connector.Request;
import org.apache.catalina.connector.Response;
import org.apache.catalina.util.LifecycleSupport;
import org.apache.catalina.util.StringManager;


/**
 * 

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: 769328 $ $Date: 2009-04-28 18:39:24 +0800 (Tue, 28 Apr 2009) $ */ public class CometConnectionManagerValve extends ValveBase implements Lifecycle, HttpSessionListener, LifecycleListener { // ----------------------------------------------------- Instance Variables /** * The descriptive information related to this implementation. */ protected static final String info = "org.apache.catalina.valves.CometConnectionManagerValve/1.0"; /** * The string manager for this package. */ protected StringManager sm = StringManager.getManager(Constants.Package); /** * The lifecycle event support for this component. */ protected LifecycleSupport lifecycle = new LifecycleSupport(this); /** * Has this component been started yet? */ protected boolean started = false; /** * List of current Coment connections. */ protected List cometRequests = Collections.synchronizedList(new ArrayList()); /** * Name of session attribute used to store list of comet connections. */ protected String cometRequestsAttribute = "org.apache.tomcat.comet.connectionList"; // ------------------------------------------------------------- Properties // ------------------------------------------------------ Lifecycle Methods /** * Add a lifecycle event listener to this component. * * @param listener The listener to add */ public void addLifecycleListener(LifecycleListener listener) { lifecycle.addLifecycleListener(listener); } /** * Get the lifecycle listeners associated with this lifecycle. If this * Lifecycle has no listeners registered, a zero-length array is returned. */ public LifecycleListener[] findLifecycleListeners() { return lifecycle.findLifecycleListeners(); } /** * Remove a lifecycle event listener from this component. * * @param listener The listener to add */ public void removeLifecycleListener(LifecycleListener listener) { lifecycle.removeLifecycleListener(listener); } /** * 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 */ public void start() throws LifecycleException { // 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); } } /** * 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 */ public void stop() throws LifecycleException { // 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); } } public void lifecycleEvent(LifecycleEvent event) { if (event.getType() == Lifecycle.BEFORE_STOP_EVENT) { // The container is getting stopped, close all current connections Iterator iterator = cometRequests.iterator(); while (iterator.hasNext()) { Request request = iterator.next(); // Remove the session tracking attribute as it isn't // serializable or required. HttpSession session = request.getSession(false); if (session != null) { session.removeAttribute(cometRequestsAttribute); } // Close the comet connection try { CometEventImpl cometEvent = request.getEvent(); cometEvent.setEventType(CometEvent.EventType.END); cometEvent.setEventSubType( CometEvent.EventSubType.WEBAPP_RELOAD); getNext().event(request, request.getResponse(), cometEvent); cometEvent.close(); } catch (Exception e) { container.getLogger().warn( sm.getString("cometConnectionManagerValve.event"), e); } } cometRequests.clear(); } } // --------------------------------------------------------- Public Methods /** * Return descriptive information about this Valve implementation. */ public String getInfo() { return (info); } /** * 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 */ public void invoke(Request request, Response response) throws IOException, ServletException { // 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); // Track the conection for webapp reload cometRequests.add(request); // Track the connection for session expiration synchronized (session) { Request[] requests = (Request[]) session.getAttribute(cometRequestsAttribute); if (requests == null) { requests = new Request[1]; requests[0] = request; session.setAttribute(cometRequestsAttribute, requests); } else { Request[] newRequests = new Request[requests.length + 1]; for (int i = 0; i < requests.length; i++) { newRequests[i] = requests[i]; } newRequests[requests.length] = request; session.setAttribute(cometRequestsAttribute, newRequests); } } } } /** * 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 */ public void event(Request request, Response response, CometEvent event) throws IOException, ServletException { // 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 the connection from webapp reload tracking cometRequests.remove(request); // Remove connection from session expiration tracking // Note: can't get the session if it has been invalidated but // OK since session listener will have done clean-up HttpSession session = request.getSession(false); if (session != null) { synchronized (session) { Request[] reqs = null; try { reqs = (Request[]) session.getAttribute(cometRequestsAttribute); } catch (IllegalStateException ise) { // Ignore - session has been invalidated // Listener will have cleaned up } if (reqs != null) { boolean found = false; for (int i = 0; !found && (i < reqs.length); i++) { found = (reqs[i] == request); } if (found) { if (reqs.length > 1) { Request[] newConnectionInfos = new Request[reqs.length - 1]; int pos = 0; for (int i = 0; i < reqs.length; i++) { if (reqs[i] != request) { newConnectionInfos[pos++] = reqs[i]; } } try { session.setAttribute( cometRequestsAttribute, newConnectionInfos); } catch (IllegalStateException ise) { // Ignore - session has been invalidated // Listener will have cleaned up } } else { try { session.removeAttribute( cometRequestsAttribute); } catch (IllegalStateException ise) { // Ignore - session has been invalidated // Listener will have cleaned up } } } } } } } } } public void sessionCreated(HttpSessionEvent se) { } public void sessionDestroyed(HttpSessionEvent se) { // Close all Comet connections associated with this session Request[] reqs = (Request[]) se.getSession().getAttribute(cometRequestsAttribute); if (reqs != null) { for (int i = 0; i < reqs.length; i++) { Request req = reqs[i]; try { CometEventImpl event = req.getEvent(); event.setEventType(CometEvent.EventType.END); event.setEventSubType(CometEvent.EventSubType.SESSION_END); ((CometProcessor) req.getWrapper().getServlet()).event(event); event.close(); } catch (Exception e) { req.getWrapper().getParent().getLogger().warn(sm.getString( "cometConnectionManagerValve.listenerEvent"), e); } } } } }




© 2015 - 2024 Weber Informatics LLC | Privacy Policy