package org.xins.server;
import java.io.IOException;
import java.text.DateFormat;
import java.text.SimpleDateFormat;
import java.util.Collections;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.Properties;
import javax.management.openmbean.CompositeDataSupport;
import javax.management.openmbean.CompositeType;
import javax.management.openmbean.OpenDataException;
import javax.management.openmbean.OpenType;
import javax.management.openmbean.SimpleType;
import javax.management.openmbean.TabularDataSupport;
import javax.management.openmbean.TabularType;
import org.apache.log4j.Logger;
import org.apache.log4j.jmx.HierarchyDynamicMBean;
import org.xins.common.Utils;
import org.xins.common.collections.MapStringUtils;
import org.xins.common.net.IPAddressUtils;
import org.xins.common.text.DateConverter;
import org.xins.common.text.TextUtils;
import org.w3c.dom.Element;
import org.xins.common.xml.ElementList;
public final class APIManager implements APIManagerMBean {
private static final DateFormat DATE_FORMATTER = new SimpleDateFormat("yyyy.MM.DD HH:MM:ss.SSS");
private final API _api;
private String _ip;
APIManager(API api) {
_api = api;
_ip = IPAddressUtils.getLocalHostIPAddress();
}
public String getAPIVersion() throws IOException {
return _api.getBootstrapProperties().get(API.API_VERSION_PROPERTY);
}
public String getXINSVersion() throws IOException {
return Library.getVersion();
}
public String getAPIName() throws IOException {
return _api.getName();
}
public CompositeDataSupport getBootstrapProperties() throws IOException {
Properties bootstrapProps = MapStringUtils.toProperties(_api.getBootstrapProperties());
return propertiesToCompositeData(bootstrapProps);
}
public CompositeDataSupport getRuntimeProperties() throws IOException {
Properties runtimeProps = MapStringUtils.toProperties(_api.getRuntimeProperties());
return propertiesToCompositeData(runtimeProps);
}
public String getStartupTime() throws IOException {
return DateConverter.toDateString(_api.getStartupTimestamp());
}
public String[] getFunctionNames() throws IOException {
List<Function> functions = _api.getFunctionList();
String[] functionNames = new String[functions.size()];
for (int i = 0; i < functions.size(); i++) {
Function nextFunction = functions.get(i);
functionNames[i] = nextFunction.getName();
}
return functionNames;
}
public TabularDataSupport getStatistics() throws IOException {
String[] statsNames = {"Function", "Count", "Error Code", "Average", "Min Date",
"Min Duration", "Max Date", "Max Duration", "Last Date", "Last Duration"};
OpenType[] statsTypes = {SimpleType.STRING, SimpleType.LONG, SimpleType.STRING,
SimpleType.LONG, SimpleType.DATE, SimpleType.LONG, SimpleType.DATE, SimpleType.LONG,
SimpleType.DATE, SimpleType.LONG};
try {
CompositeType statType = new CompositeType("Statistic",
"A statistic of a function", statsNames, statsNames, statsTypes);
TabularType tabType = new TabularType("Function statistics",
"Statistics of the functions", statType, statsNames);
TabularDataSupport tabularData = new TabularDataSupport(tabType);
StatisticsInterceptor statInterceptor = _api.getStatisticInterceptor();
if (statInterceptor != null) {
for (Map.Entry<String, FunctionStatistics> stat : statInterceptor.getStatistics().entrySet()) {
String functionName = stat.getKey();
FunctionStatistics statistic = stat.getValue();
Element success = statistic.getSuccessfulElement();
HashMap statMap = statisticsToMap(success, functionName);
CompositeDataSupport statData = new CompositeDataSupport(statType, statMap);
tabularData.put(statData);
Element[] unsuccess = statistic.getUnsuccessfulElement(true);
for (int i = 0; i < unsuccess.length; i++) {
HashMap statMap2 = statisticsToMap(unsuccess[i], functionName);
CompositeDataSupport statData2 = new CompositeDataSupport(statType, statMap2);
tabularData.put(statData2);
}
}
}
return tabularData;
} catch (OpenDataException odex) {
Utils.logProgrammingError(odex);
return null;
}
}
public void noOp() throws IOException, NoSuchFunctionException, AccessDeniedException {
Map<String, Object> backpack = new HashMap<String, Object>();
backpack.put(BackpackConstants.IP, _ip);
FunctionRequest noOpRequest = new FunctionRequest("_NoOp", Collections.EMPTY_MAP, null, backpack);
_api.handleCall(noOpRequest, null);
}
public void reloadProperties() throws IOException, NoSuchFunctionException, AccessDeniedException {
Map<String, Object> backpack = new HashMap<String, Object>();
backpack.put(BackpackConstants.IP, _ip);
FunctionRequest reloadPropertiesRequest = new FunctionRequest("_ReloadProperties", Collections.EMPTY_MAP, null, backpack);
_api.handleCall(reloadPropertiesRequest, null);
}
private HashMap statisticsToMap(Element statElement, String functionName) {
HashMap statMap = new HashMap();
statMap.put("Function", functionName);
statMap.put("Count", new Long(statElement.getAttribute("count")));
if (!TextUtils.isEmpty(statElement.getAttribute("errorcode"))) {
statMap.put("Error Code", statElement.getAttribute("errorcode"));
} else if (statElement.getTagName().equals("unsuccessful")) {
statMap.put("Error Code", "<unsuccessful>");
} else if (statElement.getTagName().equals("successful")) {
statMap.put("Error Code", "<successful>");
}
if (!"N/A".equals(statElement.getAttribute("average"))) {
statMap.put("Average", new Long(statElement.getAttribute("average")));
} else {
statMap.put("Average", null);
}
try {
Element minStat = new ElementList(statElement, "min").get(0);
if (!"N/A".equals(minStat.getAttribute("duration"))) {
synchronized (DATE_FORMATTER) {
statMap.put("Min Date", DATE_FORMATTER.parse(minStat.getAttribute("start")));
}
statMap.put("Min Duration", new Long(minStat.getAttribute("duration")));
} else {
statMap.put("Min Date", null);
statMap.put("Min Duration", null);
}
} catch (Exception ex) {
Utils.logProgrammingError(ex);
}
try {
Element maxStat = new ElementList(statElement, "max").get(0);
if (!"N/A".equals(maxStat.getAttribute("duration"))) {
synchronized (DATE_FORMATTER) {
statMap.put("Max Date", DATE_FORMATTER.parse(maxStat.getAttribute("start")));
}
statMap.put("Max Duration", new Long(maxStat.getAttribute("duration")));
} else {
statMap.put("Max Date", null);
statMap.put("Max Duration", null);
}
} catch (Exception ex) {
Utils.logProgrammingError(ex);
}
try {
Element lastStat = new ElementList(statElement, "last").get(0);
if (!"N/A".equals(lastStat.getAttribute("duration"))) {
synchronized (DATE_FORMATTER) {
statMap.put("Last Date", DATE_FORMATTER.parse(lastStat.getAttribute("start")));
}
statMap.put("Last Duration", new Long(lastStat.getAttribute("duration")));
} else {
statMap.put("Last Date", null);
statMap.put("Last Duration", null);
}
} catch (Exception ex) {
Utils.logProgrammingError(ex);
}
return statMap;
}
private CompositeDataSupport propertiesToCompositeData(Properties properties) {
try {
String[] keys = (String[]) properties.keySet().toArray(new String[properties.size()]);
OpenType[] itemTypes = new OpenType[keys.length];
Object[] values = new Object[keys.length];
for (int i = 0; i < itemTypes.length; i++) {
itemTypes[i] = SimpleType.STRING;
values[i] = properties.getProperty(keys[i]);
}
CompositeType propsType = new CompositeType("Properties type", "properties", keys, keys, itemTypes);
CompositeDataSupport propsData = new CompositeDataSupport(propsType, keys, values);
return propsData;
} catch (OpenDataException odex) {
Utils.logProgrammingError(odex);
return null;
}
}
static void registerMBean(API api) throws Throwable {
javax.management.MBeanServer mBeanServer;
try {
mBeanServer = (javax.management.MBeanServer) Class.forName("java.lang.management.ManagementFactory").getMethod("getPlatformMBeanServer", null).invoke(null, null);
} catch (ClassNotFoundException cnfe) {
mBeanServer = javax.management.MBeanServerFactory.createMBeanServer();
}
APIManager mBean = new APIManager(api);
javax.management.ObjectName objectName = new javax.management.ObjectName("org.xins.server.api." + api.getName() + ":type=APIManager");
mBeanServer.registerMBean(mBean, objectName);
HierarchyDynamicMBean hdm = new HierarchyDynamicMBean();
javax.management.ObjectName mbo = new javax.management.ObjectName("org.xins.server.api." + api.getName() + ":hiearchy=log4j");
mBeanServer.registerMBean(hdm, mbo);
Logger rootLogger = Logger.getRootLogger();
hdm.addLoggerMBean(rootLogger.getName());
}
}