view src/nabble/view/web/util/SessionService.java @ 0:7ecd1a4ef557

add content
author Franklin Schmidt <fschmidt@gmail.com>
date Thu, 21 Mar 2019 19:15:52 -0600
parents
children
line wrap: on
line source

package nabble.view.web.util;

import nabble.view.lib.Jtp;
import nabble.model.Executors;

import javax.servlet.ServletException;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;
import java.io.PrintWriter;
import java.util.Map;
import java.util.HashMap;
import java.util.Collections;
import java.util.concurrent.TimeUnit;


public final class SessionService extends HttpServlet {

	protected void service(HttpServletRequest request, HttpServletResponse response)
			throws ServletException, IOException
	{
		response.setHeader("Content-Type","application/x-javascript");
		Jtp.dontCache(response);
		String action = request.getParameter("action");
		String clientID = request.getParameter("cid");
		if (clientID == null)
			return;

		SessionData sessionData = getSessionData(clientID);
		if ("set".equals(action)) {
			String[] vs = request.getParameterValues("v");
			for (String v : vs) {
				int posPipe = v.indexOf('|');
				String key = v.substring(0, posPipe);
				String oldValue = sessionData.attributes.get(key);
				String value = v.substring(posPipe+1);
				value = oldValue == null? value : oldValue + value; // concat
				sessionData.attributes.put(key, value);
			}
		} else if ("get".equals(action)) {
			PrintWriter out = response.getWriter();
			String[] keys = request.getParameterValues("key");
			for (String key : keys) {
				String value = sessionData.attributes.get(key);
				if (value != null) {
					out.print(value);
					sessionData.attributes.remove(key);
				}
			}
		}
	}


	private static final Map<String, SessionData> sessions = Collections.synchronizedMap(new HashMap<String, SessionData>());

	private static synchronized SessionData getSessionData(String clientID) {
		SessionData sessionData = sessions.get(clientID);
		if (sessionData == null) {
			sessionData = new SessionData();
			sessions.put(clientID, sessionData);
		}
		sessionData.lastUsage = System.currentTimeMillis();
		return sessionData;
	}

	private static class SessionData {
		private long lastUsage;
		private final Map<String, String> attributes = new HashMap<String, String>();
	}

	private static final long TIME_LIMIT = 2L * 60L * 1000L; // two minutes
	static {
		// Custom Garbage Collection algorithm:
		// Removes SessionData objects that are old in memory.

		// A - If the sessionData has no cookies, then it was used just for the iframe resize.
		// So we can delete them after two minutes without problems. If the user tries to resize
		// the iframe after that, another object will be created for the transfer.

		Executors.scheduleWithFixedDelay(new Runnable(){public void run(){
			synchronized(SessionService.class) {
				long now = System.currentTimeMillis();
				String[] keys = sessions.keySet().toArray(new String[0]);
				for( String key : keys ) {
					if( now - sessions.get(key).lastUsage > TIME_LIMIT )
						sessions.remove(key);
				}
			}
		}}, 5*60, 5*60, TimeUnit.SECONDS); // Every 5 minutes
	}
}