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