Java tutorial
/* * Copyright 2013 VTT Technical Research Centre of Finland * * Licensed under the Apache License, Version 2.0 (the "License"); you may not * use this file except in compliance with the License. You may obtain a copy of * the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the * License for the specific language governing permissions and limitations under * the License. */ package fi.vtt.RVaadin; import java.io.ByteArrayInputStream; import java.io.InputStream; import java.util.concurrent.Semaphore; import org.rosuda.REngine.REXP; import org.rosuda.REngine.REXPMismatchException; import org.rosuda.REngine.Rserve.RConnection; import org.rosuda.REngine.Rserve.RserveException; import com.vaadin.server.StreamResource; /** * RImageSource wraps the R graphics generated by Rserve into a * StreamResource.StreamSource object to be used with Vaadin. See The Book of * Vaadin for more details (under Section Stream Resources) and the * 'PlotDemo.java' example from the Rserve source package. * * @author Arho Virkki */ @SuppressWarnings("serial") public class RImageSource implements StreamResource.StreamSource { private RConnection rc; private String RPlotCall; /* Plot geometry */ private int width = 500; private int height = 500; /* Semaphore reference for not calling R simultaneously */ private Semaphore semaphore = null; /* Image type */ String device = "png"; /** * Construct the SteamSource for given R connection and plot command, and * fine-tune the device size with additional parameters. * * @param rc * The R connection * @param RPlotCall * The string to contain the plot call * @param width * Width of the plot * @param height * Height of the plot * @param Semaphore * to restrict the R access to one thread * @param device * Device type ("png", "pdf",...) * */ public RImageSource(RConnection rc, String RPlotCall, int width, int height, Semaphore semaphore, String device) { this.rc = rc; this.RPlotCall = RPlotCall; this.width = width; this.height = height; this.semaphore = semaphore; this.device = device; } /* The method which returns the R graphics as a stream */ public InputStream getStream() { try { semaphore.acquire(); // System.out.println("Semaphore acquired"); // System.out.flush(); /* The R Cairo package is used for high-quality graphics */ boolean CairoOK = rc.parseAndEval("suppressWarnings(require('Cairo',quietly=TRUE))").asInteger() > 0; if (!CairoOK) { System.err.println("RVaadin: Could not find Cairo package"); rc.parseAndEval("cat('RVaadin: Error: " + "Could not find Cairo package.\n')"); } /* * Observe the usage of R's try and error mechanism in Java, and * remember that device == 'png', 'pdf', ... */ REXP xp = rc.parseAndEval("try(Cairo" + device.toUpperCase() + "('tmp." + device + "', " + "width=" + width + ", height=" + height + "))"); if (xp.inherits("try-error")) { System.err.println("Can't open " + device + " graphics device:\n" + xp.asString()); /* Plot the first warning into the error console */ REXP w = rc.eval("if (exists('last.warning') && " + "length(last.warning)>0) " + "names(last.warning)[1] else 0"); if (w.isString()) { System.err.println(w.asString()); } } /* * Now, state the actual plot command and then close the Cairo * device to produce the graphics */ rc.parseAndEval(RPlotCall); rc.parseAndEval("dev.off()"); /* * The author of RServe claims that there is no I/O API for REngine * as it's actually more efficient to use R. */ String fileName = "tmp." + device; xp = rc.parseAndEval("r <- readBin('" + fileName + "','raw', file.info('" + fileName + "')$size); " + "unlink('" + fileName + "'); r"); return new ByteArrayInputStream(xp.asBytes()); } catch (RserveException rse) { /* RserveException (transport layer - e.g. Rserve is not running */ System.out.println(rse); return null; } catch (REXPMismatchException mme) { /* REXP mismatch exception (we got something else as expected) */ System.out.println(mme); mme.printStackTrace(); return null; } catch (Exception e) { /* something else */ System.err.println("Errors in RPLotCall: " + e.getMessage()); e.printStackTrace(); return null; } finally { semaphore.release(); // System.out.println("Semaphore released"); // System.out.flush(); } } }