You are viewing a plain text version of this content. The canonical link for it is here.
Posted to dev@tomcat.apache.org by rj...@apache.org on 2009/09/08 19:27:04 UTC

svn commit: r812589 - in /tomcat/sandbox/tomcat-oacc/trunk/src/share/org/apache/catalina/cluster/session: DeltaSession.java LocalStrings.properties LocalStrings_es.properties SerializablePrincipal.java

Author: rjung
Date: Tue Sep  8 17:27:04 2009
New Revision: 812589

URL: http://svn.apache.org/viewvc?rev=812589&view=rev
Log:
Port changes form TC6.0.x to DeltaSession and SerializablePrincipal
as well as the LocalStrings.

Modified:
    tomcat/sandbox/tomcat-oacc/trunk/src/share/org/apache/catalina/cluster/session/DeltaSession.java
    tomcat/sandbox/tomcat-oacc/trunk/src/share/org/apache/catalina/cluster/session/LocalStrings.properties
    tomcat/sandbox/tomcat-oacc/trunk/src/share/org/apache/catalina/cluster/session/LocalStrings_es.properties
    tomcat/sandbox/tomcat-oacc/trunk/src/share/org/apache/catalina/cluster/session/SerializablePrincipal.java

Modified: tomcat/sandbox/tomcat-oacc/trunk/src/share/org/apache/catalina/cluster/session/DeltaSession.java
URL: http://svn.apache.org/viewvc/tomcat/sandbox/tomcat-oacc/trunk/src/share/org/apache/catalina/cluster/session/DeltaSession.java?rev=812589&r1=812588&r2=812589&view=diff
==============================================================================
--- tomcat/sandbox/tomcat-oacc/trunk/src/share/org/apache/catalina/cluster/session/DeltaSession.java (original)
+++ tomcat/sandbox/tomcat-oacc/trunk/src/share/org/apache/catalina/cluster/session/DeltaSession.java Tue Sep  8 17:27:04 2009
@@ -17,60 +17,44 @@
 
 package org.apache.catalina.cluster.session;
 
-import java.beans.PropertyChangeSupport;
+import java.io.Externalizable;
 import java.io.IOException;
 import java.io.NotSerializableException;
+import java.io.ObjectInput;
+import java.io.ObjectOutput;
 import java.io.ObjectInputStream;
 import java.io.ObjectOutputStream;
 import java.io.Serializable;
-import java.lang.reflect.Method;
-import java.security.AccessController;
 import java.security.Principal;
-import java.security.PrivilegedAction;
 import java.util.ArrayList;
 import java.util.Enumeration;
 import java.util.HashMap;
 import java.util.Hashtable;
-import java.util.Iterator;
-import java.util.Map;
+import java.util.concurrent.atomic.AtomicInteger;
+import java.util.concurrent.locks.Lock;
+import java.util.concurrent.locks.ReentrantReadWriteLock;
 
-import javax.servlet.ServletContext;
 import javax.servlet.http.HttpSession;
-import javax.servlet.http.HttpSessionAttributeListener;
-import javax.servlet.http.HttpSessionBindingEvent;
-import javax.servlet.http.HttpSessionBindingListener;
 import javax.servlet.http.HttpSessionContext;
 import javax.servlet.http.HttpSessionEvent;
 import javax.servlet.http.HttpSessionListener;
 
 import org.apache.catalina.Context;
-import org.apache.catalina.Globals;
 import org.apache.catalina.Manager;
 import org.apache.catalina.Session;
-import org.apache.catalina.SessionEvent;
-import org.apache.catalina.SessionListener;
 import org.apache.catalina.cluster.CatalinaCluster;
-import org.apache.catalina.cluster.ClusterSession;
+import org.apache.catalina.cluster.ClusterManager;
 import org.apache.catalina.cluster.ClusterMessage;
+import org.apache.catalina.cluster.ClusterSession;
 import org.apache.catalina.realm.GenericPrincipal;
+import org.apache.catalina.session.StandardSession;
 import org.apache.catalina.util.Enumerator;
 import org.apache.catalina.util.StringManager;
 
 /**
  * 
- * Similar to the StandardSession, this code is identical, but for update and
- * some small issues, simply copied in the first release. This session will keep
+ * Similar to the StandardSession except that this session will keep
  * track of deltas during a request.
- * <p>
- * <b>IMPLEMENTATION NOTE </b>: An instance of this class represents both the
- * internal (Session) and application level (HttpSession) view of the session.
- * However, because the class itself is not declared public, Java logic outside
- * of the <code>org.apache.catalina.session</code> package cannot cast an
- * HttpSession view of this instance back to a Session view.
- * <p>
- * <b>IMPLEMENTATION NOTE </b>: If you add fields to this class, you must make
- * sure that you carry them over in the read/writeObject methods so that this
- * class is properly serialized.
  * 
  * @author Filip Hanik
  * @author Craig R. McClanahan
@@ -80,165 +64,29 @@
  * @version $Revision$ $Date$
  */
 
-public class DeltaSession implements HttpSession, Session, Serializable,
-        ClusterSession {
+public class DeltaSession extends StandardSession implements ClusterSession {
 
-    public static org.apache.juli.logging.Log log = org.apache.juli.logging.LogFactory
-            .getLog(DeltaManager.class);
+    public static org.apache.juli.logging.Log log = org.apache.juli.logging.LogFactory.getLog(DeltaSession.class);
 
     /**
      * The string manager for this package.
      */
-    protected static StringManager smp = StringManager
-            .getManager(Constants.Package);
-
+    protected static StringManager sm = StringManager.getManager(Constants.Package);
 
     // ----------------------------------------------------- Instance Variables
 
     /**
-     * Type array.
-     */
-    protected static final String EMPTY_ARRAY[] = new String[0];
-
-    /**
-     * The dummy attribute value serialized when a NotSerializableException is
-     * encountered in <code>writeObject()</code>.
-     */
-    private static final String NOT_SERIALIZED = "___NOT_SERIALIZABLE_EXCEPTION___";
-
-    /**
-     * The collection of user data attributes associated with this Session.
-     */
-    private Map attributes = new Hashtable();
-
-    /**
-     * The authentication type used to authenticate our cached Principal, if
-     * any. NOTE: This value is not included in the serialized version of this
-     * object.
-     */
-    private transient String authType = null;
-
-    /**
-     * The <code>java.lang.Method</code> for the
-     * <code>fireContainerEvent()</code> method of the
-     * <code>org.apache.catalina.core.StandardContext</code> method, if our
-     * Context implementation is of this class. This value is computed
-     * dynamically the first time it is needed, or after a session reload (since
-     * it is declared transient).
-     */
-    private transient Method containerEventMethod = null;
-
-    /**
-     * The method signature for the <code>fireContainerEvent</code> method.
-     */
-    private static final Class containerEventTypes[] = { String.class,
-            Object.class };
-
-    /**
-     * The time this session was created, in milliseconds since midnight,
-     * January 1, 1970 GMT.
-     */
-    private long creationTime = 0L;
-
-    /**
-     * We are currently processing a session expiration, so bypass certain
-     * IllegalStateException tests. NOTE: This value is not included in the
-     * serialized version of this object.
-     */
-    private transient boolean expiring = false;
-
-    /**
-     * The facade associated with this session. NOTE: This value is not included
-     * in the serialized version of this object.
-     */
-    private transient DeltaSessionFacade facade = null;
-
-    /**
-     * The session identifier of this Session.
-     */
-    private String id = null;
-
-    /**
      * Descriptive information describing this Session implementation.
      */
     private static final String info = "DeltaSession/1.1";
 
     /**
-     * The last accessed time for this Session.
-     */
-    private volatile long lastAccessedTime = creationTime;
-
-    /**
-     * The session event listeners for this Session.
-     */
-    private transient ArrayList listeners = new ArrayList();
-
-    /**
-     * The Manager with which this Session is associated.
-     */
-    private transient Manager manager = null;
-
-    /**
-     * The maximum time interval, in seconds, between client requests before the
-     * servlet container may invalidate this session. A negative time indicates
-     * that the session should never time out.
-     */
-    private int maxInactiveInterval = -1;
-
-    /**
      * The maxInactiveInterval + tolerance time interval, in seconds, between client requests before
      * the servlet container may invalidate a backup session from other cluster node.
      */
     private int expireTolerance = 300;
 
     /**
-     * Flag indicating whether this session is new or not.
-     */
-    private boolean isNew = false;
-
-    /**
-     * Flag indicating whether this session is valid or not.
-     */
-    protected boolean isValid = false;
-
-    /**
-     * Internal notes associated with this session by Catalina components and
-     * event listeners. <b>IMPLEMENTATION NOTE: </b> This object is <em>not</em>
-     * saved and restored across session serializations!
-     */
-    private transient Map notes = new Hashtable();
-
-    /**
-     * The authenticated Principal associated with this session, if any.
-     * <b>IMPLEMENTATION NOTE: </b> This object is <i>not </i> saved and
-     * restored across session serializations!
-     */
-    private transient Principal principal = null;
-
-    /**
-     * The string manager for this package.
-     */
-    private static StringManager sm = StringManager
-            .getManager(Constants.Package);
-
-    /**
-     * The HTTP session context associated with this session.
-     */
-    private static HttpSessionContext sessionContext = null;
-
-    /**
-     * The property change support for this component. NOTE: This value is not
-     * included in the serialized version of this object.
-     */
-    private transient PropertyChangeSupport support = new PropertyChangeSupport(
-            this);
-
-    /**
-     * The current accessed time for this session.
-     */
-    private volatile long thisAccessedTime = creationTime;
-
-    /**
      * only the primary session will expire, or be able to expire due to
      * inactivity. This is set to false as soon as I receive this session over
      * the wire in a session message. That means that someone else has made a
@@ -258,12 +106,10 @@
      */
     private transient long lastTimeReplicated = System.currentTimeMillis();
 
-    /**
-     * The access count for this session
-     */
-    protected transient int accessCount = 0;
 
-    private Object lock = new Object();
+    protected Lock diffLock = new ReentrantReadWriteLock().writeLock();
+
+    private long version;
 
     // ----------------------------------------------------------- Constructors
     
@@ -273,188 +119,73 @@
      * @param manager
      *            The manager with which this Session is associated
      */
-    public DeltaSession(Manager manager) {
+    public DeltaSession() {
+        this(null);
+    }
 
-        super();
-        this.manager = manager;
+    public DeltaSession(Manager manager) {
+        super(manager);
         this.resetDeltaRequest();
     }
 
     // ----------------------------------------------------- Session Properties
 
-    /**
-     * 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
+     * Lock during serialization
      */
-    public void setPrimarySession(boolean primarySession) {
-        this.isPrimarySession = primarySession;
+    public void lock() {
+        diffLock.lock();
     }
 
     /**
-     * Return the authentication type used to authenticate our cached Principal,
-     * if any.
+     * Unlock after serialization
      */
-    public String getAuthType() {
-
-        return (this.authType);
-
+    public void unlock() {
+        diffLock.unlock();
     }
 
     /**
-     * Set the authentication type used to authenticate our cached Principal, if
-     * any.
-     * 
-     * @param authType
-     *            The new cached authentication type
+     * returns true if this session is the primary session, if that is the case,
+     * the manager can expire it upon timeout.
      */
-    public void setAuthType(String authType) {
-
-        String oldAuthType = this.authType;
-        this.authType = authType;
-        support.firePropertyChange("authType", oldAuthType, this.authType);
-
+    public boolean isPrimarySession() {
+        return isPrimarySession;
     }
 
     /**
-     * Set the creation time for this session. This method is called by the
-     * Manager when an existing Session instance is reused.
+     * Sets whether this is the primary session or not.
      * 
-     * @param time
-     *            The new creation time
-     */
-    public void setCreationTime(long time) {
-
-        this.creationTime = time;
-        this.lastAccessedTime = time;
-        this.thisAccessedTime = time;
-
-    }
-
-    /**
-     * Return the session identifier for this session.
-     */
-    public String getId() {
-        return (this.id);
-
-    }
-
-
-    /**
-     * Return the session identifier for this session.
+     * @param primarySession
+     *            Flag value
      */
-    public String getIdInternal() {
-
-        return (this.id);
-
+    public void setPrimarySession(boolean primarySession) {
+        this.isPrimarySession = primarySession;
     }
 
-
     /**
      * Set the session identifier for this session without notify listeners.
-     * 
+     *
      * @param id
      *            The new session identifier
      */
     public void setIdInternal(String id) {
-        if ((this.id != null) && (manager != null))
-            manager.remove(this);
-
         this.id = id;
-
-        if (manager != null)
-            manager.add(this);
-        if ( deltaRequest == null ) resetDeltaRequest();
-        else deltaRequest.setSessionId(id);
+        resetDeltaRequest();
     }
 
     /**
      * Set the session identifier for this session.
-     * 
+     *
      * @param id
      *            The new session identifier
      */
     public void setId(String id) {
-        setIdInternal(id);
-        tellNew();
-     }
-
-    /**
-     * Inform the listeners about the new session.
-     *  
-     */
-    public void tellNew() {
-
-        // Notify interested session event listeners
-        fireSessionEvent(Session.SESSION_CREATED_EVENT, null);
-
-        // Notify interested application event listeners
-        Context context = (Context) manager.getContainer();
-        //fix for standalone manager without container
-        if (context != null) {
-            Object listeners[] = context.getApplicationLifecycleListeners();
-            if (listeners != null) {
-                HttpSessionEvent event = new HttpSessionEvent(getSession());
-                for (int i = 0; i < listeners.length; i++) {
-                    if (!(listeners[i] instanceof HttpSessionListener))
-                        continue;
-                    HttpSessionListener listener = (HttpSessionListener) listeners[i];
-                    try {
-                        fireContainerEvent(context, "beforeSessionCreated",
-                                listener);
-                        listener.sessionCreated(event);
-                        fireContainerEvent(context, "afterSessionCreated",
-                                listener);
-                    } catch (Throwable t) {
-                        try {
-                            fireContainerEvent(context, "afterSessionCreated",
-                                    listener);
-                        } catch (Exception e) {
-                            ;
-                        }
-                        manager.getContainer().getLogger().error
-                           (sm.getString("standardSession.sessionEvent"), t);
-                    }
-                }
-            }
-        }
+        super.setId(id);
+        resetDeltaRequest();
     }
 
-    /**
-     * Return descriptive information about this Session implementation and the
-     * corresponding version number, in the format
-     * <code>&lt;description&gt;/&lt;version&gt;</code>.
-     */
-    public String getInfo() {
-
-        return (info);
-
-    }
-
-    /**
-     * Return the last time the client sent a request associated with this
-     * session, as the number of milliseconds since midnight, January 1, 1970
-     * GMT. Actions that your application takes, such as getting or setting a
-     * value associated with the session, do not affect the access time.
-     */
-    public long getLastAccessedTime() {
-
-        if (!isValid()) {
-            throw new IllegalStateException(sm
-                    .getString("standardSession.getLastAccessedTime.ise"));
-        }
-            
-        return (this.lastAccessedTime);
-    }
+   
 
     /**
      * Return the last client access time without invalidation check
@@ -464,65 +195,31 @@
         return (this.lastAccessedTime);
     }
 
-    /**
-     * Return the Manager within which this Session is valid.
-     */
-    public Manager getManager() {
-
-        return (this.manager);
-
-    }
-
-    /**
-     * Set the Manager within which this Session is valid.
-     * 
-     * @param manager
-     *            The new Manager
-     */
-    public void setManager(Manager manager) {
-
-        this.manager = manager;
-
-    }
-
-    /**
-     * Return the maximum time interval, in seconds, between client requests
-     * before the servlet container will invalidate the session. A negative time
-     * indicates that the session should never time out.
-     */
-    public int getMaxInactiveInterval() {
-
-        return (this.maxInactiveInterval);
 
-    }
-
-    /**
-     * Set the maximum time interval, in seconds, between client requests before
-     * the servlet container will invalidate the session. A negative time
-     * indicates that the session should never time out.
-     * 
-     * @param interval
-     *            The new maximum interval
-     */
+   
     public void setMaxInactiveInterval(int interval) {
-        setMaxInactiveInterval(interval, true);
+        this.setMaxInactiveInterval(interval,true);
     }
-
     public void setMaxInactiveInterval(int interval, boolean addDeltaRequest) {
-
-        this.maxInactiveInterval = interval;
+        super.maxInactiveInterval = interval;
         if (isValid && interval == 0) {
             expire();
         } else {
-            if (addDeltaRequest && (deltaRequest != null))
-                deltaRequest.setMaxInactiveInterval(interval);
+            if (addDeltaRequest && (deltaRequest != null)) {
+                try {
+                    lock();
+                    deltaRequest.setMaxInactiveInterval(interval);
+                }finally{
+                    unlock();
+                }
+            }
+                
         }
-
     }
 
     /**
      * Set the <code>isNew</code> flag for this session.
-     * 
+     *
      * @param isNew
      *            The new value for the <code>isNew</code> flag
      */
@@ -531,22 +228,15 @@
     }
 
     public void setNew(boolean isNew, boolean addDeltaRequest) {
-        this.isNew = isNew;
-        if (addDeltaRequest && (deltaRequest != null))
-            deltaRequest.setNew(isNew);
-    }
-
-    /**
-     * Return 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. If there is
-     * no current associated Principal, return <code>null</code>.
-     */
-    public Principal getPrincipal() {
-
-        return (this.principal);
-
+        super.setNew(isNew);
+        if (addDeltaRequest && (deltaRequest != null)){
+            try {
+                lock();
+                deltaRequest.setNew(isNew);
+            }finally{
+                unlock();
+            }
+        }
     }
 
     /**
@@ -554,7 +244,7 @@
      * 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
      */
@@ -563,53 +253,29 @@
     }
 
     public void setPrincipal(Principal principal, boolean addDeltaRequest) {
-        Principal oldPrincipal = this.principal;
-        this.principal = principal;
-        support.firePropertyChange("principal", oldPrincipal, this.principal);
-        if (addDeltaRequest && (deltaRequest != null))
-            deltaRequest.setPrincipal(principal);
-    }
-
-    /**
-     * Return the <code>HttpSession</code> for which this object is the
-     * facade.
-     */
-    public HttpSession getSession() {
-
-        if (facade == null) {
-            if (System.getSecurityManager() != null) {
-                final DeltaSession fsession = this;
-                facade = (DeltaSessionFacade) AccessController
-                        .doPrivileged(new PrivilegedAction() {
-                            public Object run() {
-                                return new DeltaSessionFacade(fsession);
-                            }
-                        });
-            } else {
-                facade = new DeltaSessionFacade(this);
-            }
+        try { 
+            lock();
+            super.setPrincipal(principal);
+            if (addDeltaRequest && (deltaRequest != null))
+                deltaRequest.setPrincipal(principal);
+        } finally {
+            unlock();
         }
-        return (facade);
-
     }
 
     /**
      * Return the <code>isValid</code> flag for this session.
      */
     public boolean isValid() {
-
         if (this.expiring) {
             return true;
         }
-
         if (!this.isValid) {
             return false;
         }
-
-        if (accessCount > 0) {
+        if (ACTIVITY_CHECK && accessCount.get() > 0) {
             return true;
         }
-
         if (maxInactiveInterval >= 0) {
             long timeNow = System.currentTimeMillis();
             int timeIdle = (int) ((timeNow - thisAccessedTime) / 1000L);
@@ -627,75 +293,18 @@
                 }
             }
         }
-
         return (this.isValid);
     }
 
-    /**
-     * Set the <code>isValid</code> flag for this session.
-     * 
-     * @param isValid
-     *            The new value for the <code>isValid</code> flag
-     */
-    public void setValid(boolean isValid) {
-
-        this.isValid = isValid;
-    }
-
     // ------------------------------------------------- Session Public Methods
 
-    /**
-     * Update the accessed time information for this session. This method should
-     * be called by the context when a request comes in for a particular
-     * session, even if the application does not reference it.
-     */
-    public void access() {
-
-        this.lastAccessedTime = this.thisAccessedTime;
-        this.thisAccessedTime = System.currentTimeMillis();
-
-        evaluateIfValid();
-
-        if (Globals.STRICT_SERVLET_COMPLIANCE) {
-            synchronized (lock) {
-                accessCount++;
-            }
-        }
-    }
-
     public void endAccess() {
-        isNew = false;
-        if (Globals.STRICT_SERVLET_COMPLIANCE) {
-            synchronized (lock) {
-                accessCount--;
-            }
-        }
+        super.endAccess();
         if(manager instanceof DeltaManager)
             ((DeltaManager)manager).registerSessionAtReplicationValve(this);
     }
 
     /**
-     * Add a session event listener to this component.
-     */
-    public void addSessionListener(SessionListener listener) {
-
-        synchronized (listeners) {
-            listeners.add(listener);
-        }
-
-    }
-
-    /**
-     * Perform the internal processing required to invalidate this session,
-     * without triggering an exception if the session has already expired.
-     */
-    public void expire() {
-
-        expire(true);
-
-    }
-
-    /**
      * Perform the internal processing required to invalidate this session,
      * without triggering an exception if the session has already expired.
      * 
@@ -707,18 +316,20 @@
     }
 
     public void expire(boolean notify, boolean notifyCluster) {
-
-        // Mark this session as "being expired" if needed
-        if (expiring)
-            return;
         String expiredId = getIdInternal();
+        // Check to see if expire is in progress or has previously been called
+        if (expiring || !isValid)
+            return;
 
         synchronized (this) {
+            // Check again, now we are inside the sync so this code only runs once
+            // Double check locking - expiring and isValid need to be volatile
+            if (expiring || !isValid)
+                return;
 
             if (manager == null)
                 return;
 
-            expiring = true;
 
             if(expiredId != null && manager instanceof DeltaManager) {
                 DeltaManager dmanager = (DeltaManager)manager;
@@ -733,67 +344,69 @@
                 }
             }
 
+            // Mark this session as "being expired"
+            expiring = true;
+
             // Notify interested application event listeners
             // FIXME - Assumes we call listeners in reverse order
             Context context = (Context) manager.getContainer();
-            //fix for standalone manager without container
-            if (context != null) {
-                Object listeners[] = context.getApplicationLifecycleListeners();
-                if (notify && (listeners != null)) {
-                    HttpSessionEvent event = new HttpSessionEvent(getSession());
-                    for (int i = 0; i < listeners.length; i++) {
-                        int j = (listeners.length - 1) - i;
-                        if (!(listeners[j] instanceof HttpSessionListener))
-                            continue;
-                        HttpSessionListener listener = (HttpSessionListener) listeners[j];
+            Object listeners[] = context.getApplicationLifecycleListeners();
+            if (notify && (listeners != null)) {
+                HttpSessionEvent event =
+                    new HttpSessionEvent(getSession());
+                for (int i = 0; i < listeners.length; i++) {
+                    int j = (listeners.length - 1) - i;
+                    if (!(listeners[j] instanceof HttpSessionListener))
+                        continue;
+                    HttpSessionListener listener =
+                        (HttpSessionListener) listeners[j];
+                    try {
+                        fireContainerEvent(context,
+                                           "beforeSessionDestroyed",
+                                           listener);
+                        listener.sessionDestroyed(event);
+                        fireContainerEvent(context,
+                                           "afterSessionDestroyed",
+                                           listener);
+                    } catch (Throwable t) {
                         try {
                             fireContainerEvent(context,
-                                    "beforeSessionDestroyed", listener);
-                            listener.sessionDestroyed(event);
-                            fireContainerEvent(context,
-                                    "afterSessionDestroyed", listener);
-                        } catch (Throwable t) {
-                            try {
-                                fireContainerEvent(context,
-                                        "afterSessionDestroyed", listener);
-                            } catch (Exception e) {
-                                ;
-                            }
-                            manager.getContainer().getLogger().error(sm
-                                    .getString("standardSession.sessionEvent"),
-                                    t);
+                                               "afterSessionDestroyed",
+                                               listener);
+                        } catch (Exception e) {
+                            ;
                         }
+                        manager.getContainer().getLogger().error
+                            (sm.getString("standardSession.sessionEvent"), t);
                     }
                 }
             }
-
-            accessCount = 0;
+            if (ACTIVITY_CHECK) {
+                accessCount.set(0);
+            }
             setValid(false);
 
-            if (manager != null) {
+            /*
+             * Compute how long this session has been alive, and update
+             * session manager's related properties accordingly
+             */
+            long timeNow = System.currentTimeMillis();
+            int timeAlive = (int) ((timeNow - creationTime)/1000);
+            synchronized (manager) {
+                if (timeAlive > manager.getSessionMaxAliveTime()) {
+                    manager.setSessionMaxAliveTime(timeAlive);
+                }
+                int numExpired = manager.getExpiredSessions();
+                numExpired++;
+                manager.setExpiredSessions(numExpired);
+                int average = manager.getSessionAverageAliveTime();
+                average = ((average * (numExpired-1)) + timeAlive)/numExpired;
+                manager.setSessionAverageAliveTime(average);
+            }
 
-                /*
-                 * Compute how long this session has been alive, and update
-                 * session manager's related properties accordingly
-                 */
-                long timeNow = System.currentTimeMillis();
-                int timeAlive = (int) ((timeNow - creationTime)/1000);
-                synchronized (manager) {
-                    if (timeAlive > manager.getSessionMaxAliveTime()) {
-                        manager.setSessionMaxAliveTime(timeAlive);
-                    }
-                    int numExpired = manager.getExpiredSessions();
-                    numExpired++;
-                    manager.setExpiredSessions(numExpired);
-                    int average = manager.getSessionAverageAliveTime();
-                    average = ((average * (numExpired-1)) + timeAlive)/numExpired;
-                    manager.setSessionAverageAliveTime(average);
-                }
+            // Remove this session from our manager's active sessions
+            manager.remove(this);
 
-                // Remove this session from our manager's active sessions
-                manager.remove(this);
-            }
-            
             // Notify interested session event listeners
             if (notify) {
                 fireSessionEvent(Session.SESSION_DESTROYED_EVENT, null);
@@ -805,36 +418,21 @@
             // Unbind any objects associated with this session
             String keys[] = keys();
             for (int i = 0; i < keys.length; i++)
-                removeAttributeInternal(keys[i], notify, false);
+                removeAttributeInternal(keys[i], notify);
 
-            if (notifyCluster && manager != null) {
-                if (log.isDebugEnabled())
-                    log.debug(smp.getString("deltaSession.notifying",
-                        ((DeltaManager) manager).getName(), new Boolean(
-                                isPrimarySession()), expiredId));
-                ((DeltaManager) manager).sessionExpired(expiredId);
-            }
         }
 
-    }
-
-    /**
-     * Return the object bound with the specified name to the internal notes for
-     * this session, or <code>null</code> if no such binding exists.
-     * 
-     * @param name
-     *            Name of the note to be returned
-     */
-    public Object getNote(String name) {
-            return (notes.get(name));
-    }
 
-    /**
-     * Return an Iterator containing the String names of all notes bindings that
-     * exist for this session.
-     */
-    public Iterator getNoteNames() {
-            return (notes.keySet().iterator());
+        if (notifyCluster) {
+            if (log.isDebugEnabled())
+                log.debug(sm.getString("deltaSession.notifying",
+                                       ((ClusterManager)manager).getName(), 
+                                       new Boolean(isPrimarySession()), 
+                                       expiredId));
+            if ( manager instanceof DeltaManager ) {
+                ( (DeltaManager) manager).sessionExpired(expiredId);
+            }
+        }
     }
 
     /**
@@ -842,74 +440,38 @@
      * preparation for reuse of this object.
      */
     public void recycle() {
-
-        // Reset the instance variables associated with this Session
-        attributes.clear();
-        setAuthType(null);
-        creationTime = 0L;
-        expiring = false;
-        id = null;
-        lastAccessedTime = 0L;
-        maxInactiveInterval = -1;
-        accessCount = 0;
-        notes.clear();
-        setPrincipal(null);
-        isNew = false;
-        isValid = false;
-        manager = null;
-        deltaRequest.clear();
-
-    }
-
-    /**
-     * Remove any object bound to the specified name in the internal notes for
-     * this session.
-     * 
-     * @param name
-     *            Name of the note to be removed
-     */
-    public void removeNote(String name) {
-        notes.remove(name);
-    }
-
-    /**
-     * Remove a session event listener from this component.
-     */
-    public void removeSessionListener(SessionListener listener) {
-
-        synchronized (listeners) {
-            listeners.remove(listener);
+        try {
+            lock();
+            super.recycle();
+            deltaRequest.clear();
+        }finally{
+            unlock();
         }
-
     }
 
-    /**
-     * Bind an object to a specified name in the internal notes associated with
-     * this session, replacing any existing binding for this name.
-     * 
-     * @param name
-     *            Name to which the object should be bound
-     * @param value
-     *            Object to be bound to the specified name
-     */
-    public void setNote(String name, Object value) {
-        notes.put(name, value);
-    }
 
     /**
      * Return a string representation of this object.
      */
     public String toString() {
-
         StringBuffer sb = new StringBuffer();
         sb.append("DeltaSession[");
         sb.append(id);
         sb.append("]");
         return (sb.toString());
+    }
+
+    // ------------------------------------------------ Session Package Methods
 
+    public void readExternal(ObjectInput in) throws IOException,ClassNotFoundException {
+        try {
+            lock();
+            readObjectData(in);
+        }finally{
+            unlock();
+        }
     }
 
-    // ------------------------------------------------ Session Package Methods
 
     /**
      * Read a serialized version of the contents of this session object from the
@@ -924,11 +486,12 @@
      * @exception IOException
      *                if an input/output error occurs
      */
-    public void readObjectData(ObjectInputStream stream)
-            throws ClassNotFoundException, IOException {
-
+    @Override
+    public void readObjectData(ObjectInputStream stream) throws ClassNotFoundException, IOException {
+        readObject((ObjectInput)stream);
+    }
+    public void readObjectData(ObjectInput stream) throws ClassNotFoundException, IOException {
         readObject(stream);
-
     }
 
     /**
@@ -942,231 +505,38 @@
      * @exception IOException
      *                if an input/output error occurs
      */
+    @Override
     public void writeObjectData(ObjectOutputStream stream) throws IOException {
-
+        writeObjectData((ObjectOutput)stream);
+    }
+    public void writeObjectData(ObjectOutput stream) throws IOException {
         writeObject(stream);
-
     }
 
     public void resetDeltaRequest() {
-        if (deltaRequest == null) {
-            deltaRequest = new DeltaRequest(getIdInternal(), false);
-        } else {
-            deltaRequest.reset();
-            deltaRequest.setSessionId(getIdInternal());
+        try {
+            lock();
+            if (deltaRequest == null) {
+                deltaRequest = new DeltaRequest(getIdInternal(), false);
+            } else {
+                deltaRequest.reset();
+                deltaRequest.setSessionId(getIdInternal());
+            }
+        }finally{
+            unlock();
         }
     }
 
     public DeltaRequest getDeltaRequest() {
-        if (deltaRequest == null)
-            resetDeltaRequest();
+        if (deltaRequest == null) resetDeltaRequest();
         return deltaRequest;
     }
 
     // ------------------------------------------------- HttpSession Properties
 
-    /**
-     * Return the time when this session was created, in milliseconds since
-     * midnight, January 1, 1970 GMT.
-     * 
-     * @exception IllegalStateException
-     *                if this method is called on an invalidated session
-     */
-    public long getCreationTime() {
-
-        if (!expiring && !isValid)
-            throw new IllegalStateException(sm
-                    .getString("standardSession.getCreationTime.ise"));
-
-        return (this.creationTime);
-
-    }
-
-    /**
-     * Return the ServletContext to which this session belongs.
-     */
-    public ServletContext getServletContext() {
-
-        if (manager == null)
-            return (null);
-        Context context = (Context) manager.getContainer();
-        if (context == null)
-            return (null);
-        else
-            return (context.getServletContext());
-
-    }
-
-    /**
-     * Return the session context with which this session is associated.
-     * 
-     * @deprecated As of Version 2.1, this method is deprecated and has no
-     *             replacement. It will be removed in a future version of the
-     *             Java Servlet API.
-     */
-    public HttpSessionContext getSessionContext() {
-
-        if (sessionContext == null)
-            sessionContext = new StandardSessionContext();
-        return (sessionContext);
-
-    }
-
     // ----------------------------------------------HttpSession Public Methods
 
-    /**
-     * Return the object bound with the specified name in this session, or
-     * <code>null</code> if no object is bound with that name.
-     * 
-     * @param name
-     *            Name of the attribute to be returned
-     * 
-     * @exception IllegalStateException
-     *                if this method is called on an invalidated session
-     */
-    public Object getAttribute(String name) {
-
-        if (!isValid())
-            throw new IllegalStateException(sm
-                    .getString("standardSession.getAttribute.ise"));
-        return (attributes.get(name));
-    }
-
-    /**
-     * Return an <code>Enumeration</code> of <code>String</code> objects
-     * containing the names of the objects bound to this session.
-     * 
-     * @exception IllegalStateException
-     *                if this method is called on an invalidated session
-     */
-    public Enumeration getAttributeNames() {
-
-        if (!isValid())
-            throw new IllegalStateException(sm
-                    .getString("standardSession.getAttributeNames.ise"));
-        return (new Enumerator(attributes.keySet(), true));
-    }
-
-    /**
-     * Return the object bound with the specified name in this session, or
-     * <code>null</code> if no object is bound with that name.
-     * 
-     * @param name
-     *            Name of the value to be returned
-     * 
-     * @exception IllegalStateException
-     *                if this method is called on an invalidated session
-     * 
-     * @deprecated As of Version 2.2, this method is replaced by
-     *             <code>getAttribute()</code>
-     */
-    public Object getValue(String name) {
-
-        return (getAttribute(name));
-
-    }
-
-    /**
-     * Return the set of names of objects bound to this session. If there are no
-     * such objects, a zero-length array is returned.
-     * 
-     * @exception IllegalStateException
-     *                if this method is called on an invalidated session
-     * 
-     * @deprecated As of Version 2.2, this method is replaced by
-     *             <code>getAttributeNames()</code>
-     */
-    public String[] getValueNames() {
-
-        if (!isValid())
-            throw new IllegalStateException(sm
-                    .getString("standardSession.getValueNames.ise"));
-
-        return (keys());
-
-    }
-
-    /**
-     * Invalidates this session and unbinds any objects bound to it.
-     * 
-     * @exception IllegalStateException
-     *                if this method is called on an invalidated session
-     */
-    public void invalidate() {
-
-        if (!isValid())
-            throw new IllegalStateException(sm
-                    .getString("standardSession.invalidate.ise"));
-
-        // Cause this session to expire
-        expire();
-
-    }
-
-    /**
-     * Return <code>true</code> if the client does not yet know about the
-     * session, or if the client chooses not to join the session. For example,
-     * if the server used only cookie-based sessions, and the client has
-     * disabled the use of cookies, then a session would be new on each request.
-     * 
-     * @exception IllegalStateException
-     *                if this method is called on an invalidated session
-     */
-    public boolean isNew() {
-
-        if (!isValid())
-            throw new IllegalStateException(sm
-                    .getString("standardSession.isNew.ise"));
-
-        return (this.isNew);
-
-    }
-
-    /**
-     * Bind an object to this session, using the specified name. If an object of
-     * the same name is already bound to this session, the object is replaced.
-     * <p>
-     * After this method executes, and if the object implements
-     * <code>HttpSessionBindingListener</code>, the container calls
-     * <code>valueBound()</code> on the object.
-     * 
-     * @param name
-     *            Name to which the object is bound, cannot be null
-     * @param value
-     *            Object to be bound, cannot be null
-     * 
-     * @exception IllegalStateException
-     *                if this method is called on an invalidated session
-     * 
-     * @deprecated As of Version 2.2, this method is replaced by
-     *             <code>setAttribute()</code>
-     */
-    public void putValue(String name, Object value) {
-
-        setAttribute(name, value);
-
-    }
-
-    /**
-     * Remove the object bound with the specified name from this session. If the
-     * session does not have an object bound with this name, this method does
-     * nothing.
-     * <p>
-     * After this method executes, and if the object implements
-     * <code>HttpSessionBindingListener</code>, the container calls
-     * <code>valueUnbound()</code> on the object.
-     * 
-     * @param name
-     *            Name of the object to remove from this session.
-     * 
-     * @exception IllegalStateException
-     *                if this method is called on an invalidated session
-     */
-    public void removeAttribute(String name) {
-
-        removeAttribute(name, true);
 
-    }
 
     /**
      * Remove the object bound with the specified name from this session. If the
@@ -1182,7 +552,7 @@
      * @param notify
      *            Should we notify interested listeners that this attribute is
      *            being removed?
-     * 
+     *
      * @exception IllegalStateException
      *                if this method is called on an invalidated session
      */
@@ -1190,41 +560,13 @@
         removeAttribute(name, notify, true);
     }
 
-    public void removeAttribute(String name, boolean notify,
-            boolean addDeltaRequest) {
-
+    public void removeAttribute(String name, boolean notify,boolean addDeltaRequest) {
         // Validate our current state
-        if (!isValid())
-            throw new IllegalStateException(sm
-                    .getString("standardSession.removeAttribute.ise"));
+        if (!isValid()) throw new IllegalStateException(sm.getString("standardSession.removeAttribute.ise"));
         removeAttributeInternal(name, notify, addDeltaRequest);
     }
 
     /**
-     * Remove the object bound with the specified name from this session. If the
-     * session does not have an object bound with this name, this method does
-     * nothing.
-     * <p>
-     * After this method executes, and if the object implements
-     * <code>HttpSessionBindingListener</code>, the container calls
-     * <code>valueUnbound()</code> on the object.
-     * 
-     * @param name
-     *            Name of the object to remove from this session.
-     * 
-     * @exception IllegalStateException
-     *                if this method is called on an invalidated session
-     * 
-     * @deprecated As of Version 2.2, this method is replaced by
-     *             <code>removeAttribute()</code>
-     */
-    public void removeValue(String name) {
-
-        removeAttribute(name);
-
-    }
-
-    /**
      * Bind an object to this session, using the specified name. If an object of
      * the same name is already bound to this session, the object is replaced.
      * <p>
@@ -1247,13 +589,10 @@
         setAttribute(name, value, true, true);
     }
 
-    public void setAttribute(String name, Object value, boolean notify,
-            boolean addDeltaRequest) {
+    public void setAttribute(String name, Object value, boolean notify,boolean addDeltaRequest) {
 
         // Name cannot be null
-        if (name == null)
-            throw new IllegalArgumentException(sm
-                    .getString("standardSession.setAttribute.namenull"));
+        if (name == null) throw new IllegalArgumentException(sm.getString("standardSession.setAttribute.namenull"));
 
         // Null value is the same as removeAttribute()
         if (value == null) {
@@ -1261,107 +600,13 @@
             return;
         }
 
-        // Validate our current state
-        if (!isValid())
-            throw new IllegalStateException(sm
-                    .getString("standardSession.setAttribute.ise"));
-        if (!(value instanceof java.io.Serializable)) {
-            throw new IllegalArgumentException("Attribute [" + name
-                    + "] is not serializable");
-        }
-
-        if (addDeltaRequest && (deltaRequest != null))
-            deltaRequest.setAttribute(name, value);
-
-
-        // Construct an event with the new value
-        HttpSessionBindingEvent event = null;
-
-        // Call the valueBound() method if necessary
-        if (value instanceof HttpSessionBindingListener && notify) {
-            // Don't call any notification if replacing with the same value
-            Object oldValue = attributes.get(name);
-            if (value != oldValue) {
-                event = new HttpSessionBindingEvent(getSession(), name, value);
-                try {
-                    ((HttpSessionBindingListener) value).valueBound(event);
-                } catch (Exception x) {
-                    manager.getContainer().getLogger().error
-                        (smp.getString("deltaSession.valueBound.ex"), x);
-                }
-            }
-        }
-
-        // Replace or add this attribute
-        Object unbound = attributes.put(name, value);
-        // Call the valueUnbound() method if necessary
-        if ((unbound != null) && (unbound != value) && notify
-                && (unbound instanceof HttpSessionBindingListener)) {
-            try {
-                ((HttpSessionBindingListener) unbound)
-                        .valueUnbound(new HttpSessionBindingEvent(
-                                (HttpSession) getSession(), name));
-            } catch (Exception x) {
-                manager.getContainer().getLogger().error
-                    (smp.getString("deltaSession.valueBinding.ex"), x);
-            }
-
-        }
-
-        //dont notify any listeners
-        if (!notify)
-            return;
-
-        // Notify interested application event listeners
-        Context context = (Context) manager.getContainer();
-        if (context != null) {
-            Object listeners[] = context.getApplicationEventListeners();
-            if (listeners == null)
-                return;
-            for (int i = 0; i < listeners.length; i++) {
-                if (!(listeners[i] instanceof HttpSessionAttributeListener))
-                    continue;
-                HttpSessionAttributeListener listener = (HttpSessionAttributeListener) listeners[i];
-                try {
-                    if (unbound != null) {
-                        fireContainerEvent(context,
-                                "beforeSessionAttributeReplaced", listener);
-                        if (event == null) {
-                            event = new HttpSessionBindingEvent(getSession(),
-                                    name, unbound);
-                        }
-                        listener.attributeReplaced(event);
-                        fireContainerEvent(context,
-                                "afterSessionAttributeReplaced", listener);
-                    } else {
-                        fireContainerEvent(context,
-                                "beforeSessionAttributeAdded", listener);
-                        if (event == null) {
-                            event = new HttpSessionBindingEvent(getSession(),
-                                    name, value);
-                        }
-                        listener.attributeAdded(event);
-                        fireContainerEvent(context,
-                                "afterSessionAttributeAdded", listener);
-                    }
-                } catch (Throwable t) {
-                    try {
-                        if (unbound != null) {
-                            fireContainerEvent(context,
-                                    "afterSessionAttributeReplaced", listener);
-                        } else {
-                            fireContainerEvent(context,
-                                    "afterSessionAttributeAdded", listener);
-                        }
-                    } catch (Exception e) {
-                        ;
-                    }
-                    manager.getContainer().getLogger().error
-                        (sm.getString("standardSession.attributeEvent"),t);
-                }
-            }
+        try {
+            lock();
+            super.setAttribute(name,value, notify);
+            if (addDeltaRequest && (deltaRequest != null)) deltaRequest.setAttribute(name, value);
+        } finally {
+            unlock();
         }
-
     }
 
     // -------------------------------------------- HttpSession Private Methods
@@ -1381,57 +626,66 @@
      * @exception IOException
      *                if an input/output error occurs
      */
-    private void readObject(ObjectInputStream stream)
-            throws ClassNotFoundException, IOException {
+    @Override
+    protected void readObject(ObjectInputStream stream) throws ClassNotFoundException, IOException {
+        readObject((ObjectInput)stream);
+    }
+
+    private void readObject(ObjectInput stream) throws ClassNotFoundException, IOException {
 
         // Deserialize the scalar instance variables (except Manager)
         authType = null; // Transient only
-        creationTime = ((Long) stream.readObject()).longValue();
-        lastAccessedTime = ((Long) stream.readObject()).longValue();
-        maxInactiveInterval = ((Integer) stream.readObject()).intValue();
-        isNew = ((Boolean) stream.readObject()).booleanValue();
-        isValid = ((Boolean) stream.readObject()).booleanValue();
-        thisAccessedTime = ((Long) stream.readObject()).longValue();
+        creationTime = ( (Long) stream.readObject()).longValue();
+        lastAccessedTime = ( (Long) stream.readObject()).longValue();
+        maxInactiveInterval = ( (Integer) stream.readObject()).intValue();
+        isNew = ( (Boolean) stream.readObject()).booleanValue();
+        isValid = ( (Boolean) stream.readObject()).booleanValue();
+        thisAccessedTime = ( (Long) stream.readObject()).longValue();
+        version = ( (Long) stream.readObject()).longValue();
         boolean hasPrincipal = stream.readBoolean();
         principal = null;
         if (hasPrincipal) {
-            principal = SerializablePrincipal.readPrincipal(stream,
-                    getManager().getContainer().getRealm());
+            principal = SerializablePrincipal.readPrincipal(stream,getManager().getContainer().getRealm());
         }
 
         //        setId((String) stream.readObject());
         id = (String) stream.readObject();
-        org.apache.juli.logging.Log managerLog = manager.getContainer().getLogger() ;
-        if (managerLog.isDebugEnabled())
-            managerLog.debug(smp.getString("deltaSession.readSession",  id));
+        if (log.isDebugEnabled()) log.debug(sm.getString("deltaSession.readSession", id));
 
         // Deserialize the attribute count and attribute values
-        if (attributes == null)
-            attributes = new Hashtable();
-        int n = ((Integer) stream.readObject()).intValue();
+        if (attributes == null) attributes = new Hashtable();
+        int n = ( (Integer) stream.readObject()).intValue();
         boolean isValidSave = isValid;
         isValid = true;
         for (int i = 0; i < n; i++) {
             String name = (String) stream.readObject();
             Object value = (Object) stream.readObject();
-            if ((value instanceof String) && (value.equals(NOT_SERIALIZED)))
+            if ( (value instanceof String) && (value.equals(NOT_SERIALIZED)))
                 continue;
-            if (managerLog.isDebugEnabled())
-                managerLog.debug("  loading attribute '" + name +
-                    "' with value '" + value + "'");
             attributes.put(name, value);
         }
         isValid = isValidSave;
-        
+
         if (listeners == null) {
             listeners = new ArrayList();
         }
-        
+
         if (notes == null) {
             notes = new Hashtable();
         }
+        activate();
+    }
+
+    public void writeExternal(ObjectOutput out ) throws java.io.IOException {
+        try {
+            lock();
+            writeObject(out);
+        }finally {
+            unlock();
+        }
     }
 
+
     /**
      * Write a serialized version of this session object to the specified object
      * output stream.
@@ -1446,15 +700,18 @@
      * HttpSessionBindingListener. If you do not want any such attributes, be
      * sure the <code>distributable</code> property of the associated Manager
      * is set to <code>true</code>.
-     * 
+     *
      * @param stream
      *            The output stream to write to
-     * 
+     *
      * @exception IOException
      *                if an input/output error occurs
      */
-    private void writeObject(ObjectOutputStream stream) throws IOException {
-
+    protected void writeObject(ObjectOutputStream stream) throws IOException {
+        writeObject((ObjectOutput)stream);
+    }
+    
+    private void writeObject(ObjectOutput stream) throws IOException {
         // Write the scalar instance variables (except Manager)
         stream.writeObject(new Long(creationTime));
         stream.writeObject(new Long(lastAccessedTime));
@@ -1462,16 +719,14 @@
         stream.writeObject(new Boolean(isNew));
         stream.writeObject(new Boolean(isValid));
         stream.writeObject(new Long(thisAccessedTime));
+        stream.writeObject(new Long(version));
         stream.writeBoolean(getPrincipal() != null);
         if (getPrincipal() != null) {
-            SerializablePrincipal.writePrincipal((GenericPrincipal) principal,
-                    stream);
+            SerializablePrincipal.writePrincipal((GenericPrincipal) principal,stream);
         }
 
         stream.writeObject(id);
-        org.apache.juli.logging.Log managerLog = manager.getContainer().getLogger() ;
-        if (managerLog.isDebugEnabled())
-            managerLog.debug(smp.getString("deltaSession.writeSession",id));
+        if (log.isDebugEnabled()) log.debug(sm.getString("deltaSession.writeSession", id));
 
         // Accumulate the names of serializable and non-serializable attributes
         String keys[] = keys();
@@ -1492,197 +747,70 @@
         int n = saveNames.size();
         stream.writeObject(new Integer(n));
         for (int i = 0; i < n; i++) {
-            stream.writeObject((String) saveNames.get(i));
+            stream.writeObject( (String) saveNames.get(i));
             try {
                 stream.writeObject(saveValues.get(i));
-                if (managerLog.isDebugEnabled()) {
-                    managerLog.debug(" storing attribute '" + saveNames.get(i) +
-                        "' with value '" + saveValues.get(i) + "'");
-                }
             } catch (NotSerializableException e) {
-                managerLog.warn(sm.getString("standardSession.notSerializable",
-                        saveNames.get(i), id), e);
+                log.error(sm.getString("standardSession.notSerializable",saveNames.get(i), id), e);
                 stream.writeObject(NOT_SERIALIZED);
-                if(managerLog.isDebugEnabled()) {
-                    managerLog.debug("  storing attribute '" + saveNames.get(i)
-                        + "' with value NOT_SERIALIZED");
-                }
+                log.error("  storing attribute '" + saveNames.get(i)+ "' with value NOT_SERIALIZED");
             }
         }
 
     }
 
-    private void evaluateIfValid() {
-        /*
-         * If this session has expired or is in the process of expiring or will
-         * never expire, return
-         */
-        if (!this.isValid || expiring || maxInactiveInterval < 0)
-            return;
-
-        isValid();
-
-    }
-
     // -------------------------------------------------------- Private Methods
 
-    /**
-     * Fire container events if the Context implementation is the
-     * <code>org.apache.catalina.core.StandardContext</code>.
-     * 
-     * @param context
-     *            Context for which to fire events
-     * @param type
-     *            Event type
-     * @param data
-     *            Event data
-     * 
-     * @exception Exception
-     *                occurred during event firing
-     */
-    private void fireContainerEvent(Context context, String type, Object data)
-            throws Exception {
-
-        if (!"org.apache.catalina.core.StandardContext".equals(context
-                .getClass().getName())) {
-            return; // Container events are not supported
-        }
-        // NOTE: Race condition is harmless, so do not synchronize
-        if (containerEventMethod == null) {
-            containerEventMethod = context.getClass().getMethod(
-                    "fireContainerEvent", containerEventTypes);
-        }
-        Object containerEventParams[] = new Object[2];
-        containerEventParams[0] = type;
-        containerEventParams[1] = data;
-        containerEventMethod.invoke(context, containerEventParams);
-
-    }
-
-    /**
-     * Notify all session event listeners that a particular event has occurred
-     * for this Session. The default implementation performs this notification
-     * synchronously using the calling thread.
-     * 
-     * @param type
-     *            Event type
-     * @param data
-     *            Event data
-     */
-    public void fireSessionEvent(String type, Object data) {
-        if (listeners.size() < 1)
-            return;
-        SessionEvent event = new SessionEvent(this, type, data);
-        SessionListener list[] = new SessionListener[0];
-        synchronized (listeners) {
-            list = (SessionListener[]) listeners.toArray(list);
-        }
-
-        for (int i = 0; i < list.length; i++) {
-            ((SessionListener) list[i]).sessionEvent(event);
-        }
-
-    }
-
-    /**
-     * Return the names of all currently defined session attributes as an array
-     * of Strings. If there are no defined attributes, a zero-length array is
-     * returned.
-     */
-    protected String[] keys() {
-        return ((String[]) attributes.keySet().toArray(EMPTY_ARRAY));
-    }
+    
 
     /**
      * Return the value of an attribute without a check for validity.
      */
     protected Object getAttributeInternal(String name) {
-        return (attributes.get(name));  
+        return (attributes.get(name));
     }
 
     protected void removeAttributeInternal(String name, boolean notify,
-            boolean addDeltaRequest) {
-
-        // Remove this attribute from our collection
-        Object value = attributes.remove(name);
-        if (value == null)
-            return;
-
-        if (addDeltaRequest && (deltaRequest != null))
-            deltaRequest.removeAttribute(name);
+                                           boolean addDeltaRequest) {
+        try {
+            lock();
+            // Remove this attribute from our collection
+            Object value = attributes.get(name);
+            if (value == null) return;
 
-        // Do we need to do valueUnbound() and attributeRemoved() notification?
-        if (!notify) {
-            return;
-        }
+            super.removeAttributeInternal(name,notify);
+            if (addDeltaRequest && (deltaRequest != null)) deltaRequest.removeAttribute(name);
 
-        // Call the valueUnbound() method if necessary
-         HttpSessionBindingEvent event = null;
-         if (value instanceof HttpSessionBindingListener) {
-            event = new HttpSessionBindingEvent(
-                (HttpSession) getSession(), name, value);
-            try {
-                ((HttpSessionBindingListener) value).valueUnbound(event);
-            } catch (Exception x) {
-                manager.getContainer().getLogger().error
-                    (smp.getString("deltaSession.valueUnbound.ex"), x);
-            }
-        }
-        // Notify interested application event listeners
-        Context context = (Context) manager.getContainer();
-        if (context != null) {
-            Object listeners[] = context.getApplicationEventListeners();
-            if (listeners == null)
-                return;
-            for (int i = 0; i < listeners.length; i++) {
-                if (!(listeners[i] instanceof HttpSessionAttributeListener))
-                    continue;
-                HttpSessionAttributeListener listener = (HttpSessionAttributeListener) listeners[i];
-                try {
-                    fireContainerEvent(context,
-                            "beforeSessionAttributeRemoved", listener);
-                    if (event == null) {
-                        event = new HttpSessionBindingEvent
-                            (getSession(), name, value);
-                    }
-                    listener.attributeRemoved(event);
-                    fireContainerEvent(context, "afterSessionAttributeRemoved",
-                            listener);
-                } catch (Throwable t) {
-                    try {
-                        fireContainerEvent(context,
-                                "afterSessionAttributeRemoved", listener);
-                    } catch (Exception e) {
-                        ;
-                    }
-                    manager.getContainer().getLogger().error
-                        (sm.getString("standardSession.attributeEvent"),t);
-                }
-            }
+        }finally {
+            unlock();
         }
-
     }
 
     protected long getLastTimeReplicated() {
         return lastTimeReplicated;
     }
 
+    public long getVersion() {
+        return version;
+    }
+
     protected void setLastTimeReplicated(long lastTimeReplicated) {
         this.lastTimeReplicated = lastTimeReplicated;
     }
 
-    protected void setAccessCount(int accessCount) {
-        this.accessCount = accessCount;
+    public void setVersion(long version) {
+        this.version = version;
     }
 
-    protected int getAccessCount() {
-        return accessCount;
+    protected void setAccessCount(int count) {
+        if ( accessCount == null && ACTIVITY_CHECK ) accessCount = new AtomicInteger();
+        if ( accessCount != null ) super.accessCount.set(count);
     }
 
     protected void setExpireTolerance(int expireTolerance) {
         this.expireTolerance = expireTolerance;
       }
-    
+
     protected int getExpireTolerance() {
         return expireTolerance;
     }
@@ -1702,7 +830,8 @@
  *             will be removed in a future version of this API.
  */
 
-final class StandardSessionContext implements HttpSessionContext {
+final class StandardSessionContext
+    implements HttpSessionContext {
 
     private HashMap dummy = new HashMap();
 
@@ -1715,9 +844,7 @@
      *             removed in a future version of the API.
      */
     public Enumeration getIds() {
-
         return (new Enumerator(dummy));
-
     }
 
     /**
@@ -1732,9 +859,7 @@
      *             the API.
      */
     public HttpSession getSession(String id) {
-
         return (null);
-
     }
 
 }

Modified: tomcat/sandbox/tomcat-oacc/trunk/src/share/org/apache/catalina/cluster/session/LocalStrings.properties
URL: http://svn.apache.org/viewvc/tomcat/sandbox/tomcat-oacc/trunk/src/share/org/apache/catalina/cluster/session/LocalStrings.properties?rev=812589&r1=812588&r2=812589&view=diff
==============================================================================
--- tomcat/sandbox/tomcat-oacc/trunk/src/share/org/apache/catalina/cluster/session/LocalStrings.properties (original)
+++ tomcat/sandbox/tomcat-oacc/trunk/src/share/org/apache/catalina/cluster/session/LocalStrings.properties Tue Sep  8 17:27:04 2009
@@ -59,9 +59,6 @@
 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}]
@@ -90,23 +87,7 @@
 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}

Modified: tomcat/sandbox/tomcat-oacc/trunk/src/share/org/apache/catalina/cluster/session/LocalStrings_es.properties
URL: http://svn.apache.org/viewvc/tomcat/sandbox/tomcat-oacc/trunk/src/share/org/apache/catalina/cluster/session/LocalStrings_es.properties?rev=812589&r1=812588&r2=812589&view=diff
==============================================================================
--- tomcat/sandbox/tomcat-oacc/trunk/src/share/org/apache/catalina/cluster/session/LocalStrings_es.properties (original)
+++ tomcat/sandbox/tomcat-oacc/trunk/src/share/org/apache/catalina/cluster/session/LocalStrings_es.properties Tue Sep  8 17:27:04 2009
@@ -59,9 +59,6 @@
 deltaRequest.showPrincipal = El Principal [{0}] est\u00E1 puesto a sesi\u00F3n {1}
 deltaRequest.wrongPrincipalClass = DeltaManager s\u00F3lo soporta GenericPrincipal. Tu reino utiliz\u00F3 clase principal {0}.
 deltaSession.notifying = Notificando cl\u00FAster de expiraci\u00F3n primaria\={0} sessionId [{1}]
-deltaSession.valueBound.ex = Oyente ligado a sesi\u00F3n lanz\u00F3 una excepci\u00F3n
-deltaSession.valueBinding.ex = Oyente lig\u00E1ndose a sesi\u00F3n lanz\u00F3 una excepci\u00F3n
-deltaSession.valueUnbound.ex = Oyente desligado de sesi\u00F3n lanz\u00F3 una excepci\u00F3n
 deltaSession.readSession = readObject() cargando sesi\u00F3n [{0}]
 deltaSession.readAttribute = sesi\u00F3n [{0}] cargando atributo '{1}' con valor '{2}'
 deltaSession.writeSession = writeObject() guardando sesi\u00F3n [{0}]
@@ -89,23 +86,7 @@
 jvmRoute.valve.started = JvmRouteBinderValve arrancada
 jvmRoute.valve.stopped = JvmRouteBinderValve parada
 jvmRoute.set.orignalsessionid = Puesta id Orginal de Sesi\u00F3n en atributo de requerimiento {0} valor\: {1}
-standardSession.getId.ise = getId\: Sesi\u00F3n ya invalidada
-standardSession.attributeEvent = El oyente de evento de atributo de sesi\u00F3n lanz\u00F3 excepci\u00F3n
-standardSession.attributeEvent = El oyente de evento de atributo de sesi\u00F3n lanz\u00F3 excepci\u00F3n
-standardSession.bindingEvent = El oyente de evento de ligado de sesi\u00F3n lanz\u00F3 excepci\u00F3n
-standardSession.invalidate.ise = invalidar\: Sesi\u00F3n ya invalidada
-standardSession.isNew.ise = isNew\: Sesi\u00F3n ya invalidada
-standardSession.getAttribute.ise = getAttribute\: Sesi\u00F3n ya invalidada
-standardSession.getAttributeNames.ise = getAttributeNames\: Sesi\u00F3n ya invalidada
-standardSession.getCreationTime.ise = getCreationTime\: Sesi\u00F3n ya invalidada
-standardSession.getLastAccessedTime.ise = getLastAccessedTime\: Sesi\u00F3n ya invalidada
-standardSession.getId.ise = getId\: Sesi\u00F3n ya invalidada
-standardSession.getMaxInactiveInterval.ise = getMaxInactiveInterval\: Sesi\u00F3n ya invalidada
-standardSession.getValueNames.ise = getValueNames\: Sesi\u00F3n ya invalidada
 standardSession.notSerializable = No puedo serializar atributo de sesi\u00F3n {0} para sesi\u00F3n {1}
 standardSession.removeAttribute.ise = removeAttribute\: Sesi\u00F3n ya invalidada
 standardSession.sessionEvent = El oyente de evento de sesi\u00F3n lanz\u00F3 excepci\u00F3n
-standardSession.setAttribute.iae = setAttribute\: Atributo no serializable
-standardSession.setAttribute.ise = setAttribute\: Sesi\u00F3n ya invalidada
 standardSession.setAttribute.namenull = setAttribute\: par\u00E1metro de nombre no puede ser nulo
-standardSession.sessionCreated = Id de Sesi\u00F3n Creada \= {0}

Modified: tomcat/sandbox/tomcat-oacc/trunk/src/share/org/apache/catalina/cluster/session/SerializablePrincipal.java
URL: http://svn.apache.org/viewvc/tomcat/sandbox/tomcat-oacc/trunk/src/share/org/apache/catalina/cluster/session/SerializablePrincipal.java?rev=812589&r1=812588&r2=812589&view=diff
==============================================================================
--- tomcat/sandbox/tomcat-oacc/trunk/src/share/org/apache/catalina/cluster/session/SerializablePrincipal.java (original)
+++ tomcat/sandbox/tomcat-oacc/trunk/src/share/org/apache/catalina/cluster/session/SerializablePrincipal.java Tue Sep  8 17:27:04 2009
@@ -19,29 +19,35 @@
 package org.apache.catalina.cluster.session;
 
 
+import java.io.IOException;
+import java.io.ObjectInput;
+import java.io.ObjectOutput;
+import java.io.Serializable;
 import java.util.Arrays;
 import java.util.List;
+
 import org.apache.catalina.Realm;
+import org.apache.catalina.realm.GenericPrincipal;
 
 
 /**
  * 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.
+ * 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$ $Date$
  */
-import org.apache.catalina.realm.GenericPrincipal;
-public class SerializablePrincipal  implements java.io.Serializable {
+public class SerializablePrincipal  implements Serializable {
 
 
     // ----------------------------------------------------------- Constructors
 
-    public SerializablePrincipal()
-    {
+    public SerializablePrincipal() {
         super();
     }
+    
+    
     /**
      * Construct a new Principal, associated with the specified Realm, for the
      * specified username and password.
@@ -68,7 +74,7 @@
      * @param roles List of roles (must be Strings) possessed by this user
      */
     public SerializablePrincipal(Realm realm, String name, String password,
-                            List roles) {
+                            List<String> roles) {
 
         super();
         this.realm = realm;
@@ -76,7 +82,7 @@
         this.password = password;
         if (roles != null) {
             this.roles = new String[roles.size()];
-            this.roles = (String[]) roles.toArray(this.roles);
+            this.roles = roles.toArray(this.roles);
             if (this.roles.length > 0)
                 Arrays.sort(this.roles);
         }
@@ -163,10 +169,12 @@
 
     public GenericPrincipal getPrincipal( Realm realm )
     {
-        return new GenericPrincipal(realm,name,password,getRoles()!=null?Arrays.asList(getRoles()):null);
+        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{
+    public static GenericPrincipal readPrincipal(ObjectInput in, Realm realm)
+            throws IOException, ClassNotFoundException {
         String name = in.readUTF();
         boolean hasPwd = in.readBoolean();
         String pwd = null;
@@ -177,7 +185,8 @@
         return new GenericPrincipal(realm,name,pwd,Arrays.asList(roles));
     }
     
-    public static void writePrincipal(GenericPrincipal p, java.io.ObjectOutputStream out) throws java.io.IOException {
+    public static void writePrincipal(GenericPrincipal p, ObjectOutput out)
+            throws IOException {
         out.writeUTF(p.getName());
         out.writeBoolean(p.getPassword()!=null);
         if ( p.getPassword()!= null ) out.writeUTF(p.getPassword());



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