Logo Search packages:      
Sourcecode: rjava version File versions  Download package

JRIBootstrap.java

import java.io.File;
import java.io.PrintStream;
import java.io.FileOutputStream;
import java.io.BufferedReader;
import java.io.FileReader;
import java.lang.reflect.Constructor;
import java.lang.reflect.Method;
import java.util.StringTokenizer;

public class JRIBootstrap {
      //--- global constants ---
      public static final int HKLM = 0; // HKEY_LOCAL_MACHINE
      public static final int HKCU = 1; // HKEY_CURRENT_USER

      //--- native methods ---
      public static native String getenv(String var);
      public static native void setenv(String var, String val);

      public static native String regvalue(int root, String key, String value);
      public static native String[] regsubkeys(int root, String key);

      public static native String expand(String val);

      public static native boolean hasreg();

      public static native String arch();

      //--- helper methods ---      
      static void fail(String msg) {
            System.err.println("ERROR: "+msg);
            System.exit(1);
      }

        public static String findInPath(String path, String fn, boolean mustBeFile) {
                StringTokenizer st = new StringTokenizer(path, File.pathSeparator);
                while (st.hasMoreTokens()) {
                        String dirname=st.nextToken();
                        try {
                                File f = new File(dirname+File.separator+fn);
                        System.out.println(" * "+f+" ("+f.exists()+", "+f.isFile()+")");
                                if (f.exists() && (!mustBeFile || f.isFile())) return f.getPath();
                        } catch (Exception fex) {}
                }
                return null;
        }

    // set ONLY after findR was run
    public static boolean isWin32 = false;
    public static boolean isMac = false;

    static String findR(boolean findAllSettings) {
      String ip = null;
      try {
          if (hasreg()) {
            isWin32 = true;
            int rroot = HKLM;
            System.out.println("has registry, trying to find R");
            ip = regvalue(HKLM, "SOFTWARE\\R-core\\R","InstallPath");
            if (ip == null)
                ip = regvalue(rroot=HKCU, "SOFTWARE\\R-core\\R","InstallPath");
            if (ip == null) {
                System.out.println(" - InstallPath not present (possibly uninstalled R)");
                String[] vers = regsubkeys(rroot=HKLM, "SOFTWARE\\R-core\\R");
                if (vers == null)
                  vers = regsubkeys(rroot=HKCU, "SOFTWARE\\R-core\\R");
                if (vers!=null) {
                  String lvn = ""; // FIXME: we compare versions lexicographically which may fail if we really reach R 2.10
                  int i = 0; while (i<vers.length) {
                      if (vers[i] != null && lvn.compareTo(vers[i]) < 0)
                        lvn = vers[i];
                      i++;
                  }
                  if (!lvn.equals(""))
                      ip = regvalue(rroot, "SOFTWARE\\R-core\\R\\"+lvn, "InstallPath");
                }
            }
            if (ip == null) {
                ip = getenv("R_HOME");
                if (ip==null || ip.length()<1) ip = getenv("RHOME");
                if (ip==null || ip.length()<1) ip=null;
            }
            if (ip != null) rs_home = ip;
            return ip;
          }
          isMac = System.getProperty("os.name").startsWith("Mac");
          File f = null;
          ip = getenv("R_HOME");
          if (ip == null || ip.length()<1)
            ip = getenv("RHOME");
          if (ip == null || ip.length()<1) {
            if (isMac) {
                f=new File("/Library/Frameworks/R.framework/Resources/bin/R");
                if (!f.exists())
                  f=new File(getenv("HOME")+"/Library/Frameworks/R.framework/Resources/bin/R");
                if (!f.exists())
                  f=null;
            }
            if (f==null) {
                String fn = findInPath(getenv("PATH"), "R", true);
                if (fn == null)
                  fn = findInPath("/usr/bin:/usr/local/bin:/sw/bin:/opt/bin:/usr/lib/R/bin:/usr/local/lib/R/bin", "R", true);
                if (fn != null) f = new File(fn);
            }
            if (!findAllSettings) {
                String s = f.getAbsolutePath();
                if (s.length()>6) ip = s.substring(0, s.length()-6);
            }
          }
          if (findAllSettings) {
            if (f==null && ip!=null) f=new File(u2w(ip+"/bin/R"));
            if (f!=null) ip = getRSettings(f.getAbsolutePath());
          }

      } catch (Exception e) {
      }
      return ip;
    }

    public static String rs_home = "";
    public static String rs_arch = "";
    public static String rs_docdir = "";
    public static String rs_incdir = "";
    public static String rs_sharedir = "";
    public static String rs_ldp = "";
    public static String rs_dyldp = "";
    public static String rs_unzip = "";
    public static String rs_latex = "";
    public static String rs_paper = "";
    public static String rs_print = "";
    public static String rs_libs = "";

    public static void setREnv() {
      if (rs_home!=null && rs_home.length()>0) setenv("R_HOME", rs_home);
      if (rs_arch!=null && rs_arch.length()>0) setenv("R_ARCH", rs_arch);
      if (rs_docdir!=null && rs_docdir.length()>0) setenv("R_DOC_DIR", rs_docdir);
      if (rs_incdir!=null && rs_incdir.length()>0) setenv("R_INCLUDE_DIR", rs_incdir);
      if (rs_sharedir!=null && rs_sharedir.length()>0) setenv("R_SHARE_DIR", rs_sharedir);
      if (rs_ldp!=null && rs_ldp.length()>0) setenv("LD_LIBRARY_PATH", rs_ldp);
      if (rs_dyldp!=null && rs_dyldp.length()>0) setenv("DYLD_LIBRARY_PATH", rs_dyldp);
      if (rs_libs!=null && rs_libs.length()>0) setenv("R_LIBS", rs_libs);
    }

    public static int execR(String cmd) {
      try {
          String binR = u2w(rs_home+"/bin/R");
          if (isWin32) {
            binR+=".exe";
            File fin = File.createTempFile("rboot",".R");
            File fout = File.createTempFile("rboot",".tmp");
            PrintStream p = new PrintStream(new FileOutputStream(fin));
            p.println(cmd);
            p.close();
            Process rp = Runtime.getRuntime().exec(new String[] {
                  binR,"CMD","BATCH","--no-restore","--no-save","--slave",fin.getAbsolutePath(),
                  fout.getAbsolutePath()});
            int i = rp.waitFor();
            if (!fin.delete()) fin.deleteOnExit();
            if (!fout.delete()) fout.deleteOnExit();
            return i;
          } else {
            Process rp = Runtime.getRuntime().exec(new String[] {
                  "/bin/sh","-c","echo \""+cmd+"\" |"+binR+" --no-restore --no-save --slave >/dev/null 2>&1" });
            return rp.waitFor();
          }
      } catch (Exception e) {
          lastError = e.toString();
          return -1;
      }
    }

    public static String getRSettings(String binR) {
      try {
          File fin = File.createTempFile("rboot",".R");
          File fout = File.createTempFile("rboot",".tmp");
          PrintStream p = new PrintStream(new FileOutputStream(fin));
          p.println("cat(unlist(lapply(c('R_HOME','R_ARCH','R_DOC_DIR','R_INCLUDE_DIR','R_SHARE_DIR','LD_LIBRARY_PATH','DYLD_LIBRARY_PATH','R_UNZIPCMD','R_LATEXCMD','R_PAPERSIZE','R_PRINTCMD'),Sys.getenv)),sep='\n')");
          p.println("cat(paste(.libPaths(),collapse=.Platform$path.sep),'\n',sep='')");
          p.close();
          Process rp = Runtime.getRuntime().exec(new String[] {
                "/bin/sh","-c",binR+" --no-restore --no-save --slave < \""+fin.getAbsolutePath()+"\" > \""+fout.getAbsolutePath()+"\"" });
          int i = rp.waitFor();
          System.out.println("getRSettings, i="+i);
          BufferedReader r = new BufferedReader(new FileReader(fout));
          rs_home = r.readLine();
          rs_arch = r.readLine();
          rs_docdir = r.readLine();
          rs_incdir = r.readLine();
          rs_sharedir = r.readLine();
          rs_ldp = r.readLine();
          rs_dyldp = r.readLine();
          rs_unzip = r.readLine();
          rs_latex = r.readLine();
          rs_paper = r.readLine();
          rs_print = r.readLine();
          rs_libs = r.readLine();
          r.close();
          if (!fin.delete()) fin.deleteOnExit();
          //if (!fout.delete()) fout.deleteOnExit();
          System.out.println(" - retrieved R settings, home: "+rs_home+" (arch="+rs_arch+", libs="+rs_libs+")");
      } catch (Exception e) {
          System.err.println("Failed to get R settings: "+e);
      }
      return rs_home;
    }

    public static String u2w(String fn) {
      return (java.io.File.separatorChar != '/')?fn.replace('/',java.io.File.separatorChar):fn;
    }

    public static Object bootRJavaLoader = null;

    public static Object getBootRJavaLoader() {
      System.out.println("JRIBootstrap.bootRJavaLoader="+bootRJavaLoader);
      return bootRJavaLoader;
    }

    static void addClassPath(String s) {
      if (bootRJavaLoader==null) return;
      try {
          Method m = bootRJavaLoader.getClass().getMethod("addClassPath", new Class[] { String.class });
          m.invoke(bootRJavaLoader, new Object[] { s });
      } catch (Exception e) {
          System.err.println("FAILED: JRIBootstrap.addClassPath");
      }
    }

    static String lastError = "";

    static String findPackage(String name) {
      String pd = null;
      if (rs_libs!=null && rs_libs.length()>0)
          pd = findInPath(rs_libs, name, false);
      if (pd == null) {
          pd = u2w(rs_home+"/library/"+name);
          if (!(new File(pd)).exists()) pd = null;
      }
      return pd;  
    }

    static Object createRJavaLoader(String rhome, String[] cp, boolean addJRI) {
      String rJavaRoot = null;
      if (rs_libs!=null && rs_libs.length()>0)
          rJavaRoot = findInPath(rs_libs, "rJava", false);
      if (rJavaRoot == null)
          rJavaRoot = u2w(rhome+"/library/rJava");

      if (!(new File(rJavaRoot)).exists()) {
          lastError="Unable to find rJava";
          return null;
      }

      File f = new File(u2w(rJavaRoot+"/java/boot"));
      if (!f.exists()) {
          // try harder ...
          lastError = "rJava too old";
          return null;
      }
      String rJavaHome = u2w(rJavaRoot);
      File lf = null;
      if (rs_arch!=null && rs_arch.length()>0) lf = new File(u2w(rJavaRoot+"/libs"+rs_arch));
      if (lf == null || !lf.exists()) lf = new File(u2w(rJavaRoot+"/libs/"+arch()));
      if (!lf.exists()) lf = new File(u2w(rJavaRoot+"/libs"));
      String rJavaLibs = lf.toString();
      JRIClassLoader mcl = JRIClassLoader.getMainLoader();
      mcl.addClassPath(f.toString()); // add rJava boot to primary CP
      try {
          // force the use of the MCL even if the system loader could find it
          Class rjlclass = mcl.findAndLinkClass("RJavaClassLoader");
          Constructor c = rjlclass.getConstructor(new Class[] { String.class, String.class });
          Object rjcl = c.newInstance(new Object[] { rJavaHome, rJavaLibs });
          System.out.println("RJavaClassLoader: "+rjcl);
          if (addJRI) {
            if (cp==null || cp.length==0)
                cp = new String[] { u2w(rJavaRoot+"/jri/JRI.jar") };
            else {
                String[] ncp = new String[cp.length+1];
                System.arraycopy(cp, 0, ncp, 1, cp.length);
                ncp[0] = u2w(rJavaRoot+"/jri/JRI.jar");
                cp = ncp;
            }
          }
          if (cp==null || cp.length==0)
            cp = new String[] { u2w(rJavaRoot+"/java/boot") };
          else {
            String[] ncp = new String[cp.length+1];
            System.arraycopy(cp, 0, ncp, 1, cp.length);
            ncp[0] = u2w(rJavaRoot+"/java/boot");
            cp = ncp;
          }
          if (cp != null) {
            System.out.println(" - adding class paths");
            Method m = rjlclass.getMethod("addClassPath", new Class[] { String[].class });
            m.invoke(rjcl, new Object[] { cp });
          }
          return rjcl;
      } catch (Exception rtx) {
          System.err.println("ERROR: Unable to create new RJavaClassLoader in JRIBootstrap! ("+rtx+")");
          rtx.printStackTrace();
          System.exit(2);
      }
      return null;
    }
      
      //--- main bootstrap method ---
      public static void bootstrap(String[] args) {
            System.out.println("JRIBootstrap("+args+")");
            try {
                  System.loadLibrary("boot");
            } catch (Exception e) {
                  fail("Unable to load boot library!");
            }
            
            // just testing from now on
            String rhome = findR(true);
            if (rhome == null) fail("Unable to find R!");
            if (isWin32) {
                String path = getenv("PATH");
                if (path==null || path.length()<1) path=rhome+"\\bin";
                else path=rhome+"\\bin;"+path;
                setenv("PATH",path);
            }
            setREnv();

            System.out.println("PATH="+getenv("PATH")+"\nR_LIBS="+getenv("R_LIBS"));

            if (!isMac && !isWin32) {
                String stage = System.getProperty("stage");
                if (stage==null || stage.length()<1) {
                  File jl = new File(u2w(System.getProperty("java.home")+"/bin/java"));
                  if (jl.exists()) {
                      try {
                        System.out.println(jl.toString()+" -cp "+System.getProperty("java.class.path")+" -Xmx512m -Dstage=2 Boot");
                        Process p = Runtime.getRuntime().exec(new String[] {
                            jl.toString(), "-cp", System.getProperty("java.class.path"),
                            "-Xmx512m", "-Dstage=2", "Boot" });
                        System.out.println("Started stage 2 ("+p+"), waiting for it to finish...");
                        System.exit(p.waitFor());
                      } catch (Exception re) {
                      }
                  }
                }
            }

            String needPkg = null;
            String rj = findPackage("rJava");
            if (rj == null) {
                System.err.println("**ERROR: rJava is not installed");
                if (needPkg==null) needPkg="'rJava'"; else needPkg+=",'rJava'";
            }
            String ipl = findPackage("iplots");
            if (ipl == null) {
                System.err.println("**ERROR: iplots is not installed");
                if (needPkg==null) needPkg="'iplots'"; else needPkg+=",'iplots'";
            }
            String jgr = findPackage("JGR");
            if (jgr == null) {
                System.err.println("**ERROR: JGR is not installed");
                if (needPkg==null) needPkg="'JGR'"; else needPkg+=",'JGR'";
            }
            if (needPkg != null) {
                if (!isWin32 && !isMac) {
                  System.err.println("*** Please run the following in R as root to install missing packages:\n install.packages(c("+needPkg+"),,'http://www.rforge.net/')");
                  System.exit(4);
                }
                if (execR("install.packages(c("+needPkg+"),,c('http://www.rforge.net/','http://cran.r-project.org'))")!=0) {
                  System.err.println("*** ERROR: failed to install necessary packages");
                  System.exit(4);
                }
                rj = findPackage("rJava");
                ipl = findPackage("iplots");
                jgr = findPackage("JGR");
                if (rj==null || ipl==null || jgr==null) {
                  System.err.println("*** ERROR: failed to find installed packages");
                  System.exit(5);
                }
            }

            Object o = bootRJavaLoader = createRJavaLoader(rhome, new String[] { "main" }, true);

            addClassPath(u2w(jgr+"/cont/JGR.jar"));
            addClassPath(u2w(ipl+"/cont/iplots.jar"));
            String mainClass = "org.rosuda.JGR.JGR";

            try {
                Method m = o.getClass().getMethod("bootClass", new Class[] { String.class, String.class, String[].class });
                m.invoke(o, new Object[] { mainClass, "main", args });
            } catch(Exception ie) {           
                System.out.println("cannot boot the final class: "+ie);
                ie.printStackTrace();
            }
      }

      public static void main(String[] args) {
            System.err.println("*** WARNING: JRIBootstrap.main should NOT be called directly, it is intended for debugging use ONLY. Use Boot wrapper instead.");
            // just for testing
            bootstrap(args);
      }
}

Generated by  Doxygen 1.6.0   Back to index