1 /* Copyright (c) 2011 Peter Troshin
\r
2 * Copyright (c) 2013 Alexander Sherstnev
\r
4 * JAva Bioinformatics Analysis Web Services (JABAWS) @version: 2.0
\r
6 * This library is free software; you can redistribute it and/or modify it under the terms of the
\r
7 * Apache License version 2 as published by the Apache Software Foundation
\r
9 * This library is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without
\r
10 * even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the Apache
\r
11 * License for more details.
\r
13 * A copy of the license is in apache_license.txt. It is also available here:
\r
14 * @see: http://www.apache.org/licenses/LICENSE-2.0.txt
\r
16 * Any republication or derived work distributed in source code form
\r
17 * must include this copyright and license notice.
\r
20 package compbio.ws.client;
\r
22 import static compbio.ws.client.Constraints.hostkey;
\r
23 import static compbio.ws.client.Constraints.pseparator;
\r
24 import static compbio.ws.client.Constraints.servicekey;
\r
26 import java.io.ByteArrayInputStream;
\r
27 import java.io.Closeable;
\r
28 import java.io.IOException;
\r
29 import java.io.PrintWriter;
\r
30 import java.net.ConnectException;
\r
31 import java.net.MalformedURLException;
\r
32 import java.net.URL;
\r
33 import java.util.Arrays;
\r
34 import java.util.List;
\r
35 import java.util.logging.Level;
\r
37 import javax.xml.ws.Service;
\r
38 import javax.xml.ws.WebServiceException;
\r
40 import compbio.data.msa.JABAService;
\r
41 import compbio.data.msa.Metadata;
\r
42 import compbio.data.msa.MsaWS;
\r
43 import compbio.data.msa.SequenceAnnotation;
\r
44 import compbio.data.sequence.Alignment;
\r
45 import compbio.data.sequence.FastaSequence;
\r
46 import compbio.data.sequence.ScoreManager;
\r
47 import compbio.data.sequence.SequenceUtil;
\r
48 import compbio.metadata.JobStatus;
\r
49 import compbio.metadata.Limit;
\r
50 import compbio.metadata.LimitsManager;
\r
51 import compbio.metadata.Option;
\r
52 import compbio.metadata.Preset;
\r
53 import compbio.metadata.PresetManager;
\r
54 import compbio.metadata.RunnerConfig;
\r
55 import compbio.metadata.UnsupportedRuntimeException;
\r
56 import compbio.util.FileUtil;
\r
57 import compbio.util.Util;
\r
60 * Class for testing web services
\r
64 * @version 1.5 February 2013
\r
66 public class WSTester {
\r
69 * Test sequences to be used as input for WS
\r
71 public static final String fastaInput2records =
\r
72 ">Foo\nMTADGPRELLQLRAAVRHRPQDFVAWLMLADAELGMGDTTAGEMAVQRGLALHPGHPEAV\n"
\r
73 + ">Bar\nASDAAPEHPGIALWLHALEDAGQAEAAAAYTRAHQLLPEEPYITAQLLNAVA\n";
\r
74 public static final String fastaInput1record =
\r
75 ">Foo\nMTADGPRELLQLRAAVRHRPQDFVAWLMLADAELGMGDTTAGEMAVQRGLALHPGHPEAV\n";
\r
76 public static final String fastaAlignment =
\r
77 ">Foo\nMTADGPRELLQLRAAVRHRPQDFVAWLMLADAELGMGDTTAGEMAVQRGLALHPGHPEAV--------\n"
\r
78 + ">Bar\nASDAAPEH------------PGIALWLHALE-DAGQAEAAA---AYTRAHQLLPEEPYITAQLLNAVA\n";
\r
79 public static final String fastaRNAAlignment =
\r
80 ">Foo\nC-UUGCGUUAAUGAGAACAGAAACG-UAAA--CUAUAA-CCUAG-G-GGUUUCUGUUGGAUGGUUG----GCAAC\n"
\r
81 + ">Bar\nG-UGGCGCUUAUGACGCAGUUGUCU-UAAA-CUCGAAC--UCGA-GCGGGCAAUUGCUGAU-UACGAUUAACCAC\n";
\r
83 public static final String clustalRNAAlignment =
\r
85 "Foo C-UUGCGUUAAUGAGAACAGAAACG-UAAA--CUAUAA-CCUAG-G-GGUUUCUGUUGGA\n" +
\r
86 "Bar G-UGGCGCUUAUGACGCAGUUGUCU-UAAA-CUCGAAC--UCGA-GCGGGCAAUUGCUGA\n" +
\r
87 "Foo UGGUUG----GCAAC\n" +
\r
88 "Bar U-UACGAUUAACCAC";
\r
92 private static final String FAILED = "FAILED";
\r
93 private static final String OK = "OK";
\r
94 private static final String UNSUPPORTED = "UNSUPPORTED";
\r
97 * Converting input to a form accepted by WS
\r
99 * @return List of FastaSequence records
\r
101 private static List<FastaSequence> loadSeqs(int nLines) {
\r
104 return SequenceUtil.readFasta(new ByteArrayInputStream(fastaInput1record.getBytes()));
\r
106 return SequenceUtil.readFasta(new ByteArrayInputStream(fastaInput2records.getBytes()));
\r
107 } catch (IOException ignored) {
\r
108 // Should not happen as a source is not a external stream
\r
109 ignored.printStackTrace();
\r
115 * Converting input to a form accepted by WS
\r
117 * @return List of FastaSequence records
\r
119 private static List<FastaSequence> loadAlignment() {
\r
121 return SequenceUtil.readFasta(new ByteArrayInputStream(
\r
122 fastaAlignment.getBytes()));
\r
123 } catch (IOException ignored) {
\r
124 // Should not happen as a source is not a external stream
\r
125 ignored.printStackTrace();
\r
130 * Converting input to a form accepted by WS
\r
132 * @return List of FastaSequence records with aligned RNA sequences
\r
134 private static List<FastaSequence> loadRNAAlignment() {
\r
136 return SequenceUtil.readFasta(new ByteArrayInputStream(fastaRNAAlignment.getBytes()));
\r
137 } catch (IOException ignored) {
\r
138 // Should not happen as a source is not a external stream
\r
139 ignored.printStackTrace();
\r
144 private final PrintWriter writer;
\r
145 private final String hostname;
\r
148 * Construct an instance of JABAWS tester
\r
151 * - fully qualified host and context name of JABAWS e.g.
\r
152 * http://nanna.cluster.lifesci.dundee.ac.uk:8080/jaba
\r
154 * a PrintWriter instance to writer test log to.
\r
156 public WSTester(String hostname, PrintWriter writer) {
\r
157 if (Util.isEmpty(hostname)) {
\r
158 throw new NullPointerException("Hostname must be provided!");
\r
160 this.hostname = hostname;
\r
161 this.writer = writer;
\r
167 static void printUsage() {
\r
168 System.out.println("Usage: <Class or Jar file name> " + hostkey
\r
169 + pseparator + "host_and_context " + "<" + servicekey
\r
170 + pseparator + "serviceName>");
\r
171 System.out.println();
\r
172 System.out.println(hostkey
\r
174 + "<host_and_context> - a full URL to the JABAWS web server including context path e.g. http://10.31.1.159:8080/ws");
\r
175 System.out.println(servicekey
\r
177 + "<ServiceName> - optional if unspecified all services are tested otherwise one of "
\r
178 + Arrays.toString(Services.values()));
\r
179 System.out.println();
\r
184 * Calls alignment with preset
\r
189 * list of the Preset
\r
190 * @throws UnsupportedRuntimeException
\r
192 private <T> boolean presetAlign(MsaWS<T> msaws, List<Preset<T>> presets)
\r
193 throws UnsupportedRuntimeException {
\r
194 boolean succeed = false;
\r
195 for (Preset<T> preset : presets) {
\r
196 writer.print("Aligning with preset '" + preset.getName() + "'... ");
\r
197 Alignment al = null;
\r
199 String taskId = msaws.presetAlign(loadSeqs(2), preset);
\r
200 al = msaws.getResult(taskId);
\r
202 writer.println(OK);
\r
205 } catch (Exception e) {
\r
206 if (e instanceof UnsupportedRuntimeException) {
\r
207 // If executable is not supported than none of the presets
\r
210 throw (UnsupportedRuntimeException) e;
\r
212 reportException(e);
\r
220 private <T> boolean testMsaWS(MsaWS<T> msaws, Services service) throws Exception {
\r
221 assert msaws != null;
\r
223 boolean succeed = testDefaultAlignment(msaws, service);
\r
224 // If exception above is thrown than the tests below is not run
\r
226 PresetManager<T> pmanager = msaws.getPresets();
\r
227 if (pmanager != null && pmanager.getPresets().size() > 0) {
\r
228 writer.println("Testing alignment with presets:");
\r
229 List<Preset<T>> plist = pmanager.getPresets();
\r
230 succeed = !succeed ? presetAlign(msaws, plist) : succeed;
\r
232 testMetadata(msaws);
\r
236 * Call most of web services functions and check the output
\r
241 * @throws UnsupportedRuntimeException
\r
242 * is thrown if the connection to a web service was made, but
\r
243 * the web service is not functional. e.g. when native
\r
244 * executable does not exists for a server platform
\r
246 @SuppressWarnings("unchecked")
\r
247 private <T> boolean checkService(JABAService wservice, Services service) {
\r
249 if (wservice == null) {
\r
250 throw new NullPointerException("JABAService instance must be provided!");
\r
253 if (wservice instanceof MsaWS) {
\r
254 return testMsaWS((MsaWS<T>) wservice, service);
\r
255 } else if (wservice instanceof SequenceAnnotation) {
\r
256 return testSequenceAnnotationWS(
\r
257 (SequenceAnnotation<T>) wservice, service);
\r
259 throw new UnsupportedOperationException("The service: " + wservice.getClass() + " is not supported! ");
\r
261 } catch (Exception e) {
\r
262 reportException(e);
\r
267 private <T> boolean testSequenceAnnotationWS(
\r
268 SequenceAnnotation<T> wservice, Services service) throws Exception {
\r
269 writer.print("Calling annotation test.........");
\r
271 List<FastaSequence> input = loadSeqs(2);
\r
272 if (service == Services.AAConWS ) {
\r
273 input = loadAlignment();
\r
274 } else if (service == Services.RNAalifoldWS) {
\r
275 input = loadRNAAlignment();
\r
277 boolean success = testDefaultAnalyse(input, wservice, null, null);
\r
279 PresetManager<T> presetman = wservice.getPresets();
\r
280 if (presetman != null) {
\r
281 List<Preset<T>> presets = presetman.getPresets();
\r
282 if (presets != null && !presets.isEmpty()) {
\r
283 Preset<T> preset = presets.get(0);
\r
284 writer.print("Calling analyse with Preset.........");
\r
285 success = testDefaultAnalyse(input, wservice, preset, null);
\r
288 testMetadata(wservice);
\r
292 private <T> boolean testDefaultAnalyse(List<FastaSequence> fastalist,
\r
293 SequenceAnnotation<T> wsproxy, Preset<T> preset,
\r
294 List<Option<T>> customOptions) throws Exception {
\r
296 ScoreManager scores = null;
\r
298 String jobId = null;
\r
299 if (customOptions != null) {
\r
300 jobId = wsproxy.customAnalize(fastalist, customOptions);
\r
301 } else if (preset != null) {
\r
302 jobId = wsproxy.presetAnalize(fastalist, preset);
\r
304 jobId = wsproxy.analize(fastalist);
\r
306 Thread.sleep(1000);
\r
307 scores = wsproxy.getAnnotation(jobId);
\r
308 if (scores != null) {
\r
309 writer.println(OK);
\r
312 return scores != null;
\r
315 private void reportException(Exception e) {
\r
316 writer.println(FAILED);
\r
317 writer.println("Exception while waiting for results. Exception details are below:");
\r
318 writer.println(e.getLocalizedMessage());
\r
319 e.printStackTrace(writer);
\r
322 private <T> void testMetadata(Metadata<T> msaws)
\r
323 throws UnsupportedRuntimeException {
\r
325 writer.print("Querying presets...");
\r
326 PresetManager<T> pmanager = msaws.getPresets();
\r
327 if (pmanager != null && pmanager.getPresets().size() > 0) {
\r
328 writer.println(OK);
\r
330 writer.println(UNSUPPORTED);
\r
333 writer.print("Querying Parameters...");
\r
334 RunnerConfig<T> options = msaws.getRunnerOptions();
\r
335 if (options != null && options.getArguments().size() > 0) {
\r
336 writer.println(OK);
\r
338 writer.println(UNSUPPORTED);
\r
341 writer.print("Querying Limits...");
\r
342 LimitsManager<T> limits = msaws.getLimits();
\r
343 if (limits != null && limits.getLimits().size() > 0) {
\r
344 writer.println(OK);
\r
345 // writer.println("Limits details: \n" + limits.toString());
\r
347 writer.println(UNSUPPORTED);
\r
350 writer.print("Querying Local Engine Limits...");
\r
351 Limit<T> localLimit = msaws
\r
352 .getLimit(PresetManager.LOCAL_ENGINE_LIMIT_PRESET);
\r
353 if (localLimit != null) {
\r
354 writer.println(OK);
\r
356 writer.println(UNSUPPORTED);
\r
361 * Align using default settings
\r
365 * @throws UnsupportedRuntimeException
\r
367 private <T> boolean testDefaultAlignment(MsaWS<T> msaws, Services service) throws Exception {
\r
368 writer.print("Testing alignment with default parameters:");
\r
369 Alignment al = null;
\r
370 boolean succeed = false;
\r
373 if (service == Services.JpredWS) {
\r
374 taskId = msaws.align(loadAlignment());
\r
376 taskId = msaws.align(loadSeqs(2));
\r
378 writer.print("\nQuerying job status...");
\r
379 JobStatus status = msaws.getJobStatus(taskId);
\r
380 while (status != JobStatus.FINISHED) {
\r
381 Thread.sleep(1000);
\r
382 status = msaws.getJobStatus(taskId);
\r
384 writer.println(OK);
\r
385 writer.print("Retrieving results...");
\r
386 al = msaws.getResult(taskId);
\r
389 writer.println(OK);
\r
394 * Test JWS2 web services
\r
399 * -h=<Your web application server host name, port and JWS2
\r
402 * -s=<ServiceName> which is optional. If service name is not
\r
403 * provided then all known JWS2 web services are tested
\r
404 * @throws IOException
\r
406 public static <T> void main(String[] args) throws IOException {
\r
408 if (args == null || args.length < 1) {
\r
409 WSTester.printUsage();
\r
412 String host = CmdHelper.getHost(args);
\r
413 String serviceName = CmdHelper.getServiceName(args);
\r
414 if (!Jws2Client.validURL(host)) {
\r
415 System.err.println("<host_and_context> parameter is not provided or is incorrect!");
\r
418 WSTester tester = new WSTester(host, new PrintWriter(System.out, true));
\r
420 if (serviceName != null) {
\r
421 Services service = Services.getService(serviceName);
\r
422 if (service == null) {
\r
423 tester.writer.println("Service '" + serviceName + "' is not supported. Valid values are: "
\r
424 + Arrays.toString(Services.values()));
\r
425 tester.writer.println();
\r
429 tester.checkService(service);
\r
433 tester.writer.println("<ServiceName> is not provided checking all known services...");
\r
435 for (Services serv : Services.values()) {
\r
436 tester.writer.println();
\r
437 tester.checkService(serv);
\r
443 * Connects to a web service by the host and the service name web service type
\r
446 * the fully qualified name of JABAWS server including JABAWS
\r
448 * http://nanna.cluster.lifesci.dundee.ac.uk:8080/jaba
\r
450 * the name of the JABAWS service to connect to
\r
451 * @return JABAService<T>
\r
452 * @throws WebServiceException
\r
453 * @throws ConnectException
\r
454 * if fails to connect to the service on the host
\r
456 private JABAService connect(String host, Services service)
\r
457 throws WebServiceException, ConnectException {
\r
459 System.out.println ("Attempting to connect with " + service.toString() + "...");
\r
461 url = new URL(host + "/" + service.toString() + "?wsdl");
\r
462 System.out.println ("URL: " + url.toString());
\r
463 } catch (MalformedURLException e) {
\r
464 e.printStackTrace();
\r
466 Service serv = null;
\r
468 serv = service.getService(url, service.getServiceNamespace());
\r
469 } catch (WebServiceException wse) {
\r
470 wse.printStackTrace();
\r
472 if (serv == null) {
\r
473 throw new ConnectException("Could not connect to " + url + ". Is the server down?");
\r
475 JABAService srv = service.getInterface(serv);
\r
476 System.out.println ("Connected successfully!");
\r
481 * Test JABA web service
\r
484 * the service to test
\r
485 * @return true if the service works as expected, false otherwise
\r
486 * @throws WebServiceException
\r
487 * @throws ConnectException
\r
489 public boolean checkService(Services service) throws ConnectException,
\r
490 WebServiceException {
\r
491 JABAService ws = connect(hostname, service);
\r
493 String line = "Cannot estabilish the connection to host " + hostname + " with service ";
\r
494 writer.println(line + service.toString());
\r
497 boolean succeed = false;
\r
499 writer.println("Checking service " + service.toString());
\r
500 succeed = checkService(ws, service);
\r
502 FileUtil.closeSilently(((Closeable) ws));
\r
504 reportResults(service, succeed);
\r
508 private void reportResults(Services serv, boolean succeed) {
\r
510 writer.println("Check is completed. The Service " + serv + " IS WORKING\n");
\r
512 writer.println("Check is aborted. The Service " + serv + " HAS SOME PROBLEMS\n");
\r