1 /* Copyright (c) 2013 Alexander Sherstnev
\r
2 * Copyright (c) 2011 Peter Troshin
\r
4 * JAva Bioinformatics Analysis Web Services (JABAWS) @version: 2.0
\r
6 * This library is free software; you can redistribute it and/or modify it under the terms of the
\r
7 * Apache License version 2 as published by the Apache Software Foundation
\r
9 * This library is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without
\r
10 * even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the Apache
\r
11 * License for more details.
\r
13 * A copy of the license is in apache_license.txt. It is also available here:
\r
14 * @see: http://www.apache.org/licenses/LICENSE-2.0.txt
\r
16 * Any republication or derived work distributed in source code form
\r
17 * must include this copyright and license notice.
\r
20 package compbio.stat.servlet;
\r
22 import java.io.IOException;
\r
23 import java.io.PrintWriter;
\r
24 import java.io.StringWriter;
\r
25 import java.lang.management.ManagementFactory;
\r
26 import java.net.InetAddress;
\r
27 import java.net.UnknownHostException;
\r
30 import java.text.SimpleDateFormat;
\r
32 import javax.management.AttributeNotFoundException;
\r
33 import javax.management.InstanceNotFoundException;
\r
34 import javax.management.MBeanException;
\r
35 import javax.management.MBeanServer;
\r
36 import javax.management.MalformedObjectNameException;
\r
37 import javax.management.ObjectName;
\r
38 import javax.management.Query;
\r
39 import javax.management.ReflectionException;
\r
40 import javax.servlet.RequestDispatcher;
\r
41 import javax.servlet.ServletException;
\r
42 import javax.servlet.http.HttpServlet;
\r
43 import javax.servlet.http.HttpServletRequest;
\r
44 import javax.servlet.http.HttpServletResponse;
\r
46 import compbio.engine.conf.PropertyHelperManager;
\r
47 import compbio.stat.servlet.util.RefreshIterator;
\r
48 import compbio.stat.servlet.util.Scheduler;
\r
49 import compbio.stat.servlet.util.SchedulerTask;
\r
50 import compbio.util.PropertyHelper;
\r
51 import compbio.util.Util;
\r
52 import org.apache.log4j.Logger;
\r
54 import compbio.ws.client.Services;
\r
55 import compbio.ws.client.WSTester;
\r
60 * <li>Test web services and display results on the web page</li>
\r
66 public class ServiceStatus extends HttpServlet {
\r
68 private static final Logger log = Logger.getLogger(ServiceStatus.class);
\r
70 private static PropertyHelper ph = PropertyHelperManager.getPropertyHelper();
\r
72 private final Scheduler scheduler = new Scheduler();
\r
74 private List<String> getEndPoints() throws MalformedObjectNameException, NullPointerException, UnknownHostException,
\r
75 AttributeNotFoundException, InstanceNotFoundException, MBeanException, ReflectionException {
\r
76 MBeanServer mbs = ManagementFactory.getPlatformMBeanServer();
\r
77 Set<ObjectName> objs = mbs.queryNames(new ObjectName("*:type=Connector,*"),
\r
78 Query.match(Query.attr("protocol"), Query.value("HTTP/1.1")));
\r
79 List<String> endPoints = new ArrayList<String>();
\r
80 for (Iterator<ObjectName> i = objs.iterator(); i.hasNext(); ) {
\r
81 ObjectName obj = i.next();
\r
82 String scheme = mbs.getAttribute(obj, "scheme").toString();
\r
83 String port = obj.getKeyProperty("port");
\r
84 String hostname = InetAddress.getLocalHost().getHostName();
\r
85 endPoints.add(scheme + "://" + hostname + ":" + port);
\r
90 private static int getIntProperty(String propValue) {
\r
92 if (!Util.isEmpty(propValue)) {
\r
93 propValue = propValue.trim();
\r
94 value = Integer.parseInt(propValue);
\r
99 private static int refreshServiceStatusFrequency() {
\r
100 return getIntProperty(ph.getProperty("local.service.status.refresh.frequency"));
\r
103 static int refreshUsageStatsFrequency() {
\r
104 return getIntProperty(ph.getProperty("local.usage.stats.refresh.frequency"));
\r
108 public void init() {
\r
109 // startup the scheduler with current time
\r
110 int hour = Calendar.getInstance().get(Calendar.HOUR_OF_DAY);
\r
111 int min = Calendar.getInstance().get(Calendar.MINUTE);
\r
112 int sec = Calendar.getInstance().get(Calendar.SECOND);
\r
113 // refresh sleep time (in between requests) - minutes
\r
114 final int refresh_freq = refreshServiceStatusFrequency();
\r
116 scheduler.schedule(new SchedulerTask() {
\r
117 public void run() {
\r
120 private void refreshCache() {
\r
121 hitEndpointForRefresh();
\r
122 log.info("Refreshing the In Memory Cache...");
\r
123 log.info(String.format("Refreshing again in %d minutes", refresh_freq));
\r
125 }, new RefreshIterator(hour, min, sec, refresh_freq));
\r
128 public void clearContextCache() {
\r
129 // try remove the current values from the context
\r
131 this.getServletConfig().getServletContext().removeAttribute("serviceStatusResults");
\r
132 this.getServletConfig().getServletContext().removeAttribute("serviceStatusTimestamp");
\r
133 this.getServletConfig().getServletContext().removeAttribute("serviceStatusStart");
\r
134 this.getServletConfig().getServletContext().removeAttribute("serviceStatusEnd");
\r
135 this.getServletConfig().getServletContext().removeAttribute("serviceStatusAllGood");
\r
136 log.info("In Memory Cache Cleared!");
\r
137 } catch (Exception e) {
\r
138 log.warn("In Memory Cache Not Cleared. Perhaps not available yet!");
\r
142 private void hitEndpointForRefresh() {
\r
143 String endpointURL;
\r
144 endpointURL = (String) this.getServletConfig().getServletContext().getAttribute("serviceStatusURL");
\r
145 if (endpointURL != null){
\r
147 URL url = new URL(endpointURL);
\r
148 System.out.println(endpointURL);
\r
149 HttpURLConnection connection = (HttpURLConnection) url.openConnection();
\r
150 connection.setRequestProperty("User-Agent", "JABAWS Service Status Refreshing the Context Cache");
\r
151 int status = connection.getResponseCode();
\r
152 log.info(String.format("Hitting %s with an internal user-agent! status code: %s",
\r
153 endpointURL, status));
\r
154 } catch (IOException e) {
\r
155 log.warn("Something wrong when hitting " + endpointURL);
\r
161 public ArrayList<ServiceTestResult> testServiceStatus(HttpServletRequest req) throws ServletException, IOException {
\r
163 ArrayList<ServiceTestResult> testResults = new ArrayList<ServiceTestResult>();
\r
165 // run the service status checkup
\r
166 List<String> eps = new ArrayList<String>();
\r
168 eps = getEndPoints();
\r
169 } catch (MalformedObjectNameException e) {
\r
170 // TODO Auto-generated catch block
\r
171 e.printStackTrace();
\r
172 } catch (AttributeNotFoundException e) {
\r
173 // TODO Auto-generated catch block
\r
174 e.printStackTrace();
\r
175 } catch (InstanceNotFoundException e) {
\r
176 // TODO Auto-generated catch block
\r
177 e.printStackTrace();
\r
178 } catch (NullPointerException e) {
\r
179 // TODO Auto-generated catch block
\r
180 e.printStackTrace();
\r
181 } catch (MBeanException e) {
\r
182 // TODO Auto-generated catch block
\r
183 e.printStackTrace();
\r
184 } catch (ReflectionException e) {
\r
185 // TODO Auto-generated catch block
\r
186 e.printStackTrace();
\r
188 if (1 != eps.size()) {
\r
189 log.info(eps.size() + "EndPoints found");
\r
190 //System.out.println(" " + eps.size() + " EndPoints found");
\r
191 for (String endpoint : eps) {
\r
192 log.info(eps.size() + "EndPoint is " + endpoint);
\r
193 //System.out.println(" EndPoint is " + endpoint);
\r
197 String serverPath = new String();
\r
198 for (String endpoint : eps) {
\r
199 serverPath = endpoint + req.getContextPath();
\r
202 for (Services service : Services.values()) {
\r
203 StringWriter testres = new StringWriter();
\r
204 PrintWriter writer = new PrintWriter(testres, true);
\r
205 WSTester tester = new WSTester(serverPath, writer);
\r
206 ServiceTestResult result = new ServiceTestResult(service);
\r
208 result.failed = tester.checkService(service);
\r
209 } catch (Exception e) {
\r
210 log.info(e, e.getCause());
\r
211 String mess = "Fails to connect to the web service: " + service + ". Reason: ";
\r
212 writer.println(mess + e.getLocalizedMessage() + "\nDetails: ");
\r
213 e.printStackTrace(writer);
\r
217 result.details = testres.toString();
\r
218 testResults.add(result);
\r
220 return testResults;
\r
223 public String overallStatusGood(ArrayList<ServiceTestResult> testResults) {
\r
224 // assumes all good but returns as soon as some service is down
\r
225 String success = "true";
\r
226 for (int i = 0; i < testResults.size(); i++) {
\r
227 if (!testResults.get(i).failed) {
\r
236 protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
\r
238 * // PROBLEM: the code tries to test not WS endpoints on an internal
\r
239 * Tomcat, but on an external // endpoints with wrong info on the
\r
240 * proxing StringBuffer jabawspath = req.getRequestURL(); jabawspath =
\r
241 * jabawspath.delete(jabawspath.lastIndexOf("/"), jabawspath.length());
\r
242 * String serverPath = jabawspath.toString();
\r
245 ArrayList<ServiceTestResult> testResults = new ArrayList<ServiceTestResult>();
\r
246 String timeStamp = new String();
\r
249 String refresh_freq;
\r
252 // save the main caller URL in the context
\r
253 String url = new String();
\r
254 url = req.getRequestURL().toString();
\r
255 System.out.println("UR: " + url);
\r
256 this.getServletConfig().getServletContext().setAttribute("serviceStatusURL", url);
\r
258 // check user-agent: this is a trick to get the cache refreshed periodically
\r
259 String useragent = new String();
\r
260 useragent = req.getHeader("user-agent");
\r
261 // check if there are values available in the context
\r
262 if (this.getServletConfig().getServletContext().getAttribute("serviceStatusResults") == null ||
\r
263 useragent.equals("JABAWS Service Status Refreshing the Context Cache")) {
\r
265 // test the services and timeit
\r
266 startTime = System.nanoTime();
\r
267 testResults = testServiceStatus(req);
\r
268 endTime = System.nanoTime();
\r
269 // try clear the previous values if any
\r
270 clearContextCache();
\r
271 // add the current values to the context
\r
272 this.getServletConfig().getServletContext().setAttribute("serviceStatusResults", testResults);
\r
273 timeStamp = new SimpleDateFormat("dd/MM/yyyy HH:mm:ss").format(
\r
274 Calendar.getInstance().getTime());
\r
275 this.getServletConfig().getServletContext().setAttribute("serviceStatusTimestamp", timeStamp);
\r
276 this.getServletConfig().getServletContext().setAttribute("serviceStatusStart", startTime);
\r
277 this.getServletConfig().getServletContext().setAttribute("serviceStatusEnd", endTime);
\r
278 refresh_freq = String.valueOf(refreshServiceStatusFrequency());
\r
279 this.getServletConfig().getServletContext().setAttribute("serviceStatusRefreshFreq", refresh_freq);
\r
280 goodStatus = overallStatusGood(testResults);
\r
281 this.getServletConfig().getServletContext().setAttribute("serviceStatusAllGood", goodStatus);
\r
284 // get last results available
\r
285 testResults = (ArrayList) this.getServletConfig().getServletContext().getAttribute("serviceStatusResults");
\r
286 timeStamp = (String) this.getServletConfig().getServletContext().getAttribute("serviceStatusTimestamp");
\r
287 startTime = (Long) this.getServletConfig().getServletContext().getAttribute("serviceStatusStart");
\r
288 endTime = (Long) this.getServletConfig().getServletContext().getAttribute("serviceStatusEnd");
\r
289 refresh_freq = (String) this.getServletConfig().getServletContext().getAttribute("serviceStatusRefreshFreq");
\r
292 req.setAttribute("results", testResults);
\r
293 req.setAttribute("timestamp", timeStamp);
\r
294 req.setAttribute("timeexec", (endTime - startTime) / 100000000);
\r
295 req.setAttribute("refreshfreq", refresh_freq);
\r
296 RequestDispatcher rd = req.getRequestDispatcher("statpages/ServicesStatus.jsp");
\r
297 rd.forward(req, resp);
\r