package org.jivesoftware.openfire.plugin.gojara.sessions;
import java.sql.Timestamp;
import java.util.ArrayList;
import java.util.Collections;
import java.util.Date;
import java.util.Map;
import java.util.Set;
import java.util.concurrent.ConcurrentHashMap;
import org.jivesoftware.openfire.plugin.gojara.database.*;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
/**
* This is the central point for doing anything Gojara GatewaySession related. We keep track of Users connected to
* Transports, stats about these and provide some methods for Presentation in JSP Pages.
*
* @author axel.frederik.brand
*/
public class TransportSessionManager {
private static TransportSessionManager myself;
private DatabaseManager db;
private GojaraAdminManager adminManager;
private Map<String, Map<String, Long>> transportSessions = new ConcurrentHashMap<String, Map<String, Long>>(16, 0.75f, 1);
private static final Logger Log = LoggerFactory.getLogger(TransportSessionManager.class);
private TransportSessionManager() {
db = DatabaseManager.getInstance();
adminManager = GojaraAdminManager.getInstance();
Log.info(" Created TransportSessionManager");
}
public static synchronized TransportSessionManager getInstance() {
if (myself == null) {
myself = new TransportSessionManager();
}
return myself;
}
/**
* adds a subdomain to watched transports
*
* @param subdomain
*/
public void addTransport(String subdomain) {
transportSessions.put(subdomain, new ConcurrentHashMap<String, Long>(64, 0.75f, 1));
Log.debug("Added key to transportSessionMap: " + subdomain);
}
/**
* removes subdomain from watched transports
*
* @param subdomain
*/
public void removeTransport(String subdomain) {
transportSessions.remove(subdomain);
Log.debug("Removed " + subdomain + "from TransportSessionMap ");
}
public boolean isTransportActive(String subdomain) {
return transportSessions.containsKey(subdomain) ? true : false;
}
/**
* register is seperate to connect because a user may register to transport but not connect to it, e.g. with wrong credentials.
* we still want to keep track of those registrations so we know they happened and we can reset them
*
* @param transport
* @param user
*/
public void registerUserTo(String transport, String user) {
db.insertOrUpdateSession(transport, user, 0);
}
/**
* Add the session of user that connected to gateway and update or create timestamp for session
*
* @param transport
* @param user
* @return
*/
public boolean connectUserTo(String transport, String user) {
//dont update if user is already present, else lots of away to online changes might be spammed
if (transportSessions.get(transport) != null && transportSessions.get(transport).get(user) == null) {
long millis = System.currentTimeMillis();
transportSessions.get(transport).put(user, millis);
db.insertOrUpdateSession(transport, user, millis);
return true;
}
return false;
}
public boolean disconnectUserFrom(String transport, String user) {
// Log.debug("Trying to remove User " + JID.nodeprep(user) + " from Session for Transport " + transport);
if (isUserConnectedTo(transport, user)) {
transportSessions.get(transport).remove(user);
return true;
}
return false;
}
public boolean isUserConnectedTo(String transport, String user) {
return transportSessions.get(transport).containsKey(user);
}
/**
* Removes registration from our database.
*
* @param transport
* @param user
* @return String that describes what happened.
*/
public void removeRegistrationOfUserFromDB(String transport, String user) {
db.removeSessionEntry(transport, user);
}
/**
* Initializes Sessions through adminmanager, ofc needs to be called at a point where there are Transports registered in
* transportSessions
*/
public void initializeSessions() {
Log.info("Initializing Sessions.");
for (String transport : transportSessions.keySet()) {
adminManager.getOnlineUsersOf(transport);
}
}
/**
* @return Set of currently active Gateways
*/
public final Set<String>getActiveGateways() {
return transportSessions.keySet();
}
public final Map<String, Map<String, Long>> getSessions() {
return transportSessions;
}
/**
* Puts all Sessions into an ArrayList of GatewaySession Objects, and sorts it according to specified sorting
* attributes.
*
* @param sortby
* username, transport or LoginTime
* @param sortorder
* ASC or DESC
* @return Sorted/Unsorted ArrayList of GatewaySession Objects
*/
public ArrayList<GatewaySession> getSessionsSorted(String sortby, String sortorder) {
ArrayList<GatewaySession> result = new ArrayList<GatewaySession>(getNumberOfActiveSessions());
for (Map.Entry<String, Map<String,Long>> gateway : transportSessions.entrySet()) {
for (Map.Entry<String, Long> entry : gateway.getValue().entrySet()) {
Timestamp stamp = new Timestamp(entry.getValue());
Date date = new Date(stamp.getTime());
result.add(new GatewaySession(entry.getKey(), gateway.getKey(), date));
}
}
if (sortby.equals("username")) {
Collections.sort(result, new SortUserName());
} else if (sortby.equals("transport")) {
Collections.sort(result, new SortTransport());
} else if (sortby.equals("loginTime")) {
Collections.sort(result, new SortLastActivity());
}
if (sortorder.equals("DESC")) {
Collections.reverse(result);
}
return result;
}
/**
* @return count of recognized active Sessions
*/
public int getNumberOfActiveSessions() {
int result = 0;
for (Map.Entry<String, Map<String,Long>> gateway : transportSessions.entrySet()) {
result += gateway.getValue().size();
}
return result;
}
/**
* Returns number of active Sessions for specified transport or 0 if not valid transport.
* @param transport
* @return
*/
public int getNumberOfActiveSessionsFor(String transport) {
if (transportSessions.containsKey(transport))
return transportSessions.get(transport).size();
return 0;
}
/**
* Searches for Sessions with given Username and returns them as ArrList
*
* @param username
* @return
*/
public ArrayList<GatewaySession> getConnectionsFor(String username) {
ArrayList<GatewaySession> userconnections = new ArrayList<GatewaySession>();
for (Map.Entry<String, Map<String, Long>> transport : transportSessions.entrySet()) {
if (transport.getValue().containsKey(username)) {
Timestamp stamp = new Timestamp(transport.getValue().get(username));
Date date = new Date(stamp.getTime());
userconnections.add(new GatewaySession(username, transport.getKey(), date));
}
}
return userconnections;
}
/**
* Returns Registrations associated with Username
*
* @param username
* @return ArrayList of SessionEntries
*/
public ArrayList<SessionEntry> getRegistrationsFor(String username) {
return db.getSessionEntriesFor(username);
}
/**
* Get all registrations sorted by attribute and order. Validation for correctness of attributes is done in DB
* Manager, returns default sorting: username ASC when not valid
*/
public ArrayList<SessionEntry> getAllRegistrations(String orderAttr, String order) {
return db.getAllSessionEntries(orderAttr, order);
}
public int getNumberOfRegistrations() {
return db.getNumberOfRegistrations();
}
public int getNumberOfRegistrationsForTransport(String transport) {
if (transportSessions.containsKey(transport)) {
return db.getNumberOfRegistrationsForTransport(transport);
}
return 0;
}
}