/** * Wraps the execution of an arbitrary R expression. Both errors and results are logged. * * @param input * The R expression to evaluate. * * @return The result or the error of the evaluation of the given R expression. The method tries to convert it into a string, if possible. */ public Object evalWithR(final String input) throws InvalidREvaluationResultException { Object out = null; try { out = this.rCon.eval(input); Object output = null; if (out instanceof REXPString) { output = ((REXPString) out).asString(); } else if (out instanceof REXPLogical) { output = ((REXPLogical) out).toDebugString(); } else if (out != null) { output = out; } else { throw new InvalidREvaluationResultException("Got a null result for evaluation input: \"" + input + "\""); } RBridgeControl.LOGGER.trace("> REXP: {} return: {}", input, output); } catch (final REXPMismatchException exc) { RBridgeControl.LOGGER.error("Error R expr.: {} Cause: {}", input, exc.getMessage(), exc); } return out; }
REXP parseEvalResponse(RPacket rp) throws RserveException { int rxo=0; byte[] pc=rp.getCont(); if (rsrvVersion>100) { /* since 0101 eval responds correctly by using DT_SEXP type/len header which is 4 bytes long */ rxo=4; /* we should check parameter type (should be DT_SEXP) and fail if it's not */ if (pc[0]!=RTalk.DT_SEXP && pc[0]!=(RTalk.DT_SEXP|RTalk.DT_LARGE)) throw new RserveException(this,"Error while processing eval output: SEXP (type "+RTalk.DT_SEXP+") expected but found result type "+pc[0]+"."); if (pc[0]==(RTalk.DT_SEXP|RTalk.DT_LARGE)) rxo=8; // large data need skip of 8 bytes /* 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. */ } if (pc.length>rxo) { try { REXPFactory rx=new REXPFactory(); rx.parseREXP(pc, rxo); return rx.getREXP(); } catch (REXPMismatchException me) { me.printStackTrace(); throw new RserveException(this, "Error when parsing response: " + me.getMessage(), me); } } return null; }
REXP parseEvalResponse(RPacket rp) throws RserveException { int rxo=0; byte[] pc=rp.getCont(); if (rsrvVersion>100) { /* since 0101 eval responds correctly by using DT_SEXP type/len header which is 4 bytes long */ rxo=4; /* we should check parameter type (should be DT_SEXP) and fail if it's not */ if (pc[0]!=RTalk.DT_SEXP && pc[0]!=(RTalk.DT_SEXP|RTalk.DT_LARGE)) throw new RserveException(this,"Error while processing eval output: SEXP (type "+RTalk.DT_SEXP+") expected but found result type "+pc[0]+"."); if (pc[0]==(RTalk.DT_SEXP|RTalk.DT_LARGE)) rxo=8; // large data need skip of 8 bytes /* 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. */ } if (pc.length>rxo) { try { REXPFactory rx=new REXPFactory(); rx.parseREXP(pc, rxo); return rx.getREXP(); } catch (REXPMismatchException me) { me.printStackTrace(); throw new RserveException(this, "Error when parsing response: "+me.getMessage()); } } return null; }
/** assign a content of a REXP to a symbol in R. The symbol is created if it doesn't exist already. * @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"). * @param rexp contents */ public void assign(String sym, REXP rexp) throws RserveException { if (!connected || rt==null) throw new RserveException(this,"Not connected"); try { REXPFactory r = new REXPFactory(rexp); int rl=r.getBinaryLength(); byte[] symn=sym.getBytes(); int sl=symn.length+1; if ((sl&3)>0) sl=(sl&0xfffffc)+4; // make sure the symbol length is divisible by 4 byte[] rq=new byte[sl+rl+((rl>0xfffff0)?12:8)]; int ic; for(ic=0;ic<symn.length;ic++) rq[ic+4]=symn[ic]; while(ic<sl) { rq[ic+4]=0; ic++; }; // pad with 0 RTalk.setHdr(RTalk.DT_STRING,sl,rq,0); RTalk.setHdr(RTalk.DT_SEXP,rl,rq,sl+4); r.getBinaryRepresentation(rq,sl+((rl>0xfffff0)?12:8)); RPacket rp=rt.request(RTalk.CMD_setSEXP,rq); if (rp!=null && rp.isOk()) return; throw new RserveException(this,"assign failed",rp); } catch (REXPMismatchException me) { throw new RserveException(this, "Error creating binary representation: "+me.getMessage(), me); } }
/** assign a content of a REXP to a symbol in R. The symbol is created if it doesn't exist already. * @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"). * @param rexp contents */ public void assign(String sym, REXP rexp) throws RserveException { if (!connected || rt==null) throw new RserveException(this,"Not connected"); try { REXPFactory r = new REXPFactory(rexp); int rl=r.getBinaryLength(); byte[] symn=sym.getBytes(); int sl=symn.length+1; if ((sl&3)>0) sl=(sl&0xfffffc)+4; // make sure the symbol length is divisible by 4 byte[] rq=new byte[sl+rl+((rl>0xfffff0)?12:8)]; int ic; for(ic=0;ic<symn.length;ic++) rq[ic+4]=symn[ic]; while(ic<sl) { rq[ic+4]=0; ic++; }; // pad with 0 RTalk.setHdr(RTalk.DT_STRING,sl,rq,0); RTalk.setHdr(RTalk.DT_SEXP,rl,rq,sl+4); r.getBinaryRepresentation(rq,sl+((rl>0xfffff0)?12:8)); RPacket rp=rt.request(RTalk.CMD_setSEXP,rq); if (rp!=null && rp.isOk()) return; throw new RserveException(this,"assign failed",rp); } catch (REXPMismatchException me) { throw new RserveException(this, "Error creating binary representation: "+me.getMessage()); } }
public REXP eval(REXP what, REXP where, boolean resolve) throws REngineException { if (!connected || rt==null) throw new RserveException(this, "Not connected"); if (where != null) throw new REngineException(this, "Rserve doesn't support environments other than .GlobalEnv"); try { REXPFactory r = new REXPFactory(what); int rl = r.getBinaryLength(); byte[] rq = new byte[rl + ((rl > 0xfffff0) ? 8 : 4)]; RTalk.setHdr(RTalk.DT_SEXP, rl, rq, 0); r.getBinaryRepresentation(rq, ((rl > 0xfffff0) ? 8 : 4)); RPacket rp = rt.request(resolve ? RTalk.CMD_eval : RTalk.CMD_voidEval, rq); if (rp != null && rp.isOk()) return parseEvalResponse(rp); throw new RserveException(this,"eval failed", rp); } catch (REXPMismatchException me) { throw new RserveException(this, "Error creating binary representation: " + me.getMessage(), me); } }
} catch (REXPMismatchException e) { callback.fail("RShell failed: " + e.getMessage(), e); } catch (REngineException e) {