/* 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); } }