1 /* vim: set ts=2: */ 2 /** 3 * Copyright (c) 2006 The Regents of the University of California. 4 * All rights reserved. 5 * 6 * Redistribution and use in source and binary forms, with or without 7 * modification, are permitted provided that the following conditions 8 * are met: 9 * 1. Redistributions of source code must retain the above copyright 10 * notice, this list of conditions, and the following disclaimer. 11 * 2. Redistributions in binary form must reproduce the above 12 * copyright notice, this list of conditions, and the following 13 * disclaimer in the documentation and/or other materials provided 14 * with the distribution. 15 * 3. Redistributions must acknowledge that this software was 16 * originally developed by the UCSF Computer Graphics Laboratory 17 * under support by the NIH National Center for Research Resources, 18 * grant P41-RR01081. 19 * 20 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDER "AS IS" AND ANY 21 * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 22 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR 23 * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS BE LIABLE 24 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR 25 * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT 26 * OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR 27 * BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, 28 * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE 29 * OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, 30 * EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 31 * 32 */ 33 package ext.edu.ucsf.rbvi.strucviz2.port; 34 35 import java.io.BufferedReader; 36 import java.io.IOException; 37 import java.io.InputStream; 38 import java.io.InputStreamReader; 39 import java.util.ArrayList; 40 import java.util.HashMap; 41 import java.util.List; 42 import java.util.Map; 43 44 import org.slf4j.Logger; 45 import org.slf4j.LoggerFactory; 46 47 import ext.edu.ucsf.rbvi.strucviz2.StructureManager; 48 49 /*************************************************** 50 * Thread Classes * 51 **************************************************/ 52 53 /** 54 * Reply listener thread 55 */ 56 public class ListenerThreads extends Thread 57 { 58 private BufferedReader lineReader = null; 59 60 private Process chimera = null; 61 62 private Map<String, List<String>> replyLog = null; 63 64 private Logger logger; 65 66 private StructureManager structureManager = null; 67 68 private boolean stopMe = false; 69 70 /** 71 * Create a new listener thread to read the responses from Chimera 72 * 73 * @param chimera 74 * a handle to the Chimera Process 75 * @param structureManager 76 * a handle to the Chimera structure manager 77 */ ListenerThreads(Process chimera, StructureManager structureManager)78 public ListenerThreads(Process chimera, StructureManager structureManager) 79 { 80 this.chimera = chimera; 81 this.structureManager = structureManager; 82 replyLog = new HashMap<String, List<String>>(); 83 // Get a line-oriented reader 84 InputStream readChan = chimera.getInputStream(); 85 lineReader = new BufferedReader(new InputStreamReader(readChan)); 86 logger = LoggerFactory 87 .getLogger(ext.edu.ucsf.rbvi.strucviz2.port.ListenerThreads.class); 88 } 89 90 /** 91 * Start the thread running 92 */ run()93 public void run() 94 { 95 // System.out.println("ReplyLogListener running"); 96 while (!stopMe) 97 { 98 try 99 { 100 chimeraRead(); 101 } catch (IOException e) 102 { 103 logger.warn("UCSF Chimera has exited: " + e.getMessage()); 104 return; 105 } finally 106 { 107 if (lineReader != null) 108 { 109 try 110 { 111 lineReader.close(); 112 } catch (IOException e) 113 { 114 } 115 } 116 } 117 } 118 } 119 getResponse(String command)120 public List<String> getResponse(String command) 121 { 122 List<String> reply; 123 // System.out.println("getResponse: "+command); 124 // TODO do we need a maximum wait time before aborting? 125 while (!replyLog.containsKey(command)) 126 { 127 try 128 { 129 Thread.currentThread().sleep(100); 130 } catch (InterruptedException e) 131 { 132 } 133 } 134 135 synchronized (replyLog) 136 { 137 reply = replyLog.get(command); 138 // System.out.println("getResponse ("+command+") = "+reply); 139 replyLog.remove(command); 140 } 141 return reply; 142 } 143 clearResponse(String command)144 public void clearResponse(String command) 145 { 146 try 147 { 148 Thread.currentThread().sleep(100); 149 } catch (InterruptedException e) 150 { 151 } 152 if (replyLog.containsKey(command)) 153 { 154 replyLog.remove(command); 155 } 156 return; 157 } 158 159 /** 160 * Read input from Chimera 161 * 162 * @return a List containing the replies from Chimera 163 */ chimeraRead()164 private void chimeraRead() throws IOException 165 { 166 if (chimera == null) 167 { 168 return; 169 } 170 171 String line = null; 172 while ((line = lineReader.readLine()) != null) 173 { 174 // System.out.println("From Chimera-->" + line); 175 if (line.startsWith("CMD")) 176 { 177 chimeraCommandRead(line.substring(4)); 178 } 179 else if (line.startsWith("ModelChanged: ")) 180 { 181 (new ModelUpdater()).start(); 182 } 183 else if (line.startsWith("SelectionChanged: ")) 184 { 185 (new SelectionUpdater()).start(); 186 } 187 else if (line.startsWith("Trajectory residue network info:")) 188 { 189 (new NetworkUpdater(line)).start(); 190 } 191 } 192 return; 193 } 194 chimeraCommandRead(String command)195 private void chimeraCommandRead(String command) throws IOException 196 { 197 // Generally -- looking for: 198 // CMD command 199 // ........ 200 // END 201 // We return the text in between 202 List<String> reply = new ArrayList<String>(); 203 boolean updateModels = false; 204 boolean updateSelection = false; 205 boolean importNetwork = false; 206 String line = null; 207 208 synchronized (replyLog) 209 { 210 while ((line = lineReader.readLine()) != null) 211 { 212 // System.out.println("From Chimera (" + command + ") -->" + line); 213 if (line.startsWith("CMD")) 214 { 215 logger.warn("Got unexpected command from Chimera: " + line); 216 217 } 218 else if (line.startsWith("END")) 219 { 220 break; 221 } 222 if (line.startsWith("ModelChanged: ")) 223 { 224 updateModels = true; 225 } 226 else if (line.startsWith("SelectionChanged: ")) 227 { 228 updateSelection = true; 229 } 230 else if (line.length() == 0) 231 { 232 continue; 233 } 234 else if (!line.startsWith("CMD")) 235 { 236 reply.add(line); 237 } 238 else if (line.startsWith("Trajectory residue network info:")) 239 { 240 importNetwork = true; 241 } 242 } 243 replyLog.put(command, reply); 244 } 245 if (updateModels) 246 { 247 (new ModelUpdater()).start(); 248 } 249 if (updateSelection) 250 { 251 (new SelectionUpdater()).start(); 252 } 253 if (importNetwork) 254 { 255 (new NetworkUpdater(line)).start(); 256 } 257 return; 258 } 259 260 /** 261 * Model updater thread 262 */ 263 class ModelUpdater extends Thread 264 { 265 ModelUpdater()266 public ModelUpdater() 267 { 268 } 269 run()270 public void run() 271 { 272 structureManager.updateModels(); 273 structureManager.modelChanged(); 274 } 275 } 276 277 /** 278 * Selection updater thread 279 */ 280 class SelectionUpdater extends Thread 281 { 282 SelectionUpdater()283 public SelectionUpdater() 284 { 285 } 286 run()287 public void run() 288 { 289 try 290 { 291 logger.info("Responding to chimera selection"); 292 structureManager.chimeraSelectionChanged(); 293 } catch (Exception e) 294 { 295 logger.warn("Could not update selection", e); 296 } 297 } 298 } 299 300 /** 301 * Selection updater thread 302 */ 303 class NetworkUpdater extends Thread 304 { 305 306 private String line; 307 NetworkUpdater(String line)308 public NetworkUpdater(String line) 309 { 310 this.line = line; 311 } 312 run()313 public void run() 314 { 315 try 316 { 317 // ((TaskManager<?, ?>) structureManager.getService(TaskManager.class)) 318 // .execute(new ImportTrajectoryRINTaskFactory(structureManager, line) 319 // .createTaskIterator()); 320 } catch (Exception e) 321 { 322 logger.warn("Could not import trajectory network", e); 323 } 324 } 325 } 326 327 /** 328 * Set a flag that this thread should clean up and exit. 329 */ requestStop()330 public void requestStop() 331 { 332 this.stopMe = true; 333 } 334 } 335