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