Java tutorial
/* * 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(@Current Context context, boolean verbose, boolean reset) { // Ask the JVM nicely to run garbage collection java.lang.System.gc(); // Invoke any finalizers on environments that have been queued for // garbage collection context.getSession().runFinalizers(); // We don't have details comparable to the output of // GNU R's method, but return something that hopefully // won't break anything. 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; } }