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