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