/* Copyright (c) 2013 Alexander Sherstnev
* Copyright (c) 2011 Peter Troshin
*
* JAva Bioinformatics Analysis Web Services (JABAWS) @version: 2.0
*
* This library is free software; you can redistribute it and/or modify it under the terms of the
* Apache License version 2 as published by the Apache Software Foundation
*
* This library 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 Apache
* License for more details.
*
* A copy of the license is in apache_license.txt. It is also available here:
* @see: http://www.apache.org/licenses/LICENSE-2.0.txt
*
* Any republication or derived work distributed in source code form
* must include this copyright and license notice.
*/
package compbio.stat.servlet;
import java.io.IOException;
import java.io.PrintWriter;
import java.io.StringWriter;
import java.lang.management.ManagementFactory;
import java.net.InetAddress;
import java.net.UnknownHostException;
import java.util.*;
import java.net.*;
import java.text.SimpleDateFormat;
import javax.management.AttributeNotFoundException;
import javax.management.InstanceNotFoundException;
import javax.management.MBeanException;
import javax.management.MBeanServer;
import javax.management.MalformedObjectNameException;
import javax.management.ObjectName;
import javax.management.Query;
import javax.management.ReflectionException;
import javax.servlet.RequestDispatcher;
import javax.servlet.ServletException;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import compbio.engine.conf.PropertyHelperManager;
import compbio.stat.servlet.util.RefreshIterator;
import compbio.stat.servlet.util.Scheduler;
import compbio.stat.servlet.util.SchedulerTask;
import compbio.util.PropertyHelper;
import compbio.util.Util;
import org.apache.log4j.Logger;
import compbio.ws.client.Services;
import compbio.ws.client.WSTester;
/**
* Use cases:
*
*
Test web services and display results on the web page
*
*
* @author pvtroshin
*/
public class ServiceStatus extends HttpServlet {
private static final Logger log = Logger.getLogger(ServiceStatus.class);
private static PropertyHelper ph = PropertyHelperManager.getPropertyHelper();
private final Scheduler scheduler = new Scheduler();
private List getEndPoints() throws MalformedObjectNameException, NullPointerException, UnknownHostException,
AttributeNotFoundException, InstanceNotFoundException, MBeanException, ReflectionException {
MBeanServer mbs = ManagementFactory.getPlatformMBeanServer();
Set objs = mbs.queryNames(new ObjectName("*:type=Connector,*"),
Query.match(Query.attr("protocol"), Query.value("HTTP/1.1")));
List endPoints = new ArrayList();
for (Iterator i = objs.iterator(); i.hasNext(); ) {
ObjectName obj = i.next();
String scheme = mbs.getAttribute(obj, "scheme").toString();
String port = obj.getKeyProperty("port");
String hostname = InetAddress.getLocalHost().getHostName();
endPoints.add(scheme + "://" + hostname + ":" + port);
}
return endPoints;
}
private static int getIntProperty(String propValue) {
int value = 0;
if (!Util.isEmpty(propValue)) {
propValue = propValue.trim();
value = Integer.parseInt(propValue);
}
return value;
}
private static int refreshServiceStatusFrequency() {
return getIntProperty(ph.getProperty("local.service.status.refresh.frequency"));
}
static int refreshUsageStatsFrequency() {
return getIntProperty(ph.getProperty("local.usage.stats.refresh.frequency"));
}
@Override
public void init() {
// startup the scheduler with current time
int hour = Calendar.getInstance().get(Calendar.HOUR_OF_DAY);
int min = Calendar.getInstance().get(Calendar.MINUTE);
int sec = Calendar.getInstance().get(Calendar.SECOND);
// refresh sleep time (in between requests) - minutes
final int refresh_freq = refreshServiceStatusFrequency();
scheduler.schedule(new SchedulerTask() {
public void run() {
refreshCache();
}
private void refreshCache() {
hitEndpointForRefresh();
log.info("Refreshing the In Memory Cache...");
log.info(String.format("Refreshing again in %d minutes", refresh_freq));
}
}, new RefreshIterator(hour, min, sec, refresh_freq));
}
public void clearContextCache() {
// try remove the current values from the context
try {
this.getServletConfig().getServletContext().removeAttribute("serviceStatusResults");
this.getServletConfig().getServletContext().removeAttribute("serviceStatusTimestamp");
this.getServletConfig().getServletContext().removeAttribute("serviceStatusStart");
this.getServletConfig().getServletContext().removeAttribute("serviceStatusEnd");
this.getServletConfig().getServletContext().removeAttribute("serviceStatusAllGood");
log.info("In Memory Cache Cleared!");
} catch (Exception e) {
log.warn("In Memory Cache Not Cleared. Perhaps not available yet!");
}
}
private void hitEndpointForRefresh() {
String endpointURL;
endpointURL = (String) this.getServletConfig().getServletContext().getAttribute("serviceStatusURL");
if (endpointURL != null){
try {
URL url = new URL(endpointURL);
System.out.println(endpointURL);
HttpURLConnection connection = (HttpURLConnection) url.openConnection();
connection.setRequestProperty("User-Agent", "JABAWS Service Status Refreshing the Context Cache");
int status = connection.getResponseCode();
log.info(String.format("Hitting %s with an internal user-agent! status code: %s",
endpointURL, status));
} catch (IOException e) {
log.warn("Something wrong when hitting " + endpointURL);
log.warn(e);
}
}
}
public ArrayList testServiceStatus(HttpServletRequest req) throws ServletException, IOException {
ArrayList testResults = new ArrayList();
// run the service status checkup
List eps = new ArrayList();
try {
eps = getEndPoints();
} catch (MalformedObjectNameException e) {
// TODO Auto-generated catch block
e.printStackTrace();
} catch (AttributeNotFoundException e) {
// TODO Auto-generated catch block
e.printStackTrace();
} catch (InstanceNotFoundException e) {
// TODO Auto-generated catch block
e.printStackTrace();
} catch (NullPointerException e) {
// TODO Auto-generated catch block
e.printStackTrace();
} catch (MBeanException e) {
// TODO Auto-generated catch block
e.printStackTrace();
} catch (ReflectionException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
if (1 != eps.size()) {
log.info(eps.size() + "EndPoints found");
//System.out.println(" " + eps.size() + " EndPoints found");
for (String endpoint : eps) {
log.info(eps.size() + "EndPoint is " + endpoint);
//System.out.println(" EndPoint is " + endpoint);
}
}
String serverPath = new String();
for (String endpoint : eps) {
serverPath = endpoint + req.getContextPath();
}
for (Services service : Services.values()) {
StringWriter testres = new StringWriter();
PrintWriter writer = new PrintWriter(testres, true);
WSTester tester = new WSTester(serverPath, writer);
ServiceTestResult result = new ServiceTestResult(service);
try {
result.failed = tester.checkService(service);
} catch (Exception e) {
log.info(e, e.getCause());
String mess = "Fails to connect to the web service: " + service + ". Reason: ";
writer.println(mess + e.getLocalizedMessage() + "\nDetails: ");
e.printStackTrace(writer);
} finally {
writer.close();
}
result.details = testres.toString();
testResults.add(result);
}
return testResults;
}
public String overallStatusGood(ArrayList testResults) {
// assumes all good but returns as soon as some service is down
String success = "true";
for (int i = 0; i < testResults.size(); i++) {
if (!testResults.get(i).failed) {
success = "false";
break;
}
}
return success;
}
@Override
protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
/**
* // PROBLEM: the code tries to test not WS endpoints on an internal
* Tomcat, but on an external // endpoints with wrong info on the
* proxing StringBuffer jabawspath = req.getRequestURL(); jabawspath =
* jabawspath.delete(jabawspath.lastIndexOf("/"), jabawspath.length());
* String serverPath = jabawspath.toString();
*/
ArrayList testResults = new ArrayList();
String timeStamp = new String();
long startTime;
long endTime;
String refresh_freq;
String goodStatus;
// save the main caller URL in the context
String url = new String();
url = req.getRequestURL().toString();
System.out.println("UR: " + url);
this.getServletConfig().getServletContext().setAttribute("serviceStatusURL", url);
// check user-agent: this is a trick to get the cache refreshed periodically
String useragent = new String();
useragent = req.getHeader("user-agent");
// check if there are values available in the context
if (this.getServletConfig().getServletContext().getAttribute("serviceStatusResults") == null ||
useragent.equals("JABAWS Service Status Refreshing the Context Cache")) {
// test the services and timeit
startTime = System.nanoTime();
testResults = testServiceStatus(req);
endTime = System.nanoTime();
// try clear the previous values if any
clearContextCache();
// add the current values to the context
this.getServletConfig().getServletContext().setAttribute("serviceStatusResults", testResults);
timeStamp = new SimpleDateFormat("dd/MM/yyyy HH:mm:ss").format(
Calendar.getInstance().getTime());
this.getServletConfig().getServletContext().setAttribute("serviceStatusTimestamp", timeStamp);
this.getServletConfig().getServletContext().setAttribute("serviceStatusStart", startTime);
this.getServletConfig().getServletContext().setAttribute("serviceStatusEnd", endTime);
refresh_freq = String.valueOf(refreshServiceStatusFrequency());
this.getServletConfig().getServletContext().setAttribute("serviceStatusRefreshFreq", refresh_freq);
goodStatus = overallStatusGood(testResults);
this.getServletConfig().getServletContext().setAttribute("serviceStatusAllGood", goodStatus);
} else {
// get last results available
testResults = (ArrayList) this.getServletConfig().getServletContext().getAttribute("serviceStatusResults");
timeStamp = (String) this.getServletConfig().getServletContext().getAttribute("serviceStatusTimestamp");
startTime = (Long) this.getServletConfig().getServletContext().getAttribute("serviceStatusStart");
endTime = (Long) this.getServletConfig().getServletContext().getAttribute("serviceStatusEnd");
refresh_freq = (String) this.getServletConfig().getServletContext().getAttribute("serviceStatusRefreshFreq");
}
req.setAttribute("results", testResults);
req.setAttribute("timestamp", timeStamp);
req.setAttribute("timeexec", (endTime - startTime) / 1000000000);
req.setAttribute("refreshfreq", refresh_freq);
RequestDispatcher rd = req.getRequestDispatcher("statpages/ServicesStatus.jsp");
rd.forward(req, resp);
}
}