ViewVC Help
View File | Revision Log | Show Annotations | View Changeset | Root Listing
root/owl/trunk/tools/PymolServerOutputStream.java
Revision: 479
Committed: Tue Dec 18 11:19:24 2007 UTC (16 years, 9 months ago) by duarte
Original Path: branches/aglappe-jung/tools/PymolServerOutputStream.java
File size: 6329 byte(s)
Log Message:
Submission of commands is now async
Line User Rev File contents
1 stehr 10 package tools;
2    
3     import java.io.IOException;
4     import java.io.OutputStream;
5     import java.io.PrintWriter;
6     import java.net.MalformedURLException;
7 duarte 203 import java.net.URL;
8 stehr 10 import java.util.Vector;
9 duarte 203 //import org.apache.xmlrpc.*;
10     import org.apache.xmlrpc.client.*;
11     //import org.apache.xmlrpc.common.*;
12     import org.apache.xmlrpc.XmlRpcException;
13 stehr 10 /**
14     * Package: tools
15     * Class: PymolServerOutput
16     * Author: Henning Stehr, stehr@molgen.mpg.de
17     * Date: 2/Feb/2006
18     *
19     * This class provides an output stream to send commands to a
20     * pymol server. It wraps the XML-RPC connection to the server
21     * using the url taken by the constructor. For convenience the
22     * OutputStream should be wrapped into a PrintStream.
23     *
24     * Code example:
25     * url = "http://localhost:9123";
26     * PrintWriter serverOut = new PrintWriter(new PymolServerOutputStream(url), true);
27     * serverOut.println("load /project/StruPPi/PDBs/mainPDB/1RX4.pdb, hello");
28     *
29     * Notes:
30     * - When constructing the PrintWriter, make sure to turn on automatic flushing
31     * by giving "true" as the second parameter, otherwise flush() has to be invoked
32     * manually to send the command to the server.
33     * - Automatic flushing is only invoked when using 'println' rather than 'print'.
34     * - For some reason, this does not work with a PrintStream only with a PrintWriter.
35     * - '\n' in command strings causes problems
36     *
37     * Changelog:
38     * 06/02/02 first created by HS
39     */
40     public class PymolServerOutputStream extends OutputStream {
41    
42     static final String DEFAULTXMLRPCCOMMAND = "do";
43     static final int INITIALBUFFERCAPACITY = 255;
44     static final int BUFFERCAPACITYINCREASE = 255;
45 duarte 203 public static final int PYMOLCOMMANDLENGTHLIMIT = 1060;
46 stehr 10
47     byte[] commandBuffer;
48     int commandBufferPtr, // current load
49     commandBufferCap; // capacity
50     XmlRpcClient client;
51    
52     /**
53     * Create a new output stream to the server running at the given url
54     */
55     public PymolServerOutputStream(String url) {
56    
57     // create empty command buffer
58     commandBuffer = new byte[INITIALBUFFERCAPACITY];
59     commandBufferCap = INITIALBUFFERCAPACITY;
60     commandBufferPtr = 0;
61    
62     try {
63     // initialize connection to server
64 duarte 203 this.client = new XmlRpcClient();
65     XmlRpcClientConfigImpl config = new XmlRpcClientConfigImpl();
66     config.setServerURL(new URL(url));
67     client.setConfig(config);
68 stehr 10 } catch(MalformedURLException e) {
69     System.err.println("Error: Malformed URL in constructor of PymolServerOutputStream");
70     e.printStackTrace();
71     }
72     }
73    
74    
75     /**
76     * Store bytes in command buffer
77     */
78     @Override
79     public void write(int arg0) throws IOException {
80     if(commandBufferPtr >= commandBufferCap) {
81     // get more space
82     byte[] newBuffer = new byte[commandBufferCap + BUFFERCAPACITYINCREASE];
83 stehr 26 for(int i = 0; i < commandBufferPtr; i++) {
84 stehr 10 newBuffer[i] = commandBuffer[i];
85     }
86     commandBuffer = newBuffer;
87 stehr 26 commandBufferCap += BUFFERCAPACITYINCREASE;
88 stehr 10 }
89     commandBuffer[commandBufferPtr++] = (byte) arg0;
90     }
91    
92    
93     /**
94     * Send command to server whenever flush is invoked
95     */
96     @Override
97     public void flush() throws IOException {
98 stehr 28 // prevent overlong commands from being sent to server
99     if(commandBufferPtr > PYMOLCOMMANDLENGTHLIMIT + 1) {
100     throw new IOException();
101     }
102 stehr 10 // prepare parameter vector
103 stehr 28 Vector<String> myvector = new Vector<String>();
104     String commandString = new String(this.commandBuffer, 0, commandBufferPtr).trim();
105     myvector.add(commandString);
106 stehr 10 // reset command buffer
107     this.commandBuffer = new byte[INITIALBUFFERCAPACITY];
108 stehr 11 this.commandBufferCap = INITIALBUFFERCAPACITY;
109     this.commandBufferPtr = 0;
110 duarte 479 TimingOutCallback callback = new TimingOutCallback(1000);
111    
112 stehr 10 // submit command
113     try {
114 duarte 479 //this.client.execute(DEFAULTXMLRPCCOMMAND, myvector);
115     this.client.executeAsync(DEFAULTXMLRPCCOMMAND, myvector, callback);
116     callback.waitForResponse();
117 stehr 10 } catch(XmlRpcException e) {
118 duarte 203 // System.out.println("XMP-RPC exception occured.");
119 stehr 10 // send IOException instead, so use of XML-RPC is transparent
120 duarte 203 throw new IOException(e.getMessage());
121 duarte 479 } catch (Throwable e) {
122     throw new IOException(e.getMessage());
123     }
124 stehr 10 }
125    
126     // test function for current class
127     public static void main(String[] args) {
128    
129     String serverUrl = "http://gelb:9123";
130 stehr 28 String command0 = "delete hello";
131 stehr 10 String command1 = "load /project/StruPPi/PDBs/mainPDB/1RX4.pdb, hello";
132     String command2 = "show cartoon";
133     String command3 = "select hello2, resi 12";
134     String command4 = "show sticks, hello2";
135     String command5 = "zoom hello2";
136    
137     // try to connect directly
138     System.out.println("Trying to connect directly by XML-RPC...");
139     try {
140 duarte 203
141     XmlRpcClient client = new XmlRpcClient();
142     XmlRpcClientConfigImpl config = new XmlRpcClientConfigImpl();
143     config.setServerURL(new URL(serverUrl));
144     client.setConfig(config);
145    
146    
147 stehr 10 Vector<String> myvector = new Vector<String>();
148     myvector.add(command1);
149     try {
150     client.execute(DEFAULTXMLRPCCOMMAND,myvector);
151     System.out.println("done.");
152     }
153     catch( XmlRpcException e) {
154     e.printStackTrace();
155     }
156     }
157     catch(MalformedURLException e){
158     e.printStackTrace();
159     }
160    
161     // try using OutputStream
162     System.out.println("Trying to connect via PymolServerOutputStream...");
163     try {
164     // create new output stream
165     OutputStream serverOut = new PymolServerOutputStream(serverUrl);
166    
167     // send data to output stream
168     serverOut.write(command0.getBytes());
169     // execute command
170     serverOut.flush();
171    
172     System.out.println("done.");
173    
174     } catch(MalformedURLException e) {
175     System.out.println("Error: The server URL is wrong.");
176     e.printStackTrace();
177     System.exit(1);
178     } catch(IOException e) {
179     System.out.println("Error writing to server url.");
180     e.printStackTrace();
181     System.exit(1);
182     }
183    
184     // now try using OutputStream wrapped into PrintStream
185     System.out.println("Trying to connect via PrintWriter...");
186     PrintWriter serverOutPw = new PrintWriter(new PymolServerOutputStream(serverUrl), true);
187     serverOutPw.println(command0);
188     serverOutPw.println(command1);
189     serverOutPw.println(command2);
190     serverOutPw.println(command3);
191     serverOutPw.println(command4);
192     serverOutPw.println(command5);
193     System.out.println("done.");
194     }
195    
196     }