001/* 002 * BioJava development code 003 * 004 * This code may be freely distributed and modified under the 005 * terms of the GNU Lesser General Public Licence. This should 006 * be distributed with the code. If you do not have a copy, 007 * see: 008 * 009 * http://www.gnu.org/copyleft/lesser.html 010 * 011 * Copyright for this code is held jointly by the individual 012 * authors. These should be listed in @author doc comments. 013 * 014 * For more information on the BioJava project and its aims, 015 * or to join the biojava-l mailing list, visit the home page 016 * at: 017 * 018 * http://www.biojava.org/ 019 * 020 */ 021package org.biojava.nbio.structure.align.client; 022 023import org.biojava.nbio.structure.Atom; 024import org.biojava.nbio.structure.StructureException; 025import org.biojava.nbio.structure.align.fatcat.FatCatRigid; 026import org.biojava.nbio.structure.align.model.AFPChain; 027import org.biojava.nbio.structure.align.util.AtomCache; 028import org.biojava.nbio.structure.align.util.URLConnectionTools; 029import org.biojava.nbio.structure.align.util.ResourceManager; 030import org.biojava.nbio.structure.align.xml.*; 031import org.slf4j.Logger; 032import org.slf4j.LoggerFactory; 033 034import java.io.BufferedReader; 035import java.io.IOException; 036import java.io.InputStream; 037import java.io.InputStreamReader; 038import java.net.URL; 039import java.net.URLEncoder; 040import java.util.Random; 041import java.util.SortedSet; 042import java.util.TreeSet; 043 044public class JFatCatClient { 045 private final static Logger logger = LoggerFactory.getLogger(JFatCatClient.class); 046 047 private static ResourceManager resourceManager = ResourceManager.getResourceManager("jfatcat"); 048 049 private static final String serverAPPEND = "show?name1=%s&name2=%s"; 050 051 private static final String sendAPPEND = "submit?name1=%s&name2=%s&version=%s"; 052 053 private static final String multiSendAPPEND = "jobSubmit?username=%s&version=%s"; 054 055 private static final String representAPPEND = "representatives?cluster=%s"; 056 057 private static final String serverHasResult = "hasResult?method=%s&name1=%s&name2=%s"; 058 059 private static final int DEFAULT_TIMEOUT = 5000; 060 061 private static final String serverPositionInQueue = "queuePosition?method=%s&name1=%s&name2=%s"; 062 063 private static Random generator; 064 065 private static String newline = System.getProperty("line.separator"); 066 067 private static String KILL_JOB = "KILL_JOB"; 068 069 private static String COME_BACK_LATER = "COME_BACK_LATER"; 070 071 static { 072 073 generator = new Random(); 074 075 } 076 077 public static void main(String[] args) throws Exception { 078 //System.out.println(hasPrecalculatedResult("http://source.rcsb.org/jfatcatserver/align/", "jCE Circular Permutation", "1CDG.A", "1TIM.A")); 079 AtomCache cache = new AtomCache(); 080 String name1= "2W72.A"; 081 String name2= "1D2Z.D"; 082 083 Atom[] ca1 = cache.getAtoms(name1); 084 Atom[] ca2 = cache.getAtoms(name2); 085 086 int timeout = 10000; 087 088 String testServer = "http://source.rcsb.org/jfatcatserver/align/"; 089 090 System.out.println(getAFPChainFromServer(testServer, FatCatRigid.algorithmName, name1, name2, ca1, ca2, timeout)); 091 092 PdbPairsMessage msg = getPdbPairs(testServer, 1, "test"); 093 094 System.out.println(msg); 095 096 System.out.println(getRepresentatives(FarmJobParameters.DEFAULT_SERVER_URL, 40)); 097 } 098 099 public static boolean hasPrecalculatedResult(String serverLocation, String method, String name1, String name2 ){ 100 return hasPrecalculatedResult(serverLocation, method, name1, name2, DEFAULT_TIMEOUT ); 101 } 102 103 public static boolean hasPrecalculatedResult(String serverLocation, String method, String name1, String name2, int timeout){ 104 105 String serverURL = serverLocation + serverHasResult; 106 107 108 boolean hasResults = false; 109 try { 110 String u = String.format(serverURL,URLEncoder.encode(method,"UTF-8"),name1,name2) ; 111 URL url = new URL(u); 112 //System.out.println("has result ? ..." + url); 113 114 InputStream stream = URLConnectionTools.getInputStream(url,timeout); 115 116 String xml = null; 117 118 if ( stream != null) { 119 120 xml = convertStreamToString(stream); 121 logger.info(" has PrecalcResults got XML from server: " + xml); 122 HasResultXMLConverter conv = new HasResultXMLConverter(); 123 hasResults = conv.fromXML(xml); 124 } 125 126 } catch (IOException e){ 127 // log error and return false 128 logger.error("error in JFatCatClient: getAFPChainFromServer",e); 129 } 130 return hasResults; 131 } 132 133 134 public int getPositionInQueue(String serverLocation, String method, String name1, String name2){ 135 return getPositionInQueue(serverLocation, method, name1, name2, DEFAULT_TIMEOUT); 136 } 137 138 public int getPositionInQueue(String serverLocation, String method, String name1, String name2, int timeout){ 139 String serverURL = serverLocation + serverPositionInQueue; 140 141 142 int position = Integer.MIN_VALUE; 143 try { 144 String u = String.format(serverURL,URLEncoder.encode(method,"UTF-8"),name1,name2) ; 145 URL url = new URL(u); 146 147 InputStream stream = URLConnectionTools.getInputStream(url,timeout); 148 149 String xml = null; 150 151 if ( stream != null) { 152 153 xml = convertStreamToString(stream); 154 //System.out.println("got XML from server: " + xml); 155 PositionInQueueXMLConverter conv = new PositionInQueueXMLConverter(); 156 position = conv.fromXML(xml); 157 } 158 159 } catch (IOException e){ 160 logger.error("error in JFatCatClient: getAFPChainFromServer",e); // TODO dmyersturnbull: method should throw; we shouldn't catch here 161 } 162 return position; 163 164 } 165 public static AFPChain getAFPChainFromServer(String serverLocation , String name1, String name2, Atom[] ca1, Atom[] ca2) { 166 String method = FatCatRigid.algorithmName; 167 return getAFPChainFromServer(serverLocation, method, name1, name2, ca1, ca2,DEFAULT_TIMEOUT); 168 } 169 170 public static AFPChain getAFPChainFromServer(String serverLocation , String method, String name1, String name2, Atom[] ca1, Atom[] ca2, int timeout) 171 { 172 173 String serverURL = serverLocation + serverAPPEND; 174 175 try { 176 String u = String.format(serverURL,name1,name2) ; 177 178 if ( method != null) 179 u+= "&method=" + URLEncoder.encode(method,"UTF-8"); 180 181 URL url = new URL(u); 182 logger.info("requesting alignment from server..." + url); 183 // have a short timeout for this... 184 // 5 sec 185 InputStream stream = URLConnectionTools.getInputStream(url,timeout); 186 187 String xml = null; 188 189 if ( stream != null) { 190 191 xml = convertStreamToString(stream); 192 } 193 if (xml != null) { 194 195 return AFPChainXMLParser.fromXML (xml, name1, name2, ca1, ca2); 196 197 } else { 198 return null; 199 } 200 // TODO dmyersturnbull: method should throw; we shouldn't catch here 201 } catch (IOException e){ 202 logger.error("error in JFatCatClient: getAFPChainFromServer",e); 203 } catch (StructureException e) { 204 logger.error("error in JFatCatClient: getAFPChainFromServer",e); 205 } 206 return null; 207 } 208 209 210 public static String convertStreamToString(InputStream stream){ 211 BufferedReader reader = new BufferedReader(new InputStreamReader(stream)); 212 StringBuilder sb = new StringBuilder(); 213 214 String line = null; 215 try { 216 while ((line = reader.readLine()) != null) { 217 sb.append(line).append(newline); 218 } 219 } catch (IOException e) { 220 logger.error("Couldn't convert stream to string", e); // TODO dmyersturnbull: method should throw; we shouldn't catch here 221 } finally { 222 try { 223 stream.close(); 224 } catch (IOException e) { 225 logger.warn("Can't close stream", e); 226 } 227 } 228 229 return sb.toString(); 230 } 231 232 public static String sendMultiAFPChainToServer(String serverLocation, String multiXML, String username) throws JobKillException{ 233 String version = resourceManager.getString("jfatcat.version"); 234 return sendMultiAFPChainToServer(serverLocation, multiXML, username, version); 235 } 236 237 public static String sendMultiAFPChainToServer(String serverLocation, String multiXML, String username, String version) throws JobKillException{ 238 String multiSendURL = serverLocation + multiSendAPPEND; 239 240 String responseS = ""; 241 242 String u = String.format(multiSendURL,username,version); 243 244 int timeout = getTimeout(); 245 246 boolean submitted = false; 247 248 while (! submitted ){ 249 try { 250 URL url = new URL(u); 251 InputStream response = URLConnectionTools.doPOST(url, multiXML,timeout); 252 responseS = convertStreamToString(response); 253 submitted = true; 254 if (! responseS.contains("OK")) 255 logger.error("server returned " + responseS); 256 257 // server is busy... wait a bit and try again 258 if ( responseS.startsWith(COME_BACK_LATER)){ 259 submitted = false; 260 } 261 262 } catch (Exception e){ 263 logger.error("Error in JFatCatClient: while sending results back to server",e); 264 265 try { 266 int randomSleep = getRandomSleepTime(); 267 logger.warn("sleeping " + (randomSleep/1000) + " sec."); 268 Thread.sleep(randomSleep); 269 } catch (InterruptedException ex){ 270 logger.warn("Interrupted while sleeping", ex); 271 } 272 } 273 } 274 275 if ( responseS.startsWith(KILL_JOB)){ 276 throw new JobKillException("Server responded with KILL message."); 277 278 } 279 280 281 return responseS; 282 } 283 284 public static int getRandomSleepTime() { 285 286 // now wait between 7 and 13 min. 287 288 int minTime = 560000; 289 290 int maxTime = 7800000 - minTime; 291 292 int nextId = generator.nextInt(maxTime); 293 return minTime + nextId; 294 295 } 296 297 298 public static final void sendAFPChainToServer(String serverLocation, AFPChain afpChain,Atom[] ca1, Atom[] ca2) throws JobKillException 299 { 300 301 String sendURL = serverLocation + sendAPPEND; 302 303 String version = resourceManager.getString("jfatcat.version"); 304 305 int timeout = getTimeout(); 306 307 try { 308 309 // just to make sure that similarity has been calculated! 310 afpChain.getSimilarity(); 311 312 String xml = AFPChainXMLConverter.toXML(afpChain, ca1, ca2); 313 314 String u = String.format(sendURL,afpChain.getName1() , afpChain.getName2(),version); 315 316 URL url = new URL(u); 317 318 InputStream response = URLConnectionTools.doPOST(url, xml,timeout); 319 320 logger.debug("got response: {}", convertStreamToString(response)); 321 322 if ( xml.startsWith("KILL_JOB")){ 323 throw new JobKillException("Server responded with KILL message."); 324 } 325 326 } catch (IOException e){ 327 logger.error("error in JFatCatClient: sendAFPChainToServer",e); 328 } 329 330 } 331 332 public static final int getTimeout(){ 333 String timeoutS = resourceManager.getString("connection.timeout"); 334 int timeout = 60000; 335 336 try { 337 timeout = Integer.parseInt(timeoutS); 338 } catch (NumberFormatException ex ){ 339 logger.error("Bad connection.timeout parameter",ex); 340 } 341 return timeout; 342 } 343 344 345 public static final PdbPairsMessage getPdbPairs(String url,int nrPair, String username) throws IOException, JobKillException { 346 347 348 String urlS= url + "getPairs?" + "nrPairs=" + nrPair + "&username=" + URLEncoder.encode(username, "UTF-8"); 349 int timeout = getTimeout(); 350 351 PdbPairsMessage msg = null; 352 logger.info("requesting {}", urlS); 353 URL serverUrl = new URL(urlS); 354 // we are very tolerant with requesting a set of pairs, since we probably depend on getting it to get work started... 355 // 1 min... 356 InputStream stream = URLConnectionTools.getInputStream(serverUrl,timeout); 357 String xml = null; 358 359 if ( stream != null) { 360 361 xml = convertStreamToString(stream); 362 if (xml != null) { 363 if ( xml.startsWith("KILL_JOB")){ 364 // we got the KILL signal from the server... 365 throw new JobKillException("Server responded with KILL message."); 366 } 367 msg = PdbPairXMLConverter.convertXMLtoPairs(xml); 368 369 } 370 } 371 372 return msg; 373 } 374 375 376 public static final SortedSet<String> getRepresentatives(String serverLocation, int cutoff){ 377 SortedSet<String> representatives = new TreeSet<String>(); 378 379 String representURL = serverLocation + representAPPEND; 380 381 if ( cutoff < 20) 382 cutoff = 40; 383 int timeout = getTimeout(); 384 String u = String.format(representURL,cutoff); 385 386 logger.info("Fetching representatives from "+u); 387 try { 388 URL url = new URL(u); 389 390 InputStream stream = URLConnectionTools.getInputStream(url,timeout); 391 392 String xml = null; 393 394 if ( stream != null) { 395 396 xml = convertStreamToString(stream); 397 } 398 if (xml != null) { 399 representatives = RepresentativeXMLConverter.fromXML(xml); 400 } 401 } catch (IOException e){ // TODO dmyersturnbull: method should throw; we shouldn't catch here 402 logger.error("Error fetching representatives",e); 403 } 404 return representatives; 405 } 406 407 408 409}