Package org.renjin.primitives

Source Code of org.renjin.primitives.System

/*
* R : A Computer Language for Statistical Data Analysis
* Copyright (C) 1995, 1996  Robert Gentleman and Ross Ihaka
* Copyright (C) 1997--2008  The R Development Core Team
* Copyright (C) 2003, 2004  The R Foundation
* Copyright (C) 2010 bedatadriven
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program.  If not, see <http://www.gnu.org/licenses/>.
*/

package org.renjin.primitives;

import com.google.common.annotations.VisibleForTesting;
import com.google.common.collect.Lists;
import org.apache.commons.vfs2.FileObject;
import org.apache.commons.vfs2.provider.local.LocalFile;
import org.renjin.RVersion;
import org.renjin.eval.Context;
import org.renjin.eval.EvalException;
import org.renjin.invoke.annotations.*;
import org.renjin.sexp.*;

import java.io.File;
import java.io.IOException;
import java.lang.management.ManagementFactory;
import java.lang.management.RuntimeMXBean;
import java.lang.management.ThreadMXBean;
import java.net.InetAddress;
import java.net.URISyntaxException;
import java.text.SimpleDateFormat;
import java.util.Date;
import java.util.List;
import java.util.Map;

public class System {

  private static final double NANOSECONDS_PER_SECOND = 1000000000d;
 
  private static final double MILLISECONDS_PER_SECOND = 1000d;
 

  @Internal
  public static String getRHome(@Current Context context) throws URISyntaxException {
    return context.getSession().getHomeDirectory();
  }

  @Internal
  public static ListVector Version() {
    // this is just copied from my local R installation
    // we'll have to see later what makes the most sense to put here,
    // whether we need to pretend to be some version of R
    return ListVector.newNamedBuilder()
        .add("platform", "i386-pc-mingw32")
        .add("arch", "i386")
        .add("os", "mingw32")
        .add("system", "i386, mingw32")
        .add("status", "")
        .add("major", RVersion.MAJOR)
        .add("minor", RVersion.MINOR)
        .add("year", "2009")
        .add("month", "12")
        .add("day", "14")
        .add("language", "R")
        .add("svn rev", "50720")
        .add("version.string", "R version " + RVersion.MAJOR + "." + RVersion.MINOR + "(2009-12-14)")
        .build();

  }

  @Internal("Sys.getenv")
  public static StringVector getEnvironment(@Current Context context, StringVector names, String unset) {
    StringVector.Builder result = new StringArrayVector.Builder();

    Map<String, String> map = context.getSession().getSystemEnvironment();
    if(names.length() == 0) {
      for(Map.Entry<String,String> entry : map.entrySet()) {
        result.add(entry.getKey() + "=" + entry.getValue());
      }
    } else {
      for(String name : names) {
        String value = map.get(name);
        result.add(value == null ? unset : value);
      }
    }
    return result.build();
  }

  @Internal("Sys.setenv")
  public static LogicalVector setEnvironment(@Current Context context, StringVector names, StringVector values) {

    Map<String, String> map = context.getSession().getSystemEnvironment();

    LogicalArrayVector.Builder result = new LogicalArrayVector.Builder();
    for(int i=0;i!=names.length();++i) {
      map.put(names.getElementAsString(i), values.getElementAsString(i));
      result.add(true);
    }
    return result.build();
  }

  @Invisible
  @Internal("Sys.unsetenv")
  public static LogicalVector unsetEnvironment(@Current Context context, StringVector names) {

    Map<String, String> map = context.getSession().getSystemEnvironment();

    LogicalArrayVector.Builder result = new LogicalArrayVector.Builder();
    for(int i=0;i!=names.length();++i) {
      map.remove(names.getElementAsString(i));
      result.add(true);
    }
    return result.build();
  }

  private enum LocaleCategory {
    LC_COLLATE,
    LC_MONETARY,
    LC_NUMERIC,
    LC_TIME,
    LC_MESSAGES,
    LC_PAPER,
    LC_MEASUREMENT;

    String value() {
      return "English_United States.1252";
    }
  }

  private static final int LC_ALL = 1;

  @Internal("Sys.getlocale")
  public static String getLocale(int categoryIndex) {
    if(categoryIndex == LC_ALL) {
      StringBuilder info = new StringBuilder();
      boolean needsSemi = false;
      for(LocaleCategory category : LocaleCategory.values()) {
        if(needsSemi) {
          info.append(';');
        } else {
          needsSemi = true;
        }
        info.append(category.name()).append('=').append(category.value());
      }
      return info.toString();
    } else {
      return LocaleCategory.values()[categoryIndex-2].value();
    }
  }


  @Internal("Sys.setlocale")
  public static String setLocale(int categoryIndex, String locale) {
    java.lang .System.out.println("locale = " + locale);
    return "";
  }

  @Internal
  public static StringVector commandArgs(@Current Context context) {
    return context.getSession().getCommandLineArguments();
  }

  /**
   * Report on the optional features which have been compiled into this build of R.
   *
   * @param what
   * @return
   */
  @Internal
  public static LogicalVector capabilities(StringVector what) {
    LogicalArrayVector.Builder result = new LogicalArrayVector.Builder();
    StringVector.Builder names = new StringVector.Builder();

    for(String capability : what) {
      if(Capabilities.NAMES.contains(capability)) {
        names.add(capability);
        result.add(false);
      }
    }
    result.setAttribute(Symbols.NAMES, names.build());
    return result.build();
  }

  @Internal
  public static LogicalVector capabilities() {

    LogicalArrayVector.Builder result = new LogicalArrayVector.Builder();
    StringVector.Builder names = new StringVector.Builder();

    for(String capability : Capabilities.NAMES) {
      names.add(capability);
      result.add(false);
    }
    result.setAttribute(Symbols.NAMES, names.build());
    return result.build();
  }
 
  @Internal
  public static StringVector date() {
    // R Style Date Format
    // Example in R: Fri Sep  9 12:20:00 2011
    // Example in Renjin: Fri Sep 09 12:20:00 2011
    SimpleDateFormat sdf = new SimpleDateFormat("EEE MMM dd HH:mm:ss yyyy");
    StringVector.Builder b = new StringVector.Builder();
    Date d = new Date();
    String parsed = null;
    parsed = sdf.format(d);
    b.add(parsed);
    return (b.build());
  }
 
  @Internal("Sys.info")
  public static StringVector sysInfo() {
    StringVector.Builder sb = new StringVector.Builder();
    sb.add(java.lang.System.getProperty("os.name"));
    sb.add(java.lang.System.getProperty("os.version"));
    /*
     * os.build does not exist! maybe we can put jvm info instead?
     *
     */
    sb.add(java.lang.System.getProperty("os.build"));
    try{
      sb.add(InetAddress.getLocalHost().getHostName());
    }catch(Exception e){
      sb.add("Can not get hostname");
    }
    sb.add(java.lang.System.getProperty("os.arch"));
    /*
     *
     * login.name does not exist!
     */
    sb.add(java.lang.System.getProperty("login.name"));
    sb.add(java.lang.System.getProperty("user.name"));

    sb.setAttribute("names", new StringArrayVector("sysname", "release", "version", "nodename", "machine", "login", "user"));
    return (sb.build());
  }
 
  @Internal("Sys.getpid")
  public static int SysGetPid(){
    String name;
    try {
      name = java.lang.management.ManagementFactory.getRuntimeMXBean().getName();
    } catch (Exception e) {
      throw new EvalException("Can not catch the pid.", e);
    }
    int atIndex = name.indexOf("@");
    int result =  1;
    try{
      result = Integer.parseInt(name.substring(0,atIndex));
    } catch (Exception e) {
      //Handled string wrong?
    }
    return result;
  }
 
  @Internal("Sys.sleep")
  public static void SysSleep(double seconds){
    try{
      Thread.currentThread().sleep((long)(seconds * 1000));
    }catch (InterruptedException ie){
      throw new EvalException("Sys.sleep interrupted");
    }
  }

  @Internal
  public static DoubleVector gc(boolean verbose, boolean reset) {
    try {
      java.lang.System.gc();
    } catch(Exception e) {
     
    }
    return new DoubleArrayVector();
  }
 
  /**
   * Returns object of class ‘"proc_time"’ which is a numeric vector of
   * length 5, containing the user, system, and total elapsed times for
   * the currently running R process, and the cumulative sum of user
   * and system times of any child processes spawned by it on which it
   * has waited.
   *
   * _The ‘user time’ is the CPU time charged for the execution of user
   *  instructions of the calling process. The ‘system time’ is the CPU
   *  time charged for execution by the system on behalf of the calling
   *  process._
   */
  @Builtin("proc.time")
  public static DoubleVector procTime() {

    DoubleArrayVector.Builder result = new DoubleArrayVector.Builder();
    StringVector.Builder names = new StringVector.Builder();


    long totalCPUTime;
    long userCPUTime;
    long elapsedTime;

    // There doesn't seem to be any platform-independent way of accessing
    // CPU use for the whole JVM process, so we'll have to make do
    // with the timings for the thread we're running on.
    //
    // Additionally, the MX Beans may not be available in all environments,
    // so we need to fallback to app
    try {
      ThreadMXBean threadMXBean = ManagementFactory.getThreadMXBean();
      totalCPUTime = threadMXBean.getCurrentThreadCpuTime();
      userCPUTime = threadMXBean.getCurrentThreadUserTime();

      RuntimeMXBean runtimeMXBean = ManagementFactory.getRuntimeMXBean();
      elapsedTime = runtimeMXBean.getUptime();
    } catch(Error e) {
      // ThreadMXBean is not available in all environments
      // Specifically, AppEngine will throw variously SecurityErrors or
      // ClassNotFoundErrors if we try to access these classes
      userCPUTime = totalCPUTime = java.lang.System.nanoTime();
      elapsedTime = new Date().getTime();
    }

    // user.self
    names.add("user.self");
    result.add( userCPUTime / NANOSECONDS_PER_SECOND );

    // sys.self
    names.add("sys.self");
    result.add( (totalCPUTime - userCPUTime) / NANOSECONDS_PER_SECOND );

    // elapsed
    // (wall clock time)
    names.add("elapsed");
    result.add(elapsedTime / MILLISECONDS_PER_SECOND);

    // AFAIK, we don't have any platform independent way of accessing
    // this info.

    // user.child
    names.add("user.child");
    result.add(0);

    // sys.child
    names.add("sys.child");
    result.add(0);

    result.setAttribute(Symbols.NAMES, names.build());
    result.setAttribute(Symbols.CLASS, StringVector.valueOf("proc_time"));
    return result.build();

  }


  @Internal
  public static String machine() {
    return "Unix";
  }
 
  @Internal
  public static void dirchmod(StringVector dir ) {
    // not supported
  }

  @Internal("Sys.chmod")
  public static boolean sysChmod(@Recycle String path, int mode, boolean useUmask) {
    // Not supported on our "platform"
    // There are many cases where a Sys.chmod call would fail, so I think this
    /// is a perfectly valid and complete implementation
    return false;
  }
 
  /**
   * ‘Sys.umask’ sets the ‘umask’ and returns the previous value: as a
   * special case ‘mode = NA’ just returns the current value.  It may
   * not be supported (when a warning is issued and ‘"0"’ is returned).
   * For more details see your OS's documentation on the system call
   * ‘umask’, e.g. ‘man 2 umask’
   */
  @Internal("Sys.umask")
  public static int sysChmod(int umask) {
   
    // Not supported on our "platform"
    // There are many cases where a Sys.chmod call would fail, so I think this
    /// is a perfectly valid and complete implementation
    return 0;
  }
 
  @Internal("system")
  public static SEXP system(@Current Context context, String command, int flag, SEXP stdin, SEXP stdout, SEXP stderr) throws IOException, InterruptedException {
    boolean invisible = (flag >= 20 && flag < 29);
    boolean minimized = (flag >= 10 && flag < 19);
   
    List<String> args = parseArgs(command);
    ProcessBuilder builder = new ProcessBuilder(args);
   
    FileObject workingDir = context.getSession().getWorkingDirectory();
    if(workingDir instanceof LocalFile) {
      File localDir = new File(workingDir.getURL().getFile());
      builder.directory(localDir);
    }
    Process process = builder.start();
    process.waitFor();
   
    int exitValue = process.exitValue();
    return new IntArrayVector(exitValue);
  }
 
  @VisibleForTesting
  static List<String> parseArgs(String commandLine) {
    List<String> terms = Lists.newArrayList();
    boolean dquoted = false;
    boolean squoted = false;
    char lastChar = 0;
    StringBuilder currentTerm = new StringBuilder();
    for(int i=0;i!=commandLine.length();++i) {
      char c = commandLine.charAt(i);
      if(!dquoted && !squoted && Character.isWhitespace(c)) {
        if(!Character.isWhitespace(lastChar)) {
          terms.add(currentTerm.toString());
          currentTerm.setLength(0);
        }      
      } else if(!squoted && c == '"') {
        dquoted = !dquoted;
     
      } else if(!dquoted && c == '\'') {
        squoted = !squoted;
       
      } else {
        currentTerm.append(c);
      }
      lastChar = c;
    }
    if(currentTerm.length() > 0) {
      terms.add(currentTerm.toString());
    }
    return terms;
  }
 
}
  
TOP

Related Classes of org.renjin.primitives.System

TOP
Copyright © 2018 www.massapi.com. All rights reserved.
All source code are property of their respective owners. Java is a trademark of Sun Microsystems, Inc and owned by ORACLE Inc. Contact coftware#gmail.com.