Package com.sun.enterprise.ee.web.sessmgmt

Source Code of com.sun.enterprise.ee.web.sessmgmt.ReplicationStore

/*
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS HEADER.
*
* Copyright 1997-2007 Sun Microsystems, Inc. All rights reserved.
*
* The contents of this file are subject to the terms of either the GNU
* General Public License Version 2 only ("GPL") or the Common Development
* and Distribution License("CDDL") (collectively, the "License").  You
* may not use this file except in compliance with the License. You can obtain
* a copy of the License at https://glassfish.dev.java.net/public/CDDL+GPL.html
* or glassfish/bootstrap/legal/LICENSE.txt.  See the License for the specific
* language governing permissions and limitations under the License.
*
* When distributing the software, include this License Header Notice in each
* file and include the License file at glassfish/bootstrap/legal/LICENSE.txt.
* Sun designates this particular file as subject to the "Classpath" exception
* as provided by Sun in the GPL Version 2 section of the License file that
* accompanied this code.  If applicable, add the following below the License
* Header, with the fields enclosed by brackets [] replaced by your own
* identifying information: "Portions Copyrighted [year]
* [name of copyright owner]"
*
* Contributor(s):
*
* If you wish your version of this file to be governed by only the CDDL or
* only the GPL Version 2, indicate your decision by adding "[Contributor]
* elects to include this software in this distribution under the [CDDL or GPL
* Version 2] license."  If you don't indicate a single choice of license, a
* recipient has the option to distribute your version of this file under
* either the CDDL, the GPL Version 2 or to extend the choice of license to
* its licensees as provided above.  However, if you add GPL Version 2 code
* and therefore, elected the GPL Version 2 license, then the option applies
* only if the new code is made subject to such option by the copyright
* holder.
*/
/*
* ReplicationStore.java
*
* Created on November 17, 2005, 10:24 AM
*/

package com.sun.enterprise.ee.web.sessmgmt;

import com.sun.appserv.ha.spi.BackingStore;
import com.sun.appserv.ha.spi.BackingStoreException;
import com.sun.appserv.ha.util.SimpleMetadata;
import com.sun.appserv.ha.util.SimpleMetadataFactory;
import com.sun.appserv.ha.util.Metadata;
import com.sun.appserv.ha.uow.ReplicableEntity;
import com.sun.appserv.util.cache.BaseCache;
import com.sun.enterprise.ee.web.authenticator.ReplicationSingleSignOn;
import com.sun.enterprise.security.web.SingleSignOn;
import com.sun.enterprise.security.web.SingleSignOnEntry;
import com.sun.enterprise.web.ServerConfigLookup;
import org.apache.catalina.*;
import org.apache.catalina.session.*;

import java.io.*;
import java.util.logging.Level;
import java.util.logging.Logger;
import java.util.zip.GZIPInputStream;
import java.util.Map;
import java.util.concurrent.atomic.AtomicBoolean;

/**
*
* @author Larry White
*/
public class ReplicationStore extends HAStoreBase implements HAStorePoolElement,
        SessionStoreInterface {

    public final static String BEKEY
        = ReplicationState.BEKEY;
    private final static String EXTENDED_UTILITY_CLASS_NAME
        = "org.jvnet.glassfish.comms.replication.sessmgmt.ExtendedReplicationUtil";   
    public final static String LOGGER_MEM_REP
        = ReplicationState.LOGGER_MEM_REP;
   
    private static boolean useReplicationUnicastLoadBatching = false;
   
    static {
        ServerConfigLookup lookup = new ServerConfigLookup();
        useReplicationUnicastLoadBatching
            = lookup.isReplicationUnicastLoadBatchingEnabled();       
    }    
   
    /**
     * The logger to use for logging ALL web container related messages.
     */
    //protected static final Logger _logger
    //    = LogDomains.getLogger(LogDomains.WEB_LOGGER);
    private static final Logger _logger
        = Logger.getLogger(LOGGER_MEM_REP);   
   
    protected final static String MODE_WEB = ReplicationState.MODE_WEB;
   
    protected ReplicationUtil replicationUtil = createReplicationUtil();   

    private String instanceName = ReplicationUtil.getInstanceName();
   
    /**
     * Creates a new instance of ReplicationStore
     */
    public ReplicationStore() {
        setLogLevel();       
    }
   
    protected ReplicationUtil createReplicationUtil() {
        ReplicationUtil replicationUtil = new ReplicationUtil();
        try {
            replicationUtil =
                (ReplicationUtil) (Class.forName(EXTENDED_UTILITY_CLASS_NAME)).newInstance();
        } catch (Exception ex) {
            ;
        }
        return replicationUtil;
    }
   
    public String getApplicationId() {
        if(applicationId != null) {
            return applicationId;
        }
        applicationId = "WEB:" + super.getApplicationId();
        return applicationId;
    }   

    // HAStorePoolElement methods begin
   
    /**
     * Save the specified Session into this Store.  Any previously saved
     * information for the associated session identifier is replaced.
     *
     * @param session Session to be saved
     *
     * @exception IOException if an input/output error occurs
     */   
    public void valveSave(Session session) throws IOException {
        HASession haSess = (HASession)session;
        if(_logger.isLoggable(Level.FINE)) {
            _logger.fine("ReplicationStore>>valveSave id=" + haSess.getIdInternal() +
            " isPersistent=" + haSess.isPersistent() + " isDirty=" + haSess.isDirty());
        }       
        if( haSess.isPersistent() && !haSess.isDirty() ) {
            this.updateLastAccessTime(session);
        } else {
            this.doValveSave(session);
            haSess.setPersistent(true);
        }
        haSess.setDirty(false);
    }   

    /**
     * Save the specified Session into this Store.  Any previously saved
     * information for the associated session identifier is replaced.
     *
     * @param session Session to be saved
     *
     * @exception IOException if an input/output error occurs
     */   
    public void doValveSave(Session session) throws IOException {
        if(_logger.isLoggable(Level.FINE)) {
            _logger.fine("ReplicationStore>>doValveSave:id =" + ((HASession)session).getIdInternal());
            _logger.fine("ReplicationStore>>doValveSave:valid =" + ((StandardSession)session).getIsValid());
            _logger.fine("ReplicationStore>>doValveSave:ssoId=" + ((HASession)session).getSsoId());           
        }       
        // begin 6470831 do not save if session is not valid
        if( !((StandardSession)session).getIsValid() ) {
            return;
        }
        // end 6470831        
        String userName = "";
        if(session.getPrincipal() !=null){
            userName = session.getPrincipal().getName();
            ((BaseHASession)session).setUserName(userName);
        }
        byte[] sessionState = this.getByteArray(session, isReplicationCompressionEnabled());
        ReplicationManagerBase mgr
            = (ReplicationManagerBase)this.getManager();
        BackingStore replicator = mgr.getBackingStore();
        if(_logger.isLoggable(Level.FINE)) {
            _logger.fine("ReplicationStore>>doValveSave replicator: " + replicator);
            _logger.fine("ReplicationStore>>doValveSave version:" + session.getVersion());                      
        }       
        SimpleMetadata simpleMetadata =
            SimpleMetadataFactory.createSimpleMetadata(session.getVersion()//version
                ((BaseHASession)session).getLastAccessedTimeInternal(), //lastaccesstime
                session.getMaxInactiveInterval(), //maxinactiveinterval
                sessionState, //state
                ((HASession)session).getExtraParameters()); //containerExtraParam
        String beKey = session.getBeKey();
        if(beKey != null) {
            simpleMetadata.setBeKey(beKey);
        }
        try {
            HASession haSess = (HASession)session;
            replicator.save(session.getIdInternal(), //id
                    simpleMetadata, haSess.isPersistent())//TODO: Revist the last param
        } catch (BackingStoreException ex) {
            IOException ex1 =
                (IOException) new IOException("Error during save: " + ex.getMessage()).initCause(ex);
            throw ex1;
        }
    }

    public ReplicationState getTransmitState(Session session) throws IOException {
        ReplicationManagerBase mgr
            = (ReplicationManagerBase)this.getManager();
        BackingStore replicator = mgr.getBackingStore();
        if(!(replicator instanceof JxtaBackingStoreImpl)) {
            return null;
        }
        JxtaBackingStoreImpl jxtaReplicator = (JxtaBackingStoreImpl)replicator;
        ReplicationState transmitState = null;
        String userName = "";
        if(session.getPrincipal() !=null){
            userName = session.getPrincipal().getName();
            ((BaseHASession)session).setUserName(userName);
        }
        byte[] sessionState = this.getByteArray(session, isReplicationCompressionEnabled());

        SimpleMetadata simpleMetadata =
            SimpleMetadataFactory.createSimpleMetadata(session.getVersion()//version
                ((BaseHASession)session).getLastAccessedTimeInternal(), //lastaccesstime
                session.getMaxInactiveInterval(), //maxinactiveinterval
                sessionState, //state
                ((HASession)session).getExtraParameters()); //containerExtraParam
        String beKey = session.getBeKey();
        if(beKey != null) {
            simpleMetadata.setBeKey(beKey);
        }
        //need this here because save not called
        simpleMetadata.setOwningInstanceName(ReplicationUtil.getInstanceName());
        try {
            transmitState = jxtaReplicator.getSimpleTransmitState(session.getIdInternal(), simpleMetadata);
        } catch (BackingStoreException ex) {}
        return transmitState;
    }
   
    //state is already formatted as a response
    public void sendResponse(ReplicationState state) {
        if(_logger.isLoggable(Level.FINE)) {
            _logger.fine("ReplicationStore>>sendResponse");                      
        }       
       this.doReturnTransmit(state);
    }
   
    protected void transmitSession(Session session, String command) throws IOException {
        ReplicationState transmitState =
            createReplicationState(session, command);
        if(_logger.isLoggable(Level.FINE)) {
            _logger.fine("ReplicationStore>>transmitSession: command: " + command);                      
        }
        this.doTransmit(transmitState);
       
        //remove after testing
        //this.testDeserializeState(transmitState);
    }
   
    protected void transmitSession(Session session, String command, boolean wait) throws IOException {
        ReplicationState transmitState =
            createReplicationState(session, command);
        if(_logger.isLoggable(Level.FINE)) {
            _logger.fine("ReplicationStore>>transmitSession: command: " + command);                      
        }
        this.doTransmit(transmitState, wait);
       
        //remove after testing
        //this.testDeserializeState(transmitState);
    }
   
    private boolean isMethodVoidReturn(String methodName) {
        return ReplicationState.isMethodVoidReturn(methodName);
    }
   
    ReplicationState createReplicationState(Session session, String command)
        throws IOException {
        HttpSessionExtraParams containerExtraParam = ((BaseHASession)session).getExtraParameters();
        byte[] sessionState = this.getByteArray(session);
        byte[] containerExtraParamState = null;
        if(containerExtraParam != null) {
            try {
                containerExtraParamState = ReplicationUtil.getByteArray(containerExtraParam, isReplicationCompressionEnabled());
            } catch (IOException ex) {
            IOException ex1 =
                (IOException) new IOException("error during serialization of extra parameters" + ex.getMessage()).initCause(ex);
                throw ex1;
            }
        }
        ReplicationState transmitState =
            new ReplicationState(MODE_WEB, //web mode
                session.getIdInternal(), //id 
                getApplicationId(),     //appid
                session.getVersion()//version
                ((BaseHASession)session).getLastAccessedTimeInternal()//lastaccesstime
                session.getMaxInactiveInterval(), //maxInactiveInterval (seconds)               
                getSsoId((StandardSession)session)//ssoid (extraParam)
                null, //queryResult not used here
                ReplicationUtil.getInstanceName(), //instanceName
                command,            //command
                sessionState,      //state
                null,         //trunkState
                containerExtraParamState); //containerExtraParamState
        if(_logger.isLoggable(Level.FINE)) {
            _logger.fine("ReplicationStore>>createReplicationState:transmitState = " + transmitState);                      
        }       
        return transmitState;
    }   
   
    private void testDeserializeState(ReplicationState transmitState) {
        try {
            Session sess = this.getSession(transmitState);
            //System.out.println("sess = " + sess);
        } catch (Exception e) {
            _logger.log(Level.WARNING, "exception occurred in testDeserializeState", e);
        }
    }
   
    public void cleanup() {
        //FIXME;
    }
   
    public BaseCache getSessions(){
        //FIXME
        return null;
    }
 
    public void setSessions(BaseCache sesstable) {
        //FIXME;
    }
   
    // HAStorePoolElement methods end
   
    // Store method begin
   
    /**
     * Save the specified Session into this Store.  Any previously saved
     * information for the associated session identifier is replaced.
     *
     * @param session Session to be saved
     *
     * @exception IOException if an input/output error occurs
     */   
    public void save(Session session) throws IOException {       
        HASession haSess = (HASession)session;
        if( haSess.isPersistent() && !haSess.isDirty() ) {
            this.updateLastAccessTime(session);
        } else {
            this.doSave(session);
            haSess.setPersistent(true);
        }
        haSess.setDirty(false);       
    }
   
    protected boolean isReplicationCompressionEnabled() {
        ReplicationManagerBase repMgr
            = (ReplicationManagerBase)this.getManager();
        return repMgr.isReplicationCompressionEnabled();
    }   
   
    /**
     * Save the specified Session into this Store.  Any previously saved
     * information for the associated session identifier is replaced.
     *
     * @param session Session to be saved
     *
     * @exception IOException if an input/output error occurs
     */   
    public void doSave(Session session) throws IOException {
        byte[] sessionState = this.getByteArray(session, isReplicationCompressionEnabled());
        ReplicationManagerBase mgr
            = (ReplicationManagerBase)this.getManager();
        BackingStore replicator = mgr.getBackingStore();
        if(_logger.isLoggable(Level.FINE)) {
            _logger.fine("ReplicationStore>>save: replicator: " + replicator);                      
        }        
        SimpleMetadata simpleMetadata =
            SimpleMetadataFactory.createSimpleMetadata(session.getVersion()//version
                ((BaseHASession)session).getLastAccessedTimeInternal(), //lastaccesstime
                session.getMaxInactiveInterval(), //maxinactiveinterval
                sessionState, //state
                ((HASession)session).getExtraParameters()); //containerExtraParams
        String beKey = session.getBeKey();
        if(beKey != null) {
            simpleMetadata.setBeKey(beKey);
        }       
        try {       
            replicator.save(session.getIdInternal(), //id
                    simpleMetadata, !((HASession) session).isPersistent())//TODO: Revist the last param
        } catch (BackingStoreException ex) {
            IOException ex1 =
                (IOException) new IOException("Error during save: " + ex.getMessage()).initCause(ex);
            throw ex1;
        }
    }       
   
    /**
    * Clear sessions
    *
    * @exception IOException if an input/output error occurs
    */  
    public synchronized void clear() throws IOException {
        //FIXME

    }
   
    /**
    * Remove the Session with the specified session identifier from
    * this Store, if present.  If no such Session is present, this method
    * takes no action.
    *
    * @param id Session identifier of the Session to be removed
    *
    * @exception IOException if an input/output error occurs
    */
    public void doRemove(String id) throws IOException  {
        if(_logger.isLoggable(Level.FINE)) {
            _logger.fine("ReplicationStore>>doRemove");                      
        }       
        ReplicationManagerBase mgr
            = (ReplicationManagerBase)this.getManager();
        BackingStore replicator = mgr.getBackingStore();
        if(_logger.isLoggable(Level.FINE)) {
            _logger.fine("ReplicationStore>>doRemove: replicator: " + replicator);                      
        }       
        try {
            replicator.remove(id);
        } catch (BackingStoreException ex) {
            //FIXME
        }
    }    
   
    /**
    * Remove the Session with the specified session identifier from
    * this Store, if present.  If no such Session is present, this method
    * takes no action.
    *
    * @param id Session identifier of the Session to be removed
    *
    * @exception IOException if an input/output error occurs
    */
    public synchronized void removeSynchronized(String id) throws IOException  {
        if(_logger.isLoggable(Level.FINE)) {
            _logger.fine("ReplicationStore>>removeSynchronized");                      
        }        
        ReplicationManagerBase mgr
            = (ReplicationManagerBase)this.getManager();
        BackingStore replicator = mgr.getBackingStore();
        if(_logger.isLoggable(Level.FINE)) {
            _logger.fine("ReplicationStore>>removeSynchronized: replicator: " + replicator);                      
        }       
        try {
            replicator.remove(id);
        } catch (BackingStoreException ex) {
            //FIXME
        }
    }
   
    /**
    * Remove the list of ids in removedIdsData from
    * this Store, if present.  If no such Session is present, this method
    * takes no action.
    *
    * @param msgID message id for this remove all message
    * @param removedIdsData serialized list of ids to remove
    *
    * @exception IOException if an input/output error occurs
    */
    public void removeIds(long msgID, byte[] removedIdsData) throws IOException  {
        if(_logger.isLoggable(Level.FINE)) {
            _logger.fine("ReplicationStore>>removeIds");                      
        }        
        ReplicationManagerBase mgr
            = (ReplicationManagerBase)this.getManager();
        JxtaBackingStoreImpl replicator = (JxtaBackingStoreImpl)mgr.getBackingStore();
        if(_logger.isLoggable(Level.FINE)) {
            _logger.fine("ReplicationStore>>removeIds: replicator: " + replicator);                      
        }       
        try {
            replicator.removeIds(msgID, removedIdsData);
        } catch (BackingStoreException ex) {
            //FIXME
        }
    }    
   
    /**
     * Called by our background reaper thread to remove expired
     * sessions in the replica - this can be done on the same
     * instance - i.e. each instance will do its own
     *
     */
    public void processExpires() {       
       
//        ReplicationManagerBase replicationMgr =
//            (ReplicationManagerBase) this.getManager();
//        if(!(replicationMgr.isThirdPartyBackingStoreInUse())) {
//            replicationMgr.processExpiredReplicas();
//        } else {
//            removeExpiredSessions();
//        }
        removeExpiredSessions();
    }
   
    /** This method deletes all the sessions corresponding to the "appId"
     * that should be expired
     * @return number of removed sessions
     */   
    public int removeExpiredSessions() {       
        if(_logger.isLoggable(Level.FINE)) {
            _logger.fine("IN ReplicationStore>>removeExpiredSessions");
        }
        int result = 0;
        ReplicationManagerBase mgr
            = (ReplicationManagerBase)this.getManager();
        if(mgr == null) {
            return result;
        }
        BackingStore replicator = mgr.getBackingStore();
        try {
            result = replicator.removeExpired();
        } catch (BackingStoreException ex) {
            //FIXME
        }
        if(_logger.isLoggable(Level.FINE)) {
            _logger.fine("ReplicationStore>>removeExpiredSessions():number of expired sessions = " + result);
        }
        return result;

    }      
   
    //FIXME: this could return null which would mean a problem
    //might want to throw exception in that case
    protected ReplicationState doTransmit(ReplicationState transmitState) {
        return doTransmit(transmitState, true);
        //FIXME above is just for testing put back original later
        /*
        JxtaReplicationSender replicationSender =
                JxtaReplicationSender.createInstance();
        ReplicationState resultState =
                replicationSender.sendReplicationState(transmitState);
        return resultState;
         */
    }
   
    //FIXME: this could return null which would mean a problem
    //might want to throw exception in that case
    protected ReplicationState doTransmit(ReplicationState transmitState, boolean wait) {
        //FIXME
        JxtaReplicationSender replicationSender =
                JxtaReplicationSender.createInstance();
        ReplicationState resultState =
                replicationSender.sendReplicationState(transmitState, wait);
        return resultState;
    }   
   
    protected ReplicationState doReturnTransmit(ReplicationState transmitState) {
        JxtaReplicationReceiver replicationReceiver =
                JxtaReplicationReceiver.createInstance();
        ReplicationState resultState =
                replicationReceiver.sendReplicationStateResponse(transmitState);       
        return resultState;
    }
   
    /**
    * Load and return the Session associated with the specified session
    * identifier from this Store, without removing it.  If there is no
    * such stored Session, return <code>null</code>.
    *
    * @param id Session identifier of the session to load
    *
    * @exception ClassNotFoundException if a deserialization error occurs
    * @exception IOException if an input/output error occurs
    */
    public Session load(String id) throws ClassNotFoundException, IOException {
        return load(id, null);
    }   
   
    public Session load(String id, String version) throws ClassNotFoundException, IOException {
        try {
            ExpatListElement expat = this.getExpatListElementFor(id);
            if (expat != null && expat.isFromActive()) {
                /**
                 * Irrespective of the backing store implementation, if the session
                 * is activated in the remote instance, then we should load it from there.
                 */
                return loadFromRemoteActiveCache(id, expat);
            } else {
                return loadFromBackingStore(id, version);
            }
        } catch (BackingStoreException ex) {
            IOException ex1 =
                    (IOException) new IOException("Error during load: " + ex.getMessage()).initCause(ex);
            throw ex1;
        }
    }

    public Session loadFromRemoteActiveCache(String id, ExpatListElement expat)
            throws IOException, ClassNotFoundException, BackingStoreException {
        /**
         * For the in-memory implementation, the restarted instance might
         * have the session in its replica cache, if the load-factor is used.
         */
        BaseCache replicaCache = getReplicaCache();
        if(replicaCache != null) {
            replicaCache.remove(id);
        }
        ReplicationState sessionState = loadSessionFromRemoteActiveCache(
                id, String.valueOf(expat.getVersion()), expat.getInstanceName());
        if (_logger.isLoggable(Level.FINE)) {
            _logger.fine("ReplicationStore>>loadFromActiveCache:id="
                    + id + ", sessionState=" + sessionState);
        }
        Session session = getSession(sessionState);
        validateAndSave(session);
        return session;
    }

    public Session loadFromBackingStore(String id, String version)
            throws IOException, ClassNotFoundException, BackingStoreException {
        SimpleMetadata metaData = (SimpleMetadata) getBackingStore().load(id, version);
        if(_logger.isLoggable(Level.FINE)) {
            _logger.fine("ReplicationStore>>loadFromBackingStore:id=" +
                    id + ", metaData=" + metaData);
        }
        Session session = getSession(metaData);
        validateAndSave(session);
        return session;
    }

    BackingStore getBackingStore() {
        ReplicationManagerBase mgr
                = (ReplicationManagerBase) this.getManager();
        BackingStore replicator = mgr.getBackingStore();
        return replicator;
    }


    /**
    * Load and return the Session associated with the specified session
    * identifier from this Store, without removing it.  If there is no
    * such stored Session, return <code>null</code>.
    *
    * @param id Session identifier of the session to load
    *
    * @exception ClassNotFoundException if a deserialization error occurs
    * @exception IOException if an input/output error occurs
    */
    public Metadata __load(String id, String version)
            throws BackingStoreException {
        SimpleMetadata result = null;
        if(id == null) {
            return result;
        }
        ReplicationManagerBase repMgr =
            (ReplicationManagerBase)this.getManager();
        if(_logger.isLoggable(Level.FINE)) {
            repMgr.printReplicatedSessionIds();                     
        }       
        //repMgr.printReplicatedSessionIds();
        ReplicationState localCachedState = repMgr.transferFromReplicationCache(id);
        if(_logger.isLoggable(Level.FINE)) {
            _logger.fine("ReplicationStore>>load:localCachedState=" + localCachedState);                      
        }
        //check if we got a hit from our own replica cache
        //and if so return it immediately
        if(version != null && localCachedState != null) {
            long versionLong = ReplicationUtil.parseLong(version);
            if(localCachedState.getVersion() == versionLong) {
                return ReplicationState.createSimpleMetadataFrom(localCachedState, isReplicationCompressionEnabled());
            }
        }
        ReplicationState broadcastResultState
            = findSessionViaBroadcastOrUnicast(id, version);
        ReplicationState bestState = ReplicationState.getBestResult(
                localCachedState, broadcastResultState);
        if(_logger.isLoggable(Level.FINE)) {
            _logger.fine("ReplicationStore>>__load:id=" + id + ", broadcastResultState " +
                    "from broadcast or unicast=" + broadcastResultState + ", bestState = " + bestState);
        }
        result = ReplicationState.createSimpleMetadataFrom(
                bestState, isReplicationCompressionEnabled());
        return result;
    }   
   

    private void validateAndSave(Session session) throws IOException {
        if (session != null) {
            if (__removeFromRemotelyLoadedSessionIds(session.getId())) {
                //save session - save will reset dirty to false
                if (_logger.isLoggable(Level.FINE)) {
                    _logger.fine("ReplicationStore>>validateAndSave saving " +
                            "the session after loading it. Session=" + session);
                }
                ((HASession) session).setDirty(true);
                valveSave(session);
                //send acknowledgement of load receipt
                //no response to wait for in this case
                sendLoadAcknowledgement(session.getId(), session.getVersion(), session.getBeKey());
            }
        }
    }
   
    protected ReplicationState getBestResult(ReplicationState localState, ReplicationState broadcastResultState) {
        if(_logger.isLoggable(Level.FINE)) {
            _logger.fine("ReplicationStore>>getBestResult:localState=" + localState + "other=" + broadcastResultState);                      
        }       
        if(localState == null) {
            return broadcastResultState;
        }
        //localState is not null
        if(broadcastResultState == null) {
            return localState;
        }
        //both are non-null
        if(broadcastResultState.getVersion() >= localState.getVersion()) {
            return broadcastResultState;
        } else {
            return localState;
        }
    }

    protected void sendLoadAcknowledgement(String id,
                                           long version, String beKey) {
        ReplicationState loadReceivedState =
            ReplicationState.createBroadcastLoadReceivedState(
                MODE_WEB, id,
                getApplicationId(), version,
                ReplicationUtil.getInstanceName(),
                    ReplicationManagerBase.MESSAGE_BROADCAST_LOAD_RECEIVED);
        sendLoadAcknowledgement(loadReceivedState, beKey);
    }
   
    private void sendLoadAcknowledgement(ReplicationState bestState, String beKey) {
        //send acknowledgement of load receipt
        //no response to wait for in this case
        JxtaReplicationSender sender
            = JxtaReplicationSender.createInstance();
        ReplicationState loadReceivedState =
            ReplicationState.createBroadcastLoadReceivedState(MODE_WEB,
                (String)bestState.getId(), this.getApplicationId(),
                bestState.getVersion(), ReplicationUtil.getInstanceName(),
                ReplicationManagerBase.MESSAGE_BROADCAST_LOAD_RECEIVED);

        ReplicationUtil repUtil = ReplicationUtil.createReplicationUtil();
        if ((beKey != null) && repUtil.isInstanceLoadBalancedByCLB()){
            loadReceivedState.setProperty(ReplicationState.IGNORE_REMOVE_INSTANCE_NAME,
                repUtil.getFailoverServerInstanceForBeKey(beKey));
        } else {
            ReplicationHealthChecker healthChecker = ReplicationHealthChecker.getInstance();
            String currentReplicaPartner = healthChecker.getCurrentPartnerInstanceName();
                loadReceivedState.setProperty(ReplicationState.IGNORE_REMOVE_INSTANCE_NAME,
                currentReplicaPartner);
        }
       
        sender.sendBroadcastQuery(loadReceivedState);
    }
   
    protected ExpatListElement getExpatListElementFor(String id) {
        ReplicationManagerBase mgr
            = (ReplicationManagerBase)getManager();
        if(mgr.isExpectingExpatIdsMap()) {
            //in this period do not trust expatIdsMap
            return null;
        } else {
            return mgr.getExpatListElement(id);
        }
    }

   protected ExpatListElement removeExpatListElementFor(String id) {
       ReplicationManagerBase mgr
           = (ReplicationManagerBase)getManager();
       return mgr.removeExpatListElement(id);
   }
   
    private ReplicationState findSessionViaBroadcastOrUnicast(String id, String version)
        throws BackingStoreException {
        try {
            ExpatListElement expat = this.getExpatListElementFor(id);
            if(expat == null || expat.getInstanceName() == null) {
                return findSessionViaBroadcast(id, version);
            } else {
                if(_logger.isLoggable(Level.FINE)) {
                    _logger.fine("doing unicast load id = " + id + " version = " + version + "to instance: " + expat.getInstanceName());
                }
                return findSessionViaUnicast(id, version, expat.getInstanceName());
            }
        } finally {
            removeExpatListElementFor(id);
        }
    }

    private ReplicationState loadSessionFromRemoteActiveCache(String id,
                                                              String version,
                                                              String instanceName)
            throws BackingStoreException {
        ReplicationState returnState = findSessionViaUnicast(id, version, instanceName);
        if (returnState != null && returnState.getState() != null) {
            __addToRemotelyLoadedSessionIds(id);
            removeExpatListElementFor(id);
        }
        return returnState;
    }
   
    private ReplicationState findSessionViaUnicast(String id, String version, String instanceName)
        throws BackingStoreException {
  if (ReplicationUtil.getInstanceName().equals(instanceName)) {
      // We can't unicast to ourselves. This request can happen
      // for version unaware loads; we return null to indicate
      // to use whatever is in the replica cache
      return null;
  }
        return sendUnicastLoadQuery(id, version, instanceName);
    }   
   
    private ReplicationState findSessionViaBroadcast(String id, String version)
        throws BackingStoreException {
        if(_logger.isLoggable(Level.FINE)) {
            _logger.fine("ReplicationStore>>findSessionViaBroadcast");                      
        }       
        ReplicationManagerBase mgr
            = (ReplicationManagerBase)this.getManager();
        BackingStore replicator = mgr.getBackingStore();
        JxtaBackingStoreImpl jxtaReplicator = null;
        if(replicator instanceof JxtaBackingStoreImpl) {
            jxtaReplicator = (JxtaBackingStoreImpl)replicator;
        }
        if(_logger.isLoggable(Level.FINE)) {
            _logger.fine("ReplicationStore>>findSessionViaBroadcast: replicator: " + replicator);                      
        }       
        ReplicationState queryResult = jxtaReplicator != null ?
                jxtaReplicator.__load(id, version) : null;
       
        return queryResult;
    }
   
    void sendUnicastLoadAcknowledgement(String id, String instanceName)
        throws IOException {   
        //send load received ack to instanceName
        ReplicationManagerBase mgr
            = (ReplicationManagerBase)getManager();
        String theCommand = mgr.MESSAGE_BROADCAST_LOAD_RECEIVED;
        ReplicationState loadReceivedState =
            ReplicationState.createBroadcastLoadReceivedState(MODE_WEB, id, this.getApplicationId(), 0L, ReplicationUtil.getInstanceName(), theCommand);             
        JxtaReplicationSender sender
            = JxtaReplicationSender.createInstance();
        sender.sendOverPropagatedPipe(loadReceivedState, instanceName, false);
        //if we want to batch unicast load acks use next line
        //sender.sendReplicationReceivedState(loadReceivedState, instanceName);
    }        

    ReplicationState sendUnicastLoadQuery(String id, String version, String instanceName)
    {
        //send load query to instanceName via unicast
        ReplicationManagerBase mgr
            = (ReplicationManagerBase)getManager();
        String theCommand = mgr.LOAD_SESSION_COMMAND;
        ReplicationState loadState
            = ReplicationState.createUnicastLoadState(MODE_WEB, id, this.getApplicationId(), ReplicationUtil.parseLong(version), ReplicationUtil.getInstanceName(), theCommand);
        JxtaReplicationSender sender
            = JxtaReplicationSender.createInstance();
        ReplicationState returnState
            = sender.sendReplicationLoadState(loadState, instanceName, useReplicationUnicastLoadBatching);
        return returnState;
    }

    SimpleMetadata loadUnicast(String id, String version, String instanceName)
            throws BackingStoreException {
        ReplicationState state = sendUnicastLoadQuery(id, version, instanceName);
        SimpleMetadata result = ReplicationState.createSimpleMetadataFrom(state, isReplicationCompressionEnabled());
        if(result != null) {
            __addToRemotelyLoadedSessionIds(id);
        }
        return result;
    }

    protected void __addToRemotelyLoadedSessionIds(String id) {
        ReplicationManagerBase mgr
                = (ReplicationManagerBase) this.getManager();
        mgr.getRemotelyLoadedSessionIds().add(id);
    }

    protected boolean __removeFromRemotelyLoadedSessionIds(String id) {
        ReplicationManagerBase mgr
                = (ReplicationManagerBase) this.getManager();
        return mgr.getRemotelyLoadedSessionIds().remove(id);
    }

    /**
     * update the lastaccess time of the specified Session into this Store.
     *
     * @param session Session to be saved
     *
     * @exception IOException if an input/output error occurs
     */   
    public void updateLastAccessTime(Session session) throws IOException {
       
        ReplicationManagerBase mgr
            = (ReplicationManagerBase)this.getManager();
        BackingStore replicator = mgr.getBackingStore();
        if(_logger.isLoggable(Level.FINE)) {
            _logger.fine("ReplicationStore>>updateLastAccessTime: replicator: " + replicator);                      
        }        
        try {
            /* FIXED
            replicator.updateLastAccessTime(session.getIdInternal(), //id
                    ((BaseHASession)session).getLastAccessedTimeInternal(), //lastaccesstime
                    session.getVersion()); //version
            */
            SimpleMetadata smd = SimpleMetadataFactory.createSimpleMetadata(session.getVersion(),
                    ((BaseHASession)session).getLastAccessedTimeInternal());
            replicator.save(session.getIdInternal(), smd, !((HASession) session).isPersistent()); //version
        } catch (BackingStoreException ex) {
            //FIXME
        }
    }       
   
    /**
    * Return an array containing the session identifiers of all Sessions
    * currently saved in this Store.  If there are no such Sessions, a
    * zero-length array is returned.
    *
    * @exception IOException if an input/output error occurred
    */ 
    public String[] keys() throws IOException  {
        //FIXME
        return new String[0];
    }
   
    public int getSize() throws IOException {
        int result = 0;
        ReplicationManagerBase mgr
            = (ReplicationManagerBase)this.getManager();
        BackingStore replicator = mgr.getBackingStore();
        if(_logger.isLoggable(Level.FINE)) {
            _logger.fine("ReplicationStore>>getSize: replicator: " + replicator);                      
        }        
        try {
            result = replicator.size();
        } catch (BackingStoreException ex) {
            //nothing to do - ok to eat exception
        }
        return result;
    }   
   
    // Store methods end

    private Session getSession(SimpleMetadata metaData) throws IOException {
        if (metaData == null || metaData.getState() == null) {
            return null;
        } else {
            HttpSessionExtraParams extraParams
                    = (HttpSessionExtraParams) metaData.getExtraParam();
            String ssoId = null;
            if (extraParams != null) {
                //ssoid is the extraParam in extraParams
                ssoId = extraParams.getSsoId();
            }
            return getSession(metaData.getState(),
                    ssoId, metaData.getVersion());
        }
    }

    /**
    * Given a byte[] containing session data, return a session
    * object
    *
    * @param replicationState
    *   The byte[] with the session data
    *
    * @return
    *   A newly created session for the given session data, and associated
    *   with this Manager
    */
    public Session getSession(ReplicationState replicationState)
            throws IOException {
        if (replicationState == null || replicationState.getState() == null) {
            return null;
        } else {
            return getSession(replicationState.getState(),
                    replicationState.getExtraParam(), replicationState.getVersion());
        }
    }

    public Session getSession(byte[] state, String ssoId, long version) throws IOException {
        Session _session = null;
        InputStream is = null;
        BufferedInputStream bis = null;
        ByteArrayInputStream bais = null;
        Loader loader = null;   
        ClassLoader classLoader = null;
        ObjectInputStream ois = null;
        Container container = manager.getContainer();
        java.security.Principal pal=null; //MERGE chg added
        IOUtilsCaller utilsCaller = null;
           
        try
        {
            bais = new ByteArrayInputStream(state);
            bis = new BufferedInputStream(bais);
            if(isReplicationCompressionEnabled()) {
                is = new GZIPInputStream(bis);
            } else {
                is = bis;
            }           
           
            //Get the username, ssoId from replicationState
            //ssoId = replicationState.getSsoId();
            //debug("ReplicationStore.getSession()  id="+id+"  username ="+username+";");   

            if(_logger.isLoggable(Level.FINEST)) {
                _logger.finest("loaded session from replicationstore, length = "+state.length);
            }
            if (container != null) {
                loader = container.getLoader();
            }

            if (loader != null) {
                classLoader = loader.getClassLoader();
            }         
            //Bug 4832603 : EJB Reference Failover
            //HERCULES FIXME: for now reverting back
            //need to look at new EJBUtils and related serialization code
            /*
          if (classLoader != null) {
            ois = new CustomObjectInputStream(bis, classLoader);
          }
          else {
            ois = new ObjectInputStream(bis);
          }
         
            //ois = EJBUtils.getInputStream(bis, classLoader, true, true);
            //end - Bug 4832603 
             */         
            if (classLoader != null) {
                if( (utilsCaller = this.getWebUtilsCaller()) != null) {
                    try {
                        ois = utilsCaller.createObjectInputStream(is, true, classLoader);
                    } catch (Exception ex) {}
                }
            }
            if (ois == null) {
                ois = new ObjectInputStream(is);
            }
            if(ois != null) {              
                try {
                    _session = readSession(manager, ois);
                }
                finally {
                    if (ois != null) {
                        try {
                            ois.close();
                            bis = null;
                        }
                        catch (IOException e) {
                        }
                    }
                }
            }
        }
        catch(ClassNotFoundException e)
        {
            IOException ex1 = (IOException) new IOException(
                    "Error during deserialization: " + e.getMessage()).initCause(e);
            throw ex1;
        }
        catch(IOException e)
        {
            //if (_logger.isLoggable(Level.FINE)) {
            //    _logger.fine("Exception occurred in getSession", e);
            //}
            throw e;
        }
        String username = ((HASession)_session).getUserName();
        if(_logger.isLoggable(Level.FINE)) {
            _logger.fine("ReplicationStore>>getSession: username=" + username + " principal=" + _session.getPrincipal());                                 
        }       
        if((username !=null) && (!username.equals("")) && _session.getPrincipal() == null) {
            if (_debug > 0) {
                debug("Username retrieved is "+username);
            }
            pal = ((com.sun.web.security.RealmAdapter)container.getRealm()).createFailOveredPrincipal(username);
            if(_logger.isLoggable(Level.FINE)) {
                _logger.fine("ReplicationStore>>getSession:created pal=" + pal);                                 
            }            
            if (_debug > 0) {
                debug("principal created using username  "+pal);
            }
            if(pal != null) {
                _session.setPrincipal(pal);
                if (_debug > 0) {
                    debug("getSession principal="+pal+" was added to session="+_session);
                }               
            }
        }
        //--SRI       
       
        _session.setNew(false);
        if(_logger.isLoggable(Level.FINE)) {
            _logger.fine("ReplicationStore>>getSession:ssoId=" + ssoId);                                 
        }
        ((BaseHASession)_session).setSsoId(ssoId);
        if((ssoId !=null) && (!ssoId.equals("")))
            associate(ssoId, _session);
        ((HASession)_session).setVersion(version);
        ((HASession)_session).setDirty(false);
        ((HASession)_session).setPersistent(false);       
        return _session;
    }
   
    protected void associate(String ssoId, Session _session) {
        if (_debug > 0) {
            debug("Inside associate() -- ReplicationStore");
        }
        Container parent = manager.getContainer();
        SingleSignOn sso = null;
        while ((sso == null) && (parent != null)) {
            if (_debug > 0) {
                 debug("Inside associate()  while loop -- ReplicationStore");
            }
        if (!(parent instanceof Pipeline)) {
            if (_debug > 0) {
                 debug("Inside associate()  parent instanceof Pipeline -- ReplicationStore");
            }
            parent = parent.getParent();
            continue;
        }
        Valve valves[] = ((Pipeline) parent).getValves();
        for (int i = 0; i < valves.length; i++) {
            if (valves[i] instanceof SingleSignOn) {
                 if (_debug > 0) {
                    debug("Inside associate()  valves[i] instanceof SingleSignOn -- ReplicationStore");
                 }
                 if (valves[i] instanceof ReplicationSingleSignOn) {
                     sso = (SingleSignOn) valves[i];
                     break;
                 } else {
                     _logger.log(Level.WARNING, "SSO misconfigured: sso is enabled but sso failover is not enabled");
                 }
             }
        }
        if (sso == null)
            parent = parent.getParent();
        }
        if (sso != null) {
            if (_debug > 0) {
                debug("Inside associate() sso != null");
            }
            //SingleSignOnEntry ssoEntry = ((ReplicationSingleSignOn)sso).lookup(ssoId);
            SingleSignOnEntry ssoEntry = ((ReplicationSingleSignOn)sso).lookupEntry(ssoId);
            if(_logger.isLoggable(Level.FINEST)) {
                _logger.finest("ReplicationStore>>associate: ssoEntry = "+ssoEntry);
                _logger.finest("ReplicationStore>>associate: ssoEntry.principal = " + ssoEntry.principal + "_session.getPrincipal() =" + _session.getPrincipal());
            }
            if(ssoEntry!=null) {
                ssoEntry.addSession(sso, _session);
                if(ssoEntry.principal == null && _session.getPrincipal() != null) {
                    ssoEntry.principal = _session.getPrincipal();
                }
            }
        }

    }    
   
    protected String getUsername(StandardSession session) {
        String result = null;
        if(session.getPrincipal() !=null){
            result = session.getPrincipal().getName();
        } else {
            result = "";
        }
        return result;
    }
   
    protected String getSsoId(StandardSession session) {   
        return ((HASession)session).getSsoId();
    }

    // find the session in local active cache, passivate it and remove from local cache.
    public ReplicableEntity findSessionAndPassivate(String id) {
        ReplicationManagerBase mgr
                = (ReplicationManagerBase) this.getManager();
        return mgr.findSessionAndPassivate(id, new AtomicBoolean());
    }

    // get the active cache sessions.
    public Map<String, ReplicableEntity> getActiveCache() {
        ReplicationManagerBase mgr
                = (ReplicationManagerBase) this.getManager();
        return mgr.getActiveHttpSessions();
    }

    // put the state in the local replica cache.
    public void putInReplicaCache(ReplicationState state) {
        ReplicationManagerBase mgr
                = (ReplicationManagerBase) this.getManager();
        mgr.putInReplicationCache(state);
    }

    // remove the entry from replica cache with given id.
    public void removeFromReplicaCache(String id) {
        ReplicationManagerBase mgr
                = (ReplicationManagerBase) this.getManager();
        mgr.removeFromReplicationCache(id);

    }

    public BaseCache getReplicaCache() {
        ReplicationManagerBase mgr
                = (ReplicationManagerBase) this.getManager();
        return mgr.getReplicatedSessions();
    }

    public ReplicableEntity deserialize(ReplicationState state) {
        try {
            return (ReplicableEntity) getSession(state);
        } catch (IOException ex) {
            return null;
        }
    }

    public void activate(ReplicableEntity session) {
        ReplicationManagerBase mgr
                = (ReplicationManagerBase) this.getManager();
        mgr.activate((Session) session, true);
    }

    public String getMode() {
        return MODE_WEB;
    }

   
}
TOP

Related Classes of com.sun.enterprise.ee.web.sessmgmt.ReplicationStore

TOP
Copyright © 2018 www.massapi.com. All rights reserved.
All source code are property of their respective owners. Java is a trademark of Sun Microsystems, Inc and owned by ORACLE Inc. Contact coftware#gmail.com.