Adding registry web service and changes to WStester and JWS2Client code. Bugs in...
[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 javax.xml.ws.WebServiceException;\r
33 \r
34 import org.apache.log4j.Logger;\r
35 \r
36 import compbio.data.msa.JABAService;\r
37 import compbio.data.msa.Metadata;\r
38 import compbio.data.msa.MsaWS;\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.ScoreManager;\r
43 import compbio.data.sequence.SequenceUtil;\r
44 import compbio.metadata.JobStatus;\r
45 import compbio.metadata.JobSubmissionException;\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.ResultNotAvailableException;\r
52 import compbio.metadata.RunnerConfig;\r
53 import compbio.metadata.UnsupportedRuntimeException;\r
54 import compbio.metadata.WrongParameterException;\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         private static Logger log = Logger.getLogger(WSTester.class);\r
66         /**\r
67          * Sequences to be used as input for all WS\r
68          */\r
69         static final String fastaInput = ">Foo\n"\r
70                         + "MTADGPRELLQLRAAVRHRPQDFVAWLMLADAELGMGDTTAGEMAVQRGLALHPGHPEAV"\r
71                         + "\n>Bar\n"\r
72                         + "ASDAAPEHPGIALWLHALEDAGQAEAAAAYTRAHQLLPEEPYITAQLLNAVA";\r
73 \r
74         static final String fastaAlignment = ">Foo\r\n"\r
75                         + "MTADGPRELLQLRAAVRHRPQDFVAWLMLADAELGMGDTTAGEMAVQRGLALHPGHPEAV--------\r\n"\r
76                         + ">Bar\r\n"\r
77                         + "ASDAAPEH------------PGIALWLHALE-DAGQAEAAA---AYTRAHQLLPEEPYITAQLLNAVA\r\n"\r
78                         + "";\r
79 \r
80         static final List<FastaSequence> seqs = loadSeqs();\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         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\r
107          */\r
108         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         private final PrintWriter writer;\r
120 \r
121         public WSTester(PrintWriter writer) {\r
122                 this.writer = writer;\r
123         }\r
124 \r
125         /**\r
126          * Prints usage\r
127          */\r
128         void printUsage() {\r
129                 writer.println("Usage: <Class or Jar file name> " + hostkey\r
130                                 + pseparator + "host_and_context " + "<" + servicekey\r
131                                 + pseparator + "serviceName>");\r
132                 writer.println();\r
133                 writer.println(hostkey\r
134                                 + pseparator\r
135                                 + "<host_and_context> - a full URL to the JABAWS web server including context path e.g. http://10.31.1.159:8080/ws");\r
136                 writer.println(servicekey\r
137                                 + pseparator\r
138                                 + "<ServiceName> - optional if unspecified all services are tested otherwise one of "\r
139                                 + Arrays.toString(Services.values()));\r
140                 writer.println();\r
141 \r
142         }\r
143 \r
144         /**\r
145          * Calls alignment with preset\r
146          * \r
147          * @param <T>\r
148          * @param msaws\r
149          * @param presets\r
150          *            list of the Preset\r
151          * @throws UnsupportedRuntimeException\r
152          */\r
153         <T> boolean presetAlign(MsaWS<T> msaws, List<Preset<T>> presets)\r
154                         throws UnsupportedRuntimeException {\r
155                 boolean succeed = false;\r
156                 for (Preset<T> preset : presets) {\r
157                         writer.print("Aligning with preset '" + preset.getName() + "'... ");\r
158                         Alignment al = null;\r
159                         try {\r
160                                 String taskId = msaws.presetAlign(seqs, preset);\r
161                                 al = msaws.getResult(taskId);\r
162                                 if (al != null) {\r
163                                         writer.println(OK);\r
164                                 }\r
165                                 succeed = true;\r
166                         } catch (UnsupportedRuntimeException e) {\r
167                                 writer.println(FAILED);\r
168                                 // If executable is not supported than none of the presets are\r
169                                 // going to work\r
170                                 throw new UnsupportedRuntimeException(e);\r
171                         } catch (JobSubmissionException e) {\r
172                                 // TODO custom message\r
173                                 writer.println(FAILED);\r
174                                 writer.println();\r
175                                 writer.println(e.getLocalizedMessage());\r
176                                 e.printStackTrace(writer);\r
177                                 continue;\r
178                         } catch (WrongParameterException e) {\r
179                                 // TODO custom message\r
180                                 writer.println(FAILED);\r
181                                 writer.println();\r
182                                 writer.println(e.getLocalizedMessage());\r
183                                 e.printStackTrace(writer);\r
184                                 continue;\r
185                         } catch (ResultNotAvailableException e) {\r
186                                 // TODO custom message\r
187                                 writer.println(FAILED);\r
188                                 writer.println();\r
189                                 writer.println(e.getLocalizedMessage());\r
190                                 e.printStackTrace(writer);\r
191                                 continue;\r
192                         }\r
193                 }\r
194                 return succeed;\r
195         }\r
196 \r
197         private <T> boolean testMsaWS(MsaWS<T> msaws)\r
198                         throws UnsupportedRuntimeException {\r
199 \r
200                 boolean succeed = testDefaultAlignment(msaws);\r
201 \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          * Call most of web services functions and check the output\r
215          * \r
216          * @param <T>\r
217          *            web service type\r
218          * @param msaws\r
219          * @throws UnsupportedRuntimeException\r
220          *             is thrown if the connection to a web service was made, but\r
221          *             the web service is not functional. e.g. when native\r
222          *             executable does not exists for a server platform\r
223          */\r
224         @SuppressWarnings("unchecked")\r
225         public <T> boolean checkService(JABAService wservice) {\r
226                 try {\r
227                         if (wservice == null) {\r
228                                 throw new NullPointerException(\r
229                                                 "JABAService instance must be provided!");\r
230                         }\r
231                         if (wservice instanceof MsaWS) {\r
232                                 return testMsaWS((MsaWS<T>) wservice);\r
233                         } else if (wservice instanceof SequenceAnnotation) {\r
234                                 return testSequenceAnnotationWS((SequenceAnnotation<T>) wservice);\r
235                         } else {\r
236                                 throw new UnsupportedOperationException("The service: "\r
237                                                 + wservice.getClass() + " is not supported! ");\r
238                         }\r
239                 } catch (UnsupportedRuntimeException e) {\r
240                         writer.println(e.getLocalizedMessage());\r
241                         e.printStackTrace(writer);\r
242                         return false;\r
243                 }\r
244         }\r
245 \r
246         private <T> boolean testSequenceAnnotationWS(SequenceAnnotation<T> wservice)\r
247                         throws UnsupportedRuntimeException {\r
248                 boolean success = testDefaultAnalyse(loadAlignment(), wservice, null,\r
249                                 null);\r
250                 PresetManager<T> presetman = wservice.getPresets();\r
251                 if (presetman != null) {\r
252                         List<Preset<T>> presets = presetman.getPresets();\r
253                         if (presets != null && !presets.isEmpty()) {\r
254                                 Preset<T> preset = presets.get(0);\r
255                                 success = testDefaultAnalyse(loadAlignment(), wservice, preset,\r
256                                                 null);\r
257                         }\r
258                 }\r
259                 testMetadata(wservice);\r
260                 return success;\r
261         }\r
262 \r
263         <T> boolean testDefaultAnalyse(List<FastaSequence> fastalist,\r
264                         SequenceAnnotation<T> wsproxy, Preset<T> preset,\r
265                         List<Option<T>> customOptions) throws UnsupportedRuntimeException {\r
266 \r
267                 ScoreManager scores = null;\r
268                 try {\r
269                         String jobId = null;\r
270                         if (customOptions != null) {\r
271                                 jobId = wsproxy.customAnalize(fastalist, customOptions);\r
272                         } else if (preset != null) {\r
273                                 jobId = wsproxy.presetAnalize(fastalist, preset);\r
274                         } else {\r
275                                 jobId = wsproxy.analize(fastalist);\r
276                         }\r
277                         writer.println("\n\ncalling analise.........");\r
278                         Thread.sleep(1000);\r
279                         scores = wsproxy.getAnnotation(jobId);\r
280 \r
281                 } catch (JobSubmissionException e) {\r
282                         writer.println("Exception while submitting job to a web server. "\r
283                                         + "Exception details are below:");\r
284                         e.printStackTrace(writer);\r
285                 } catch (ResultNotAvailableException e) {\r
286                         writer.println("Exception while waiting for results. "\r
287                                         + "Exception details are below:");\r
288                         e.printStackTrace(writer);\r
289                 } catch (InterruptedException e) {\r
290                         // ignore and propagate an interruption\r
291                         Thread.currentThread().interrupt();\r
292                         writer.println("Exception while waiting for results. "\r
293                                         + "Exception details are below:");\r
294                         e.printStackTrace(writer);\r
295                 } catch (WrongParameterException e) {\r
296                         writer.println("Exception while parsing the web method input parameters. "\r
297                                         + "Exception details are below:");\r
298                         e.printStackTrace(writer);\r
299                 }\r
300                 return scores != null;\r
301         }\r
302 \r
303         private <T> void testMetadata(Metadata<T> msaws)\r
304                         throws UnsupportedRuntimeException {\r
305 \r
306                 writer.print("Querying presets...");\r
307                 PresetManager<T> pmanager = msaws.getPresets();\r
308                 if (pmanager != null && pmanager.getPresets().size() > 0) {\r
309                         writer.println(OK);\r
310                 } else {\r
311                         writer.println(UNSUPPORTED);\r
312                 }\r
313 \r
314                 writer.print("Querying Parameters...");\r
315                 RunnerConfig<T> options = msaws.getRunnerOptions();\r
316                 if (options != null && options.getArguments().size() > 0) {\r
317                         writer.println(OK);\r
318                 } else {\r
319                         writer.println(UNSUPPORTED);\r
320                 }\r
321 \r
322                 writer.print("Querying Limits...");\r
323                 LimitsManager<T> limits = msaws.getLimits();\r
324                 if (limits != null && limits.getLimits().size() > 0) {\r
325                         writer.println(OK);\r
326                 } else {\r
327                         writer.println(UNSUPPORTED);\r
328                 }\r
329 \r
330                 writer.print("Querying Local Engine Limits...");\r
331                 Limit<T> localLimit = msaws\r
332                                 .getLimit(PresetManager.LOCAL_ENGINE_LIMIT_PRESET);\r
333                 if (localLimit != null) {\r
334                         writer.println(OK);\r
335                 } else {\r
336                         writer.println(UNSUPPORTED);\r
337                 }\r
338         }\r
339 \r
340         /**\r
341          * Align using default settings\r
342          * \r
343          * @param <T>\r
344          * @param msaws\r
345          * @throws UnsupportedRuntimeException\r
346          */\r
347         public <T> boolean testDefaultAlignment(MsaWS<T> msaws)\r
348                         throws UnsupportedRuntimeException {\r
349                 writer.print("Testing alignment with default parameters:");\r
350                 Alignment al = null;\r
351                 boolean succeed = false;\r
352                 try {\r
353                         String taskId = msaws.align(seqs);\r
354                         writer.print("\nQuerying job status...");\r
355                         JobStatus status = msaws.getJobStatus(taskId);\r
356                         while (status != JobStatus.FINISHED) {\r
357                                 Thread.sleep(1000);\r
358                                 status = msaws.getJobStatus(taskId);\r
359                         }\r
360                         writer.println(OK);\r
361                         writer.print("Retrieving results...");\r
362                         al = msaws.getResult(taskId);\r
363                         succeed = true;\r
364                 } catch (ResultNotAvailableException e) {\r
365                         writer.println(FAILED);\r
366                         writer.println(e.getLocalizedMessage());\r
367                         e.printStackTrace(writer);\r
368                 } catch (JobSubmissionException e) {\r
369                         writer.println(FAILED);\r
370                         writer.println();\r
371                         writer.println(e.getLocalizedMessage());\r
372                         e.printStackTrace(writer);\r
373                 } catch (InterruptedException e) {\r
374                         writer.println(FAILED);\r
375                         writer.println();\r
376                         writer.println(e.getLocalizedMessage());\r
377                         e.printStackTrace(writer);\r
378                 }\r
379                 if (al != null) {\r
380                         writer.println(OK);\r
381                 }\r
382                 return succeed;\r
383         }\r
384 \r
385         /**\r
386          * Connect to a WS using the host and the service name\r
387          * \r
388          * @param <T>\r
389          * @param host\r
390          * @param service\r
391          * @return\r
392          */\r
393         <T> JABAService connect(String host, Services service) {\r
394                 JABAService jabaservice = null;\r
395                 try {\r
396                         writer.print("Connecting to service " + service + " on " + host\r
397                                         + " ... ");\r
398                         jabaservice = Jws2Client.connect(host, service);\r
399                         writer.println(OK);\r
400                 } catch (WebServiceException e) {\r
401                         writer.println(FAILED);\r
402                         writer.println(e.getLocalizedMessage());\r
403                         e.printStackTrace(writer);\r
404                 }\r
405                 return jabaservice;\r
406         }\r
407 \r
408         /**\r
409          * Test JWS2 web services\r
410          * \r
411          * @param <T>\r
412          *            web service type\r
413          * @param args\r
414          *            -h=<Your web application server host name, port and JWS2\r
415          *            context path>\r
416          * \r
417          *            -s=<ServiceName> which is optional. If service name is not\r
418          *            provided then all known JWS2 web services are tested\r
419          * @throws IOException\r
420          */\r
421         public static <T> void main(String[] args) throws IOException {\r
422                 WSTester tester = new WSTester(new PrintWriter(System.out, true));\r
423                 if (args == null || args.length < 1) {\r
424                         tester.printUsage();\r
425                         System.exit(0);\r
426                 }\r
427                 String host = CmdHelper.getHost(args);\r
428                 String serviceName = CmdHelper.getServiceName(args);\r
429                 if (!Jws2Client.validURL(host)) {\r
430                         tester.writer\r
431                                         .println("<host_and_context> parameter is not provided or is incorrect!");\r
432                         System.exit(1);\r
433                 }\r
434                 boolean succeed = false;\r
435                 MsaWS<T> msaws = null;\r
436                 if (serviceName != null) {\r
437                         Services service = Services.getService(serviceName);\r
438                         if (service == null) {\r
439                                 tester.writer.println("Service '" + serviceName\r
440                                                 + "' is not supported. Valid values are: "\r
441                                                 + Arrays.toString(Services.values()));\r
442                                 tester.writer.println();\r
443                                 tester.printUsage();\r
444                                 System.exit(1);\r
445                         }\r
446 \r
447                         msaws = (MsaWS<T>) tester.connect(host, service);\r
448                         if (msaws == null) {\r
449                                 System.exit(1);\r
450                         }\r
451                         try {\r
452                                 succeed = tester.checkService(msaws);\r
453                         } finally {\r
454                                 ((Closeable) msaws).close();\r
455                         }\r
456                         // TODO test results printing!\r
457                         tester.reportResults(service, succeed);\r
458                         System.exit(0);\r
459                 }\r
460 \r
461                 tester.writer\r
462                                 .println("<ServiceName> is not provided checking all known services...");\r
463 \r
464                 for (Services serv : Services.values()) {\r
465                         tester.writer.println();\r
466                         msaws = (MsaWS<T>) tester.connect(host, serv);\r
467                         if (msaws == null) {\r
468                                 continue;\r
469                         }\r
470                         try {\r
471                                 succeed = tester.checkService(msaws);\r
472                         } finally {\r
473                                 ((Closeable) msaws).close();\r
474                         }\r
475                         tester.reportResults(serv, succeed);\r
476                 }\r
477 \r
478         }\r
479         private void reportResults(Services serv, boolean succeed) {\r
480                 if (succeed) {\r
481                         writer.println("Check is completed. The Service " + serv\r
482                                         + " IS WORKING");\r
483                 } else {\r
484                         writer.println("Check is completed. The Service " + serv\r
485                                         + " HAS SOME PROBLEMS");\r
486                 }\r
487         }\r
488 }\r