/* Copyright (c) 2011 Peter Troshin * * JAva Bioinformatics Analysis Web Services (JABAWS) @version: 2.0 * * This library is free software; you can redistribute it and/or modify it under the terms of the * Apache License version 2 as published by the Apache Software Foundation * * This library is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without * even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the Apache * License for more details. * * A copy of the license is in apache_license.txt. It is also available here: * @see: http://www.apache.org/licenses/LICENSE-2.0.txt * * Any republication or derived work distributed in source code form * must include this copyright and license notice. */ package compbio.ws.client; import static compbio.ws.client.Constraints.inputkey; import static compbio.ws.client.Constraints.outputkey; import static compbio.ws.client.Constraints.paramFile; import java.io.Closeable; import java.io.File; import java.io.FileInputStream; import java.io.FileOutputStream; import java.io.IOException; import java.io.PrintWriter; import java.io.Writer; import java.net.ConnectException; import java.net.MalformedURLException; import java.net.URL; import java.util.Arrays; import java.util.Collections; import java.util.List; import java.util.Set; import java.util.logging.Level; import java.util.logging.Logger; import javax.xml.namespace.QName; import javax.xml.ws.Service; import javax.xml.ws.WebServiceException; import compbio.data.msa.JABAService; import compbio.data.msa.Metadata; import compbio.data.msa.MsaWS; import compbio.data.msa.RegistryWS; import compbio.data.msa.SequenceAnnotation; import compbio.data.sequence.Alignment; import compbio.data.sequence.AlignmentMetadata; import compbio.data.sequence.JpredAlignment; import compbio.data.sequence.FastaSequence; import compbio.data.sequence.ScoreManager; import compbio.data.sequence.SequenceUtil; import compbio.data.sequence.UnknownFileFormatException; import compbio.metadata.JobSubmissionException; import compbio.metadata.Option; import compbio.metadata.Preset; import compbio.metadata.ResultNotAvailableException; import compbio.metadata.WrongParameterException; import compbio.util.FileUtil; /** * A command line client for JAva Bioinformatics Analysis Web Services * * @author pvtroshin * @version 1.0 */ public class Jws2Client { /** * Use java.util.Logger instead of log4j logger to reduce the size of the client package */ private static final Logger log = Logger.getLogger(Jws2Client.class.getCanonicalName()); /** * Attempt to construct the URL object from the string * * @param urlstr * @return true if it succeed false otherwise */ public static boolean validURL(String urlstr) { try { if (urlstr == null || urlstr.trim().length() == 0) { return false; } new URL(urlstr); } catch (MalformedURLException e) { return false; } return true; } /** * Connects to the service and do the job as requested, if something goes * wrong reports or/and prints usage help. * * @param * web service type * @param cmd * command line options * @throws IOException */ @SuppressWarnings("unchecked") Jws2Client(String[] cmd) throws IOException { String hostname = CmdHelper.getHost(cmd); if (hostname == null) { System.err.println("Host name is not provided!"); System.out.println(Constraints.help_text); System.exit(1); } if (!validURL(hostname)) { System.err.println("Host name is not valid!"); System.out.println(Constraints.help_text); System.exit(1); } boolean listServices = CmdHelper.listServices(cmd); if (listServices) { listAllServices(hostname); System.exit(0); } String serviceName = CmdHelper.getServiceName(cmd); if (serviceName == null) { System.err.println("Service name is no provided!"); System.out.println(Constraints.help_text); System.exit(1); } Services service = Services.getService(serviceName); if (service == null) { String mess = "Service " + serviceName + " is no available! Valid values are: "; System.err.println(mess + Arrays.toString(Services.values())); System.out.println(Constraints.help_text); System.exit(1); } if (CmdHelper.testService(cmd)) { testService(hostname, service, new PrintWriter(System.out, true)); System.exit(0); } Metadata thews = (Metadata) connect(hostname, service); Preset preset = null; if (null != CmdHelper.getPresetName(cmd)) { preset = MetadataHelper.getPreset(thews, CmdHelper.getPresetName(cmd)); } List> customOptions = null; if (null != IOHelper.getFile(cmd, paramFile, true)) { List prms = IOHelper.loadParameters(IOHelper.getFile(cmd, paramFile, true)); customOptions = MetadataHelper.processParameters(prms, thews.getRunnerOptions()); } if (null != IOHelper.getFile(cmd, inputkey, true)) { File infile = IOHelper.getFile(cmd, inputkey, true); File outfile = IOHelper.getFile(cmd, outputkey, false); Writer writer = null; if (outfile != null) { writer = IOHelper.getWriter(outfile); } else { writer = new PrintWriter(System.out, true); } if (service.getServiceType() == SequenceAnnotation.class) { ScoreManager result = analize(infile, ((SequenceAnnotation) thews), preset, customOptions); IOHelper.writeOut(writer, result); writer.close(); } else if (service.getServiceType() == MsaWS.class) { Alignment alignment = align(infile, (MsaWS) thews, preset, customOptions); if (serviceName.equalsIgnoreCase("JpredWS")) { writer.close(); JpredAlignment jpred = (JpredAlignment)alignment; if (outfile != null) { FileOutputStream fout = new FileOutputStream(outfile); SequenceUtil.writeFastaKeepTheStream(fout, jpred.getJpredSequences(), 60); fout.close(); } else { SequenceUtil.writeFasta(System.out, jpred.getJpredSequences()); } } else { IOHelper.writeOut(writer, alignment); writer.close(); } AlignmentMetadata md = alignment.getMetadata(); System.out.println("Output has been prepared with " + md.getProgram()); } } if (CmdHelper.listParameters(cmd)) { System.out.println(MetadataHelper.getParametersList(thews)); } if (CmdHelper.listPresets(cmd)) { System.out.println(MetadataHelper.getPresetList(thews)); } if (CmdHelper.listLimits(cmd)) { System.out.println(MetadataHelper.getLimits(thews)); } log.fine("Disconnecting..."); ((Closeable) thews).close(); log.fine("Disconnected successfully!"); } /** * Connects to a web service by the host and the service name web service type * * @param host * the fully qualified name of JABAWS server including JABAWS * context name e.g * http://nanna.cluster.lifesci.dundee.ac.uk:8080/jaba * @param service * the name of the JABAWS service to connect to * @return JABAService * @throws WebServiceException * @throws ConnectException * if fails to connect to the service on the host */ public static JABAService connect(String host, Services service) throws WebServiceException, ConnectException { URL url = null; log.log(Level.FINE, "Attempting to connect with " + service.toString() + "..."); System.out.println ("Attempting to connect with " + service.toString() + "..."); try { url = new URL(host + "/" + service.toString() + "?wsdl"); } catch (MalformedURLException e) { e.printStackTrace(); // ignore as the host name is already verified } Service serv = null; try { serv = service.getService(url, service.getServiceNamespace()); } catch (WebServiceException wse) { wse.printStackTrace(); } if (serv == null) { throw new ConnectException("Could not connect to " + url + ". Is the server down?"); } JABAService serviceIF = service.getInterface(serv); log.log(Level.INFO, "Connected successfully!"); return serviceIF; } /** * Get a connection of JABAWS registry * * @param host * the fully qualified name of JABAWS server including JABAWS * context name e.g * http://nanna.cluster.lifesci.dundee.ac.uk:8080/jaba * @return compbio.data.msa.RegistryWS - instance of a RegistryWS web * service * @throws WebServiceException * @throws ConnectException */ public static compbio.data.msa.RegistryWS connectToRegistry(String host) throws WebServiceException, ConnectException { URL url = null; String service = "RegistryWS"; log.log(Level.FINE, "Attempting to connect..."); try { url = new URL(host + "/" + service + "?wsdl"); } catch (MalformedURLException e) { e.printStackTrace(); // ignore as the host name is already verified } QName qname = new QName(JABAService.V2_SERVICE_NAMESPACE, service); Service serv = Service.create(url, qname); if (serv == null) { throw new ConnectException("Could not connect to " + url + ". Is the server down?"); } QName portName = new QName(serv.getServiceName().getNamespaceURI(), service + "Port"); compbio.data.msa.RegistryWS serviceIF = serv.getPort(portName, compbio.data.msa.RegistryWS.class); log.log(Level.INFO, "Connected to " + service + " successfully!"); return serviceIF; } /** * Asks registry to test the service on the host hostname * * @param hostname * @param service * @param writer * @throws ConnectException * @throws WebServiceException */ public static void testService(String hostname, Services service, PrintWriter writer) throws ConnectException, WebServiceException { RegistryWS registry = connectToRegistry(hostname); if (registry != null) { String message = registry.testService(service); writer.println("Service " + service + " testing results: "); writer.println(message); FileUtil.closeSilently(((Closeable) registry)); } writer.flush(); } private static void listAllServices(String hostname) throws WebServiceException, IOException { RegistryWS registry = connectToRegistry(hostname); Set func_services = Collections.EMPTY_SET; Set nonfunc_services = Collections.EMPTY_SET; if (registry != null) { func_services = registry.getSupportedServices(); nonfunc_services = registry.getNonoperatedServices(); FileUtil.closeSilently(((Closeable) registry)); } else { System.out.println("Failed to connect to the registry! "); return; } if (!func_services.isEmpty()) { System.out.println("There are " + func_services.size() + " services at " + hostname + ":"); String mess = "\n\rThe list:\n"; System.out.println(mess + Services.toString(func_services)); } if (!nonfunc_services.isEmpty()) { System.out.println("There are " + nonfunc_services.size() + " non-available services at " + hostname + ":"); String mess = "The list (internal tests failed): "; System.out.println(mess + Services.toString(nonfunc_services)); } } /** * Calculate conservation for sequences loaded from a FASTA record list structure * * @param fastalist * the list of FASTA records * @param wsproxy * a web service proxy * @param preset * Preset to use optional * @param customOptions * the list of options * @return Set the conservation scores * @throws UnknownFileFormatException */ static ScoreManager analize(List fastalist, SequenceAnnotation wsproxy, Preset preset, List> customOptions) { ScoreManager scores = null; try { String jobId = null; if (customOptions != null && preset != null) { System.out.println("WARN: Parameters (-f) are defined together with a preset (-r) ignoring preset!"); } if (customOptions != null) { jobId = wsproxy.customAnalize(fastalist, customOptions); } else if (preset != null) { jobId = wsproxy.presetAnalize(fastalist, preset); } else { jobId = wsproxy.analize(fastalist); } System.out.println("\n\rcalling predictor........."); Thread.sleep(100); scores = wsproxy.getAnnotation(jobId); } catch (JobSubmissionException e) { System.err.println("Exception while submitting job to a web server. Exception details are below:"); e.printStackTrace(); } catch (ResultNotAvailableException e) { System.err.println("Exception while waiting for results. Exception details are below:"); e.printStackTrace(); } catch (InterruptedException e) { Thread.currentThread().interrupt(); System.err.println("Exception while waiting for results. Exception details are below:"); e.printStackTrace(); } catch (WrongParameterException e) { String mess = "Parsing the web method input parameters failed Exception details are below:"; System.err.println(mess); e.printStackTrace(); } return scores; } /** * Calculate conservation for sequences loaded from the file * * @param wsproxy * a web service proxy * @param file * the file to read the results from * @param preset * Preset to use optional * @param customOptions * the list of options * @return Set the conservation scores * @throws IOException * @throws UnknownFileFormatException */ static ScoreManager analize(File file, SequenceAnnotation wsproxy, Preset preset, List> customOptions) { List fastalist = null; try { fastalist = SequenceUtil.openInputStream(file.getAbsolutePath()); assert !fastalist.isEmpty() : "Input is empty!"; } catch (IOException e) { String mess = "Reading the input file failed. Check that the file contains a list of FASTA records!\n"; System.err.println(mess + "Exception details are below:"); e.printStackTrace(); } catch (UnknownFileFormatException e) { String mess = "Reading the input file failed. Exception details are below:"; System.err.println(mess); System.out.println(e.getMessage()); e.printStackTrace(); } return analize(fastalist, wsproxy, preset, customOptions); } /** * Align sequences from the file using MsaWS * * @param * web service type e.g. Clustal * @param file * to write the resulting alignment to * @param msaws * MsaWS required * @param preset * Preset to use optional * @param customOptions * file which contains new line separated list of options * @return Alignment */ static Alignment align(File file, MsaWS msaws, Preset preset, List> customOptions) { FileInputStream instream = null; Alignment alignment = null; try { instream = new FileInputStream(file); List fastalist = SequenceUtil.readFasta(instream); instream.close(); String jobId = null; if (customOptions != null && preset != null) { System.out.println("WARN: Parameters (-f) are defined together with a preset (-r) ignoring preset!"); } if (customOptions != null) { jobId = msaws.customAlign(fastalist, customOptions); } else if (preset != null) { jobId = msaws.presetAlign(fastalist, preset); } else { jobId = msaws.align(fastalist); } System.out.println("\ncalling program........."); Thread.sleep(100); alignment = msaws.getResult(jobId); } catch (IOException e) { System.err.println("Exception while reading the input file. Check that the input file is a FASTA file! " + "Exception details are below:"); e.printStackTrace(); } catch (JobSubmissionException e) { System.err.println("Exception while submitting job to a web server. Exception details are below:"); e.printStackTrace(); } catch (ResultNotAvailableException e) { System.err.println("Exception while waiting for results. Exception details are below:"); e.printStackTrace(); } catch (InterruptedException ignored) { // ignore and propagate an interruption Thread.currentThread().interrupt(); } catch (WrongParameterException e) { e.printStackTrace(); } finally { if (instream != null) { try { instream.close(); } catch (IOException ignored) { // ignore } } } return alignment; } /** * Starts command line client, if no parameter are supported print help. Two * parameters are required for successful call the JWS2 host name and a * service name. * * @param args * Usage: -h=host_and_context * -s=serviceName ACTION [OPTIONS] * * -h= - a full URL to the JWS2 web server * including context path e.g. http://10.31.1.159:8080/ws * * -s= - one of [MafftWS, MuscleWS, ClustalWS, * TcoffeeWS, ProbconsWS] ACTIONS: * * -i= - full path to fasta formatted sequence file, * from which to align sequences * * -parameters - lists parameters supported by web service * * -presets - lists presets supported by web service * * -limits - lists web services limits Please note that if input * file is specified other actions are ignored * * OPTIONS: (only for use with -i action): * * -r= - name of the preset to use * * -o= - full path to the file where to write an * alignment -f= - the name of the file with * the list of parameters to use. Please note that -r and -f * options cannot be used together. Alignment is done with either * preset or a parameters from the file, but not both! * */ public static void main(String[] args) { if (args == null) { System.out.println(Constraints.help_text); System.exit(1); } if (args.length < 2) { System.err.println("Host (-h=, e.g. -h=http://www.compbio.dundee.ac.uk/jabaws) and service (-s=, e.g. -s=Jpred) are required!"); System.out.println(Constraints.help_text); System.exit(1); } try { new Jws2Client(args); } catch (IOException e) { log.log(Level.SEVERE, "IOException in client! " + e.getMessage(), e.getCause()); System.err.println("Cannot write output file! Stack trace: "); e.printStackTrace(); } } }