Java tutorial
/* * 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; } } }