/*
* Copyright 2011-2012 the original author or authors.
*
* 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 org.springframework.data.hadoop.impala.r;
import java.io.BufferedReader;
import java.io.File;
import java.io.IOException;
import java.io.InputStreamReader;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;
import org.apache.commons.io.IOUtils;
import org.springframework.core.io.FileSystemResourceLoader;
import org.springframework.core.io.Resource;
import org.springframework.core.io.support.PathMatchingResourcePatternResolver;
import org.springframework.core.io.support.ResourcePatternResolver;
import org.springframework.shell.core.CommandMarker;
import org.springframework.shell.core.annotation.CliCommand;
import org.springframework.shell.core.annotation.CliOption;
import org.springframework.shell.support.util.StringUtils;
import org.springframework.stereotype.Component;
/**
* Provider of R commands.
*
* @author Costin Leau
*/
@Component
public class RCommands implements CommandMarker {
private static final String PREFIX = "r ";
private static final String BIN = "bin" + File.separator + "Rscript";
private String home = "";
private String cmd = home + BIN;
private File wkdir = new File(".");
private ResourcePatternResolver resourceResolver = new PathMatchingResourcePatternResolver(
new FileSystemResourceLoader());
public RCommands() {
String os = System.getProperty("os.name").toLowerCase();
// set default R paths - best effort
if (os.contains("win")) {
home = "C:\\Program Files\\R\\";
File f = new File(home);
if (f.exists() && f.isDirectory()) {
File[] listFiles = f.listFiles();
if (listFiles != null && listFiles.length > 0) {
home = listFiles[0].getAbsolutePath() + "\\";
}
}
}
else if (os.contains("mac")) {
home = "/Library/Frameworks/R.framework/Resources/";
}
else if (os.contains("sunos")) {
home = "/usr/lib/";
}
else {
// else linux/unix
home = "/usr/";
}
cmd = home + BIN;
}
private String info() {
StringBuilder sb = new StringBuilder();
sb.append("R [");
//String version = "unknown";
//sb.append(version);
//sb.append("][");
sb.append("home=");
sb.append(home);
sb.append("][workDir=");
sb.append(wkdir.getAbsolutePath());
sb.append("]");
return sb.toString();
}
@CliCommand(value = { PREFIX + "cfg" }, help = "Configures R")
public String config(@CliOption(key = { "home" }, mandatory = false, help = "R home directory") String home,
@CliOption(key = { "workDir" }, mandatory = false, help = "working directory") String wkdir)
throws Exception {
if (StringUtils.hasText(home)) {
if (new File(home).exists()) {
if (!home.endsWith(File.separator)) {
home += File.separator;
}
this.home = home;
cmd = home + BIN;
}
else {
return "Cannot find path [" + home + "]";
}
}
if (StringUtils.hasText(wkdir)) {
File f = new File(wkdir);
if (f.exists()) {
this.wkdir = f;
}
else {
return "Cannot find path [" + wkdir + "]";
}
}
return info();
}
@CliCommand(value = { PREFIX + "script" }, help = "Executes a R script")
public String script(@CliOption(key = { "", "location" }, mandatory = true, help = "Script location") String location,
@CliOption(key = { "args" }, mandatory = false, help = "Script arguments") String args) {
if (!new File(cmd).exists()) {
return "Cannot find R command [" + cmd + "]";
}
Resource resource = resourceResolver.getResource(fixLocation(location));
if (!resource.exists()) {
return "No resource found at " + location;
}
String uri = location;
try {
uri = resource.getFile().getAbsolutePath();
} catch (IOException ex) {
// ignore - we'll use location
}
Process process;
List<String> cmds = new ArrayList<String>();
cmds.add(cmd);
cmds.add(uri);
if (StringUtils.hasText(args)) {
cmds.addAll(Arrays.asList(StringUtils.tokenizeToStringArray(args, " ")));
}
BufferedReader output = null;
try {
process = new ProcessBuilder(cmds).directory(wkdir).redirectErrorStream(true).start();
output = new BufferedReader(new InputStreamReader(process.getInputStream()));
String line;
while ((line = output.readLine()) != null) {
System.out.println(line);
}
int code = process.waitFor();
return "R script executed with exit code - " + code;
} catch (Exception ex) {
return "R script execution failed - " + ex;
} finally {
IOUtils.closeQuietly(output);
}
}
private static String fixLocation(String location) {
if (StringUtils.hasText(location) && !location.contains(":")) {
return "file:" + location;
}
return location;
}
}