2 |
26 Feb 07 |
jari |
1 |
package org.tigr.microarray.mev.r; |
2 |
26 Feb 07 |
jari |
2 |
|
2 |
26 Feb 07 |
jari |
3 |
import java.io.*; |
2 |
26 Feb 07 |
jari |
4 |
import java.net.*; |
2 |
26 Feb 07 |
jari |
5 |
|
2 |
26 Feb 07 |
jari |
/** class providing TCP/IP connection to an Rserv |
2 |
26 Feb 07 |
jari |
@version $Id$ |
2 |
26 Feb 07 |
jari |
8 |
*/ |
2 |
26 Feb 07 |
jari |
9 |
public class Rconnection { |
2 |
26 Feb 07 |
jari |
/** last error string */ |
2 |
26 Feb 07 |
jari |
11 |
String lastError=null; |
2 |
26 Feb 07 |
jari |
12 |
Socket s; |
2 |
26 Feb 07 |
jari |
13 |
boolean connected=false; |
2 |
26 Feb 07 |
jari |
14 |
InputStream is; |
2 |
26 Feb 07 |
jari |
15 |
OutputStream os; |
2 |
26 Feb 07 |
jari |
16 |
boolean authReq=false; |
2 |
26 Feb 07 |
jari |
17 |
int authType=AT_plain; |
2 |
26 Feb 07 |
jari |
18 |
String Key=null; |
2 |
26 Feb 07 |
jari |
19 |
Rtalk rt=null; |
2 |
26 Feb 07 |
jari |
20 |
|
2 |
26 Feb 07 |
jari |
/** This static variable specifies the character set used to encode string for transfer. Under normal circumstances there should be no reason for changing this variable. The default is UTF-8, which makes sure that 7-bit ASCII characters are sent in a backward-compatible fashion. Currently (Rserve 0.1-7) there is no further conversion on Rserve's side, i.e. the strings are passed to R without re-coding. If necessary the setting should be changed <u>before</u> connecting to the Rserve in case later Rserves will provide a possibility of setting the encoding during the handshake. */ |
2 |
26 Feb 07 |
jari |
22 |
public static String transferCharset="UTF-8"; |
2 |
26 Feb 07 |
jari |
23 |
|
2 |
26 Feb 07 |
jari |
/** authorization type: plain text */ |
2 |
26 Feb 07 |
jari |
25 |
public static final int AT_plain = 0; |
2 |
26 Feb 07 |
jari |
/** authorization type: unix crypt */ |
2 |
26 Feb 07 |
jari |
27 |
public static final int AT_crypt = 1; |
2 |
26 Feb 07 |
jari |
28 |
|
2 |
26 Feb 07 |
jari |
/** version of the server (as reported in IDstring just after Rsrv) */ |
2 |
26 Feb 07 |
jari |
30 |
protected int rsrvVersion; |
2 |
26 Feb 07 |
jari |
31 |
|
2 |
26 Feb 07 |
jari |
/** make a new local connection on default port (6311) */ |
2 |
26 Feb 07 |
jari |
33 |
public Rconnection() throws RSrvException { |
2 |
26 Feb 07 |
jari |
34 |
this("127.0.0.1",6311); |
2 |
26 Feb 07 |
jari |
35 |
} |
2 |
26 Feb 07 |
jari |
36 |
|
2 |
26 Feb 07 |
jari |
/** make a new connection to specified host on default port (6311) |
2 |
26 Feb 07 |
jari |
@param host host name/IP |
2 |
26 Feb 07 |
jari |
39 |
*/ |
2 |
26 Feb 07 |
jari |
40 |
public Rconnection(String host) throws RSrvException { |
2 |
26 Feb 07 |
jari |
41 |
this(host,6311); |
2 |
26 Feb 07 |
jari |
42 |
} |
2 |
26 Feb 07 |
jari |
43 |
|
2 |
26 Feb 07 |
jari |
/** make a new connection to specified host and given port. |
2 |
26 Feb 07 |
jari |
Make sure you check {@link #isConnected} and/or {@link #isOk}. |
2 |
26 Feb 07 |
jari |
@param host host name/IP |
2 |
26 Feb 07 |
jari |
@param port TCP port |
2 |
26 Feb 07 |
jari |
48 |
*/ |
2 |
26 Feb 07 |
jari |
49 |
public Rconnection(String host, int port) throws RSrvException { |
2 |
26 Feb 07 |
jari |
50 |
try { |
2 |
26 Feb 07 |
jari |
51 |
if (connected) s.close(); |
2 |
26 Feb 07 |
jari |
52 |
s=null; |
2 |
26 Feb 07 |
jari |
53 |
} catch (Exception e) { |
2 |
26 Feb 07 |
jari |
54 |
throw new RSrvException(this,"Cannot connect: "+e.getMessage()); |
2 |
26 Feb 07 |
jari |
55 |
} |
2 |
26 Feb 07 |
jari |
56 |
connected=false; |
2 |
26 Feb 07 |
jari |
57 |
try { |
2 |
26 Feb 07 |
jari |
58 |
s=new Socket(host,port); |
2 |
26 Feb 07 |
jari |
// disable Nagle's algorithm since we really want immediate replies |
2 |
26 Feb 07 |
jari |
60 |
s.setTcpNoDelay(true); |
2 |
26 Feb 07 |
jari |
61 |
} catch (Exception sce) { |
2 |
26 Feb 07 |
jari |
62 |
throw new RSrvException(this,"Cannot connect: "+sce.getMessage()); |
2 |
26 Feb 07 |
jari |
63 |
} |
2 |
26 Feb 07 |
jari |
64 |
try { |
2 |
26 Feb 07 |
jari |
65 |
is=s.getInputStream(); |
2 |
26 Feb 07 |
jari |
66 |
os=s.getOutputStream(); |
2 |
26 Feb 07 |
jari |
67 |
} catch (Exception gse) { |
2 |
26 Feb 07 |
jari |
68 |
throw new RSrvException(this,"Cannot get io stream: "+gse.getMessage()); |
2 |
26 Feb 07 |
jari |
69 |
} |
2 |
26 Feb 07 |
jari |
70 |
rt=new Rtalk(is,os); |
2 |
26 Feb 07 |
jari |
71 |
byte[] IDs=new byte[32]; |
2 |
26 Feb 07 |
jari |
72 |
int n=-1; |
2 |
26 Feb 07 |
jari |
73 |
try { |
2 |
26 Feb 07 |
jari |
74 |
n=is.read(IDs); |
2 |
26 Feb 07 |
jari |
75 |
} catch (Exception sre) { |
2 |
26 Feb 07 |
jari |
76 |
throw new RSrvException(this,"Error while receiving data: "+sre.getMessage()); |
2 |
26 Feb 07 |
jari |
77 |
} |
2 |
26 Feb 07 |
jari |
78 |
try { |
2 |
26 Feb 07 |
jari |
79 |
if (n!=32) { |
2 |
26 Feb 07 |
jari |
80 |
lastError="Handshake failed: expected 32 bytes header, got "+n; |
2 |
26 Feb 07 |
jari |
81 |
throw new RSrvException(this,lastError); |
2 |
26 Feb 07 |
jari |
82 |
} |
2 |
26 Feb 07 |
jari |
83 |
String ids=new String(IDs); |
2 |
26 Feb 07 |
jari |
84 |
if (ids.substring(0,4).compareTo("Rsrv")!=0) { |
2 |
26 Feb 07 |
jari |
85 |
lastError="Handshake failed: Rsrv signature expected, but received \""+ids+"\" instead."; |
2 |
26 Feb 07 |
jari |
86 |
throw new RSrvException(this,lastError); |
2 |
26 Feb 07 |
jari |
87 |
} |
2 |
26 Feb 07 |
jari |
88 |
try { |
2 |
26 Feb 07 |
jari |
89 |
rsrvVersion=Integer.parseInt(ids.substring(4,8)); |
2 |
26 Feb 07 |
jari |
90 |
} catch (Exception px) {} |
2 |
26 Feb 07 |
jari |
// we support (knowingly) up to 102 - including long data support |
2 |
26 Feb 07 |
jari |
92 |
if (rsrvVersion>102) { |
2 |
26 Feb 07 |
jari |
93 |
lastError="Handshake failed: The server uses more recent protocol than this client."; |
2 |
26 Feb 07 |
jari |
94 |
throw new RSrvException(this,lastError); |
2 |
26 Feb 07 |
jari |
95 |
} |
2 |
26 Feb 07 |
jari |
96 |
if (ids.substring(8,12).compareTo("QAP1")!=0) { |
2 |
26 Feb 07 |
jari |
97 |
lastError="Handshake failed: unupported transfer protocol ("+ids.substring(8,12)+"), I talk only QAP1."; |
2 |
26 Feb 07 |
jari |
98 |
throw new RSrvException(this,lastError); |
2 |
26 Feb 07 |
jari |
99 |
} |
2 |
26 Feb 07 |
jari |
100 |
for (int i=12;i<32;i+=4) { |
2 |
26 Feb 07 |
jari |
101 |
String attr=ids.substring(i,i+4); |
2 |
26 Feb 07 |
jari |
102 |
if (attr.compareTo("ARpt")==0) { |
2 |
26 Feb 07 |
jari |
103 |
if (!authReq) { // this method is only fallback when no other was specified |
2 |
26 Feb 07 |
jari |
104 |
authReq=true; |
2 |
26 Feb 07 |
jari |
105 |
authType=AT_plain; |
2 |
26 Feb 07 |
jari |
106 |
} |
2 |
26 Feb 07 |
jari |
107 |
} |
2 |
26 Feb 07 |
jari |
108 |
if (attr.compareTo("ARuc")==0) { |
2 |
26 Feb 07 |
jari |
109 |
authReq=true; |
2 |
26 Feb 07 |
jari |
110 |
authType=AT_crypt; |
2 |
26 Feb 07 |
jari |
111 |
} |
2 |
26 Feb 07 |
jari |
112 |
if (attr.charAt(0)=='K') { |
2 |
26 Feb 07 |
jari |
113 |
Key=attr.substring(1,3); |
2 |
26 Feb 07 |
jari |
114 |
} |
2 |
26 Feb 07 |
jari |
115 |
} |
2 |
26 Feb 07 |
jari |
116 |
connected=true; |
2 |
26 Feb 07 |
jari |
117 |
lastError="OK"; |
2 |
26 Feb 07 |
jari |
118 |
} catch (RSrvException innerX) { |
2 |
26 Feb 07 |
jari |
119 |
try { s.close(); } catch (Exception ex01) {}; is=null; os=null; s=null; |
2 |
26 Feb 07 |
jari |
120 |
throw innerX; |
2 |
26 Feb 07 |
jari |
121 |
} |
2 |
26 Feb 07 |
jari |
122 |
} |
2 |
26 Feb 07 |
jari |
123 |
|
2 |
26 Feb 07 |
jari |
124 |
public void finalize() { |
2 |
26 Feb 07 |
jari |
125 |
close(); |
2 |
26 Feb 07 |
jari |
126 |
is=null; is=null; |
2 |
26 Feb 07 |
jari |
127 |
} |
2 |
26 Feb 07 |
jari |
128 |
|
2 |
26 Feb 07 |
jari |
/** get server version as reported during the handshake. |
2 |
26 Feb 07 |
jari |
@return server version as integer (Rsrv0100 will return 100) */ |
2 |
26 Feb 07 |
jari |
131 |
public int getServerVersion() { |
2 |
26 Feb 07 |
jari |
132 |
return rsrvVersion; |
2 |
26 Feb 07 |
jari |
133 |
} |
2 |
26 Feb 07 |
jari |
134 |
|
2 |
26 Feb 07 |
jari |
/** closes current connection */ |
2 |
26 Feb 07 |
jari |
136 |
public void close() { |
2 |
26 Feb 07 |
jari |
137 |
try { |
2 |
26 Feb 07 |
jari |
138 |
if (s!=null) s.close(); |
2 |
26 Feb 07 |
jari |
139 |
connected=false; |
2 |
26 Feb 07 |
jari |
140 |
} catch(Exception e) { }; |
2 |
26 Feb 07 |
jari |
141 |
} |
2 |
26 Feb 07 |
jari |
142 |
|
2 |
26 Feb 07 |
jari |
/** evaluates the given command, but does not fetch the result (useful for assignment |
2 |
26 Feb 07 |
jari |
operations) |
2 |
26 Feb 07 |
jari |
@param cmd command/expression string |
2 |
26 Feb 07 |
jari |
@return <code>true</code> if successful */ |
2 |
26 Feb 07 |
jari |
147 |
public void voidEval(String cmd) throws RSrvException { |
2 |
26 Feb 07 |
jari |
148 |
if (!connected || rt==null) { |
2 |
26 Feb 07 |
jari |
149 |
lastError="Error: not connected!"; |
2 |
26 Feb 07 |
jari |
150 |
throw new RSrvException(this,lastError); |
2 |
26 Feb 07 |
jari |
151 |
} |
2 |
26 Feb 07 |
jari |
152 |
Rpacket rp=rt.request(Rtalk.CMD_voidEval,cmd+"\n"); |
2 |
26 Feb 07 |
jari |
153 |
if (rp!=null && rp.isOk()) return; |
2 |
26 Feb 07 |
jari |
154 |
lastError=(rp!=null)?"Request return code: "+rp.getStat():"Communication error (Rtalk returned null)"; |
2 |
26 Feb 07 |
jari |
155 |
throw new RSrvException(this,lastError,rp.getStat()); |
2 |
26 Feb 07 |
jari |
156 |
} |
2 |
26 Feb 07 |
jari |
157 |
|
2 |
26 Feb 07 |
jari |
/** evaluates the given command and retrieves the result |
2 |
26 Feb 07 |
jari |
@param cmd command/expression string |
2 |
26 Feb 07 |
jari |
@return R-xpression or <code>null</code> if an error occured */ |
2 |
26 Feb 07 |
jari |
161 |
public REXP eval(String cmd) throws RSrvException { |
2 |
26 Feb 07 |
jari |
162 |
if (!connected || rt==null) { |
2 |
26 Feb 07 |
jari |
163 |
lastError="Error: not connected!"; |
2 |
26 Feb 07 |
jari |
164 |
throw new RSrvException(this,lastError); |
2 |
26 Feb 07 |
jari |
165 |
} |
2 |
26 Feb 07 |
jari |
166 |
Rpacket rp=rt.request(Rtalk.CMD_eval,cmd+"\n"); |
2 |
26 Feb 07 |
jari |
167 |
if (rp!=null && rp.isOk()) { |
2 |
26 Feb 07 |
jari |
168 |
int rxo=0; |
2 |
26 Feb 07 |
jari |
169 |
byte[] pc=rp.getCont(); |
2 |
26 Feb 07 |
jari |
170 |
if (rsrvVersion>100) { /* since 0101 eval responds correctly by using DT_SEXP type/len header which is 4 bytes long */ |
2 |
26 Feb 07 |
jari |
171 |
rxo=4; |
2 |
26 Feb 07 |
jari |
/* we should check parameter type (should be DT_SEXP) and fail if it's not */ |
2 |
26 Feb 07 |
jari |
173 |
if (pc[0]!=Rtalk.DT_SEXP && pc[0]!=(Rtalk.DT_SEXP|Rtalk.DT_LARGE)) { |
2 |
26 Feb 07 |
jari |
174 |
lastError="Error while processing eval output: SEXP (type "+Rtalk.DT_SEXP+") expected but found result type "+pc[0]+"."; |
2 |
26 Feb 07 |
jari |
175 |
throw new RSrvException(this,lastError); |
2 |
26 Feb 07 |
jari |
176 |
} |
2 |
26 Feb 07 |
jari |
177 |
if (pc[0]==(Rtalk.DT_SEXP|Rtalk.DT_LARGE)) |
2 |
26 Feb 07 |
jari |
178 |
rxo=8; // large data need skip of 8 bytes |
2 |
26 Feb 07 |
jari |
/* warning: we are not checking or using the length - we assume that only the one SEXP is returned. This is true for the current CMD_eval implementation, but may not be in the future. */ |
2 |
26 Feb 07 |
jari |
180 |
} |
2 |
26 Feb 07 |
jari |
181 |
REXP rx=null; |
2 |
26 Feb 07 |
jari |
182 |
if (pc.length>rxo) { |
2 |
26 Feb 07 |
jari |
183 |
rx=new REXP(); |
2 |
26 Feb 07 |
jari |
184 |
REXP.parseREXP(rx,pc,rxo); |
2 |
26 Feb 07 |
jari |
185 |
} |
2 |
26 Feb 07 |
jari |
186 |
return rx; |
2 |
26 Feb 07 |
jari |
187 |
} |
2 |
26 Feb 07 |
jari |
188 |
lastError=(rp!=null)?"Request return code: "+rp.getStat():"Communication error (Rtalk returned null)"; |
2 |
26 Feb 07 |
jari |
189 |
throw new RSrvException(this,lastError,(rp!=null)?rp.getStat():-1); |
2 |
26 Feb 07 |
jari |
190 |
} |
2 |
26 Feb 07 |
jari |
191 |
|
2 |
26 Feb 07 |
jari |
/** assign a string value to a symbol in R. The symbol is created if it doesn't exist already. |
2 |
26 Feb 07 |
jari |
@param sym symbol name. Currently assign uses CMD_setSEXP command of Rserve, i.e. the symbol value is NOT parsed. It is the responsibility of the user to make sure that the symbol name is valid in R (recall the difference between a symbol and an expression!). In fact R will always create the symbol, but it may not be accessible (examples: "bar\nfoo" or "bar$foo"). |
2 |
26 Feb 07 |
jari |
@param ct contents |
2 |
26 Feb 07 |
jari |
@return <code>true</code> on success, otherwise <code>false</code> |
2 |
26 Feb 07 |
jari |
196 |
*/ |
2 |
26 Feb 07 |
jari |
197 |
public void assign(String sym, String ct) throws RSrvException { |
2 |
26 Feb 07 |
jari |
198 |
if (!connected || rt==null) { |
2 |
26 Feb 07 |
jari |
199 |
lastError="Error: not connected!"; |
2 |
26 Feb 07 |
jari |
200 |
throw new RSrvException(this,lastError); |
2 |
26 Feb 07 |
jari |
201 |
} |
2 |
26 Feb 07 |
jari |
202 |
byte[] symn=sym.getBytes(); |
2 |
26 Feb 07 |
jari |
203 |
byte[] ctn=ct.getBytes(); |
2 |
26 Feb 07 |
jari |
204 |
int sl=symn.length+1; |
2 |
26 Feb 07 |
jari |
205 |
int cl=ctn.length+1; |
2 |
26 Feb 07 |
jari |
206 |
if ((sl&3)>0) sl=(sl&0xfffffc)+4; // make sure the symbol length is divisible by 4 |
2 |
26 Feb 07 |
jari |
207 |
if ((cl&3)>0) cl=(cl&0xfffffc)+4; // make sure the content length is divisible by 4 |
2 |
26 Feb 07 |
jari |
208 |
byte[] rq=new byte[sl+4+cl+4]; |
2 |
26 Feb 07 |
jari |
209 |
int ic; |
2 |
26 Feb 07 |
jari |
210 |
for(ic=0;ic<symn.length;ic++) rq[ic+4]=symn[ic]; |
2 |
26 Feb 07 |
jari |
211 |
while (ic<sl) { rq[ic+4]=0; ic++; } |
2 |
26 Feb 07 |
jari |
212 |
for(ic=0;ic<ctn.length;ic++) rq[ic+sl+8]=ctn[ic]; |
2 |
26 Feb 07 |
jari |
213 |
while (ic<cl) { rq[ic+sl+8]=0; ic++; } |
2 |
26 Feb 07 |
jari |
214 |
Rtalk.setHdr(Rtalk.DT_STRING,sl,rq,0); |
2 |
26 Feb 07 |
jari |
215 |
Rtalk.setHdr(Rtalk.DT_STRING,cl,rq,sl+4); |
2 |
26 Feb 07 |
jari |
216 |
Rpacket rp=rt.request(Rtalk.CMD_setSEXP,rq); |
2 |
26 Feb 07 |
jari |
217 |
if (rp!=null && rp.isOk()) return; |
2 |
26 Feb 07 |
jari |
218 |
lastError=(rp!=null)?"Request return code: "+rp.getStat():"Communication error (Rtalk returned null)"; |
2 |
26 Feb 07 |
jari |
219 |
throw new RSrvException(this,lastError,(rp!=null)?rp.getStat():-1); |
2 |
26 Feb 07 |
jari |
220 |
} |
2 |
26 Feb 07 |
jari |
221 |
|
2 |
26 Feb 07 |
jari |
/** assign a content of a REXP to a symbol in R. The symbol is created if it doesn't exist already. |
2 |
26 Feb 07 |
jari |
@param sym symbol name. Currently assign uses CMD_setSEXP command of Rserve, i.e. the symbol value is NOT parsed. It is the responsibility of the user to make sure that the symbol name is valid in R (recall the difference between a symbol and an expression!). In fact R will always create the symbol, but it may not be accessible (examples: "bar\nfoo" or "bar$foo"). |
2 |
26 Feb 07 |
jari |
@param ct contents. currently only basic types (int, double, int[], double[]) are supported. |
2 |
26 Feb 07 |
jari |
@return <code>true</code> on success, otherwise <code>false</code> |
2 |
26 Feb 07 |
jari |
226 |
*/ |
2 |
26 Feb 07 |
jari |
227 |
public void assign(String sym, REXP r) throws RSrvException { |
2 |
26 Feb 07 |
jari |
228 |
if (!connected || rt==null) { |
2 |
26 Feb 07 |
jari |
229 |
lastError="Error: not connected!"; |
2 |
26 Feb 07 |
jari |
230 |
throw new RSrvException(this,lastError); |
2 |
26 Feb 07 |
jari |
231 |
} |
2 |
26 Feb 07 |
jari |
232 |
int rl=r.getBinaryLength(); |
2 |
26 Feb 07 |
jari |
233 |
byte[] symn=sym.getBytes(); |
2 |
26 Feb 07 |
jari |
234 |
int sl=symn.length+1; |
2 |
26 Feb 07 |
jari |
235 |
if ((sl&3)>0) sl=(sl&0xfffffc)+4; // make sure the symbol length is divisible by 4 |
2 |
26 Feb 07 |
jari |
236 |
byte[] rq=new byte[sl+rl+((rl>0xfffff0)?12:8)]; |
2 |
26 Feb 07 |
jari |
237 |
int ic; |
2 |
26 Feb 07 |
jari |
238 |
for(ic=0;ic<symn.length;ic++) rq[ic+4]=symn[ic]; |
2 |
26 Feb 07 |
jari |
239 |
while(ic<sl) { rq[ic+4]=0; ic++; }; // pad with 0 |
2 |
26 Feb 07 |
jari |
240 |
Rtalk.setHdr(Rtalk.DT_STRING,sl,rq,0); |
2 |
26 Feb 07 |
jari |
241 |
Rtalk.setHdr(Rtalk.DT_SEXP,rl,rq,sl+4); |
2 |
26 Feb 07 |
jari |
242 |
r.getBinaryRepresentation(rq,sl+((rl>0xfffff0)?12:8)); |
2 |
26 Feb 07 |
jari |
243 |
Rpacket rp=rt.request(Rtalk.CMD_setSEXP,rq); |
2 |
26 Feb 07 |
jari |
244 |
if (rp!=null && rp.isOk()) return; |
2 |
26 Feb 07 |
jari |
245 |
lastError=(rp!=null)?"Request return code: "+rp.getStat():"Communication error (Rtalk returned null)"; |
2 |
26 Feb 07 |
jari |
246 |
throw new RSrvException(this,lastError,(rp!=null)?rp.getStat():-1); |
2 |
26 Feb 07 |
jari |
247 |
} |
2 |
26 Feb 07 |
jari |
248 |
|
2 |
26 Feb 07 |
jari |
/** assign values of an array of doubles to a symbol in R (creating as vector of numbers).<br> |
2 |
26 Feb 07 |
jari |
equals to calling {@link #assign(String, REXP)} */ |
2 |
26 Feb 07 |
jari |
251 |
public void assign(String sym, double[] val) throws RSrvException { |
2 |
26 Feb 07 |
jari |
252 |
assign(sym,new REXP(val)); |
2 |
26 Feb 07 |
jari |
253 |
} |
2 |
26 Feb 07 |
jari |
254 |
|
2 |
26 Feb 07 |
jari |
/** assign values of an array of integers to a symbol in R (creating as vector of numbers).<br> |
2 |
26 Feb 07 |
jari |
equals to calling {@link #assign(String, REXP)} */ |
2 |
26 Feb 07 |
jari |
257 |
public void assign(String sym, int[] val) throws RSrvException { |
2 |
26 Feb 07 |
jari |
258 |
assign(sym,new REXP(val)); |
2 |
26 Feb 07 |
jari |
259 |
} |
2 |
26 Feb 07 |
jari |
260 |
|
2 |
26 Feb 07 |
jari |
/** open a file on the Rserve for reading |
2 |
26 Feb 07 |
jari |
@param fn file name. should not contain any path delimiters, since Rserve may restrict the access to local working directory. |
2 |
26 Feb 07 |
jari |
@return input stream to be used for reading. Note that the stream is read-once only, there is no support for seek or rewind. */ |
2 |
26 Feb 07 |
jari |
264 |
public RFileInputStream openFile(String fn) throws IOException { |
2 |
26 Feb 07 |
jari |
265 |
return new RFileInputStream(rt,fn); |
2 |
26 Feb 07 |
jari |
266 |
} |
2 |
26 Feb 07 |
jari |
267 |
|
2 |
26 Feb 07 |
jari |
/** create a file on the Rserve for writing |
2 |
26 Feb 07 |
jari |
@param fn file name. should not contain any path delimiters, since Rserve may restrict the access to local working directory. |
2 |
26 Feb 07 |
jari |
@return output stream to be used for writinging. Note that the stream is write-once only, there is no support for seek or rewind. */ |
2 |
26 Feb 07 |
jari |
271 |
public RFileOutputStream createFile(String fn) throws IOException { |
2 |
26 Feb 07 |
jari |
272 |
return new RFileOutputStream(rt,fn); |
2 |
26 Feb 07 |
jari |
273 |
} |
2 |
26 Feb 07 |
jari |
274 |
|
2 |
26 Feb 07 |
jari |
/** remove a file on the Rserve |
2 |
26 Feb 07 |
jari |
@param fn file name. should not contain any path delimiters, since Rserve may restrict the access to local working directory. |
2 |
26 Feb 07 |
jari |
@return <code>true</code> on success, <code>false</code> otherwise */ |
2 |
26 Feb 07 |
jari |
278 |
public void removeFile(String fn) throws RSrvException { |
2 |
26 Feb 07 |
jari |
279 |
if (!connected || rt==null) { |
2 |
26 Feb 07 |
jari |
280 |
lastError="Error: not connected"; |
2 |
26 Feb 07 |
jari |
281 |
throw new RSrvException(this,lastError); |
2 |
26 Feb 07 |
jari |
282 |
} |
2 |
26 Feb 07 |
jari |
283 |
Rpacket rp=rt.request(Rtalk.CMD_removeFile,fn); |
2 |
26 Feb 07 |
jari |
284 |
if (rp!=null && rp.isOk()) return; |
2 |
26 Feb 07 |
jari |
285 |
lastError=(rp!=null)?"Request return code: "+rp.getStat():"Communication error (Rtalk returned null)"; |
2 |
26 Feb 07 |
jari |
286 |
throw new RSrvException(this,lastError,(rp!=null)?rp.getStat():-1); |
2 |
26 Feb 07 |
jari |
287 |
} |
2 |
26 Feb 07 |
jari |
288 |
|
2 |
26 Feb 07 |
jari |
/** shutdown remote Rserv. Note that some Rserves cannot be shut down from |
2 |
26 Feb 07 |
jari |
client side (forked version). */ |
2 |
26 Feb 07 |
jari |
291 |
public void shutdown() throws RSrvException { |
2 |
26 Feb 07 |
jari |
292 |
if (!connected || rt==null) { |
2 |
26 Feb 07 |
jari |
293 |
lastError="Error: not connected"; |
2 |
26 Feb 07 |
jari |
294 |
throw new RSrvException(this,lastError); |
2 |
26 Feb 07 |
jari |
295 |
} |
2 |
26 Feb 07 |
jari |
296 |
Rpacket rp=rt.request(Rtalk.CMD_shutdown); |
2 |
26 Feb 07 |
jari |
297 |
if (rp!=null && rp.isOk()) return; |
2 |
26 Feb 07 |
jari |
298 |
lastError=(rp!=null)?"Request return code: "+rp.getStat():"Communication error (Rtalk returned null)"; |
2 |
26 Feb 07 |
jari |
299 |
throw new RSrvException(this,lastError,(rp!=null)?rp.getStat():-1); |
2 |
26 Feb 07 |
jari |
300 |
} |
2 |
26 Feb 07 |
jari |
301 |
|
2 |
26 Feb 07 |
jari |
/** Sets send buffer size of the Rserve (in bytes) for the current connection. All responses send by Rserve are stored in the send buffer before transmitting. This means that any objects you want to get from the Rserve need to fit into that buffer. By default the size of the send buffer is 2MB. If you need to receive larger objects from Rserve, you will need to use this function to enlarge the buffer. In order to save memory, you can also reduce the buffer size once it's not used anymore. Currently the buffer size is only limited by the memory available and/or 1GB (whichever is smaller). Current Rserve implementations won't go below buffer sizes of 32kb though. If the specified buffer size results in 'out of memory' on the server, the corresponding error is sent and the connection is terminated.<br> |
2 |
26 Feb 07 |
jari |
<i>Note:</i> This command may go away in future versions of Rserve which will use dynamic send buffer allocation. |
2 |
26 Feb 07 |
jari |
@param sbs send buffer size (in bytes) min=32k, max=1GB |
2 |
26 Feb 07 |
jari |
305 |
*/ |
2 |
26 Feb 07 |
jari |
306 |
public void setSendBufferSize(long sbs) throws RSrvException { |
2 |
26 Feb 07 |
jari |
307 |
if (!connected || rt==null) { |
2 |
26 Feb 07 |
jari |
308 |
lastError="Error: not connected"; |
2 |
26 Feb 07 |
jari |
309 |
throw new RSrvException(this,lastError); |
2 |
26 Feb 07 |
jari |
310 |
} |
2 |
26 Feb 07 |
jari |
311 |
Rpacket rp=rt.request(Rtalk.CMD_setBufferSize,(int)sbs); |
2 |
26 Feb 07 |
jari |
312 |
if (rp!=null && rp.isOk()) return; |
2 |
26 Feb 07 |
jari |
313 |
lastError=(rp!=null)?"Request return code: "+rp.getStat():"Communication error (Rtalk returned null)"; |
2 |
26 Feb 07 |
jari |
314 |
throw new RSrvException(this,lastError,(rp!=null)?rp.getStat():-1); |
2 |
26 Feb 07 |
jari |
315 |
} |
2 |
26 Feb 07 |
jari |
316 |
|
2 |
26 Feb 07 |
jari |
/** login using supplied user/pwd. Note that login must be the first |
2 |
26 Feb 07 |
jari |
command if used |
2 |
26 Feb 07 |
jari |
@param user username |
2 |
26 Feb 07 |
jari |
@param pwd password |
2 |
26 Feb 07 |
jari |
@return returns <code>true</code> on success */ |
2 |
26 Feb 07 |
jari |
322 |
public void login(String user, String pwd) throws RSrvException { |
2 |
26 Feb 07 |
jari |
323 |
if (!authReq) return; |
2 |
26 Feb 07 |
jari |
324 |
if (authType==AT_crypt) { |
2 |
26 Feb 07 |
jari |
325 |
if (Key==null) Key="rs"; |
2 |
26 Feb 07 |
jari |
326 |
Rpacket rp=rt.request(Rtalk.CMD_login,user+"\n"+jcrypt.crypt(Key,pwd)); |
2 |
26 Feb 07 |
jari |
327 |
if (rp!=null && rp.isOk()) return; |
2 |
26 Feb 07 |
jari |
328 |
lastError=(rp!=null)?"Request return code: "+rp.getStat():"Communication error (Rtalk returned null)"; |
2 |
26 Feb 07 |
jari |
329 |
try { s.close(); } catch(Exception e) {}; |
2 |
26 Feb 07 |
jari |
330 |
is=null; os=null; s=null; connected=false; |
2 |
26 Feb 07 |
jari |
331 |
throw new RSrvException(this,lastError); |
2 |
26 Feb 07 |
jari |
332 |
} |
2 |
26 Feb 07 |
jari |
333 |
Rpacket rp=rt.request(Rtalk.CMD_login,user+"\n"+pwd); |
2 |
26 Feb 07 |
jari |
334 |
if (rp!=null && rp.isOk()) return; |
2 |
26 Feb 07 |
jari |
335 |
lastError=(rp!=null)?"Request return code: "+rp.getStat():"Communication error (Rtalk returned null)"; |
2 |
26 Feb 07 |
jari |
336 |
try {s.close();} catch (Exception e) {}; |
2 |
26 Feb 07 |
jari |
337 |
is=null; os=null; s=null; connected=false; |
2 |
26 Feb 07 |
jari |
338 |
throw new RSrvException(this,lastError,(rp!=null)?rp.getStat():-1); |
2 |
26 Feb 07 |
jari |
339 |
} |
2 |
26 Feb 07 |
jari |
340 |
|
2 |
26 Feb 07 |
jari |
/** check connection state. Note that currently this state is not checked on-the-spot, |
2 |
26 Feb 07 |
jari |
that is if connection went down by an outside event this is not reflected by |
2 |
26 Feb 07 |
jari |
the flag |
2 |
26 Feb 07 |
jari |
@return <code>true</code> if this connection is alive */ |
2 |
26 Feb 07 |
jari |
345 |
public boolean isConnected() { return connected; } |
2 |
26 Feb 07 |
jari |
346 |
|
2 |
26 Feb 07 |
jari |
/** check authentication requirement sent by server |
2 |
26 Feb 07 |
jari |
@return <code>true</code> is server requires authentication. In such case first |
2 |
26 Feb 07 |
jari |
command after connecting must be {@link #login}. */ |
2 |
26 Feb 07 |
jari |
350 |
public boolean needLogin() { return authReq; } |
2 |
26 Feb 07 |
jari |
351 |
|
2 |
26 Feb 07 |
jari |
/** get last error string |
2 |
26 Feb 07 |
jari |
@return last error string */ |
2 |
26 Feb 07 |
jari |
354 |
public String getLastError() { return lastError; } |
2 |
26 Feb 07 |
jari |
355 |
} |
2 |
26 Feb 07 |
jari |
356 |
|