//
//  ========================================================================
//  Copyright (c) 1995-2017 Mort Bay Consulting Pty. Ltd.
//  ------------------------------------------------------------------------
//  All rights reserved. This program and the accompanying materials
//  are made available under the terms of the Eclipse Public License v1.0
//  and Apache License v2.0 which accompanies this distribution.
//
//      The Eclipse Public License is available at
//      http://www.eclipse.org/legal/epl-v10.html
//
//      The Apache License v2.0 is available at
//      http://www.opensource.org/licenses/apache2.0.php
//
//  You may elect to redistribute this code under either of these licenses.
//  ========================================================================
//

package org.eclipse.jetty.nosql.mongodb;

import java.io.ByteArrayInputStream;
import java.io.ByteArrayOutputStream;
import java.io.IOException;
import java.io.ObjectInputStream;
import java.io.ObjectOutputStream;
import java.net.UnknownHostException;
import java.util.Date;
import java.util.HashMap;
import java.util.Map;
import java.util.Set;

import org.eclipse.jetty.nosql.NoSqlSession;
import org.eclipse.jetty.nosql.NoSqlSessionManager;
import org.eclipse.jetty.server.SessionIdManager;
import org.eclipse.jetty.util.annotation.ManagedAttribute;
import org.eclipse.jetty.util.annotation.ManagedObject;
import org.eclipse.jetty.util.annotation.ManagedOperation;
import org.eclipse.jetty.util.log.Log;
import org.eclipse.jetty.util.log.Logger;

import com.mongodb.BasicDBObject;
import com.mongodb.DBCollection;
import com.mongodb.DBObject;
import com.mongodb.MongoException;
import com.mongodb.WriteConcern;
import com.mongodb.WriteResult;


/**
 * MongoSessionManager
 *
 * Clustered session manager using MongoDB as the shared DB instance.
 * The document model is an outer object that contains the elements:
 * <ul>
 *  <li>"id"      : session_id </li>
 *  <li>"created" : create_time </li>
 *  <li>"accessed": last_access_time </li>
 *  <li>"maxIdle" : max_idle_time setting as session was created </li>
 *  <li>"expiry"  : time at which session should expire </li>
 *  <li>"valid"   : session_valid </li>
 *  <li>"context" : a nested object containing 1 nested object per context for which the session id is in use
 * </ul>
 * Each of the nested objects inside the "context" element contains:
 * <ul>
 *  <li>unique_context_name : nested object containing name:value pairs of the session attributes for that context</li>
 * </ul>
 * <p>
 * One of the name:value attribute pairs will always be the special attribute "__metadata__". The value 
 * is an object representing a version counter which is incremented every time the attributes change.
 * </p>
 * <p>
 * For example:
 * <code>
 * { "_id"       : ObjectId("52845534a40b66410f228f23"), 
 *    "accessed" :  NumberLong("1384818548903"), 
 *    "maxIdle"  : 1,
 *    "context"  : { "::/contextA" : { "A"            : "A", 
 *                                     "__metadata__" : { "version" : NumberLong(2) } 
 *                                   },
 *                   "::/contextB" : { "B"            : "B", 
 *                                     "__metadata__" : { "version" : NumberLong(1) } 
 *                                   } 
 *                 }, 
 *    "created"  : NumberLong("1384818548903"),
 *    "expiry"   : NumberLong("1384818549903"),
 *    "id"       : "w01ijx2vnalgv1sqrpjwuirprp7", 
 *    "valid"    : true 
 * }
 * </code>
 * </p>
 * <p>
 * In MongoDB, the nesting level is indicated by "." separators for the key name. Thus to
 * interact with a session attribute, the key is composed of:
 * "context".unique_context_name.attribute_name
 *  Eg  "context"."::/contextA"."A"
 *  </p>
 */
@ManagedObject("Mongo Session Manager")
public class MongoSessionManager extends NoSqlSessionManager
{
    private static final Logger LOG = Log.getLogger(MongoSessionManager.class);
  
    private final static Logger __log = Log.getLogger("org.eclipse.jetty.server.session");
   
    /*
     * strings used as keys or parts of keys in mongo
     */
    /**
     * Special attribute for a session that is context-specific
     */
    private final static String __METADATA = "__metadata__";

    
    /**
     * Session id
     */
    public final static String __ID = "id";
    
    /**
     * Time of session creation
     */
    private final static String __CREATED = "created";
    
    /**
     * Whether or not session is valid
     */
    public final static String __VALID = "valid";
    
    /**
     * Time at which session was invalidated
     */
    public final static String __INVALIDATED = "invalidated";
    
    /**
     * Last access time of session
     */
    public final static String __ACCESSED = "accessed";
    
    /**
     * Time this session will expire, based on last access time and maxIdle
     */
    public final static String __EXPIRY = "expiry";
    
    /**
     * The max idle time of a session (smallest value across all contexts which has a session with the same id)
     */
    public final static String __MAX_IDLE = "maxIdle";
    
    /**
     * Name of nested document field containing 1 sub document per context for which the session id is in use
     */
    private final static String __CONTEXT = "context";   
    
    
    /**
     * Special attribute per session per context, incremented each time attributes are modified
     */
    public final static String __VERSION = __METADATA + ".version";

    /**
    * the context id is only set when this class has been started
    */
    private String _contextId = null;

    
    /**
     * Access to MongoDB
     */
    private DBCollection _dbSessions;
    
    
    /**
     * Utility value of 1 for a session version for this context
     */
    private DBObject _version_1;


    /* ------------------------------------------------------------ */
    public MongoSessionManager() throws UnknownHostException, MongoException
    {
        
    }
    
    
    
    /*------------------------------------------------------------ */
    @Override
    public void doStart() throws Exception
    {
        super.doStart();
        String[] hosts = getContextHandler().getVirtualHosts();

        if (hosts == null || hosts.length == 0)
            hosts = new String[]
            { "::" }; // IPv6 equiv of 0.0.0.0

        String contextPath = getContext().getContextPath();
        if (contextPath == null || "".equals(contextPath))
        {
            contextPath = "*";
        }

        _contextId = createContextId(hosts,contextPath);
        _version_1 = new BasicDBObject(getContextAttributeKey(__VERSION),1);
    }

    /* ------------------------------------------------------------ */
    /**
     * @see org.eclipse.jetty.server.session.AbstractSessionManager#setSessionIdManager(org.eclipse.jetty.server.SessionIdManager)
     */
    @Override
    public void setSessionIdManager(SessionIdManager metaManager)
    {
        MongoSessionIdManager msim = (MongoSessionIdManager)metaManager;
        _dbSessions=msim.getSessions();
        super.setSessionIdManager(metaManager);
        
    }

    /* ------------------------------------------------------------ */
    @Override
    protected synchronized Object save(NoSqlSession session, Object version, boolean activateAfterSave)
    {
        try
        {
            __log.debug("MongoSessionManager:save session {}", session.getClusterId());
            session.willPassivate();

            // Form query for upsert
            BasicDBObject key = new BasicDBObject(__ID,session.getClusterId());

            // Form updates
            BasicDBObject update = new BasicDBObject();
            boolean upsert = false;
            BasicDBObject sets = new BasicDBObject();
            BasicDBObject unsets = new BasicDBObject();

            
            // handle valid or invalid
            if (session.isValid())
            {
                long expiry = (session.getMaxInactiveInterval() > 0?(session.getAccessed()+(1000L*getMaxInactiveInterval())):0);
                __log.debug("MongoSessionManager: calculated expiry {} for session {}", expiry, session.getId());
                
                // handle new or existing
                if (version == null)
                {
                    // New session
                    upsert = true;
                    version = new Long(1);
                    sets.put(__CREATED,session.getCreationTime());
                    sets.put(__VALID,true);
                   
                    sets.put(getContextAttributeKey(__VERSION),version);
                    sets.put(__MAX_IDLE, getMaxInactiveInterval());
                    sets.put(__EXPIRY, expiry);
                }
                else
                {
                    version = new Long(((Number)version).longValue() + 1);
                    update.put("$inc",_version_1); 
                    //if max idle time and/or expiry is smaller for this context, then choose that for the whole session doc
                    BasicDBObject fields = new BasicDBObject();
                    fields.append(__MAX_IDLE, true);
                    fields.append(__EXPIRY, true);
                    DBObject o = _dbSessions.findOne(new BasicDBObject("id",session.getClusterId()), fields);
                    if (o != null)
                    {
                        Integer currentMaxIdle = (Integer)o.get(__MAX_IDLE);
                        Long currentExpiry = (Long)o.get(__EXPIRY);
                        if (currentMaxIdle != null && getMaxInactiveInterval() > 0 && getMaxInactiveInterval() < currentMaxIdle)
                            sets.put(__MAX_IDLE, getMaxInactiveInterval());
                        if (currentExpiry != null && expiry > 0 && expiry != currentExpiry)
                            sets.put(__EXPIRY, expiry);
                    }
                }
                
                sets.put(__ACCESSED,session.getAccessed());
                Set<String> names = session.takeDirty();
                if (isSaveAllAttributes() || upsert)
                {
                    names.addAll(session.getNames()); // note dirty may include removed names
                }
                    
                for (String name : names)
                {
                    Object value = session.getAttribute(name);
                    if (value == null)
                        unsets.put(getContextKey() + "." + encodeName(name),1);
                    else
                        sets.put(getContextKey() + "." + encodeName(name),encodeName(value));
                }
            }
            else
            {
                sets.put(__VALID,false);
                sets.put(__INVALIDATED, System.currentTimeMillis());
                unsets.put(getContextKey(),1); 
            }

            // Do the upsert
            if (!sets.isEmpty())
                update.put("$set",sets);
            if (!unsets.isEmpty())
                update.put("$unset",unsets);

            _dbSessions.update(key,update,upsert,false,WriteConcern.SAFE);

            if (__log.isDebugEnabled())
                __log.debug("MongoSessionManager:save:db.sessions.update( {}, {} )", key, update);
           
            if (activateAfterSave)
                session.didActivate();

            return version;
        }
        catch (Exception e)
        {
            LOG.warn(e);
        }
        return null;
    }

    /*------------------------------------------------------------ */
    @Override
    protected Object refresh(NoSqlSession session, Object version)
    {
        __log.debug("MongoSessionManager:refresh session {}", session.getId());

        // check if our in memory version is the same as what is on the disk
        if (version != null)
        {
            DBObject o = _dbSessions.findOne(new BasicDBObject(__ID,session.getClusterId()),_version_1);

            if (o != null)
            {
                Object saved = getNestedValue(o, getContextAttributeKey(__VERSION));
                
                if (saved != null && saved.equals(version))
                {
                    __log.debug("MongoSessionManager:refresh not needed session {}", session.getId());
                    return version;
                }
                version = saved;
            }
        }

        // If we are here, we have to load the object
        DBObject o = _dbSessions.findOne(new BasicDBObject(__ID,session.getClusterId()));

        // If it doesn't exist, invalidate
        if (o == null)
        {
            __log.debug("MongoSessionManager:refresh:marking session {} invalid, no object", session.getClusterId());
            session.invalidate();
            return null;
        }
        
        // If it has been flagged invalid, invalidate
        Boolean valid = (Boolean)o.get(__VALID);
        if (valid == null || !valid)
        {
            __log.debug("MongoSessionManager:refresh:marking session {} invalid, valid flag {}", session.getClusterId(), valid);
            session.invalidate();
            return null;
        }

        // We need to update the attributes. We will model this as a passivate,
        // followed by bindings and then activation.
        session.willPassivate();
        try
        {     
            DBObject attrs = (DBObject)getNestedValue(o,getContextKey());    
            //if disk version now has no attributes, get rid of them
            if (attrs == null || attrs.keySet().size() == 0)
            {
                session.clearAttributes();
            }
            else
            {
                //iterate over the names of the attributes on the disk version, updating the value
                for (String name : attrs.keySet())
                {
                    //skip special metadata field which is not one of the session attributes
                    if (__METADATA.equals(name))
                        continue;

                    String attr = decodeName(name);
                    Object value = decodeValue(attrs.get(name));

                    //session does not already contain this attribute, so bind it
                    if (session.getAttribute(attr) == null)
                    { 
                        session.doPutOrRemove(attr,value);
                        session.bindValue(attr,value);
                    }
                    else //session already contains this attribute, update its value
                    {
                        session.doPutOrRemove(attr,value);
                    }

                }
                // cleanup, remove values from session, that don't exist in data anymore:
                for (String str : session.getNames())
                {
                   if (!attrs.keySet().contains(encodeName(str)))
                   {
                        session.doPutOrRemove(str,null);
                        session.unbindValue(str,session.getAttribute(str));
                    }
                }
            }

            /*
             * We are refreshing so we should update the last accessed time.
             */
            BasicDBObject key = new BasicDBObject(__ID,session.getClusterId());
            BasicDBObject sets = new BasicDBObject();
            // Form updates
            BasicDBObject update = new BasicDBObject();
            sets.put(__ACCESSED,System.currentTimeMillis());
            // Do the upsert
            if (!sets.isEmpty())
            {
                update.put("$set",sets);
            }            
            
            _dbSessions.update(key,update,false,false,WriteConcern.SAFE);
            
            session.didActivate();

            return version;
        }
        catch (Exception e)
        {
            LOG.warn(e);
        }

        return null;
    }

    /*------------------------------------------------------------ */
    @Override
    protected synchronized NoSqlSession loadSession(String clusterId)
    {
        DBObject o = _dbSessions.findOne(new BasicDBObject(__ID,clusterId));
        
        __log.debug("MongoSessionManager:id={} loaded={}", clusterId, o);
        if (o == null)
            return null;
        
        Boolean valid = (Boolean)o.get(__VALID);
        __log.debug("MongoSessionManager:id={} valid={}", clusterId, valid);
        if (valid == null || !valid)
            return null;
        
        try
        {
            Object version = o.get(getContextAttributeKey(__VERSION));
            Long created = (Long)o.get(__CREATED);
            Long accessed = (Long)o.get(__ACCESSED);
          
            NoSqlSession session = null;

            // get the session for the context
            DBObject attrs = (DBObject)getNestedValue(o,getContextKey());

            __log.debug("MongoSessionManager:attrs {}", attrs);
            if (attrs != null)
            {
                __log.debug("MongoSessionManager: session {} present for context {}", clusterId, getContextKey());
                //only load a session if it exists for this context
                session = new NoSqlSession(this,created,accessed,clusterId,version);
                
                for (String name : attrs.keySet())
                {
                    //skip special metadata attribute which is not one of the actual session attributes
                    if ( __METADATA.equals(name) )
                        continue;
                    
                    String attr = decodeName(name);
                    Object value = decodeValue(attrs.get(name));

                    session.doPutOrRemove(attr,value);
                    session.bindValue(attr,value);
                }
                session.didActivate();
            }
            else
                __log.debug("MongoSessionManager: session  {} not present for context {}",clusterId, getContextKey());        

            return session;
        }
        catch (Exception e)
        {
            LOG.warn(e);
        }
        return null;
    }

    
    
    /*------------------------------------------------------------ */
    /** 
     * Remove the per-context sub document for this session id.
     * @see org.eclipse.jetty.nosql.NoSqlSessionManager#remove(org.eclipse.jetty.nosql.NoSqlSession)
     */
    @Override
    protected boolean remove(NoSqlSession session)
    {
        __log.debug("MongoSessionManager:remove:session {} for context {}",session.getClusterId(), getContextKey());

        /*
         * Check if the session exists and if it does remove the context
         * associated with this session
         */
        BasicDBObject key = new BasicDBObject(__ID,session.getClusterId());
        
        DBObject o = _dbSessions.findOne(key,_version_1);

        if (o != null)
        {
            BasicDBObject remove = new BasicDBObject();
            BasicDBObject unsets = new BasicDBObject();
            unsets.put(getContextKey(),1);
            remove.put("$unset",unsets);
            _dbSessions.update(key,remove,false,false,WriteConcern.SAFE);

            return true;
        }
        else
        {
            return false;
        }
    }

    
    
    /** 
     * @see org.eclipse.jetty.nosql.NoSqlSessionManager#expire(java.lang.String)
     */
    @Override
    protected void expire (String idInCluster)
    {
        __log.debug("MongoSessionManager:expire session {} ", idInCluster);

        //Expire the session for this context
        super.expire(idInCluster);
        
        //If the outer session document has not already been marked invalid, do so.
        DBObject validKey = new BasicDBObject(__VALID, true);       
        DBObject o = _dbSessions.findOne(new BasicDBObject(__ID,idInCluster), validKey);
        
        if (o != null && (Boolean)o.get(__VALID))
        {
            BasicDBObject update = new BasicDBObject();
            BasicDBObject sets = new BasicDBObject();
            sets.put(__VALID,false);
            sets.put(__INVALIDATED, System.currentTimeMillis());
            update.put("$set",sets);
                        
            BasicDBObject key = new BasicDBObject(__ID,idInCluster);
            _dbSessions.update(key,update,false,false,WriteConcern.SAFE);
        }       
    }
    
    
    /*------------------------------------------------------------ */
    /** 
     * Change the session id. Note that this will change the session id for all contexts for which the session id is in use.
     * @see org.eclipse.jetty.nosql.NoSqlSessionManager#update(org.eclipse.jetty.nosql.NoSqlSession, java.lang.String, java.lang.String)
     */
    @Override
    protected void update(NoSqlSession session, String newClusterId, String newNodeId) throws Exception
    {
        BasicDBObject key = new BasicDBObject(__ID, session.getClusterId());
        BasicDBObject sets = new BasicDBObject();
        BasicDBObject update = new BasicDBObject(__ID, newClusterId);
        sets.put("$set", update);
        _dbSessions.update(key, sets, false, false,WriteConcern.SAFE);
    }

    /*------------------------------------------------------------ */
    protected String encodeName(String name)
    {
        return name.replace("%","%25").replace(".","%2E");
    }

    /*------------------------------------------------------------ */
    protected String decodeName(String name)
    {
        return name.replace("%2E",".").replace("%25","%");
    }

    /*------------------------------------------------------------ */
    protected Object encodeName(Object value) throws IOException
    {
        if (value instanceof Number || value instanceof String || value instanceof Boolean || value instanceof Date)
        {
            return value;
        }
        else if (value.getClass().equals(HashMap.class))
        {
            BasicDBObject o = new BasicDBObject();
            for (Map.Entry<?, ?> entry : ((Map<?, ?>)value).entrySet())
            {
                if (!(entry.getKey() instanceof String))
                {
                    o = null;
                    break;
                }
                o.append(encodeName(entry.getKey().toString()),encodeName(entry.getValue()));
            }

            if (o != null)
                return o;
        }
        
        ByteArrayOutputStream bout = new ByteArrayOutputStream();
        ObjectOutputStream out = new ObjectOutputStream(bout);
        out.reset();
        out.writeUnshared(value);
        out.flush();
        return bout.toByteArray();
    }

    /*------------------------------------------------------------ */
    protected Object decodeValue(final Object valueToDecode) throws IOException, ClassNotFoundException
    {
        if (valueToDecode == null || valueToDecode instanceof Number || valueToDecode instanceof String || valueToDecode instanceof Boolean || valueToDecode instanceof Date)
        {
            return valueToDecode;
        }
        else if (valueToDecode instanceof byte[])
        {
            final byte[] decodeObject = (byte[])valueToDecode;
            final ByteArrayInputStream bais = new ByteArrayInputStream(decodeObject);
            final ClassLoadingObjectInputStream objectInputStream = new ClassLoadingObjectInputStream(bais);
            return objectInputStream.readUnshared();
        }
        else if (valueToDecode instanceof DBObject)
        {
            Map<String, Object> map = new HashMap<String, Object>();
            for (String name : ((DBObject)valueToDecode).keySet())
            {
                String attr = decodeName(name);
                map.put(attr,decodeValue(((DBObject)valueToDecode).get(name)));
            }
            return map;
        }
        else
        {
            throw new IllegalStateException(valueToDecode.getClass().toString());
        }
    }

   
    /*------------------------------------------------------------ */
    private String getContextKey()
    {
        return __CONTEXT + "." + _contextId;
    }
    
    /*------------------------------------------------------------ */
    /** Get a dot separated key for 
     * @param key
     * @return
     */
    private String getContextAttributeKey(String attr)
    {
        return getContextKey()+ "." + attr;
    }
    
    /*------------------------------------------------------------ */
    @ManagedOperation(value="purge invalid sessions in the session store based on normal criteria", impact="ACTION")
    public void purge()
    {   
        ((MongoSessionIdManager)_sessionIdManager).purge();
    }
    
    
    /*------------------------------------------------------------ */
    @ManagedOperation(value="full purge of invalid sessions in the session store", impact="ACTION")
    public void purgeFully()
    {   
        ((MongoSessionIdManager)_sessionIdManager).purgeFully();
    }
    
    /*------------------------------------------------------------ */
    @ManagedOperation(value="scavenge sessions known to this manager", impact="ACTION")
    public void scavenge()
    {
        ((MongoSessionIdManager)_sessionIdManager).scavenge();
    }
    
    /*------------------------------------------------------------ */
    @ManagedOperation(value="scanvenge all sessions", impact="ACTION")
    public void scavengeFully()
    {
        ((MongoSessionIdManager)_sessionIdManager).scavengeFully();
    }
    
    /*------------------------------------------------------------ */
    /**
     * returns the total number of session objects in the session store
     * 
     * the count() operation itself is optimized to perform on the server side
     * and avoid loading to client side.
     */
    @ManagedAttribute("total number of known sessions in the store")
    public long getSessionStoreCount()
    {
        return _dbSessions.find().count();      
    }
    
    /*------------------------------------------------------------ */
    /**
     * MongoDB keys are . delimited for nesting so .'s are protected characters
     * 
     * @param virtualHosts
     * @param contextPath
     * @return
     */
    private String createContextId(String[] virtualHosts, String contextPath)
    {
        String contextId = virtualHosts[0] + contextPath;
        
        contextId.replace('/', '_');
        contextId.replace('.','_');
        contextId.replace('\\','_');
        
        return contextId;
    }

    /*------------------------------------------------------------ */
    /**
     * Dig through a given dbObject for the nested value
     */
    private Object getNestedValue(DBObject dbObject, String nestedKey)
    {
        String[] keyChain = nestedKey.split("\\.");

        DBObject temp = dbObject;

        for (int i = 0; i < keyChain.length - 1; ++i)
        {
            temp = (DBObject)temp.get(keyChain[i]);
            
            if ( temp == null )
            {
                return null;
            }
        }

        return temp.get(keyChain[keyChain.length - 1]);
    }

    
    /*------------------------------------------------------------ */
     /**
     * ClassLoadingObjectInputStream
     *
     *
     */
    protected class ClassLoadingObjectInputStream extends ObjectInputStream
    {
        public ClassLoadingObjectInputStream(java.io.InputStream in) throws IOException
        {
            super(in);
        }

        public ClassLoadingObjectInputStream () throws IOException
        {
            super();
        }

        @Override
        public Class<?> resolveClass (java.io.ObjectStreamClass cl) throws IOException, ClassNotFoundException
        {
            try
            {
                return Class.forName(cl.getName(), false, Thread.currentThread().getContextClassLoader());
            }
            catch (ClassNotFoundException e)
            {
                return super.resolveClass(cl);
            }
        }
    }


}
