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

org.glassfish.web.ha.session.management.ReplicationAttributeStore Maven / Gradle / Ivy

The newest version!
/*
 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS HEADER.
 *
 * Copyright (c) 1997-2012 Oracle and/or its affiliates. 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_1_1.html
 * or packager/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 packager/legal/LICENSE.txt.
 *
 * GPL Classpath Exception:
 * Oracle designates this particular file as subject to the "Classpath"
 * exception as provided by Oracle in the GPL Version 2 section of the License
 * file that accompanied this code.
 *
 * Modifications:
 * If applicable, add the following below the License Header, with the fields
 * enclosed by brackets [] replaced by your own identifying information:
 * "Portions Copyright [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.
 */
// Portions Copyright [2016-2017] [Payara Foundation and/or its affiliates]

package org.glassfish.web.ha.session.management;

import com.sun.enterprise.container.common.spi.util.JavaEEIOUtils;
import org.glassfish.ha.store.api.BackingStore;
import org.glassfish.ha.store.api.BackingStoreException;
import org.apache.catalina.*;
import org.apache.catalina.session.*;

import java.io.*;
import java.util.ArrayList;
import java.util.Collection;
import java.util.Iterator;
import java.util.List;
import java.util.logging.Level;

/**
 *
 * @author Larry White
 * @author Rajiv Mordani
 */
public class ReplicationAttributeStore extends ReplicationStore {
    

    /** Creates a new instance of ReplicationAttributeStore */
    public ReplicationAttributeStore(JavaEEIOUtils ioUtils) {
        super(ioUtils);
        setLogLevel();
    }
    
    // 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 {
        if (!(session instanceof HASession)) {
            return;
        }
        HASession haSess = (HASession)session;
        if( haSess.isPersistent() && !haSess.isDirty() ) {
            this.updateLastAccessTime(session);
        } else {
            this.doValveSave(session);
            haSess.setPersistent(true);
        }
        haSess.setDirty(false);        
    } 
    
    // 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 {
        if (!(session instanceof HASession)) {
            return;
        }
        HASession haSess = (HASession)session;
        if( haSess.isPersistent() && !haSess.isDirty() ) {
            this.updateLastAccessTime(session);
        } else {
            this.doSave(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
     */
    @Override
    public void doValveSave(Session session) throws IOException {
        if(_logger.isLoggable(Level.FINE)) {
            _logger.fine("ReplicationAttributeStore>>doValveSave:valid =" + ((StandardSession)session).getIsValid());
            if (session instanceof HASession) {
                _logger.fine("ReplicationAttributeStore>>valveSave:ssoId=" + ((HASession)session).getSsoId());
            }
        }         
        
        // begin 6470831 do not save if session is not valid
        if( !((StandardSession)session).getIsValid() ) {
            return;
        }
        // end 6470831

        if (!(session instanceof ModifiedAttributeHASession) ||
                !(session instanceof BaseHASession)) {
            return;
        }

        ModifiedAttributeHASession modAttrSession
                = (ModifiedAttributeHASession)session;
        String userName = "";
        if(session.getPrincipal() !=null){
            userName = session.getPrincipal().getName();
            ((BaseHASession)session).setUserName(userName);
        }
        BackingStore replicator = getCompositeMetadataBackingStore();
        if(_logger.isLoggable(Level.FINE)) {
            _logger.fine("ReplicationAttributeStore>>save: replicator: " + replicator);                    
        }         
        CompositeMetadata compositeMetadata
            = createCompositeMetadata(modAttrSession);
                
        try {
            if (_logger.isLoggable(Level.FINE)) {
                _logger.fine("CompositeMetadata is " + compositeMetadata + " id is " + session.getIdInternal());
            }
            replicator.save(session.getIdInternal(), //id
                    compositeMetadata, !((HASession) session).isPersistent());
            modAttrSession.resetAttributeState();
            postSaveUpdate(modAttrSession);
        } catch (BackingStoreException ex) {
            //FIXME
        }
    }


    /**
     * 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
     */
    @Override
    public void doSave(Session session) throws IOException {
        // begin 6470831 do not save if session is not valid
        if( !((StandardSession)session).getIsValid() ) {
            return;
        }

        if (!(session instanceof ModifiedAttributeHASession) ||
                !(session instanceof HASession)) {
            return;
        }

        // end 6470831        
        ModifiedAttributeHASession modAttrSession
                = (ModifiedAttributeHASession)session;
        BackingStore replicator = getCompositeMetadataBackingStore();
        if(_logger.isLoggable(Level.FINE)) {
            _logger.fine("ReplicationAttributeStore>>doSave: replicator: " + replicator);                    
        }         
        CompositeMetadata compositeMetadata 
            = createCompositeMetadata(modAttrSession);
                
        try {
            if (_logger.isLoggable(Level.FINE)) {
                _logger.fine("CompositeMetadata is " + compositeMetadata + " id is " + session.getIdInternal());
            }

            replicator.save(session.getIdInternal(), //id
                    compositeMetadata, !((HASession) session).isPersistent());
            modAttrSession.resetAttributeState();
            postSaveUpdate(modAttrSession);
        } catch (BackingStoreException ex) {
            //FIXME
        }
    }

    @SuppressWarnings("unchecked")
    private BackingStore getCompositeMetadataBackingStore() {
        ReplicationManagerBase mgr
                = (ReplicationManagerBase) this.getManager();
        return mgr.getBackingStore();
    }

    @Override
    public Session load(String id, String version)
            throws ClassNotFoundException, IOException {
        try {
            CompositeMetadata metaData =
                    getCompositeMetadataBackingStore().load(id, version);
            if(_logger.isLoggable(Level.FINE)) {
                _logger.fine("ReplicationAttributeStore>>load:id=" + id + ", metaData=" + metaData);
            }
            Session session = getSession(metaData);
            validateAndSave(session);
            return session;
        } catch (BackingStoreException ex) {
            IOException ex1 =
                    (IOException) new IOException("Error during load: " + ex.getMessage()).initCause(ex);
            throw ex1;
        }
    }

    private void validateAndSave(Session session) throws IOException {
        if (session != null) {
            if (_logger.isLoggable(Level.FINE)) {
                _logger.fine("ReplicationAttributeStore>>validateAndSave saving " +
                        "the session after loading it. Session=" + session);
            }
            //save session - save will reset dirty to false
            ((HASession) session).setDirty(true);
            valveSave(session); // TODO :: revisit this for third party backing stores;
        }
        if (session != null) {
            ((HASession) session).setDirty(false);
            ((HASession) session).setPersistent(false);
        }
    }


    public Session getSession(CompositeMetadata metadata)
        throws IOException 
    {
        if (metadata == null || metadata.getState() == null) {
            return null;
        }
        byte[] state = metadata.getState();
        Session _session = 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
        String ssoId = null;
        long version = 0L;
            
        try
        {
            bais = new ByteArrayInputStream(state);
            bis = new BufferedInputStream(bais);
            
            //Get the username, ssoId from metadata
            //ssoId = metadata.getSsoId();
            ssoId = metadata.getStringExtraParam();
            version = metadata.getVersion();
            //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();
            }
            
            if (classLoader != null) {

                try {
                    ois = ioUtils.createObjectInputStream(bis, true, classLoader, getUniqueId());
                } catch (Exception ex) {}

            }
            if (ois == null) {
                ois = new ObjectInputStream(bis); 
            }
            
            if(ois != null) {
                try {
                    _session = readSession(manager, ois);
                } 
                finally {

                    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)
        {
            throw e;
        }
        String username = ((HASession)_session).getUserName(); 
        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 (_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("ReplicationAttributeStore>>ssoId=" + ssoId);                       
        }        
/*
        ((BaseHASession)_session).setSsoId(ssoId);
        if((ssoId !=null) && (!ssoId.equals("")))
            associate(ssoId, _session);
*/
        ((HASession)_session).setVersion(version);
        ((HASession)_session).setDirty(false);
        
        //now load entries from deserialized entries collection
        ((ModifiedAttributeHASession)_session).clearAttributeStates();
        byte[] entriesState = metadata.getState();
        Collection entries = null;
        if(entriesState != null) {
            entries = this.deserializeStatesCollection(entriesState);
            loadAttributes((ModifiedAttributeHASession)_session, entries);
        }
        loadAttributes((ModifiedAttributeHASession)_session, metadata.getEntries());
        return _session;
    }
    

    //metadata related
    
    private void postSaveUpdate(ModifiedAttributeHASession modAttrSession) {
        if(_logger.isLoggable(Level.FINE)) {
            _logger.fine("ReplicationAttributeStore>>postSaveUpdate");                       
        }
        List addedAttrs = modAttrSession.getAddedAttributes();
        List modifiedAttrs = modAttrSession.getModifiedAttributes();
        List deletedAttrs = modAttrSession.getDeletedAttributes();
        printAttrList("ADDED", addedAttrs);
        printAttrList("MODIFIED", modifiedAttrs);
        printAttrList("DELETED", deletedAttrs);

        postProcessSetAttrStates(modAttrSession, addedAttrs);
        postProcessSetAttrStates(modAttrSession, modifiedAttrs);
        
    }
    
    private void postProcessSetAttrStates(ModifiedAttributeHASession modAttrSession, List attrsList) {
        for(int i=0; i>createCompositeMetadata:trunkState=" + trunkState);                       
        }         
       
        List entries = new ArrayList();
        List addedAttrs = modAttrSession.getAddedAttributes();
        List modifiedAttrs = modAttrSession.getModifiedAttributes();
        List deletedAttrs = modAttrSession.getDeletedAttributes();
        printAttrList("ADDED", addedAttrs);
        printAttrList("MODIFIED", modifiedAttrs);
        printAttrList("DELETED", deletedAttrs);
        
        addToEntries(modAttrSession, entries, 
                SessionAttributeMetadata.Operation.ADD, addedAttrs);
        addToEntries(modAttrSession, entries, 
                SessionAttributeMetadata.Operation.UPDATE, modifiedAttrs);
        addToEntries(modAttrSession, entries,
                SessionAttributeMetadata.Operation.DELETE, deletedAttrs);

        CompositeMetadata result 
            = new CompositeMetadata(modAttrSession.getVersion(),
                modAttrSession.getLastAccessedTimeInternal(),
                modAttrSession.getMaxInactiveInterval()*1000L,
                entries, trunkState, null);
        return result;
    }
    
    private void printAttrList(String attrListType, List attrList) {
        if (_logger.isLoggable(Level.FINE)) {
            _logger.fine("AttributeType = " + attrListType);
            String nextAttrName = null;
            for(int i=0; i attributeValueList = new ArrayList();
        BufferedInputStream bis = null;
        ByteArrayInputStream bais = null;
        Loader loader = null;    
        ClassLoader classLoader = null;
        ObjectInputStream ois = null;
        Container container = manager.getContainer();
            
        try
        {
            bais = new ByteArrayInputStream(state);
            bis = new BufferedInputStream(bais);
            
            if (container != null) {
                loader = container.getLoader();
            }

            if (loader != null) {
                classLoader = loader.getClassLoader();
            }
            
            if (classLoader != null) {

                try {
                    ois = ioUtils.createObjectInputStream(bis, true, classLoader, getUniqueId());
                } catch (Exception ex) {}

            }
            if (ois == null) {
                ois = new ObjectInputStream(bis); 
            }
            if(ois != null) {
                try {
                    //first get List size
                    Object whatIsIt = ois.readObject();
                    int entriesSize = 0;
                    if(whatIsIt instanceof Integer) {
                        entriesSize = ((Integer)whatIsIt).intValue();
                    }
                    for (int i = 0; i < entriesSize; i++) {
                        Object nextAttributeValue = ois.readObject();
                        attributeValueList.add(nextAttributeValue);
                    }
                } 
                finally {
                    try {
                        ois.close();
                        bis = null;
                    }
                    catch (IOException e) {
                    }
                }
            }
        }
        catch(ClassNotFoundException e)
        {
            if (_logger.isLoggable(Level.FINE)) {
                _logger.log(Level.FINE, "ClassNotFoundException occurred in getAttributeValueCollection", e);
            }
            throw e;
        }
        catch(IOException e)
        {
            throw e;
        }      

        return attributeValueList;
    }    
    
    //end new serialization code for Collection

    /**
    * Given a session, load its attributes
    *
    * @param modifiedAttributeSession
    *   The session (header info only) having its attributes loaded
    *
    * @param attributeList
    *   The List list of loaded attributes
    *
    * @return
    *   A newly created object for the given session attribute data
    */    
    protected void loadAttributes(ModifiedAttributeHASession modifiedAttributeSession, 
            Collection attributeList) {
        if(_logger.isLoggable(Level.FINEST)) {
            _logger.finest("in loadAttributes -- ReplicationAttributeStore : session id=" + modifiedAttributeSession.getIdInternal());
        }

        String thisAttrName = null;
        //SessionAttributeMetadata.Operation thisAttrOp = null;
        Object thisAttrVal = null;
        Iterator it = attributeList.iterator();
        while (it.hasNext()) { 
            SessionAttributeMetadata nextAttrMetadata = (SessionAttributeMetadata)it.next();
            thisAttrName = nextAttrMetadata.getAttributeName();
            //thisAttrOp = nextAttrMetadata.getOperation();
            byte[] nextAttrState = nextAttrMetadata.getState();
            thisAttrVal = null;
            try { 
                thisAttrVal = getAttributeValue(nextAttrState);
            } catch (ClassNotFoundException ex1) {
                //FIXME log?
            } catch (IOException ex2) {}
            if(_logger.isLoggable(Level.FINEST)) {
                _logger.finest("Attr retrieved======" + thisAttrName);
            }

            if(thisAttrVal != null) { //start if
                if(_logger.isLoggable(Level.FINEST)) {
                    _logger.finest("Setting Attribute: " + thisAttrName);
                }
                modifiedAttributeSession.setAttribute(thisAttrName, thisAttrVal);
                modifiedAttributeSession.setAttributeStatePersistent(thisAttrName, false);
                modifiedAttributeSession.setAttributeStateDirty(thisAttrName, false);
            } //end if
        } //end while 
    } 
    


/*
    private byte[] serializeStatesCollection(Collection entries) {
        byte[] result = null;
        try {
            result = getByteArrayFromCollection(entries);
        } catch (IOException ex) {} 
        return result;
    }
    
    private byte[] serializeStatesCollectionPrevious(Collection entries) {
        byte[] result = null;
        try {
            result = getByteArray(entries);
        } catch (IOException ex) {} 
        return result;
    }    
*/


    private Collection deserializeStatesCollection(byte[] entriesState) {
        Collection result = new ArrayList();
        try {
            result = (Collection)getAttributeValueCollection(entriesState);
        } catch (ClassNotFoundException ex1) {
            // FIXME log?
        } catch (IOException ex2) {}        
        return result;
    } 
    
/*
    private Collection deserializeStatesCollectionPrevious(byte[] entriesState) {
        Collection result = new ArrayList();
        try {
            result = (Collection)getAttributeValue(entriesState);
        } catch (ClassNotFoundException ex1) {
              // FIXME log?
        } catch (IOException ex2) {}        
        return result;
    }     
*/

}