package org.jivesoftware.openfire.plugin.gojara.sessions;
import java.text.DecimalFormat;
import java.util.HashSet;
import java.util.Map;
import java.util.Set;
import java.util.concurrent.ConcurrentHashMap;
import org.jivesoftware.openfire.PacketRouter;
import org.jivesoftware.openfire.XMPPServer;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.xmpp.packet.JID;
import org.xmpp.packet.Message;
import org.xmpp.packet.Message.Type;
/**
* This Class sends Ad-Hoc commands to given spectrum2 transports, which will then be intercepted by MainInterceptor,
* and processed by GojaraAdminProcessor
*
* @author axel.frederik.brand
*
*/
public class GojaraAdminManager {
private static GojaraAdminManager myself;
private PacketRouter router;
private static final Logger Log = LoggerFactory.getLogger(GojaraAdminManager.class);
private JID adminUser;
private XMPPServer _server;
private Set<String> unconfiguredGateways;
private Set<String> configuredGateways;
private Map<String, Map<String, Integer>> gatewayStatisticsMap;
private long refreshCooldown = 0;
private GojaraAdminManager() {
_server = XMPPServer.getInstance();
router = _server.getPacketRouter();
// we dont actually need to CREATE the user, it's sufficient to create the jid. The message gets intercepted before its processed.
adminUser = _server.createJID("gojaraadmin", null);
unconfiguredGateways = new HashSet<String>();
configuredGateways = new HashSet<String>();
gatewayStatisticsMap = new ConcurrentHashMap<String, Map<String, Integer>>(16, 0.75f, 1);
}
public static GojaraAdminManager getInstance() {
if (myself == null) {
myself = new GojaraAdminManager();
}
return myself;
}
/**
* Sends a testmessage to specified gateway, when a response gets intercepted we consider gateway configured
*
*/
public void testAdminConfiguration(String gateway) {
unconfiguredGateways.add(gateway);
Message message = generateCommand(gateway, "config_check");
message.setBody("status");
router.route(message);
Log.info("Checking for admin configuration on " + gateway);
}
/**
* Gets called from Interceptor to confirm that a Gateway responded to our config_check message.
*
* @param gateway
*/
public void confirmGatewayConfig(String gateway) {
unconfiguredGateways.remove(gateway);
configuredGateways.add(gateway);
gatewayStatisticsMap.put(gateway, new ConcurrentHashMap<String, Integer>(16, 0.75f, 1));
gatherGatewayStatistics(gateway);
}
/**
* If a gateway disconnects we have to check if it was not configured as we may want to alter boolean
* areGatewaysConfigured.
*/
public void gatewayUnregistered(String gateway) {
unconfiguredGateways.remove(gateway);
configuredGateways.remove(gateway);
gatewayStatisticsMap.remove(gateway);
}
public boolean areGatewaysConfigured() {
return unconfiguredGateways.isEmpty();
}
public boolean isGatewayConfigured(String gateway) {
return configuredGateways.contains(gateway);
}
/**
* Generates a basic ad-hoc command with From,To, Type, ID & Body configured. Body might need to be reconfigured
* when additional info has to be specified, like unregister
*
* @param transport
* @param command
* @return
*/
private Message generateCommand(String transport, String command) {
Message message = new Message();
message.setFrom(adminUser);
message.setTo(transport);
message.setID(command);
message.setBody(command);
message.setType(Type.chat);
return message;
}
/**
* Sends the command online_users to specified Spectrum2 transport. We set the ID specific to the command so we can
* identify the response. Transport has to be configured for admin_jid = gojaraadmin@domain
*
* @param transport
*/
public void getOnlineUsersOf(String transport) {
// no use in sending the message if not configured for gojaraadmin
if (unconfiguredGateways.contains(transport))
return;
Message message = generateCommand(transport, "online_users");
router.route(message);
Log.debug("Sent online_users Packet!" + message.toString());
}
/**
* Sends the unregister <bare_jid> command to specified Spectrum2 transport. We set the ID specific to the command
* so we can identify the response. Transport has to be configured for admin_jid = gojaraadmin@domain
*
* @param transport
*/
public String unregisterUserFrom(String transport, String user) {
if (unconfiguredGateways.contains(transport))
return "Gateway " + transport + "is not active. Didn't send unregister for "+ user+".";
Message message = generateCommand(transport, "unregister");
message.setBody("unregister " + _server.createJID(user, null).toString());
router.route(message);
Log.debug("Sent Unregister Packet!" + message.toString());
return "Sent unregister Packet for user: "+user;
}
public void putStatisticValue(String subdomain, String statistic, int value) {
gatewayStatisticsMap.get(subdomain).put(statistic, value);
}
/**
* For JSP usage, dont refresh statistics more than once a minute
*/
public void gatherGatewayStatistics() {
if (refreshCooldown == 0) {
refreshCooldown = System.currentTimeMillis();
} else if ((System.currentTimeMillis() - refreshCooldown) < 60000) {
// once a minute max
return;
}
refreshCooldown = System.currentTimeMillis();
for (String gateway : configuredGateways) {
gatherGatewayStatistics(gateway);
}
}
/**
* gathers Gatewaystatistics for specific gateway
*
* @param gateway
*/
public void gatherGatewayStatistics(String gateway) {
uptime(gateway);
messagesFrom(gateway);
messagesTo(gateway);
usedMemoryOf(gateway);
averageMemoryOfUser(gateway);
// Log.info("Gathering Gateway-Statistics for " + gateway);
}
private void uptime(String transport) {
Message message = generateCommand(transport, "uptime");
router.route(message);
}
private void messagesFrom(String transport) {
Message message = generateCommand(transport, "messages_from_xmpp");
router.route(message);
}
private void messagesTo(String transport) {
Message message = generateCommand(transport, "messages_to_xmpp");
router.route(message);
}
private void usedMemoryOf(String transport) {
Message message = generateCommand(transport, "used_memory");
router.route(message);
}
private void averageMemoryOfUser(String transport) {
Message message = generateCommand(transport, "average_memory_per_user");
router.route(message);
}
/**
* Preps the specified stat for nicer output which is used in tables.
*
* @param gateway
* @param stat
* @return
*/
public String getStatisticsPresentationString(String gateway, String stat) {
if (gatewayStatisticsMap.containsKey(gateway)) {
if (stat.equals("uptime")) {
if (gatewayStatisticsMap.get(gateway).get("uptime") != null) {
int time = gatewayStatisticsMap.get(gateway).get("uptime");
long diffSeconds = time % 60;
long diffMinutes = time / 60 % 60;
long diffHours = time / (60 * 60) % 24;
long diffDays = time / (24 * 60 * 60);
String seconds = diffSeconds == 0 ? "" : (diffSeconds + " Sec");
String minutes = diffMinutes == 0 ? "" : (diffMinutes + " Min ");
String hours = diffHours == 0 ? "" : (diffHours + " Hours ");
String days = diffDays == 0 ? "" : (diffDays + " Days ");
return days + hours + minutes + seconds;
}
} else if (stat.equals("messages_from_xmpp")) {
if (gatewayStatisticsMap.get(gateway).get("messages_from_xmpp") != null)
return "" + gatewayStatisticsMap.get(gateway).get("messages_from_xmpp");
} else if (stat.equals("messages_to_xmpp")) {
if (gatewayStatisticsMap.get(gateway).get("messages_to_xmpp") != null)
return "" + gatewayStatisticsMap.get(gateway).get("messages_to_xmpp");
} else if (stat.equals("used_memory")) {
if (gatewayStatisticsMap.get(gateway).get("used_memory") != null) {
DecimalFormat f = new DecimalFormat("#0.00");
double mb = gatewayStatisticsMap.get(gateway).get("used_memory") / 1024.0;
return "" + f.format(mb) + " MB";
}
} else if (stat.equals("average_memory_per_user")) {
if (gatewayStatisticsMap.get(gateway).get("average_memory_per_user") != null) {
return "" + gatewayStatisticsMap.get(gateway).get("average_memory_per_user") + " KB";
}
}
}
return "-";
}
}