⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 deltasession.java

📁 业界著名的tomcat服务器的最新6.0的源代码。
💻 JAVA
📖 第 1 页 / 共 2 页
字号:
/*
 * Licensed to the Apache Software Foundation (ASF) under one or more
 * contributor license agreements.  See the NOTICE file distributed with
 * this work for additional information regarding copyright ownership.
 * The ASF licenses this file to You under the Apache License, Version 2.0
 * (the "License"); you may not use this file except in compliance with
 * the License.  You may obtain a copy of the License at
 *
 *      http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */

package org.apache.catalina.ha.session;

import java.io.Externalizable;
import java.io.IOException;
import java.io.NotSerializableException;
import java.io.ObjectInput;
import java.io.ObjectOutput;
import java.io.Serializable;
import java.security.Principal;
import java.util.ArrayList;
import java.util.Enumeration;
import java.util.HashMap;
import java.util.Hashtable;
import java.util.concurrent.locks.Lock;
import java.util.concurrent.locks.ReentrantReadWriteLock;
import javax.servlet.http.HttpSession;
import javax.servlet.http.HttpSessionContext;

import org.apache.catalina.Manager;
import org.apache.catalina.ha.ClusterManager;
import org.apache.catalina.ha.ClusterSession;
import org.apache.catalina.realm.GenericPrincipal;
import org.apache.catalina.session.StandardSession;
import org.apache.catalina.tribes.io.ReplicationStream;
import org.apache.catalina.tribes.tipis.ReplicatedMapEntry;
import org.apache.catalina.util.Enumerator;
import org.apache.catalina.util.StringManager;
import org.apache.catalina.session.StandardManager;
import org.apache.catalina.session.ManagerBase;
import java.util.concurrent.atomic.AtomicInteger;

/**
 *
 * Similar to the StandardSession except that this session will keep
 * track of deltas during a request.
 *
 * @author Filip Hanik
 * @version $Revision: 467222 $ $Date: 2006-10-24 05:17:11 +0200 (mar., 24 oct. 2006) $
 */

public class DeltaSession extends StandardSession implements Externalizable,ClusterSession,ReplicatedMapEntry {

    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 sm = StringManager.getManager(Constants.Package);

    // ----------------------------------------------------- Instance Variables

    /**
     * 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
     * request on another server.
     */
    private transient boolean isPrimarySession = true;

    /**
     * The delta request contains all the action info
     *
     */
    private transient DeltaRequest deltaRequest = null;

    /**
     * Last time the session was replicatd, used for distributed expiring of
     * session
     */
    private transient long lastTimeReplicated = System.currentTimeMillis();


    protected Lock diffLock = new ReentrantReadWriteLock().writeLock();

    private long version;

    // ----------------------------------------------------------- Constructors

    /**
     * Construct a new Session associated with the specified Manager.
     *
     * @param manager
     *            The manager with which this Session is associated
     */
    public DeltaSession() {
        this(null);
    }

    public DeltaSession(Manager manager) {
        super(manager);
        this.resetDeltaRequest();
    }

    // ----------------------------------------------------- ReplicatedMapEntry

    /**
         * Has the object changed since last replication
         * and is not in a locked state
         * @return boolean
         */
        public boolean isDirty() {
            return getDeltaRequest().getSize()>0;
        }

        /**
         * If this returns true, the map will extract the diff using getDiff()
         * Otherwise it will serialize the entire object.
         * @return boolean
         */
        public boolean isDiffable() {
            return true;
        }

        /**
         * Returns a diff and sets the dirty map to false
         * @return byte[]
         * @throws IOException
         */
        public byte[] getDiff() throws IOException {
            return getDeltaRequest().serialize();
        }

        public ClassLoader[] getClassLoaders() {
            if ( manager instanceof BackupManager ) return ((BackupManager)manager).getClassLoaders();
            else if ( manager instanceof ClusterManagerBase ) return ((ClusterManagerBase)manager).getClassLoaders();
            else if ( manager instanceof StandardManager ) {
                StandardManager sm = (StandardManager)manager;
                return ClusterManagerBase.getClassLoaders(sm.getContainer());
            } else if ( manager instanceof ManagerBase ) {
                ManagerBase mb = (ManagerBase)manager;
                return ClusterManagerBase.getClassLoaders(mb.getContainer());
            }//end if
            return null;
        }

        /**
         * Applies a diff to an existing object.
         * @param diff byte[]
         * @param offset int
         * @param length int
         * @throws IOException
         */
        public void applyDiff(byte[] diff, int offset, int length) throws IOException, ClassNotFoundException {
            ReplicationStream stream = ((ClusterManager)getManager()).getReplicationStream(diff,offset,length);
            getDeltaRequest().readExternal(stream);
            ClassLoader contextLoader = Thread.currentThread().getContextClassLoader();
            try {
                ClassLoader[] loaders = getClassLoaders();
                if ( loaders != null && loaders.length >0 ) Thread.currentThread().setContextClassLoader(loaders[0]);
                getDeltaRequest().execute(this);
            }finally {
                Thread.currentThread().setContextClassLoader(contextLoader);
            }
        }

        /**
         * Resets the current diff state and resets the dirty flag
         */
        public void resetDiff() {
            resetDeltaRequest();
        }

        /**
         * Lock during serialization
         */
        public void lock() {
            diffLock.lock();
        }

        /**
         * Unlock after serialization
         */
        public void unlock() {
            diffLock.unlock();
        }

        public void setOwner(Object owner) {
            if ( owner instanceof ClusterManager && getManager()==null) {
                ClusterManager cm = (ClusterManager)owner;
                this.setManager(cm);
                this.setValid(true);
                this.setPrimarySession(false);
                this.access();
                this.resetDeltaRequest();
                this.endAccess();
            }
        }
    // ----------------------------------------------------- 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
     */
    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) {
        this.id = id;
        resetDeltaRequest();
    }

    /**
     * Set the session identifier for this session.
     *
     * @param id
     *            The new session identifier
     */
    public void setId(String id) {
        super.setId(id);
        resetDeltaRequest();
    }

   

    /**
     * Return the last client access time without invalidation check
     * @see #getLastAccessedTime().
     */
    public long getLastAccessedTimeInternal() {
        return (this.lastAccessedTime);
    }


   
    public void setMaxInactiveInterval(int interval, boolean addDeltaRequest) {
        super.maxInactiveInterval = interval;
        if (isValid && interval == 0) {
            expire();
        } else {
            if (addDeltaRequest && (deltaRequest != null))
                deltaRequest.setMaxInactiveInterval(interval);
        }
    }

    /**
     * Set the <code>isNew</code> flag for this session.
     *
     * @param isNew
     *            The new value for the <code>isNew</code> flag
     */
    public void setNew(boolean isNew) {
        setNew(isNew, true);
    }

    public void setNew(boolean isNew, boolean addDeltaRequest) {
        super.setNew(isNew);
        if (addDeltaRequest && (deltaRequest != null))
            deltaRequest.setNew(isNew);
    }

    /**
     * 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) {
        setPrincipal(principal, true);
    }

    public void setPrincipal(Principal principal, boolean addDeltaRequest) {
        try { 
            lock();
            super.setPrincipal(principal);
            if (addDeltaRequest && (deltaRequest != null))
                deltaRequest.setPrincipal(principal);
        } finally {
            unlock();
        }
    }

    /**
     * Return the <code>isValid</code> flag for this session.
     */
    public boolean isValid() {
        if (this.expiring) {
            return true;
        }
        if (!this.isValid) {
            return false;
        }
        if (ACTIVITY_CHECK && accessCount.get() > 0) {
            return true;
        }
        if (maxInactiveInterval >= 0) {
            long timeNow = System.currentTimeMillis();
            int timeIdle = (int) ( (timeNow - thisAccessedTime) / 1000L);
            if (isPrimarySession()) {
                if (timeIdle >= maxInactiveInterval) {
                    expire(true);
                }
            } else {
                if (timeIdle >= (2 * maxInactiveInterval)) {
                    //if the session has been idle twice as long as allowed,
                    //the primary session has probably crashed, and no other
                    //requests are coming in. that is why we do this. otherwise
                    //we would have a memory leak
                    expire(true, false);
                }
            }
        }
        return (this.isValid);
    }

    // ------------------------------------------------- Session Public Methods

    /**
     * Perform the internal processing required to invalidate this session,
     * without triggering an exception if the session has already expired.
     *
     * @param notify
     *            Should we notify listeners about the demise of this session?
     */
    public void expire(boolean notify) {
        expire(notify, true);
    }

    public void expire(boolean notify, boolean notifyCluster) {
        String expiredId = getIdInternal();
        super.expire(notify);

        if (notifyCluster) {
            if (log.isDebugEnabled())
                log.debug(sm.getString("deltaSession.notifying",
                                       ((DeltaManager)manager).getName(), 
                                       new Boolean(isPrimarySession()), 
                                       expiredId));
            if ( manager instanceof DeltaManager ) {
                ( (DeltaManager) manager).sessionExpired(expiredId);
            }
        }
    }

    /**
     * Release all object references, and initialize instance variables, in
     * preparation for reuse of this object.
     */
    public void recycle() {
        super.recycle();
        deltaRequest.clear();

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -