mev-4.0.01/source/org/tigr/microarray/mev/r/Rconnection.java

Code
Comments
Other
Rev Date Author Line
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 6 /**  class providing TCP/IP connection to an Rserv
2 26 Feb 07 jari 7      @version $Id$
2 26 Feb 07 jari 8 */
2 26 Feb 07 jari 9 public class Rconnection {
2 26 Feb 07 jari 10     /** 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 21     /** 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 24     /** authorization type: plain text */
2 26 Feb 07 jari 25     public static final int AT_plain = 0;
2 26 Feb 07 jari 26     /** 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 29     /** 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 32     /** 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 37     /** make a new connection to specified host on default port (6311)
2 26 Feb 07 jari 38   @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 44     /** make a new connection to specified host and given port.
2 26 Feb 07 jari 45   Make sure you check {@link #isConnected} and/or {@link #isOk}.
2 26 Feb 07 jari 46   @param host host name/IP
2 26 Feb 07 jari 47   @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 59       // 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 91             // 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 129     /** get server version as reported during the handshake.
2 26 Feb 07 jari 130         @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 135     /** 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 143     /** evaluates the given command, but does not fetch the result (useful for assignment
2 26 Feb 07 jari 144   operations)
2 26 Feb 07 jari 145   @param cmd command/expression string
2 26 Feb 07 jari 146   @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 158     /** evaluates the given command and retrieves the result
2 26 Feb 07 jari 159   @param cmd command/expression string
2 26 Feb 07 jari 160   @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 172                 /* 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 179                 /* 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 192     /** assign a string value to a symbol in R. The symbol is created if it doesn't exist already.
2 26 Feb 07 jari 193         @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 194         @param ct contents
2 26 Feb 07 jari 195         @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 222     /** 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 223         @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 224         @param ct contents. currently only basic types (int, double, int[], double[]) are supported.
2 26 Feb 07 jari 225         @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 249     /** assign values of an array of doubles to a symbol in R (creating as vector of numbers).<br>
2 26 Feb 07 jari 250         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 255     /** assign values of an array of integers to a symbol in R (creating as vector of numbers).<br>
2 26 Feb 07 jari 256         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 261     /** open a file on the Rserve for reading
2 26 Feb 07 jari 262         @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 263         @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 268     /** create a file on the Rserve for writing
2 26 Feb 07 jari 269         @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 270         @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 275     /** remove a file on the Rserve
2 26 Feb 07 jari 276         @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 277         @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 289     /** shutdown remote Rserv. Note that some Rserves cannot be shut down from
2 26 Feb 07 jari 290   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 302     /** 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 303         <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 304         @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 317     /** login using supplied user/pwd. Note that login must be the first
2 26 Feb 07 jari 318   command if used
2 26 Feb 07 jari 319   @param user username
2 26 Feb 07 jari 320   @param pwd password
2 26 Feb 07 jari 321   @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 341     /** check connection state. Note that currently this state is not checked on-the-spot,
2 26 Feb 07 jari 342   that is if connection went down by an outside event this is not reflected by
2 26 Feb 07 jari 343   the flag
2 26 Feb 07 jari 344   @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 347     /** check authentication requirement sent by server
2 26 Feb 07 jari 348   @return <code>true</code> is server requires authentication. In such case first
2 26 Feb 07 jari 349   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 352     /** get last error string
2 26 Feb 07 jari 353   @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