WStester & registry are completed
[jabaws.git] / webservices / compbio / ws / client / WSTester.java
1 /* Copyright (c) 2009 Peter Troshin\r
2  *  \r
3  *  JAva Bioinformatics Analysis Web Services (JABAWS) @version: 1.0     \r
4  * \r
5  *  This library is free software; you can redistribute it and/or modify it under the terms of the\r
6  *  Apache License version 2 as published by the Apache Software Foundation\r
7  * \r
8  *  This library is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without\r
9  *  even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the Apache \r
10  *  License for more details.\r
11  * \r
12  *  A copy of the license is in apache_license.txt. It is also available here:\r
13  * @see: http://www.apache.org/licenses/LICENSE-2.0.txt\r
14  * \r
15  * Any republication or derived work distributed in source code form\r
16  * must include this copyright and license notice.\r
17  */\r
18 \r
19 package compbio.ws.client;\r
20 \r
21 import static compbio.ws.client.Constraints.hostkey;\r
22 import static compbio.ws.client.Constraints.pseparator;\r
23 import static compbio.ws.client.Constraints.servicekey;\r
24 \r
25 import java.io.ByteArrayInputStream;\r
26 import java.io.Closeable;\r
27 import java.io.IOException;\r
28 import java.io.PrintWriter;\r
29 import java.util.Arrays;\r
30 import java.util.List;\r
31 \r
32 import org.apache.log4j.Logger;\r
33 \r
34 import compbio.data.msa.JABAService;\r
35 import compbio.data.msa.Metadata;\r
36 import compbio.data.msa.MsaWS;\r
37 import compbio.data.msa.SequenceAnnotation;\r
38 import compbio.data.sequence.Alignment;\r
39 import compbio.data.sequence.FastaSequence;\r
40 import compbio.data.sequence.ScoreManager;\r
41 import compbio.data.sequence.SequenceUtil;\r
42 import compbio.metadata.JobStatus;\r
43 import compbio.metadata.Limit;\r
44 import compbio.metadata.LimitsManager;\r
45 import compbio.metadata.Option;\r
46 import compbio.metadata.Preset;\r
47 import compbio.metadata.PresetManager;\r
48 import compbio.metadata.RunnerConfig;\r
49 import compbio.metadata.UnsupportedRuntimeException;\r
50 import compbio.util.FileUtil;\r
51 import compbio.util.Util;\r
52 \r
53 /**\r
54  * Class for testing web services\r
55  * \r
56  * @author pvtroshin\r
57  * \r
58  * @version 1.0 February 2010\r
59  */\r
60 public class WSTester {\r
61 \r
62         private static Logger log = Logger.getLogger(WSTester.class);\r
63         /**\r
64          * Sequences to be used as input for all WS\r
65          */\r
66         static final String fastaInput = ">Foo\n"\r
67                         + "MTADGPRELLQLRAAVRHRPQDFVAWLMLADAELGMGDTTAGEMAVQRGLALHPGHPEAV"\r
68                         + "\n>Bar\n"\r
69                         + "ASDAAPEHPGIALWLHALEDAGQAEAAAAYTRAHQLLPEEPYITAQLLNAVA";\r
70 \r
71         static final String fastaAlignment = ">Foo\r\n"\r
72                         + "MTADGPRELLQLRAAVRHRPQDFVAWLMLADAELGMGDTTAGEMAVQRGLALHPGHPEAV--------\r\n"\r
73                         + ">Bar\r\n"\r
74                         + "ASDAAPEH------------PGIALWLHALE-DAGQAEAAA---AYTRAHQLLPEEPYITAQLLNAVA\r\n"\r
75                         + "";\r
76 \r
77         static final List<FastaSequence> seqs = loadSeqs();\r
78 \r
79         private static final String FAILED = "FAILED";\r
80         private static final String OK = "OK";\r
81 \r
82         private static final String UNSUPPORTED = "UNSUPPORTED";\r
83 \r
84         /**\r
85          * Converting input to a form accepted by WS\r
86          * \r
87          * @return List of FastaSequence records\r
88          */\r
89         private static List<FastaSequence> loadSeqs() {\r
90                 try {\r
91                         return SequenceUtil.readFasta(new ByteArrayInputStream(fastaInput\r
92                                         .getBytes()));\r
93                 } catch (IOException ignored) {\r
94                         // Should not happen as a source is not a external stream\r
95                         ignored.printStackTrace();\r
96                 }\r
97                 return null;\r
98         }\r
99 \r
100         /**\r
101          * Converting input to a form accepted by WS\r
102          * \r
103          * @return List of FastaSequence records\r
104          */\r
105         private static List<FastaSequence> loadAlignment() {\r
106                 try {\r
107                         return SequenceUtil.readFasta(new ByteArrayInputStream(\r
108                                         fastaAlignment.getBytes()));\r
109                 } catch (IOException ignored) {\r
110                         // Should not happen as a source is not a external stream\r
111                         ignored.printStackTrace();\r
112                 }\r
113                 return null;\r
114         }\r
115 \r
116         private final PrintWriter writer;\r
117         private final String hostname;\r
118 \r
119         public WSTester(String hostname, PrintWriter writer) {\r
120                 if (Util.isEmpty(hostname)) {\r
121                         throw new NullPointerException("Hostname must be provided!");\r
122                 }\r
123                 this.hostname = hostname;\r
124                 this.writer = writer;\r
125         }\r
126 \r
127         /**\r
128          * Prints usage\r
129          */\r
130         static void printUsage() {\r
131                 System.out.println("Usage: <Class or Jar file name> " + hostkey\r
132                                 + pseparator + "host_and_context " + "<" + servicekey\r
133                                 + pseparator + "serviceName>");\r
134                 System.out.println();\r
135                 System.out\r
136                                 .println(hostkey\r
137                                                 + pseparator\r
138                                                 + "<host_and_context> - a full URL to the JABAWS web server including context path e.g. http://10.31.1.159:8080/ws");\r
139                 System.out\r
140                                 .println(servicekey\r
141                                                 + pseparator\r
142                                                 + "<ServiceName> - optional if unspecified all services are tested otherwise one of "\r
143                                                 + Arrays.toString(Services.values()));\r
144                 System.out.println();\r
145 \r
146         }\r
147 \r
148         /**\r
149          * Calls alignment with preset\r
150          * \r
151          * @param <T>\r
152          * @param msaws\r
153          * @param presets\r
154          *            list of the Preset\r
155          * @throws UnsupportedRuntimeException\r
156          */\r
157         private <T> boolean presetAlign(MsaWS<T> msaws, List<Preset<T>> presets)\r
158                         throws UnsupportedRuntimeException {\r
159                 boolean succeed = false;\r
160                 for (Preset<T> preset : presets) {\r
161                         writer.print("Aligning with preset '" + preset.getName() + "'... ");\r
162                         Alignment al = null;\r
163                         try {\r
164                                 String taskId = msaws.presetAlign(seqs, preset);\r
165                                 al = msaws.getResult(taskId);\r
166                                 if (al != null) {\r
167                                         writer.println(OK);\r
168                                 }\r
169                                 succeed = true;\r
170                         } catch (Exception e) {\r
171                                 if (e instanceof UnsupportedRuntimeException) {\r
172                                         // If executable is not supported than none of the presets\r
173                                         // are\r
174                                         // going to work\r
175                                         throw (UnsupportedRuntimeException) e;\r
176                                 } else {\r
177                                         reportException(e);\r
178                                 }\r
179                                 continue;\r
180                         }\r
181                 }\r
182                 return succeed;\r
183         }\r
184 \r
185         private <T> boolean testMsaWS(MsaWS<T> msaws)\r
186                         throws UnsupportedRuntimeException {\r
187                 assert msaws != null;\r
188 \r
189                 boolean succeed = testDefaultAlignment(msaws);\r
190                 // If exception above is thrown than the tests below is not run\r
191 \r
192                 PresetManager<T> pmanager = msaws.getPresets();\r
193                 if (pmanager != null && pmanager.getPresets().size() > 0) {\r
194                         writer.println("Testing alignment with presets:");\r
195                         List<Preset<T>> plist = pmanager.getPresets();\r
196                         succeed = !succeed ? presetAlign(msaws, plist) : succeed;\r
197                 }\r
198                 testMetadata(msaws);\r
199                 return succeed;\r
200         }\r
201         /**\r
202          * Call most of web services functions and check the output\r
203          * \r
204          * @param <T>\r
205          *            web service type\r
206          * @param msaws\r
207          * @throws UnsupportedRuntimeException\r
208          *             is thrown if the connection to a web service was made, but\r
209          *             the web service is not functional. e.g. when native\r
210          *             executable does not exists for a server platform\r
211          */\r
212         @SuppressWarnings("unchecked")\r
213         private <T> boolean checkService(JABAService wservice) {\r
214                 try {\r
215                         if (wservice == null) {\r
216                                 throw new NullPointerException(\r
217                                                 "JABAService instance must be provided!");\r
218                         }\r
219 \r
220                         if (wservice instanceof MsaWS) {\r
221                                 return testMsaWS((MsaWS<T>) wservice);\r
222                         } else if (wservice instanceof SequenceAnnotation) {\r
223                                 return testSequenceAnnotationWS((SequenceAnnotation<T>) wservice);\r
224                         } else {\r
225                                 throw new UnsupportedOperationException("The service: "\r
226                                                 + wservice.getClass() + " is not supported! ");\r
227                         }\r
228                 } catch (UnsupportedRuntimeException e) {\r
229                         reportException(e);\r
230                         return false;\r
231                 }\r
232         }\r
233 \r
234         private <T> boolean testSequenceAnnotationWS(SequenceAnnotation<T> wservice)\r
235                         throws UnsupportedRuntimeException {\r
236                 writer.print("Calling analyse.........");\r
237                 boolean success = testDefaultAnalyse(loadAlignment(), wservice, null,\r
238                                 null);\r
239 \r
240                 PresetManager<T> presetman = wservice.getPresets();\r
241                 if (presetman != null) {\r
242                         List<Preset<T>> presets = presetman.getPresets();\r
243                         if (presets != null && !presets.isEmpty()) {\r
244                                 Preset<T> preset = presets.get(0);\r
245                                 writer.print("Calling analyse with Preset.........");\r
246                                 success = testDefaultAnalyse(loadAlignment(), wservice, preset,\r
247                                                 null);\r
248                         }\r
249                 }\r
250                 testMetadata(wservice);\r
251                 return success;\r
252         }\r
253 \r
254         private <T> boolean testDefaultAnalyse(List<FastaSequence> fastalist,\r
255                         SequenceAnnotation<T> wsproxy, Preset<T> preset,\r
256                         List<Option<T>> customOptions) throws UnsupportedRuntimeException {\r
257 \r
258                 ScoreManager scores = null;\r
259                 try {\r
260                         String jobId = null;\r
261                         if (customOptions != null) {\r
262                                 jobId = wsproxy.customAnalize(fastalist, customOptions);\r
263                         } else if (preset != null) {\r
264                                 jobId = wsproxy.presetAnalize(fastalist, preset);\r
265                         } else {\r
266                                 jobId = wsproxy.analize(fastalist);\r
267                         }\r
268                         Thread.sleep(1000);\r
269                         scores = wsproxy.getAnnotation(jobId);\r
270                         if (scores != null) {\r
271                                 writer.println(OK);\r
272                         }\r
273                 } catch (Exception e) {\r
274                         if (e instanceof UnsupportedRuntimeException) {\r
275                                 throw (UnsupportedRuntimeException) e;\r
276                         } else {\r
277                                 reportException(e);\r
278                         }\r
279                 }\r
280                 return scores != null;\r
281         }\r
282 \r
283         private void reportException(Exception e) {\r
284                 writer.println(FAILED);\r
285                 writer.println("Exception while waiting for results. "\r
286                                 + "Exception details are below:");\r
287                 writer.println(e.getLocalizedMessage());\r
288                 e.printStackTrace(writer);\r
289         }\r
290 \r
291         private <T> void testMetadata(Metadata<T> msaws)\r
292                         throws UnsupportedRuntimeException {\r
293 \r
294                 writer.print("Querying presets...");\r
295                 PresetManager<T> pmanager = msaws.getPresets();\r
296                 if (pmanager != null && pmanager.getPresets().size() > 0) {\r
297                         writer.println(OK);\r
298                 } else {\r
299                         writer.println(UNSUPPORTED);\r
300                 }\r
301 \r
302                 writer.print("Querying Parameters...");\r
303                 RunnerConfig<T> options = msaws.getRunnerOptions();\r
304                 if (options != null && options.getArguments().size() > 0) {\r
305                         writer.println(OK);\r
306                 } else {\r
307                         writer.println(UNSUPPORTED);\r
308                 }\r
309 \r
310                 writer.print("Querying Limits...");\r
311                 LimitsManager<T> limits = msaws.getLimits();\r
312                 if (limits != null && limits.getLimits().size() > 0) {\r
313                         writer.println(OK);\r
314                 } else {\r
315                         writer.println(UNSUPPORTED);\r
316                 }\r
317 \r
318                 writer.print("Querying Local Engine Limits...");\r
319                 Limit<T> localLimit = msaws\r
320                                 .getLimit(PresetManager.LOCAL_ENGINE_LIMIT_PRESET);\r
321                 if (localLimit != null) {\r
322                         writer.println(OK);\r
323                 } else {\r
324                         writer.println(UNSUPPORTED);\r
325                 }\r
326         }\r
327 \r
328         /**\r
329          * Align using default settings\r
330          * \r
331          * @param <T>\r
332          * @param msaws\r
333          * @throws UnsupportedRuntimeException\r
334          */\r
335         private <T> boolean testDefaultAlignment(MsaWS<T> msaws)\r
336                         throws UnsupportedRuntimeException {\r
337                 writer.print("Testing alignment with default parameters:");\r
338                 Alignment al = null;\r
339                 boolean succeed = false;\r
340                 try {\r
341                         String taskId = msaws.align(seqs);\r
342                         writer.print("\nQuerying job status...");\r
343                         JobStatus status = msaws.getJobStatus(taskId);\r
344                         while (status != JobStatus.FINISHED) {\r
345                                 Thread.sleep(1000);\r
346                                 status = msaws.getJobStatus(taskId);\r
347                         }\r
348                         writer.println(OK);\r
349                         writer.print("Retrieving results...");\r
350                         al = msaws.getResult(taskId);\r
351                         succeed = true;\r
352                 } catch (Exception e) {\r
353                         if (e instanceof UnsupportedRuntimeException) {\r
354                                 throw (UnsupportedRuntimeException) e;\r
355                         } else {\r
356                                 reportException(e);\r
357                         }\r
358                 }\r
359                 if (al != null) {\r
360                         writer.println(OK);\r
361                 }\r
362                 return succeed;\r
363         }\r
364         /**\r
365          * Test JWS2 web services\r
366          * \r
367          * @param <T>\r
368          *            web service type\r
369          * @param args\r
370          *            -h=<Your web application server host name, port and JWS2\r
371          *            context path>\r
372          * \r
373          *            -s=<ServiceName> which is optional. If service name is not\r
374          *            provided then all known JWS2 web services are tested\r
375          * @throws IOException\r
376          */\r
377         public static <T> void main(String[] args) throws IOException {\r
378 \r
379                 if (args == null || args.length < 1) {\r
380                         WSTester.printUsage();\r
381                         System.exit(0);\r
382                 }\r
383                 String host = CmdHelper.getHost(args);\r
384                 String serviceName = CmdHelper.getServiceName(args);\r
385                 if (!Jws2Client.validURL(host)) {\r
386                         System.err\r
387                                         .println("<host_and_context> parameter is not provided or is incorrect!");\r
388                         System.exit(1);\r
389                 }\r
390                 WSTester tester = new WSTester(host, new PrintWriter(System.out, true));\r
391 \r
392                 if (serviceName != null) {\r
393                         Services service = Services.getService(serviceName);\r
394                         if (service == null) {\r
395                                 tester.writer.println("Service '" + serviceName\r
396                                                 + "' is not supported. Valid values are: "\r
397                                                 + Arrays.toString(Services.values()));\r
398                                 tester.writer.println();\r
399                                 printUsage();\r
400                                 System.exit(1);\r
401                         }\r
402                         tester.checkService(service);\r
403                         System.exit(0);\r
404                 }\r
405 \r
406                 tester.writer\r
407                                 .println("<ServiceName> is not provided checking all known services...");\r
408 \r
409                 for (Services serv : Services.values()) {\r
410                         tester.writer.println();\r
411                         tester.checkService(serv);\r
412                 }\r
413 \r
414         }\r
415 \r
416         public boolean checkService(Services service) {\r
417                 JABAService ws = Jws2Client.connect(hostname, service);\r
418                 if (ws == null) {\r
419                         writer.println("Cannot estabilish the connection to host "\r
420                                         + hostname + " with service " + service.toString());\r
421                         return false;\r
422                 }\r
423                 boolean succeed = false;\r
424                 try {\r
425                         writer.println("Checking service " + service.toString());\r
426                         succeed = checkService(ws);\r
427                 } finally {\r
428                         FileUtil.closeSilently(((Closeable) ws));\r
429                 }\r
430                 reportResults(service, succeed);\r
431                 return succeed;\r
432         }\r
433 \r
434         private void reportResults(Services serv, boolean succeed) {\r
435                 if (succeed) {\r
436                         writer.println("Check is completed. The Service " + serv\r
437                                         + " IS WORKING\n");\r
438                 } else {\r
439                         writer.println("Check is completed. The Service " + serv\r
440                                         + " HAS SOME PROBLEMS\n");\r
441                 }\r
442         }\r
443 }\r