com.eywa.impl.app.controllers.session.SessionManager.java Source code

Java tutorial

Introduction

Here is the source code for com.eywa.impl.app.controllers.session.SessionManager.java

Source

/*
 * EYWA.COM (Eywa Commerce)
 * This program is an integrated platform with E-Commerce and Configurator system.
 * Support: Please, contact the Author on http://www.smartfeeling.org.
 * Copyright (C) 2014  Gian Angelo Geminiani
 *
 * This program is free software: you can redistribute it and/or modify
 * it under the terms of the GNU General Public License as published by
 * the Free Software Foundation, either version 3 of the License, or
 * (at your option) any later version.
 *
 * This program is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 * GNU General Public License for more details.
 *
 * You should have received a copy of the GNU General Public License
 * along with this program.  If not, see <http://www.gnu.org/licenses/>.
 */

package com.eywa.impl.app.controllers.session;

import com.eywa.impl.app.controllers.central.Activity;
import com.eywa.impl.app.controllers.central.CentralControl;
import com.eywa.impl.app.controllers.session.impl.*;
import com.eywa.impl.app.mongo.entities.File;
import com.eywa.impl.app.mongo.entities.Session;
import com.eywa.impl.app.mongo.entities.items.session.files.ItemSessionDataFile;
import com.eywa.impl.app.mongo.entities.items.session.files.ItemSessionDataFiles;
import com.eywa.impl.app.mongo.services.SessionService;
import com.eywa.impl.app.server.utils.FileFormatUtils;
import com.mongodb.DBObject;
import org.ly.commons.Delegates;
import org.ly.commons.async.future.Timed;
import org.ly.commons.logging.Level;
import org.ly.commons.logging.Logger;
import org.ly.commons.logging.util.LoggingUtils;
import org.ly.commons.util.ExceptionUtils;
import org.ly.commons.util.FormatUtils;
import org.ly.commons.util.RandomUtils;
import org.ly.commons.util.StringUtils;

import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.concurrent.TimeUnit;

/**
 * Manage Sessions and remove expired.
 */
public class SessionManager {

    private static final long DEFAULT_INTERVAL = 1 * 1000 * 60; // 1 minute

    private final Timed _timer;
    private final Map<String, ISessionTool> _clean_tools;
    private final Map<String, ISessionTool> _build_tools;
    private final Map<String, ISessionRenderTool> _render_tools;

    // ------------------------------------------------------------------------
    //                      c o n s t r u c t o r
    // ------------------------------------------------------------------------

    private SessionManager() {
        _clean_tools = new HashMap<String, ISessionTool>();
        _build_tools = new HashMap<String, ISessionTool>();
        _render_tools = new HashMap<String, ISessionRenderTool>();
        _timer = new Timed();
        this.init();

        this.getLogger().log(Level.INFO,
                "Started Session Manager. Checking sessions every " + DEFAULT_INTERVAL / 60000 + " minutes.");
    }

    // ------------------------------------------------------------------------
    //                      p u b l i c
    // ------------------------------------------------------------------------

    public DBObject create(final String userId, final String type, final String uid, final DBObject data)
            throws Exception {
        try {
            final SessionService srvc = new SessionService();
            final DBObject session = new Session(userId, type);
            if (null != data) {
                Session.setData(session, data);
            }
            if (StringUtils.hasText(uid)) {
                Session.setUid(session, uid);
            } else {
                Session.setUid(session, RandomUtils.random(8, RandomUtils.CHARS_LOW_NUMBERS));
            }
            this.checkNewSession(session);
            srvc.upsert(session);

            if (Session.isTypeViewer(session)) {
                //-- async log for stats --//
                this.logView(session);
            }

            return session;
        } catch (Throwable ignored) {
        }
        return null;
    }

    public DBObject sign(final String id, final String userId) throws Exception {
        return SessionService.sign(id, userId);
    }

    public DBObject ping(final String id) throws Exception {
        final DBObject result = SessionService.ping(id);
        if (null != result) {
            // remove not client-used fields (keep only USER_ID)
            result.removeField(Session.DATA);
            result.removeField(Session.PING_TIME);
            result.removeField(Session.IDLE_TIMEOUT);
            result.removeField(Session.PING_TIME);
            result.removeField(Session.EXPIRATION_DATE);
            result.removeField(Session.CREATION_DATE);
            result.removeField(Session.CREATIONDATE);
            result.removeField(Session.TYPE);
        }
        return result;
    }

    /**
     * Render a file ( Only for Viewer sessions )
     *
     * @param id    Session ID
     * @param index File index
     * @return ItemSessionDataFile
     */
    public DBObject render(final String id, final int index) {
        DBObject result = null;
        if (StringUtils.hasText(id)) {
            try {
                final SessionService srvc = new SessionService();
                final DBObject session = srvc.findById(id);
                if (null != session) {
                    // ping session to keep alive
                    Session.ping(session);
                    // select session type
                    if (Session.isTypeViewer(session)) {
                        result = this.render(session, index);
                        srvc.upsert(session);
                    }
                } else {
                    getLogger().warning("Attempting to access an expired session: " + id);
                }
            } catch (Throwable t) {
                getLogger().log(Level.SEVERE, null, t);
            }
        }
        return result;
    }

    public DBObject restore(final String json) throws Exception {
        return SessionService.restore(json);
    }

    public DBObject setData(final String id, final String data) throws Exception {
        return SessionService.setData(id, data);
    }

    /**
     * Check and clear expired sessions.
     * Usually this method is called from an internal timed task
     */
    public void checkExpiredSessions() {
        try {
            final List<DBObject> expired = SessionService.clean();
            if (!expired.isEmpty()) {
                for (final DBObject session : expired) {
                    this.checkExpiredSession(session);
                }
            }
        } catch (Exception t) {
            this.getLogger().log(Level.SEVERE, "Error checking expired sessions (may be database is off-line): "
                    + ExceptionUtils.getRealMessage(t), t);
        }
    }

    // ------------------------------------------------------------------------
    //                      Utils
    // ------------------------------------------------------------------------

    public boolean hasRenderer(final String format) {
        return _render_tools.containsKey(format);
    }

    public static String getTempFileName(final DBObject session, final DBObject item) {
        String file_path = ItemSessionDataFile.getFileTempPath(item);
        if (!StringUtils.hasText(file_path)) {
            file_path = ItemSessionDataFiles.getFileTempPath(Session.getData(session));
        }
        return file_path;
    }

    public static String getFileFormat(final DBObject session, final DBObject item) {
        final String file_path = getTempFileName(session, item);
        return FileFormatUtils.getFileFormat(file_path);
    }

    // ------------------------------------------------------------------------
    //                      Session Errors
    // ------------------------------------------------------------------------

    public void onError(final Object sender, final String contextMsg, final Throwable t) {
        final String message = FormatUtils.format("Error from '{0}' with message '{1}': {2}",
                sender.getClass().getSimpleName(), contextMsg, t.toString());
        this.getLogger().log(Level.SEVERE, message);
    }

    // ------------------------------------------------------------------------
    //                      p r i v a t e
    // ------------------------------------------------------------------------

    private Logger getLogger() {
        return LoggingUtils.getLogger(this);
    }

    private void init() {
        //-- clean tools --//
        _clean_tools.put(Session.TYPE_USER, new CleanToolUser(this));
        _clean_tools.put(Session.TYPE_FILE, new CleanToolFile(this));
        _clean_tools.put(Session.TYPE_VIEWER, new CleanToolFile(this));

        //-- build tools --//
        _build_tools.put(Session.TYPE_FILE, new BuildToolFile(this));
        _build_tools.put(Session.TYPE_VIEWER, new BuildToolFileViewer(this));

        //-- render tools --//
        _render_tools.put(FileFormatUtils.FORMAT_PDF, new RenderToolPDF(this));
        _render_tools.put(FileFormatUtils.FORMAT_IMAGE, new RenderToolIMAGE(this));

        //-- timed task --//
        final long interval = DEFAULT_INTERVAL;
        _timer.setMaxThreads(5).setDaemon(true).setTimeUnit(TimeUnit.MILLISECONDS).setInterval(interval);
        _timer.start(new Delegates.Function<Object>() {
            @Override
            public Object handle(Object... args) {
                checkExpiredSessions();
                return null;
            }
        });
    }

    private void stopThreads() {
        _timer.stop(true);
    }

    private void checkExpiredSession(final DBObject session) {
        if (null != session) {
            final ISessionTool tool = _clean_tools.get(Session.getType(session));
            if (null != tool) {
                try {
                    tool.handle(session);
                } catch (Throwable t) {
                    // error handling expired session
                    getLogger().log(Level.SEVERE,
                            "Error handling expired session: " + ExceptionUtils.getMessage(t));
                }
            }
        }
    }

    private void checkNewSession(final DBObject session) {
        final ISessionTool tool = _build_tools.get(Session.getType(session));
        if (null != tool) {
            try {
                tool.handle(session);
            } catch (Throwable t) {
                // error handling expired session
                getLogger().log(Level.SEVERE, "Error initializing new session: " + ExceptionUtils.getMessage(t));
            }
        }
    }

    private DBObject render(final DBObject session, final int index) {
        DBObject result = null;
        final DBObject item = SessionUtils.getFileItem(session, index);
        final String file_format = getFileFormat(session, item);
        final ISessionRenderTool renderer = _render_tools.get(file_format);
        if (null != renderer) {
            try {
                result = renderer.handle(session, item);
            } catch (Throwable t) {
                // error rendering
                getLogger().log(Level.SEVERE, "Error rendering session file: " + ExceptionUtils.getMessage(t));
            }
        } else {
            // renderer not found for this file type
            getLogger().log(Level.WARNING, "No renderer for file type: " + file_format);
        }
        return result;
    }

    private void logView(final DBObject session) {
        try {
            // session
            final String userId = Session.getUserId(session);
            final DBObject data = Session.getData(session);
            final String fileId = ItemSessionDataFiles.getFileId(data);
            //CentralControl.fileOnView(userId, fileId);
            CentralControl
                    .dispatch(Activity.newInstance().setType(Activity.TYPE_VIEW).setCollection(File.COLLECTION)
                            //.setEntity(FileService.getEntity(fileId))
                            .putData(Activity.ATTR_USER_ID, userId).putData(Activity.ATTR_FILE_ID, fileId));
        } catch (Throwable ignored) {
        }
    }

    // ------------------------------------------------------------------------
    //                      S T A T I C
    // ------------------------------------------------------------------------

    private static SessionManager __instance;

    public static SessionManager start() {
        if (null == __instance) {
            __instance = new SessionManager();
        }
        return __instance;
    }

    public static SessionManager getInstance() {
        return start();
    }

    public static void stop() {
        if (null != __instance) {
            __instance.stopThreads();
            __instance = null;
        }
    }

}