tomcat-dev mailing list archives

Site index · List index
Message view « Date » · « Thread »
Top « Date » · « Thread »
From fha...@apache.org
Subject svn commit: r380209 [9/12] - in /tomcat/container/tc5.5.x/modules: groupcom/ groupcom/etc/ groupcom/src/ groupcom/src/share/ groupcom/src/share/org/ groupcom/src/share/org/apache/ groupcom/src/share/org/apache/catalina/ groupcom/src/share/org/apache/ca...
Date Thu, 23 Feb 2006 19:55:25 GMT
Added: tomcat/container/tc5.5.x/modules/ha/src/share/org/apache/catalina/cluster/session/JvmRouteBinderValve.java
URL: http://svn.apache.org/viewcvs/tomcat/container/tc5.5.x/modules/ha/src/share/org/apache/catalina/cluster/session/JvmRouteBinderValve.java?rev=380209&view=auto
==============================================================================
--- tomcat/container/tc5.5.x/modules/ha/src/share/org/apache/catalina/cluster/session/JvmRouteBinderValve.java (added)
+++ tomcat/container/tc5.5.x/modules/ha/src/share/org/apache/catalina/cluster/session/JvmRouteBinderValve.java Thu Feb 23 11:55:14 2006
@@ -0,0 +1,548 @@
+/*
+ * Copyright 1999,2004-2005 The Apache Software Foundation.
+ * 
+ * Licensed 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.cluster.session;
+
+import java.io.IOException;
+
+import javax.servlet.ServletException;
+import javax.servlet.http.Cookie;
+
+import org.apache.catalina.Container;
+import org.apache.catalina.Context;
+import org.apache.catalina.Engine;
+import org.apache.catalina.Globals;
+import org.apache.catalina.Host;
+import org.apache.catalina.Lifecycle;
+import org.apache.catalina.LifecycleException;
+import org.apache.catalina.LifecycleListener;
+import org.apache.catalina.Manager;
+import org.apache.catalina.Session;
+import org.apache.catalina.cluster.CatalinaCluster;
+import org.apache.catalina.cluster.ClusterManager;
+import org.apache.catalina.cluster.ClusterMessage;
+import org.apache.catalina.cluster.ClusterValve;
+import org.apache.catalina.connector.Request;
+import org.apache.catalina.connector.Response;
+import org.apache.catalina.session.ManagerBase;
+import org.apache.catalina.util.LifecycleSupport;
+import org.apache.catalina.util.StringManager;
+import org.apache.catalina.valves.ValveBase;
+
+/**
+ * Valve to handle Tomcat jvmRoute takeover using mod_jk module after node
+ * failure. After a node crashed the next request going to other cluster node.
+ * Now the answering from apache is slower ( make some error handshaking. Very
+ * bad with apache at my windows.). We rewrite now the cookie jsessionid
+ * information to the backup cluster node. After the next response all client
+ * request goes direct to the backup node. The change sessionid send also to all
+ * other cluster nodes. Well, now the session stickyness work directly to the
+ * backup node and traffic don't go back too restarted cluster nodes!
+ * 
+ * At all cluster node you must configure the as ClusterListener since 5.5.10
+ * {@link org.apache.catalina.cluster.session.JvmRouteSessionIDBinderListener JvmRouteSessionIDBinderListener}
+ * or before with
+ * org.apache.catalina.cluster.session.JvmRouteSessionIDBinderListenerLifecycle.
+ * 
+ * Add this Valve to your host definition at conf/server.xml .
+ * 
+ * Since 5.5.10 as direct cluster valve:<br/>
+ * <pre>
+ *  &lt;Cluster&gt;
+ *  &lt;Valve className=&quot;org.apache.catalina.cluster.session.JvmRouteBinderValve&quot; /&gt;  
+ *  &lt;/Cluster&gt;
+ * </pre>
+ * <br />
+ * Before 5.5.10 as Host element:<br/>
+ * <pre>
+ *  &lt;Hostr&gt;
+ *  &lt;Valve className=&quot;org.apache.catalina.cluster.session.JvmRouteBinderValve&quot; /&gt;  
+ *  &lt;/Hostr&gt;
+ * </pre>
+ * 
+ * Trick:<br/>
+ * You can enable this mod_jk turnover mode via JMX before you drop a node to all backup nodes!
+ * Set enable true on all JvmRouteBinderValve backups, disable worker at mod_jk 
+ * and then drop node and restart it! Then enable mod_jk Worker and disable JvmRouteBinderValves again. 
+ * This use case means that only requested session are migrated.
+ * 
+ * @author Peter Rossbach
+ * @version $Revision: 326110 $ $Date: 2005-10-18 09:08:36 -0500 (Tue, 18 Oct 2005) $
+ */
+public class JvmRouteBinderValve extends ValveBase implements ClusterValve, Lifecycle {
+
+    /*--Static Variables----------------------------------------*/
+    public static org.apache.commons.logging.Log log = org.apache.commons.logging.LogFactory
+            .getLog(JvmRouteBinderValve.class);
+
+    /**
+     * The descriptive information about this implementation.
+     */
+    protected static final String info = "org.apache.catalina.cluster.session.JvmRouteBinderValve/1.2";
+
+    /*--Instance Variables--------------------------------------*/
+
+    /**
+     * the cluster
+     */
+    protected CatalinaCluster cluster;
+
+    /**
+     * The string manager for this package.
+     */
+    protected StringManager sm = StringManager.getManager(Constants.Package);
+
+    /**
+     * Has this component been started yet?
+     */
+    protected boolean started = false;
+
+    /**
+     * enabled this component
+     */
+    protected boolean enabled = true;
+
+    /**
+     * number of session that no at this tomcat instanz hosted
+     */
+    protected long numberOfSessions = 0;
+
+    protected String sessionIdAttribute = "org.apache.catalina.cluster.session.JvmRouteOrignalSessionID";
+
+    /**
+     * The lifecycle event support for this component.
+     */
+    protected LifecycleSupport lifecycle = new LifecycleSupport(this);
+
+    /*--Logic---------------------------------------------------*/
+
+    /**
+     * Return descriptive information about this implementation.
+     */
+    public String getInfo() {
+
+        return (info);
+
+    }
+
+    /**
+     * set session id attribute to failed node for request.
+     * 
+     * @return Returns the sessionIdAttribute.
+     */
+    public String getSessionIdAttribute() {
+        return sessionIdAttribute;
+    }
+
+    /**
+     * get name of failed reqeust session attribute
+     * 
+     * @param sessionIdAttribute
+     *            The sessionIdAttribute to set.
+     */
+    public void setSessionIdAttribute(String sessionIdAttribute) {
+        this.sessionIdAttribute = sessionIdAttribute;
+    }
+
+    /**
+     * @return Returns the number of migrated sessions.
+     */
+    public long getNumberOfSessions() {
+        return numberOfSessions;
+    }
+
+    /**
+     * @return Returns the enabled.
+     */
+    public boolean getEnabled() {
+        return enabled;
+    }
+
+    /**
+     * @param enabled
+     *            The enabled to set.
+     */
+    public void setEnabled(boolean enabled) {
+        this.enabled = enabled;
+    }
+
+    /**
+     * Detect possible the JVMRoute change at cluster backup node..
+     * 
+     * @param request
+     *            tomcat request being processed
+     * @param response
+     *            tomcat response being processed
+     * @exception IOException
+     *                if an input/output error has occurred
+     * @exception ServletException
+     *                if a servlet error has occurred
+     */
+    public void invoke(Request request, Response response) throws IOException,
+            ServletException {
+
+         if (getEnabled() 
+             && getCluster() != null
+             && request.getContext() != null
+             && request.getContext().getDistributable() ) {
+             // valve cluster can access manager - other cluster handle turnover 
+             // at host level - hopefully!
+             Manager manager = request.getContext().getManager();
+             if (manager != null && manager instanceof ClusterManager
+                     && getCluster().getManager(((ClusterManager)manager).getName()) != null)
+                 handlePossibleTurnover(request, response);
+        }
+        // Pass this request on to the next valve in our pipeline
+        getNext().invoke(request, response);
+    }
+
+    /**
+     * handle possible session turn over.
+     * 
+     * @see JvmRouteBinderValve#handleJvmRoute(Request, Response, String, String)
+     * @param request current request
+     * @param response current response
+     */
+    protected void handlePossibleTurnover(Request request, Response response) {
+        Session session = request.getSessionInternal(false);
+        if (session != null) {
+            long t1 = System.currentTimeMillis();
+            String jvmRoute = getLocalJvmRoute(request);
+            if (jvmRoute == null) {
+                if (log.isWarnEnabled())
+                    log.warn(sm.getString("jvmRoute.missingJvmRouteAttribute"));
+                return;
+            }
+            if (request.isRequestedSessionIdFromURL()) {
+                if (log.isDebugEnabled())
+                    log.debug(sm.getString("jvmRoute.skipURLSessionIDs"));
+            } else {
+                handleJvmRoute( request, response,session.getIdInternal(), jvmRoute);
+            }
+            if (log.isDebugEnabled()) {
+                long t2 = System.currentTimeMillis();
+                long time = t2 - t1;
+                log.debug(sm.getString("jvmRoute.turnoverInfo", new Long(time)));
+            }
+        }
+    }
+
+    /**
+     * get jvmroute from engine
+     * 
+     * @param request current request
+     * @return return jvmRoute from ManagerBase or null
+     */
+    protected String getLocalJvmRoute(Request request) {
+        Manager manager = getManager(request);
+        if(manager instanceof ManagerBase)
+            return ((ManagerBase) manager).getJvmRoute();
+        return null ;
+    }
+
+    /**
+     * get Cluster DeltaManager
+     * 
+     * @param request current request
+     * @return manager or null
+     */
+    protected Manager getManager(Request request) {
+        Manager manager = request.getContext().getManager();
+        if (log.isDebugEnabled()) {
+            if(manager != null)
+                log.debug(sm.getString("jvmRoute.foundManager", manager,  request.getContext().getName()));
+            else 
+                log.debug(sm.getString("jvmRoute.notFoundManager", manager,  request.getContext().getName()));
+        }
+        return manager;
+    }
+
+    /**
+     * @return Returns the cluster.
+     */
+    public CatalinaCluster getCluster() {
+        return cluster;
+    }
+    
+    /**
+     * @param cluster The cluster to set.
+     */
+    public void setCluster(CatalinaCluster cluster) {
+        this.cluster = cluster;
+    }
+    
+    /**
+     * Handle jvmRoute stickyness after tomcat instance failed. After this
+     * correction a new Cookie send to client with new jvmRoute and the
+     * SessionID change propage to the other cluster nodes.
+     * 
+     * @param request current request
+     * @param response
+     *            Tomcat Response
+     * @param sessionId
+     *            request SessionID from Cookie
+     * @param localJvmRoute
+     *            local jvmRoute
+     */
+    protected void handleJvmRoute(
+            Request request, Response response,String sessionId, String localJvmRoute) {
+        // get requested jvmRoute.
+        String requestJvmRoute = null;
+        int index = sessionId.indexOf(".");
+        if (index > 0) {
+            requestJvmRoute = sessionId
+                    .substring(index + 1, sessionId.length());
+        }
+        if (requestJvmRoute != null && !requestJvmRoute.equals(localJvmRoute)) {
+            if (log.isDebugEnabled()) {
+                log.debug(sm.getString("jvmRoute.failover", requestJvmRoute,
+                        localJvmRoute, sessionId));
+            }
+            // OK - turnover the session ?
+            String newSessionID = sessionId.substring(0, index) + "."
+                    + localJvmRoute;
+            Session catalinaSession = null;
+            try {
+                catalinaSession = getManager(request).findSession(sessionId);
+            } catch (IOException e) {
+                // Hups!
+            }
+            if (catalinaSession != null) {
+                changeSessionID(request, response, sessionId, newSessionID,
+                        catalinaSession);
+                numberOfSessions++;
+            } else {
+                if (log.isDebugEnabled()) {
+                    log.debug(sm.getString("jvmRoute.cannotFindSession",
+                            sessionId));
+                }
+            }
+        }
+    }
+
+    /**
+     * change session id and send to all cluster nodes
+     * 
+     * @param request current request
+     * @param response current response
+     * @param sessionId
+     *            original session id
+     * @param newSessionID
+     *            new session id for node migration
+     * @param catalinaSession
+     *            current session with original session id
+     */
+    protected void changeSessionID(Request request,
+            Response response, String sessionId, String newSessionID, Session catalinaSession) {
+        lifecycle.fireLifecycleEvent("Before session migration",
+                catalinaSession);
+        request.setRequestedSessionId(newSessionID);
+        catalinaSession.setId(newSessionID);
+        if (catalinaSession instanceof DeltaSession)
+            ((DeltaSession) catalinaSession).resetDeltaRequest();
+        setNewSessionCookie(request, response,newSessionID);
+        // set orginal sessionid at request, to allow application detect the
+        // change
+        if (sessionIdAttribute != null && !"".equals(sessionIdAttribute)) {
+            if (log.isDebugEnabled()) {
+                log.debug(sm.getString("jvmRoute.set.orignalsessionid",sessionIdAttribute,sessionId));
+            }
+            request.setAttribute(sessionIdAttribute, sessionId);
+        }
+        // now sending the change to all other clusternode!
+        ClusterManager manager = (ClusterManager)catalinaSession.getManager();
+        sendSessionIDClusterBackup(manager,request,sessionId, newSessionID);
+        lifecycle
+                .fireLifecycleEvent("After session migration", catalinaSession);
+        if (log.isDebugEnabled()) {
+            log.debug(sm.getString("jvmRoute.changeSession", sessionId,
+                    newSessionID));
+        }
+    }
+
+    /**
+     * Send the changed Sessionid to all clusternodes.
+     * 
+     * @see JvmRouteSessionIDBinderListener#messageReceived(ClusterMessage)
+     * @param manager
+     *            ClusterManager
+     * @param sessionId
+     *            current failed sessionid
+     * @param newSessionID
+     *            new session id, bind to the new cluster node
+     */
+    protected void sendSessionIDClusterBackup(ClusterManager manager,Request request,String sessionId,
+            String newSessionID) {
+        SessionIDMessage msg = new SessionIDMessage();
+        msg.setOrignalSessionID(sessionId);
+        msg.setBackupSessionID(newSessionID);
+        Context context = request.getContext();
+        msg.setContextPath(context.getPath());
+        msg.setHost(context.getParent().getName());
+        if(manager.isSendClusterDomainOnly())
+            cluster.sendClusterDomain(msg);
+        else
+            cluster.send(msg);
+    }
+
+    /**
+     * Sets a new cookie for the given session id and response and see
+     * {@link org.apache.catalina.connector.Request#configureSessionCookie(javax.servlet.http.Cookie)}
+     * 
+     * @param request current request
+     * @param response Tomcat Response
+     * @param sessionId The session id
+     */
+    protected void setNewSessionCookie(Request request,
+                                       Response response, String sessionId) {
+        if (response != null) {
+            Context context = request.getContext();
+            if (context.getCookies()) {
+                // set a new session cookie
+                Cookie newCookie = new Cookie(Globals.SESSION_COOKIE_NAME,
+                        sessionId);
+                newCookie.setMaxAge(-1);
+                String contextPath = null;
+                if (!response.getConnector().getEmptySessionPath()
+                        && (context != null)) {
+                    contextPath = context.getEncodedPath();
+                }
+                if ((contextPath != null) && (contextPath.length() > 0)) {
+                    newCookie.setPath(contextPath);
+                } else {
+                    newCookie.setPath("/");
+                }
+                if (request.isSecure()) {
+                    newCookie.setSecure(true);
+                }
+                if (log.isDebugEnabled()) {
+                    log.debug(sm.getString("jvmRoute.newSessionCookie",
+                            sessionId, Globals.SESSION_COOKIE_NAME, newCookie
+                                    .getPath(), new Boolean(newCookie
+                                    .getSecure())));
+                }
+                response.addCookie(newCookie);
+            }
+        }
+    }
+
+    // ------------------------------------------------------ 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 <code>configure()</code>,
+     * 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("jvmRoute.valve.alreadyStarted"));
+        lifecycle.fireLifecycleEvent(START_EVENT, null);
+        started = true;
+        if (cluster == null) {
+            Container hostContainer = getContainer();
+            // compatibility with JvmRouteBinderValve version 1.1
+            // ( setup at context.xml or context.xml.default )
+            if (!(hostContainer instanceof Host)) {
+                if (log.isWarnEnabled())
+                    log.warn(sm.getString("jvmRoute.configure.warn"));
+                hostContainer = hostContainer.getParent();
+            }
+            if (hostContainer instanceof Host
+                    && ((Host) hostContainer).getCluster() != null) {
+                cluster = (CatalinaCluster) ((Host) hostContainer).getCluster();
+            } else {
+                Container engine = hostContainer.getParent() ;
+                if (engine instanceof Engine
+                        && ((Engine) engine).getCluster() != null) {
+                    cluster = (CatalinaCluster) ((Engine) engine).getCluster();
+                }
+            }
+        }
+        if (cluster == null) {
+            throw new RuntimeException("No clustering support at container "
+                    + container.getName());
+        }
+        
+        if (log.isInfoEnabled())
+            log.info(sm.getString("jvmRoute.valve.started"));
+
+    }
+
+    /**
+     * 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("jvmRoute.valve.notStarted"));
+        lifecycle.fireLifecycleEvent(STOP_EVENT, null);
+        started = false;
+        cluster = null;
+        numberOfSessions = 0;
+        if (log.isInfoEnabled())
+            log.info(sm.getString("jvmRoute.valve.stopped"));
+
+    }
+
+}

Added: tomcat/container/tc5.5.x/modules/ha/src/share/org/apache/catalina/cluster/session/JvmRouteSessionIDBinderLifecycleListener.java
URL: http://svn.apache.org/viewcvs/tomcat/container/tc5.5.x/modules/ha/src/share/org/apache/catalina/cluster/session/JvmRouteSessionIDBinderLifecycleListener.java?rev=380209&view=auto
==============================================================================
--- tomcat/container/tc5.5.x/modules/ha/src/share/org/apache/catalina/cluster/session/JvmRouteSessionIDBinderLifecycleListener.java (added)
+++ tomcat/container/tc5.5.x/modules/ha/src/share/org/apache/catalina/cluster/session/JvmRouteSessionIDBinderLifecycleListener.java Thu Feb 23 11:55:14 2006
@@ -0,0 +1,216 @@
+/*
+ * Copyright 1999,2004-2005 The Apache Software Foundation.
+ *
+ * Licensed 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.cluster.session;
+
+import javax.management.MBeanServer;
+import javax.management.MBeanServerFactory;
+import javax.management.MalformedObjectNameException;
+import javax.management.ObjectName;
+import javax.management.modelmbean.ModelMBean;
+
+import org.apache.catalina.Lifecycle;
+import org.apache.catalina.LifecycleEvent;
+import org.apache.catalina.LifecycleListener;
+import org.apache.catalina.cluster.CatalinaCluster;
+
+import org.apache.catalina.core.StandardHost;
+import org.apache.catalina.util.StringManager;
+import org.apache.commons.logging.Log;
+import org.apache.commons.logging.LogFactory;
+import org.apache.commons.modeler.ManagedBean;
+import org.apache.commons.modeler.Registry;
+import org.apache.catalina.cluster.*;
+
+/**
+ * Register new JvmRouteSessionIDBinderListener to receive Session ID changes.
+ * 
+ * add following at your server.xml Host section
+ * 
+ * <pre>
+ *        &lt;Host &gt;... 
+ *          &lt;Listener className=&quot;org.apache.catalina.cluster.session.JvmRouteSessionIDBinderLifecycleListener&quot; /&gt;
+ *          &lt;Cluster ...&gt;
+ *        &lt;/Host&gt;
+ * </pre>
+ * FIXME add Engine support
+ * @deprecated
+ * @author Peter Rossbach
+ */
+public class JvmRouteSessionIDBinderLifecycleListener implements
+        LifecycleListener {
+    private static Log log = LogFactory
+            .getLog(JvmRouteSessionIDBinderLifecycleListener.class);
+
+    /**
+     * The descriptive information string for this implementation.
+     */
+    private static final String info = "org.apache.catalina.cluster.session.JvmRouteSessionIDBinderLifecycleListener/1.0";
+
+    /**
+     * The string resources for this package.
+     */
+    protected static final StringManager sm = StringManager
+            .getManager(Constants.Package);
+
+    private boolean enabled = true;
+
+    private MBeanServer mserver = null;
+
+    private Registry registry = null;
+
+    private ClusterListener sessionMoverListener;
+
+    /*
+     * start and stop cluster
+     * 
+     * @see org.apache.catalina.LifecycleListener#lifecycleEvent(org.apache.catalina.LifecycleEvent)
+     */
+    public void lifecycleEvent(LifecycleEvent event) {
+
+        if (enabled && event.getSource() instanceof StandardHost) {
+
+            if (Lifecycle.AFTER_START_EVENT.equals(event.getType())) {
+                if (log.isDebugEnabled())
+                    log.debug(sm.getString("jvmRoute.listener.started"));
+                startSessionIDListener((StandardHost) event.getSource());
+            } else if (Lifecycle.BEFORE_STOP_EVENT.equals(event.getType())) {
+                if (log.isDebugEnabled())
+                    log.debug(sm.getString("jvmRoute.listener.stopped"));
+                stopSessionIDListener((StandardHost) event.getSource());
+            }
+        }
+    }
+
+    /**
+     * stop sessionID binder at cluster
+     * 
+     * @param host
+     *            clustered host
+     */
+    protected void stopSessionIDListener(StandardHost host) {
+        if (sessionMoverListener != null) {
+            CatalinaCluster cluster = (CatalinaCluster) host.getCluster();
+            cluster.removeClusterListener(sessionMoverListener);
+            if (mserver != null) {
+                try {
+                    ObjectName objectName = getObjectName(host);
+                    mserver.unregisterMBean(objectName);
+                } catch (Exception e) {
+                    log.error(e);
+                }
+            }
+        }
+    }
+
+    /**
+     * @param host
+     * @return The object name
+     * @throws MalformedObjectNameException
+     */
+    protected ObjectName getObjectName(StandardHost host) throws MalformedObjectNameException {
+        ObjectName objectName = new ObjectName(
+                host.getDomain()
+                        + ":type=Listener,name=JvmRouteSessionIDBinderListener,host=" + host.getName());
+        return objectName;
+    }
+
+    /**
+     * start sessionID mover at cluster
+     * 
+     * @param host
+     *            clustered host
+     */
+    protected void startSessionIDListener(StandardHost host) {
+        try {
+            ObjectName objectName = null;
+            getMBeanServer();
+            objectName = getObjectName(host);
+            if (mserver.isRegistered(objectName)) {
+                if (log.isInfoEnabled())
+                    log.info(sm.getString("jvmRoute.run.already"));
+                return;
+            }
+            sessionMoverListener = new JvmRouteSessionIDBinderListener();
+            mserver.registerMBean(getManagedBean(sessionMoverListener),
+                    objectName);
+            CatalinaCluster cluster = (CatalinaCluster) host.getCluster();
+            sessionMoverListener.setCluster(cluster);
+            ((JvmRouteSessionIDBinderListener) sessionMoverListener).start();
+        } catch (Exception ex) {
+            log.error(ex.getMessage(), ex);
+        }
+    }
+
+    protected MBeanServer getMBeanServer() throws Exception {
+        if (mserver == null) {
+            if (MBeanServerFactory.findMBeanServer(null).size() > 0) {
+                mserver = (MBeanServer) MBeanServerFactory
+                        .findMBeanServer(null).get(0);
+            } else {
+                mserver = MBeanServerFactory.createMBeanServer();
+            }
+            registry = Registry.getRegistry(null, null);
+            registry.loadMetadata(this.getClass().getResourceAsStream(
+                    "mbeans-descriptors.xml"));
+        }
+        return (mserver);
+    }
+
+    /**
+     * Returns the ModelMBean
+     * 
+     * @param object
+     *            The Object to get the ModelMBean for
+     * @return The ModelMBean
+     * @throws Exception
+     *             If an error occurs this constructors throws this exception
+     */
+    protected ModelMBean getManagedBean(Object object) throws Exception {
+        ModelMBean mbean = null;
+        if (registry != null) {
+            ManagedBean managedBean = registry.findManagedBean(object
+                    .getClass().getName());
+            mbean = managedBean.createMBean(object);
+        }
+        return mbean;
+    }
+
+    /**
+     * @return Returns the enabled.
+     */
+    public boolean isEnabled() {
+        return enabled;
+    }
+
+    /**
+     * @param enabled
+     *            The enabled to set.
+     */
+    public void setEnabled(boolean enabled) {
+        this.enabled = enabled;
+    }
+
+    /**
+     * Return descriptive information about this Listener implementation and the
+     * corresponding version number, in the format
+     * <code>&lt;description&gt;/&lt;version&gt;</code>.
+     */
+    public String getInfo() {
+
+        return (info);
+
+    }
+}

Added: tomcat/container/tc5.5.x/modules/ha/src/share/org/apache/catalina/cluster/session/JvmRouteSessionIDBinderListener.java
URL: http://svn.apache.org/viewcvs/tomcat/container/tc5.5.x/modules/ha/src/share/org/apache/catalina/cluster/session/JvmRouteSessionIDBinderListener.java?rev=380209&view=auto
==============================================================================
--- tomcat/container/tc5.5.x/modules/ha/src/share/org/apache/catalina/cluster/session/JvmRouteSessionIDBinderListener.java (added)
+++ tomcat/container/tc5.5.x/modules/ha/src/share/org/apache/catalina/cluster/session/JvmRouteSessionIDBinderListener.java Thu Feb 23 11:55:14 2006
@@ -0,0 +1,165 @@
+/*
+ * Copyright 1999,2004-2005 The Apache Software Foundation.
+ *
+ * Licensed 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.cluster.session;
+
+import java.io.IOException;
+
+import org.apache.catalina.Container;
+import org.apache.catalina.Context;
+import org.apache.catalina.Engine;
+import org.apache.catalina.LifecycleException;
+import org.apache.catalina.Session;
+import org.apache.catalina.cluster.ClusterMessage;
+import org.apache.catalina.core.StandardEngine;
+import org.apache.catalina.cluster.*;
+
+/**
+ * Receive SessionID cluster change from other backup node after primary session
+ * node is failed.
+ * 
+ * @author Peter Rossbach
+ * @version $Revision: 378258 $ $Date: 2006-02-16 08:42:35 -0600 (Thu, 16 Feb 2006) $
+ */
+public class JvmRouteSessionIDBinderListener extends ClusterListener {
+ 
+    /**
+     * The descriptive information about this implementation.
+     */
+    protected static final String info = "org.apache.catalina.cluster.session.JvmRouteSessionIDBinderListener/1.1";
+
+    //--Instance Variables--------------------------------------
+
+
+    protected boolean started = false;
+
+    /**
+     * number of session that goes to this cluster node
+     */
+    private long numberOfSessions = 0;
+
+    //--Constructor---------------------------------------------
+
+    public JvmRouteSessionIDBinderListener() {
+    }
+
+    //--Logic---------------------------------------------------
+
+    /**
+     * Return descriptive information about this implementation.
+     */
+    public String getInfo() {
+
+        return (info);
+
+    }
+
+    /**
+     * @return Returns the numberOfSessions.
+     */
+    public long getNumberOfSessions() {
+        return numberOfSessions;
+    }
+
+    /**
+     * Add this Mover as Cluster Listener ( receiver)
+     * 
+     * @throws LifecycleException
+     */
+    public void start() throws LifecycleException {
+        if (started)
+            return;
+        getCluster().addClusterListener(this);
+        started = true;
+        if (log.isInfoEnabled())
+            log.info(sm.getString("jvmRoute.clusterListener.started"));
+    }
+
+    /**
+     * Remove this from Cluster Listener
+     * 
+     * @throws LifecycleException
+     */
+    public void stop() throws LifecycleException {
+        started = false;
+        getCluster().removeClusterListener(this);
+        if (log.isInfoEnabled())
+            log.info(sm.getString("jvmRoute.clusterListener.stopped"));
+    }
+
+    /**
+     * Callback from the cluster, when a message is received, The cluster will
+     * broadcast it invoking the messageReceived on the receiver.
+     * 
+     * @param msg
+     *            ClusterMessage - the message received from the cluster
+     */
+    public void messageReceived(ClusterMessage msg) {
+        if (msg instanceof SessionIDMessage && msg != null) {
+            SessionIDMessage sessionmsg = (SessionIDMessage) msg;
+            if (log.isDebugEnabled())
+                log.debug(sm.getString(
+                        "jvmRoute.receiveMessage.sessionIDChanged", sessionmsg
+                                .getOrignalSessionID(), sessionmsg
+                                .getBackupSessionID(), sessionmsg
+                                .getContextPath()));
+            Container container = getCluster().getContainer();
+            Container host = null ;
+            if(container instanceof Engine) {
+                host = container.findChild(sessionmsg.getHost());
+            } else {
+                host = container ;
+            }
+            if (host != null) {
+                Context context = (Context) host.findChild(sessionmsg
+                        .getContextPath());
+                if (context != null) {
+                    try {
+                        Session session = context.getManager().findSession(
+                                sessionmsg.getOrignalSessionID());
+                        if (session != null) {
+                            session.setId(sessionmsg.getBackupSessionID());
+                        } else if (log.isInfoEnabled())
+                            log.info(sm.getString("jvmRoute.lostSession",
+                                    sessionmsg.getOrignalSessionID(),
+                                    sessionmsg.getContextPath()));
+                    } catch (IOException e) {
+                        log.error(e);
+                    }
+
+                } else if (log.isErrorEnabled())
+                    log.error(sm.getString("jvmRoute.contextNotFound",
+                            sessionmsg.getContextPath(), ((StandardEngine) host
+                                    .getParent()).getJvmRoute()));
+            } else if (log.isErrorEnabled())
+                log.error(sm.getString("jvmRoute.hostNotFound", sessionmsg.getContextPath()));
+        }
+    }
+
+    /**
+     * Accept only SessionIDMessages
+     * 
+     * @param msg
+     *            ClusterMessage
+     * @return boolean - returns true to indicate that messageReceived should be
+     *         invoked. If false is returned, the messageReceived method will
+     *         not be invoked.
+     */
+    public boolean accept(ClusterMessage msg) {
+        return (msg instanceof SessionIDMessage);
+    }
+}
+

Added: tomcat/container/tc5.5.x/modules/ha/src/share/org/apache/catalina/cluster/session/LocalStrings.properties
URL: http://svn.apache.org/viewcvs/tomcat/container/tc5.5.x/modules/ha/src/share/org/apache/catalina/cluster/session/LocalStrings.properties?rev=380209&view=auto
==============================================================================
--- tomcat/container/tc5.5.x/modules/ha/src/share/org/apache/catalina/cluster/session/LocalStrings.properties (added)
+++ tomcat/container/tc5.5.x/modules/ha/src/share/org/apache/catalina/cluster/session/LocalStrings.properties Thu Feb 23 11:55:14 2006
@@ -0,0 +1,96 @@
+deltaManager.createSession.ise=createSession: Too many active sessions
+deltaManager.createSession.newSession=Created a DeltaSession with Id [{0}] Total count={1}
+deltaManager.createMessage.access=Manager [{0}]: create session message [{1}] access.
+deltaManager.createMessage.accessChangePrimary=Manager [{0}]: create session message [{1}] access to change primary.
+deltaManager.createMessage.allSessionData=Manager [{0}] send all session data.
+deltaManager.createMessage.allSessionTransfered=Manager [{0}] send all session data transfered
+deltaManager.createMessage.delta=Manager [{0}]: create session message [{1}] delta request.
+deltaManager.createMessage.expire=Manager [{0}]: create session message [{1}] expire.
+deltaManager.createMessage.unableCreateDeltaRequest=Unable to serialize delta request for sessionid [{0}]
+deltaManager.dropMessage=Manager [{0}]: Drop message {1} inside GET_ALL_SESSIONS sync phase start date {2} message date {3}
+deltaManager.foundMasterMember=Found for context [{0}] the replication master member [{1}]
+deltaManager.loading.cnfe=ClassNotFoundException while loading persisted sessions: {0}
+deltaManager.loading.existing.session=overload existing session {0} 
+deltaManager.loading.ioe=IOException while loading persisted sessions: {0}
+deltaManager.loading.withContextClassLoader=Manager [{0}]: Loading the object data with a context class loader.
+deltaManager.loading.withoutClassLoader=Manager [{0}]: Loading the object data without a context class loader.
+deltaManager.managerLoad=Exception loading sessions from persistent storage
+deltaManager.noCluster=Starting... no cluster associated with this context: [{0}]
+deltaManager.noMasterMember=Starting... with no other member for context [{0}] at domain [{1}]
+deltaManager.noMembers=Manager [{0}]: skipping state transfer. No members active in cluster group.
+deltaManager.noSessionState=Manager [{0}]: No session state send at {1} received, timing out after {2} ms.
+deltaManager.notStarted=Manager has not yet been started
+deltaManager.sendMessage.newSession=Manager [{0}] send new session ({1})
+deltaManager.expireSessions=Manager [{0}] expiring sessions upon shutdown
+deltaManager.receiveMessage.accessed=Manager [{0}]: received session [{1}] accessed.
+deltaManager.receiveMessage.createNewSession=Manager [{0}]: received session [{1}] created.
+deltaManager.receiveMessage.delta=Manager [{0}]: received session [{1}] delta.
+deltaManager.receiveMessage.error=Manager [{0}]: Unable to receive message through TCP channel
+deltaManager.receiveMessage.eventType=Manager [{0}]: Received SessionMessage of type=({1}) from [{2}]
+deltaManager.receiveMessage.expired=Manager [{0}]: received session [{1}] expired.
+deltaManager.receiveMessage.transfercomplete=Manager [{0}] received from node [{1}:{2}] session state transfered.
+deltaManager.receiveMessage.unloadingAfter=Manager [{0}]: unloading sessions complete
+deltaManager.receiveMessage.unloadingBegin=Manager [{0}]: start unloading sessions
+deltaManager.receiveMessage.allSessionDataAfter=Manager [{0}]: session state deserialized
+deltaManager.receiveMessage.allSessionDataBegin=Manager [{0}]: received session state data
+deltaManager.receiveMessage.fromWrongDomain=Manager [{0}]: Received wrong SessionMessage of type=({1}) from [{2}] with domain [{3}] (localdomain [{4}] 
+deltaManager.registerCluster=Register manager {0} to cluster element {1} with name {2}
+deltaManager.sessionReceived=Manager [{0}]; session state send at {1} received in {2} ms.
+deltaManager.sessionTimeout=Invalid session timeout setting {0}
+deltaManager.startClustering=Starting clustering manager at {0}
+deltaManager.stopped=Manager [{0}] is stopping
+deltaManager.unloading.ioe=IOException while saving persisted sessions: {0}
+deltaManager.waitForSessionState=Manager [{0}], requesting session state from {1}. This operation will timeout if no session state has been received within 60 seconds.
+deltaRequest.showPrincipal=Principal [{0}] is set to session {1}
+deltaRequest.wrongPrincipalClass=DeltaManager only support GenericPrincipal. Your realm used principal class {0}.
+deltaSession.notifying=Notifying cluster of expiration primary={0} sessionId [{1}]
+deltaSession.valueBound.ex=Session bound listener throw an exception
+deltaSession.valueBinding.ex=Session binding listener throw an exception
+deltaSession.valueUnbound.ex=Session unbound listener throw an exception
+deltaSession.readSession=readObject() loading session [{0}]
+deltaSession.readAttribute=session [{0}] loading attribute '{1}' with value '{2}'
+deltaSession.writeSession=writeObject() storing session [{0}]
+jvmRoute.cannotFindSession=Can't find session [{0}]
+jvmRoute.changeSession=Changed session from [{0}] to [{1}]
+jvmRoute.clusterListener.started=Cluster JvmRouteSessionIDBinderListener started
+jvmRoute.clusterListener.stopped=Cluster JvmRouteSessionIDBinderListener stopped
+jvmRoute.configure.warn=Please, setup your JvmRouteBinderValve at host valve, not at context valve!
+jvmRoute.contextNotFound=Context [{0}] not found at node [{1}]!
+jvmRoute.failover=Detected a failover with different jvmRoute - orginal route: [{0}] new one: [{1}] at session id [{2}]
+jvmRoute.foundManager=Found Cluster DeltaManager {0} at {1}
+jvmRoute.hostNotFound=No host found [{0}]
+jvmRoute.listener.started=SessionID Binder Listener started
+jvmRoute.listener.stopped=SessionID Binder Listener stopped
+jvmRoute.lostSession=Lost Session [{0}] at path [{1}]
+jvmRoute.missingJvmRouteAttribute=No engine jvmRoute attribute configured!
+jvmRoute.newSessionCookie=Setting cookie with session id [{0}] name: [{1}] path: [{2}] secure: [{3}]
+jvmRoute.notFoundManager=Not found Cluster DeltaManager {0} at {1}
+jvmRoute.receiveMessage.sessionIDChanged=Cluster JvmRouteSessionIDBinderListener received orginal session ID [{0}] set to new id [{1}] for context path [{2}]
+jvmRoute.run.already=jvmRoute SessionID receiver run already
+jvmRoute.skipURLSessionIDs=Skip reassign jvm route check, sessionid comes from URL!
+jvmRoute.turnoverInfo=Turnover Check time {0} msec
+jvmRoute.valve.alreadyStarted=jvmRoute backup sessionID correction is started
+jvmRoute.valve.notStarted=jvmRoute backup sessionID correction run already
+jvmRoute.valve.started=JvmRouteBinderValve started
+jvmRoute.valve.stopped=JvmRouteBinderValve stopped
+jvmRoute.set.orignalsessionid=Set Orginal Session id at request attriute {0} value: {1}
+standardSession.getId.ise=getId: Session already invalidated
+standardSession.attributeEvent=Session attribute event listener threw exception
+standardSession.attributeEvent=Session attribute event listener threw exception
+standardSession.bindingEvent=Session binding event listener threw exception
+standardSession.invalidate.ise=invalidate: Session already invalidated
+standardSession.isNew.ise=isNew: Session already invalidated
+standardSession.getAttribute.ise=getAttribute: Session already invalidated
+standardSession.getAttributeNames.ise=getAttributeNames: Session already invalidated
+standardSession.getCreationTime.ise=getCreationTime: Session already invalidated
+standardSession.getLastAccessedTime.ise=getLastAccessedTime: Session already invalidated
+standardSession.getId.ise=getId: Session already invalidated
+standardSession.getMaxInactiveInterval.ise=getMaxInactiveInterval: Session already invalidated
+standardSession.getValueNames.ise=getValueNames: Session already invalidated
+standardSession.notSerializable=Cannot serialize session attribute {0} for session {1}
+standardSession.removeAttribute.ise=removeAttribute: Session already invalidated
+standardSession.sessionEvent=Session event listener threw exception
+standardSession.setAttribute.iae=setAttribute: Non-serializable attribute
+standardSession.setAttribute.ise=setAttribute: Session already invalidated
+standardSession.setAttribute.namenull=setAttribute: name parameter cannot be null
+standardSession.sessionCreated=Created Session id = {0}

Added: tomcat/container/tc5.5.x/modules/ha/src/share/org/apache/catalina/cluster/session/ReplicatedSession.java
URL: http://svn.apache.org/viewcvs/tomcat/container/tc5.5.x/modules/ha/src/share/org/apache/catalina/cluster/session/ReplicatedSession.java?rev=380209&view=auto
==============================================================================
--- tomcat/container/tc5.5.x/modules/ha/src/share/org/apache/catalina/cluster/session/ReplicatedSession.java (added)
+++ tomcat/container/tc5.5.x/modules/ha/src/share/org/apache/catalina/cluster/session/ReplicatedSession.java Thu Feb 23 11:55:14 2006
@@ -0,0 +1,285 @@
+
+/*
+ * Copyright 1999,2004 The Apache Software Foundation.
+ * 
+ * Licensed 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.cluster.session;
+
+/**
+ * Title:        Tomcat Session Replication for Tomcat 4.0 <BR>
+ * Description:  A very simple straight forward implementation of
+ *               session replication of servers in a cluster.<BR>
+ *               This session replication is implemented "live". By live
+ *               I mean, when a session attribute is added into a session on Node A
+ *               a message is broadcasted to other messages and setAttribute is called on the replicated
+ *               sessions.<BR>
+ *               A full description of this implementation can be found under
+ *               <href="http://www.filip.net/tomcat/">Filip's Tomcat Page</a><BR>
+ *
+ * Copyright:    See apache license
+ * @author  Filip Hanik
+ * @version $Revision: 303842 $ $Date: 2005-04-10 11:20:46 -0500 (Sun, 10 Apr 2005) $
+ * Description:<BR>
+ * The ReplicatedSession class is a simple extension of the StandardSession class
+ * It overrides a few methods (setAttribute, removeAttribute, expire, access) and has
+ * hooks into the InMemoryReplicationManager to broadcast and receive events from the cluster.<BR>
+ * This class inherits the readObjectData and writeObject data methods from the StandardSession
+ * and does not contain any serializable elements in addition to the inherited ones from the StandardSession
+ *
+ */
+import org.apache.catalina.Manager;
+import java.io.IOException;
+import java.io.ObjectInputStream;
+import java.io.ObjectOutputStream;
+import java.security.Principal;
+
+public class ReplicatedSession extends org.apache.catalina.session.StandardSession
+implements org.apache.catalina.cluster.ClusterSession{
+
+    private transient Manager mManager = null;
+    protected boolean isDirty = false;
+    private transient long lastAccessWasDistributed = System.currentTimeMillis();
+    private boolean isPrimarySession=true;
+    
+
+    public ReplicatedSession(Manager manager) {
+        super(manager);
+        mManager = manager;
+    }
+
+
+    public boolean isDirty()
+    {
+        return isDirty;
+    }
+
+    public void setIsDirty(boolean dirty)
+    {
+        isDirty = dirty;
+    }
+
+
+    public void setLastAccessWasDistributed(long time) {
+        lastAccessWasDistributed = time;
+    }
+
+    public long getLastAccessWasDistributed() {
+        return lastAccessWasDistributed;
+    }
+
+
+    public void removeAttribute(String name) {
+        setIsDirty(true);
+        super.removeAttribute(name);
+    }
+
+    /**
+     * see parent description,
+     * plus we also notify other nodes in the cluster
+     */
+    public void removeAttribute(String name, boolean notify) {
+        setIsDirty(true);
+        super.removeAttribute(name,notify);
+    }
+
+
+    /**
+     * Sets an attribute and notifies the other nodes in the cluster
+     */
+    public void setAttribute(String name, Object value)
+    {
+        if ( value == null ) {
+          removeAttribute(name);
+          return;
+        }
+        if (!(value instanceof java.io.Serializable))
+            throw new java.lang.IllegalArgumentException("Value for attribute "+name+" is not serializable.");
+        setIsDirty(true);
+        super.setAttribute(name,value);
+    }
+
+    public void setMaxInactiveInterval(int interval) {
+        setIsDirty(true);
+        super.setMaxInactiveInterval(interval);
+    }
+
+
+    /**
+     * Sets the manager for this session
+     * @param mgr - the servers InMemoryReplicationManager
+     */
+    public void setManager(SimpleTcpReplicationManager mgr)
+    {
+        mManager = mgr;
+        super.setManager(mgr);
+    }
+
+
+    /**
+     * Set the authenticated Principal that is associated with this Session.
+     * This provides an <code>Authenticator</code> with a means to cache a
+     * previously authenticated Principal, and avoid potentially expensive
+     * <code>Realm.authenticate()</code> calls on every request.
+     *
+     * @param principal The new Principal, or <code>null</code> if none
+     */
+    public void setPrincipal(Principal principal) {
+        super.setPrincipal(principal);
+        setIsDirty(true);
+    }
+
+    public void expire() {
+        SimpleTcpReplicationManager mgr =(SimpleTcpReplicationManager)getManager();
+        mgr.sessionInvalidated(getIdInternal());
+        setIsDirty(true);
+        super.expire();
+    }
+
+    public void invalidate() {
+        SimpleTcpReplicationManager mgr =(SimpleTcpReplicationManager)getManager();
+        mgr.sessionInvalidated(getIdInternal());
+        setIsDirty(true);
+        super.invalidate();
+    }
+
+
+    /**
+     * Read a serialized version of the contents of this session object from
+     * the specified object input stream, without requiring that the
+     * StandardSession itself have been serialized.
+     *
+     * @param stream The object input stream to read from
+     *
+     * @exception ClassNotFoundException if an unknown class is specified
+     * @exception IOException if an input/output error occurs
+     */
+    public void readObjectData(ObjectInputStream stream)
+        throws ClassNotFoundException, IOException {
+
+        super.readObjectData(stream);
+
+    }
+
+
+    /**
+     * Write a serialized version of the contents of this session object to
+     * the specified object output stream, without requiring that the
+     * StandardSession itself have been serialized.
+     *
+     * @param stream The object output stream to write to
+     *
+     * @exception IOException if an input/output error occurs
+     */
+    public void writeObjectData(ObjectOutputStream stream)
+        throws IOException {
+
+        super.writeObjectData(stream);
+
+    }
+    
+    public void setId(String id, boolean tellNew) {
+
+        if ((this.id != null) && (manager != null))
+            manager.remove(this);
+
+        this.id = id;
+
+        if (manager != null)
+            manager.add(this);
+        if (tellNew) tellNew();
+    }
+    
+    
+
+
+
+
+
+
+    /**
+     * returns true if this session is the primary session, if that is the
+     * case, the manager can expire it upon timeout.
+     */
+    public boolean isPrimarySession() {
+        return isPrimarySession;
+    }
+
+    /**
+     * Sets whether this is the primary session or not.
+     * @param primarySession Flag value
+     */
+    public void setPrimarySession(boolean primarySession) {
+        this.isPrimarySession=primarySession;
+    }
+
+
+
+
+    /**
+     * Implements a log method to log through the manager
+     */
+    protected void log(String message) {
+
+        if ((mManager != null) && (mManager instanceof SimpleTcpReplicationManager)) {
+            ((SimpleTcpReplicationManager) mManager).log.debug("ReplicatedSession: " + message);
+        } else {
+            System.out.println("ReplicatedSession: " + message);
+        }
+
+    }
+
+    protected void log(String message, Throwable x) {
+
+        if ((mManager != null) && (mManager instanceof SimpleTcpReplicationManager)) {
+            ((SimpleTcpReplicationManager) mManager).log.error("ReplicatedSession: " + message,x);
+        } else {
+            System.out.println("ReplicatedSession: " + message);
+            x.printStackTrace();
+        }
+
+    }
+
+    public String toString() {
+        StringBuffer buf = new StringBuffer("ReplicatedSession id=");
+        buf.append(getIdInternal()).append(" ref=").append(super.toString()).append("\n");
+        java.util.Enumeration e = getAttributeNames();
+        while ( e.hasMoreElements() ) {
+            String name = (String)e.nextElement();
+            Object value = getAttribute(name);
+            buf.append("\tname=").append(name).append("; value=").append(value).append("\n");
+        }
+        buf.append("\tLastAccess=").append(getLastAccessedTime()).append("\n");
+        return buf.toString();
+    }
+    public int getAccessCount() {
+        return accessCount;
+    }
+    public void setAccessCount(int accessCount) {
+        this.accessCount = accessCount;
+    }
+    public long getLastAccessedTime() {
+        return lastAccessedTime;
+    }
+    public void setLastAccessedTime(long lastAccessedTime) {
+        this.lastAccessedTime = lastAccessedTime;
+    }
+    public long getThisAccessedTime() {
+        return thisAccessedTime;
+    }
+    public void setThisAccessedTime(long thisAccessedTime) {
+        this.thisAccessedTime = thisAccessedTime;
+    }
+
+}

Added: tomcat/container/tc5.5.x/modules/ha/src/share/org/apache/catalina/cluster/session/ReplicationStream.java
URL: http://svn.apache.org/viewcvs/tomcat/container/tc5.5.x/modules/ha/src/share/org/apache/catalina/cluster/session/ReplicationStream.java?rev=380209&view=auto
==============================================================================
--- tomcat/container/tc5.5.x/modules/ha/src/share/org/apache/catalina/cluster/session/ReplicationStream.java (added)
+++ tomcat/container/tc5.5.x/modules/ha/src/share/org/apache/catalina/cluster/session/ReplicationStream.java Thu Feb 23 11:55:14 2006
@@ -0,0 +1,99 @@
+/*
+ * Copyright 1999,2004-2005 The Apache Software Foundation.
+ * 
+ * Licensed 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.cluster.session;
+
+import java.io.InputStream;
+import java.io.IOException;
+import java.io.ObjectInputStream;
+import java.io.ObjectStreamClass;
+
+/**
+ * Custom subclass of <code>ObjectInputStream</code> that loads from the
+ * class loader for this web application.  This allows classes defined only
+ * with the web application to be found correctly.
+ *
+ * @author Craig R. McClanahan
+ * @author Bip Thelin
+ * @version $Revision: 377484 $, $Date: 2006-02-13 15:00:05 -0600 (Mon, 13 Feb 2006) $
+ */
+
+public final class ReplicationStream extends ObjectInputStream {
+
+
+    /**
+     * The class loader we will use to resolve classes.
+     */
+    private ClassLoader classLoader = null;
+
+    /**
+     * Construct a new instance of CustomObjectInputStream
+     *
+     * @param stream The input stream we will read from
+     * @param classLoader The class loader used to instantiate objects
+     *
+     * @exception IOException if an input/output error occurs
+     */
+    public ReplicationStream(InputStream stream,
+                             ClassLoader classLoader)
+        throws IOException {
+
+        super(stream);
+        this.classLoader = classLoader;
+    }
+
+    /**
+     * Load the local class equivalent of the specified stream class
+     * description, by using the class loader assigned to this Context.
+     *
+     * @param classDesc Class description from the input stream
+     *
+     * @exception ClassNotFoundException if this class cannot be found
+     * @exception IOException if an input/output error occurs
+     */
+    public Class resolveClass(ObjectStreamClass classDesc)
+        throws ClassNotFoundException, IOException {
+        String name = classDesc.getName();
+        boolean tryRepFirst = name.startsWith("org.apache.catalina.cluster");
+        try {
+            try
+            {
+                if ( tryRepFirst ) return findReplicationClass(name);
+                else return findExternalClass(name);
+            }
+            catch ( Exception x )
+            {
+                if ( tryRepFirst ) return findExternalClass(name);
+                else return findReplicationClass(name);
+            }
+        } catch (ClassNotFoundException e) {
+            return super.resolveClass(classDesc);
+        }
+    }
+    
+    public Class findReplicationClass(String name)
+        throws ClassNotFoundException, IOException {
+        return Class.forName(name, false, getClass().getClassLoader());
+    }
+
+    public Class findExternalClass(String name)
+        throws ClassNotFoundException, IOException {
+        return Class.forName(name, false, classLoader);
+    }
+
+
+}

Added: tomcat/container/tc5.5.x/modules/ha/src/share/org/apache/catalina/cluster/session/SerializablePrincipal.java
URL: http://svn.apache.org/viewcvs/tomcat/container/tc5.5.x/modules/ha/src/share/org/apache/catalina/cluster/session/SerializablePrincipal.java?rev=380209&view=auto
==============================================================================
--- tomcat/container/tc5.5.x/modules/ha/src/share/org/apache/catalina/cluster/session/SerializablePrincipal.java (added)
+++ tomcat/container/tc5.5.x/modules/ha/src/share/org/apache/catalina/cluster/session/SerializablePrincipal.java Thu Feb 23 11:55:14 2006
@@ -0,0 +1,190 @@
+/*
+ * Copyright 1999,2004 The Apache Software Foundation.
+ * 
+ * Licensed 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.cluster.session;
+
+
+import java.util.Arrays;
+import java.util.List;
+import org.apache.catalina.Realm;
+
+
+/**
+ * Generic implementation of <strong>java.security.Principal</strong> that
+ * is available for use by <code>Realm</code> implementations.
+ * The GenericPrincipal does NOT implement serializable and I didn't want to change that implementation
+ * hence I implemented this one instead.
+ * @author Filip Hanik
+ * @version $Revision: 303587 $ $Date: 2004-12-09 08:36:43 -0600 (Thu, 09 Dec 2004) $
+ */
+import org.apache.catalina.realm.GenericPrincipal;
+public class SerializablePrincipal  implements java.io.Serializable {
+
+
+    // ----------------------------------------------------------- Constructors
+
+    public SerializablePrincipal()
+    {
+        super();
+    }
+    /**
+     * Construct a new Principal, associated with the specified Realm, for the
+     * specified username and password.
+     *
+     * @param realm The Realm that owns this Principal
+     * @param name The username of the user represented by this Principal
+     * @param password Credentials used to authenticate this user
+     */
+    public SerializablePrincipal(Realm realm, String name, String password) {
+
+        this(realm, name, password, null);
+
+    }
+
+
+    /**
+     * Construct a new Principal, associated with the specified Realm, for the
+     * specified username and password, with the specified role names
+     * (as Strings).
+     *
+     * @param realm The Realm that owns this principal
+     * @param name The username of the user represented by this Principal
+     * @param password Credentials used to authenticate this user
+     * @param roles List of roles (must be Strings) possessed by this user
+     */
+    public SerializablePrincipal(Realm realm, String name, String password,
+                            List roles) {
+
+        super();
+        this.realm = realm;
+        this.name = name;
+        this.password = password;
+        if (roles != null) {
+            this.roles = new String[roles.size()];
+            this.roles = (String[]) roles.toArray(this.roles);
+            if (this.roles.length > 0)
+                Arrays.sort(this.roles);
+        }
+
+    }
+
+
+    // ------------------------------------------------------------- Properties
+
+
+    /**
+     * The username of the user represented by this Principal.
+     */
+    protected String name = null;
+
+    public String getName() {
+        return (this.name);
+    }
+
+
+    /**
+     * The authentication credentials for the user represented by
+     * this Principal.
+     */
+    protected String password = null;
+
+    public String getPassword() {
+        return (this.password);
+    }
+
+
+    /**
+     * The Realm with which this Principal is associated.
+     */
+    protected transient Realm realm = null;
+
+    public Realm getRealm() {
+        return (this.realm);
+    }
+
+    public void setRealm(Realm realm) {
+        this.realm = realm;
+    }
+
+
+
+
+    /**
+     * The set of roles associated with this user.
+     */
+    protected String roles[] = new String[0];
+
+    public String[] getRoles() {
+        return (this.roles);
+    }
+
+
+    // --------------------------------------------------------- Public Methods
+
+
+
+
+    /**
+     * Return a String representation of this object, which exposes only
+     * information that should be public.
+     */
+    public String toString() {
+
+        StringBuffer sb = new StringBuffer("SerializablePrincipal[");
+        sb.append(this.name);
+        sb.append("]");
+        return (sb.toString());
+
+    }
+
+    public static SerializablePrincipal createPrincipal(GenericPrincipal principal)
+    {
+        if ( principal==null) return null;
+        return new SerializablePrincipal(principal.getRealm(),
+                                         principal.getName(),
+                                         principal.getPassword(),
+                                         principal.getRoles()!=null?Arrays.asList(principal.getRoles()):null);
+    }
+
+    public GenericPrincipal getPrincipal( Realm realm )
+    {
+        return new GenericPrincipal(realm,name,password,getRoles()!=null?Arrays.asList(getRoles()):null);
+    }
+    
+    public static GenericPrincipal readPrincipal(java.io.ObjectInputStream in, Realm realm) throws java.io.IOException{
+        String name = in.readUTF();
+        boolean hasPwd = in.readBoolean();
+        String pwd = null;
+        if ( hasPwd ) pwd = in.readUTF();
+        int size = in.readInt();
+        String[] roles = new String[size];
+        for ( int i=0; i<size; i++ ) roles[i] = in.readUTF();
+        return new GenericPrincipal(realm,name,pwd,Arrays.asList(roles));
+    }
+    
+    public static void writePrincipal(GenericPrincipal p, java.io.ObjectOutputStream out) throws java.io.IOException {
+        out.writeUTF(p.getName());
+        out.writeBoolean(p.getPassword()!=null);
+        if ( p.getPassword()!= null ) out.writeUTF(p.getPassword());
+        String[] roles = p.getRoles();
+        if ( roles == null ) roles = new String[0];
+        out.writeInt(roles.length);
+        for ( int i=0; i<roles.length; i++ ) out.writeUTF(roles[i]);
+    }
+
+
+}

Added: tomcat/container/tc5.5.x/modules/ha/src/share/org/apache/catalina/cluster/session/SessionIDMessage.java
URL: http://svn.apache.org/viewcvs/tomcat/container/tc5.5.x/modules/ha/src/share/org/apache/catalina/cluster/session/SessionIDMessage.java?rev=380209&view=auto
==============================================================================
--- tomcat/container/tc5.5.x/modules/ha/src/share/org/apache/catalina/cluster/session/SessionIDMessage.java (added)
+++ tomcat/container/tc5.5.x/modules/ha/src/share/org/apache/catalina/cluster/session/SessionIDMessage.java Thu Feb 23 11:55:14 2006
@@ -0,0 +1,182 @@
+/*
+ * Copyright 1999,2004 The Apache Software Foundation.
+ *
+ * Licensed 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.cluster.session;
+
+import org.apache.catalina.cluster.ClusterMessage;
+
+/**
+ * Session id change cluster message
+ * 
+ * @author Peter Rossbach
+ * 
+ * @version $Revision: 326110 $ $Date: 2005-10-18 09:08:36 -0500 (Tue, 18 Oct 2005) $
+ */
+public class SessionIDMessage implements ClusterMessage {
+
+	private org.apache.catalina.cluster.Member address;
+
+	private int messageNumber;
+
+	private long timestamp;
+
+	private String orignalSessionID;
+
+	private String backupSessionID;
+
+	private String host ;
+	private String contextPath;
+    private int resend = ClusterMessage.FLAG_DEFAULT ;
+    private int compress = ClusterMessage.FLAG_DEFAULT ;
+
+	public org.apache.catalina.cluster.Member getAddress() {
+		return address;
+	}
+
+	public void setAddress(org.apache.catalina.cluster.Member address) {
+		this.address = address;
+	}
+
+	public String getUniqueId() {
+		StringBuffer result = new StringBuffer(getOrignalSessionID());
+		result.append("#-#");
+		result.append(getHost());
+                result.append("#-#");
+                result.append(getContextPath());
+		result.append("#-#");
+		result.append(getMessageNumber());
+		result.append("#-#");
+		result.append(System.currentTimeMillis());
+		return result.toString();
+	}
+
+	/**
+         * @return Returns the host.
+         */
+        public String getHost() {
+             return host;
+        }
+    
+        /**
+         * @param host The host to set.
+         */
+         public void setHost(String host) {
+             this.host = host;
+        }
+    
+	/**
+	 * @return Returns the contextPath.
+	 */
+	public String getContextPath() {
+		return contextPath;
+	}
+	/**
+	 * @param contextPath The contextPath to set.
+	 */
+	public void setContextPath(String contextPath) {
+		this.contextPath = contextPath;
+	}
+	/**
+	 * @return Returns the messageNumber.
+	 */
+	public int getMessageNumber() {
+		return messageNumber;
+	}
+
+	/**
+	 * @param messageNumber
+	 *            The messageNumber to set.
+	 */
+	public void setMessageNumber(int messageNumber) {
+		this.messageNumber = messageNumber;
+	}
+
+	/**
+	 * @return Returns the timestamp.
+	 */
+	public long getTimestamp() {
+		return timestamp;
+	}
+
+	/**
+	 * @param timestamp
+	 *            The timestamp to set.
+	 */
+	public void setTimestamp(long timestamp) {
+		this.timestamp = timestamp;
+	}
+
+	/**
+	 * @return Returns the backupSessionID.
+	 */
+	public String getBackupSessionID() {
+		return backupSessionID;
+	}
+
+	/**
+	 * @param backupSessionID
+	 *            The backupSessionID to set.
+	 */
+	public void setBackupSessionID(String backupSessionID) {
+		this.backupSessionID = backupSessionID;
+	}
+
+	/**
+	 * @return Returns the orignalSessionID.
+	 */
+	public String getOrignalSessionID() {
+		return orignalSessionID;
+	}
+
+	/**
+	 * @param orignalSessionID
+	 *            The orignalSessionID to set.
+	 */
+	public void setOrignalSessionID(String orignalSessionID) {
+		this.orignalSessionID = orignalSessionID;
+	}
+
+    /**
+     * @return Returns the compress.
+     * @since 5.5.10 
+     */
+    public int getCompress() {
+        return compress;
+    }
+    /**
+     * @param compress The compress to set.
+     * @since 5.5.10
+     */
+    public void setCompress(int compress) {
+        this.compress = compress;
+    }
+    /**
+     * @return Returns the resend.
+     * @since 5.5.10
+     */
+    public int getResend() {
+        return resend;
+    }
+    /**
+     * @param resend The resend to set.
+     * @since 5.5.10
+     */
+    public void setResend(int resend) {
+        this.resend = resend;
+    }
+
+
+}
+

Added: tomcat/container/tc5.5.x/modules/ha/src/share/org/apache/catalina/cluster/session/SessionMessage.java
URL: http://svn.apache.org/viewcvs/tomcat/container/tc5.5.x/modules/ha/src/share/org/apache/catalina/cluster/session/SessionMessage.java?rev=380209&view=auto
==============================================================================
--- tomcat/container/tc5.5.x/modules/ha/src/share/org/apache/catalina/cluster/session/SessionMessage.java (added)
+++ tomcat/container/tc5.5.x/modules/ha/src/share/org/apache/catalina/cluster/session/SessionMessage.java Thu Feb 23 11:55:14 2006
@@ -0,0 +1,103 @@
+/*
+ * Copyright 1999,2004 The Apache Software Foundation.
+ * 
+ * Licensed 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.cluster.session;
+import org.apache.catalina.cluster.ClusterMessage;
+
+/**
+ *
+ * <B>Class Description:</B><BR>
+ * The SessionMessage class is a class that is used when a session has been
+ * created, modified, expired in a Tomcat cluster node.<BR>
+ *
+ * The following events are currently available:
+ * <ul>
+ *   <li><pre>public static final int EVT_SESSION_CREATED</pre><li>
+ *   <li><pre>public static final int EVT_SESSION_ACCESSED</pre><li>
+ *   <li><pre>public static final int EVT_ATTRIBUTE_ADDED</pre><li>
+ *   <li><pre>public static final int EVT_ATTRIBUTE_REMOVED</pre><li>
+ *   <li><pre>public static final int EVT_SESSION_EXPIRED_WONOTIFY</pre><li>
+ *   <li><pre>public static final int EVT_SESSION_EXPIRED_WNOTIFY</pre><li>
+ *   <li><pre>public static final int EVT_GET_ALL_SESSIONS</pre><li>
+ *   <li><pre>public static final int EVT_SET_USER_PRINCIPAL</pre><li>
+ *   <li><pre>public static final int EVT_SET_SESSION_NOTE</pre><li>
+ *   <li><pre>public static final int EVT_REMOVE_SESSION_NOTE</pre><li>
+ * </ul>
+ *
+ */
+
+public interface SessionMessage extends ClusterMessage, java.io.Serializable
+{
+
+    /**
+     * Event type used when a session has been created on a node
+     */
+    public static final int EVT_SESSION_CREATED = 1;
+    /**
+     * Event type used when a session has expired
+     */
+    public static final int EVT_SESSION_EXPIRED = 2;
+
+    /**
+     * Event type used when a session has been accessed (ie, last access time
+     * has been updated. This is used so that the replicated sessions will not expire
+     * on the network
+     */
+    public static final int EVT_SESSION_ACCESSED = 3;
+    /**
+     * Event type used when a server comes online for the first time.
+     * The first thing the newly started server wants to do is to grab the
+     * all the sessions from one of the nodes and keep the same state in there
+     */
+    public static final int EVT_GET_ALL_SESSIONS = 4;
+    /**
+     * Event type used when an attribute has been added to a session,
+     * the attribute will be sent to all the other nodes in the cluster
+     */
+    public static final int EVT_SESSION_DELTA  = 13;
+
+    /**
+     * When a session state is transferred, this is the event.
+     */
+    public static final int EVT_ALL_SESSION_DATA = 12;
+    
+    /**
+     * When a session state is complete transferred, this is the event.
+     */
+    public static final int EVT_ALL_SESSION_TRANSFERCOMPLETE = 14;
+    
+
+    
+    public String getContextName();
+    
+    public String getEventTypeString();
+    
+    /**
+     * returns the event type
+     * @return one of the event types EVT_XXXX
+     */
+    public int getEventType(); 
+    /**
+     * @return the serialized data for the session
+     */
+    public byte[] getSession();
+    /**
+     * @return the session ID for the session
+     */
+    public String getSessionID();
+    
+
+
+}//SessionMessage

Added: tomcat/container/tc5.5.x/modules/ha/src/share/org/apache/catalina/cluster/session/SessionMessageImpl.java
URL: http://svn.apache.org/viewcvs/tomcat/container/tc5.5.x/modules/ha/src/share/org/apache/catalina/cluster/session/SessionMessageImpl.java?rev=380209&view=auto
==============================================================================
--- tomcat/container/tc5.5.x/modules/ha/src/share/org/apache/catalina/cluster/session/SessionMessageImpl.java (added)
+++ tomcat/container/tc5.5.x/modules/ha/src/share/org/apache/catalina/cluster/session/SessionMessageImpl.java Thu Feb 23 11:55:14 2006
@@ -0,0 +1,207 @@
+/*
+ * Copyright 1999,2004 The Apache Software Foundation.
+ * 
+ * Licensed 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.cluster.session;
+
+
+import org.apache.catalina.cluster.ClusterMessage;
+import org.apache.catalina.cluster.Member;
+
+/**
+ * Session cluster message
+ * 
+ * @author Filip Hanik
+ * @author Peter Rossbach
+ * 
+ * @version $Revision: 326110 $ $Date: 2005-10-18 09:08:36 -0500 (Tue, 18 Oct 2005) $
+ */
+public class SessionMessageImpl implements SessionMessage, java.io.Serializable {
+    
+    public SessionMessageImpl() {
+    }
+    
+    
+    /*
+
+     * Private serializable variables to keep the messages state
+     */
+    private int mEvtType = -1;
+    private byte[] mSession;
+    private String mSessionID;
+    private Member mSrc;
+    private String mContextName;
+    private long serializationTimestamp;
+    private boolean timestampSet = false ;
+    private String uniqueId;
+    private int resend = ClusterMessage.FLAG_DEFAULT ;
+    private int compress = ClusterMessage.FLAG_DEFAULT ;
+
+
+    private SessionMessageImpl( String contextName,
+                           int eventtype,
+                           byte[] session,
+                           String sessionID)
+    {
+        mEvtType = eventtype;
+        mSession = session;
+        mSessionID = sessionID;
+        mContextName = contextName;
+        uniqueId = sessionID;
+    }
+
+    /**
+     * Creates a session message. Depending on what event type you want this
+     * message to represent, you populate the different parameters in the constructor<BR>
+      * The following rules apply dependent on what event type argument you use:<BR>
+     * <B>EVT_SESSION_CREATED</B><BR>
+     *    The parameters: session, sessionID must be set.<BR>
+     * <B>EVT_SESSION_EXPIRED</B><BR>
+     *    The parameters: sessionID must be set.<BR>
+     * <B>EVT_SESSION_ACCESSED</B><BR>
+     *    The parameters: sessionID must be set.<BR>
+     * <B>EVT_SESSION_EXPIRED_XXXX</B><BR>
+     *    The parameters: sessionID must be set.<BR>
+     * <B>EVT_SESSION_DELTA</B><BR>
+     *    Send attribute delta (add,update,remove attribute or principal, ...).<BR>
+     * <B>EVT_ALL_SESSION_DATA</B><BR>
+     *    Send complete serializes session list<BR>
+     * <B>EVT_ALL_SESSION_TRANSFERCOMPLETE</B><BR>
+     *    send that all session state information are transfered
+     *    after GET_ALL_SESSION received from this sender.<BR>
+     * @param contextName - the name of the context (application
+     * @param eventtype - one of the 8 event type defined in this class
+     * @param session - the serialized byte array of the session itself
+     * @param sessionID - the id that identifies this session
+     * @param uniqueID - the id that identifies this message
+     */
+    public SessionMessageImpl( String contextName,
+                           int eventtype,
+                           byte[] session,
+                           String sessionID,
+                           String uniqueID)
+    {
+        this(contextName,eventtype,session,sessionID);
+        uniqueId = uniqueID;
+    }
+
+    /**
+     * returns the event type
+     * @return one of the event types EVT_XXXX
+     */
+    public int getEventType() { return mEvtType; }
+
+    /**
+     * @return the serialized data for the session
+     */
+    public byte[] getSession() { return mSession;}
+
+    /**
+     * @return the session ID for the session
+     */
+    public String getSessionID(){ return mSessionID; }
+    
+    /**
+     * set message send time but only the first setting works (one shot)
+     */
+    public void setTimestamp(long time) {
+        synchronized(this) {
+            if(!timestampSet) {
+                serializationTimestamp=time;
+                timestampSet = true ;
+            }
+        }
+    }
+    
+    public long getTimestamp() { return serializationTimestamp;}
+    
+    /**
+     * clear text event type name (for logging purpose only) 
+     * @return the event type in a string representating, useful for debugging
+     */
+    public String getEventTypeString()
+    {
+        switch (mEvtType)
+        {
+            case EVT_SESSION_CREATED : return "SESSION-MODIFIED";
+            case EVT_SESSION_EXPIRED : return "SESSION-EXPIRED";
+            case EVT_SESSION_ACCESSED : return "SESSION-ACCESSED";
+            case EVT_GET_ALL_SESSIONS : return "SESSION-GET-ALL";
+            case EVT_SESSION_DELTA : return "SESSION-DELTA";
+            case EVT_ALL_SESSION_DATA : return "ALL-SESSION-DATA";
+            case EVT_ALL_SESSION_TRANSFERCOMPLETE : return "SESSION-STATE-TRANSFERED";
+            default : return "UNKNOWN-EVENT-TYPE";
+        }
+    }
+
+    /**
+     * Get the address that this message originated from.  This would be set
+     * if the message was being relayed from a host other than the one
+     * that originally sent it.
+     */
+    public Member getAddress()
+    {
+        return this.mSrc;
+    }
+
+    /**
+     * Use this method to set the address that this message originated from.
+     * This can be used when re-sending the EVT_GET_ALL_SESSIONS message to
+     * another machine in the group.
+     */
+    public void setAddress(Member src)
+    {
+        this.mSrc = src;
+    }
+
+    public String getContextName() {
+       return mContextName;
+    }
+    public String getUniqueId() {
+        return uniqueId;
+    }
+    public void setUniqueId(String uniqueId) {
+        this.uniqueId = uniqueId;
+    }
+
+    /**
+     * @return Returns the compress.
+     * @since 5.5.10 
+     */
+    public int getCompress() {
+        return compress;
+    }
+    /**
+     * @param compress The compress to set.
+     * @since 5.5.10
+     */
+    public void setCompress(int compress) {
+        this.compress = compress;
+    }
+    /**
+     * @return Returns the resend.
+     * @since 5.5.10
+     */
+    public int getResend() {
+        return resend;
+    }
+    /**
+     * @param resend The resend to set.
+     * @since 5.5.10
+     */
+    public void setResend(int resend) {
+        this.resend = resend;
+    }
+
+}



---------------------------------------------------------------------
To unsubscribe, e-mail: dev-unsubscribe@tomcat.apache.org
For additional commands, e-mail: dev-help@tomcat.apache.org


Mime
View raw message