R2Run.java [src/java/m/rusle2] Revision: default Date:
/*
* To change this template, choose Tools | Templates
* and open the template in the editor.
*/
package m.rusle2;
import csip.Config;
import csip.Executable;
import csip.ServiceException;
import java.io.File;
import java.io.IOException;
import java.util.logging.Logger;
import oms3.util.ProcessComponent;
import csip.utils.Services;
import java.io.BufferedReader;
import java.io.BufferedWriter;
import java.io.FileInputStream;
import java.io.FileOutputStream;
import java.io.InputStreamReader;
import java.io.OutputStreamWriter;
import java.net.HttpURLConnection;
import java.net.URL;
import java.net.UnknownHostException;
import java.util.logging.Level;
import org.apache.commons.io.FileUtils;
import org.apache.commons.io.IOUtils;
import org.apache.commons.lang.StringEscapeUtils;
import org.apache.http.HttpResponse;
import org.apache.http.client.HttpClient;
import org.apache.http.client.methods.HttpGet;
import org.apache.http.client.methods.HttpUriRequest;
import org.apache.http.impl.client.DefaultHttpClient;
/**
*
* @author od
*/
class R2Run {
public static final Logger LOG = Logger.getLogger("R2Run");
String stdout;
String stderr;
ProcessComponent pc = new ProcessComponent();
/**
* Execute the rusle2 pyrome python script
*
* We assume that Python3.4 is installed under
* /home/ubuntu/.wine/drive_c/Python34 and that wine's working dir is
* /home/ubuntu/.wine The ownership of wine's working directory must
* correspond with the user running tomcat
*
* @param r2_rsh
* @return
* @throws IOException
*/
int executePyrome(File r2_rsh, Executable python) throws IOException, ServiceException {
LOG.info("Execute method");
//String binDir = Config.getString("m.bin.dir", "/tmp/csip/bin");
//File romeshell = Binaries.unpackResource("/bin/win-x86/RomeShell.exe", new File(binDir));
//Executable python = resources().getExe(V2_0_1.PYTHON);
python.setArguments("rusle2csip.py");
LOG.info("Executing pyrome rusle2");
int ret = python.exec();
LOG.info("executed pyrome rusle2");
if (ret != 0) {
throw new ServiceException("RUSLE 2 PYTHON error: error executing pyrome:" + ret);
}
// Binaries.unpackResource("/bin/win-x86/RomeDLL.dll", new File(binDir));
// Binaries.unpackResource("/bin/win-x86/pyrome.py", new File(binDir));
// Binaries.unpackResource("/bin/win-x86/_pyrome.pyd", new File(binDir));
// File runpyrome = new File(r2_rsh.getParent() + "/runrusle2.sh");
// String runrusle2 = "winetricks vd=off ; wine /home/ubuntu/.wine/drive_c/Python34/python.exe rusle2csip.py\n";
// FileUtils.writeStringToFile(runpyrome, runrusle2);
// runpyrome.setExecutable(true);
// pc.exe = "./runrusle2.sh";
// pc.working_dir = r2_rsh.getParent();
// pc.args = new String[]{};
stdout += "\n" + FileUtils.readFileToString(python.stdout());
stderr += "\n" + FileUtils.readFileToString(python.stderr());
// LOG.info("Executing pyrome rusle2");
// pc.execute();
// LOG.info("executed pyrome rusle2");
// stdout += "\n" + pc.stdout;
// stderr += "\n" + pc.stderr;
LOG.info("stdout: " + stdout);
LOG.info(("stderr: " + stderr));
//LOG.info("rusle2 model run stdout=" + stdout);
LOG.info("exit val: " + ret);
return ret;
}
// prepares soils file for legacy 1.3 rusle2 service
int prepareSoilsFile(String soilsHttpPtr, File workingDir, boolean bPyrome, String idx) throws IOException {
// Generate shell script to prepare soils file for romeshell or pyrome
ProcessComponent pcPrepareSoils = new ProcessComponent();
File preparesoils = new File(workingDir.getParent() + "/preparesoils" + idx + ".sh");
String prepsoils = "wget \"" + soilsHttpPtr + "\" -O soils_file" + idx + ".tmp\n";
if (bPyrome) {
prepsoils += "echo \"<?xml version=\"\\\"1.0\\\"\"?>\" > soils_file" + idx + ".xml\n";
}
prepsoils += "numlines=`cat soils_file" + idx + ".tmp | wc -l`\n";
prepsoils += "if [ $numlines -eq 1 ]\n";
prepsoils += "then\n";
prepsoils += " tail -n +1 soils_file" + idx + ".tmp >> soils_file" + idx + ".xml\n";
prepsoils += "else\n";
prepsoils += " tail -n +2 soils_file" + idx + ".tmp >> soils_file" + idx + ".xml\n";
prepsoils += "fi\n";
FileUtils.writeStringToFile(preparesoils, prepsoils);
preparesoils.setExecutable(true);
LOG.info("soilsHttpPtr=" + soilsHttpPtr);
LOG.info("the pc-exe is=" + pcPrepareSoils.exe);
pcPrepareSoils.working_dir = workingDir.getParent();
pcPrepareSoils.exe = "./preparesoils" + idx + ".sh";
pcPrepareSoils.args = new String[]{};
pcPrepareSoils.execute();
stdout += "\n" + pcPrepareSoils.stdout;
stderr += "\n" + pcPrepareSoils.stderr;
return pcPrepareSoils.exitValue;
}
//// @Deprecated
// int prepareClimateFile(String climateHttpPtr, File workingDir) throws IOException
// {
// ProcessComponent pcPrepareCli = new ProcessComponent();
// // Generate shell script to prepare climate file for pyrome
// File preparecli = new File(workingDir.getParent() + "/preparecli.sh");
// String prepcli = "wget \"" + climateHttpPtr + "\" -O cli_file0.tmp\n";
// prepcli += "echo \"<?xml version=\\\"1.0\\\"?>\" > cli_file0.xml\n";
// prepcli += "echo \"<Obj>\" >> cli_file0.xml\n";
// prepcli += "echo \"<Type>CLIMATE</Type>\" >> cli_file0.xml\n";
// prepcli += "echo \"<Filename>climates\\\\\\\\aaa</Filename>\" >> cli_file0.xml\n";
// prepcli += "tail -n +2 cli_file0.tmp >> cli_file0.xml\n";
// FileUtils.writeStringToFile(preparecli, prepcli);
// preparecli.setExecutable(true);
// LOG.info("climateHttpPtr=" + climateHttpPtr);
// LOG.info("the pc-exe is=" + pcPrepareCli.exe);
// pcPrepareCli.working_dir = workingDir.getParent();
// pcPrepareCli.exe = "./preparecli.sh";
// pcPrepareCli.args = new String[]{};
// pcPrepareCli.execute();
// stdout += "\n" + pcPrepareCli.stdout;
// stderr += "\n" + pcPrepareCli.stderr;
// return pcPrepareCli.exitValue;
// }
// void prepareClimateFileJ(String climateHttpPtr, File workingDir) throws IOException
// {
// prepareFileJ(climateHttpPtr, new File(workingDir.getParent(), "cli_file0.xml"), "CLIMATE", "climates", "");
//
// }
// // Must find the hydraulic element flow path element of a hydraulic element system
// // download this file, and modify the header, so it can be fed to python
// @Deprecated
// int prepareHydraulicElementFlowPath(String hydElemPtr, String r2db, File workingDir) throws IOException
// {
// ProcessComponent pcPrepareHydElemFP = new ProcessComponent();
// File preparehydElemFP = new File(workingDir.getParent() + "/preparehydraulic-element.sh");
// String sPrepHydElemFP = "#! /bin/bash\n";
// sPrepHydElemFP += "wget \"" + hydElemPtr + "\" -O hydelem_file.tmp\n";
// sPrepHydElemFP += "flowpathline=`grep HYD_SYSTEM_FLOW_PATH_TYPE hydelem_file.tmp`\n";
// sPrepHydElemFP += "flowpathfile=`echo $flowpathline | cut -d\"'\" -f 2`\n";
// sPrepHydElemFP += "wget \"" + r2db + "/hydraulic-element-flow-paths/" + "$flowpathfile.xml\" -O hydelemflowpath_file.tmp\n";
// sPrepHydElemFP += "echo \"<Obj>\" > hydelemflowpath_file.xml\n";
// sPrepHydElemFP += "echo \"<Filename>hydraulic-element-flow-paths\\hydelemflowpath1</Filename>\" >> hydelemflowpath_file.xml\n";
// sPrepHydElemFP += "tail -n +2 hydelemflowpath_file.tmp >> hydelemflowpath_file.xml\n";
// FileUtils.writeStringToFile(preparehydElemFP, sPrepHydElemFP);
// preparehydElemFP.setExecutable(true);
// pcPrepareHydElemFP.working_dir = workingDir.getParent();
// pcPrepareHydElemFP.exe = ".//preparehydraulic-element.sh";
// pcPrepareHydElemFP.args = new String []{};
// pcPrepareHydElemFP.execute();
// stdout += "\n" + pcPrepareHydElemFP.stdout;
// stderr += "\n" + pcPrepareHydElemFP.stderr;
// return pcPrepareHydElemFP.exitValue;
// }
void prepareHydraulicElementFlowPathJ(String hydElemPtr, String r2db, File workingDir) throws IOException {
final String hydelemFile = "hydelem_file.tmp";
String hydelemflowpathFile = "";
BufferedReader br = null;
BufferedWriter bw = null;
try {
// first open hydElemPtr file
getFile(hydElemPtr, workingDir.getParent(), hydelemFile);
// look for HYD_SYSTEM_FLOW_PATH_TYPE
LOG.info("trying to open --- " + workingDir.getParent() + "/" + hydelemFile);
File hydElemFile = new File(workingDir.getParent() + "/" + hydelemFile);
FileInputStream fis = new FileInputStream(hydElemFile);
br = new BufferedReader(new InputStreamReader(fis));
LOG.info("opened --- " + workingDir.getParent() + "/" + hydelemFile);
String inLine;
while ((inLine = br.readLine()) != null) {
if (inLine.contains("HYD_SYSTEM_FLOW_PATH_TYPE")) {
// get the text between the single two quotes- this will be the flowpathfile we need to get
// <ObR><Name>HYD_SYSTEM_FLOW_PATH_TYPE</Name><Data>'0.3% grade channel'</Data><Type>HYD_ELEMENT_FLOW_PATH</Type></ObR></Obj>
hydelemflowpathFile = inLine.split("'")[1];
LOG.info("Read hydelemflowpathFile as =" + hydelemflowpathFile);
}
}
String hydElemFlowPathPtr = r2db + "/hydraulic-element-flow-paths/" + hydelemflowpathFile + ".xml";
LOG.info("HydelemflowpathPTR is =" + hydElemFlowPathPtr);
// call ingprepareFileJ to finish the work...
// next open the flowpathfile, and perform the standard formatting
// of adding the <Obj> tag and the <Filename> tag...
prepareFileJ(hydElemFlowPathPtr, new File(workingDir.getParent(), "hydelemflowpath_file.xml"), "", "hydraulic-element-flow-paths", "hydelemflowpath", false);
} catch (Exception ioe) {
LOG.info("IO Exception while preparing file=" + ioe.toString());
ioe.printStackTrace();
} finally {
if (br != null) {
br.close();
}
if (bw != null) {
bw.close();
}
}
}
int DetermineNumberOfFlowPaths(String hydElemPtr) {
hydElemPtr = hydElemPtr.substring(hydElemPtr.lastIndexOf("\\") + 1);
// This rediumentary algorithm for determining the number of flow paths for
// a hydaulic element system is based on conversation with Jack Carlson in late 03/2016
LOG.info("***********************************************************************************\n\n\n\nHYD ELEM PTR=" + hydElemPtr);
//if (hydElemPtr.substring(hydElemPtr.lastIndexOf("\")+1).startsWith("1"))
if (hydElemPtr.startsWith("1")) {
if (hydElemPtr.contains("middle")) {
return 2;
} else {
return 1;
}
}
// presently there are only 2 kinds of hydraulic element systems with 2 elements.
// ones with only "middle" in the name which should have 3 flow paths (all evenly distributed along the slope),
// and ones with "middle" and "bottom" in the name which should have 2 flow paths (one in middle, one at bottom).
//
// presently there is one hydraulic element with "along" instead of "middle" in the name
// "2 Water and Sediment Control Basins along RUSLE slope.xml" This should be treated the same as middle.
//
if (hydElemPtr.startsWith("2")) {
if (((hydElemPtr.contains("middle")) || (hydElemPtr.contains("along"))) && (!hydElemPtr.contains("bottom"))) {
return 3;
} else // These should have middle and bottom
{
return 2;
}
}
// presently there are only 2 kinds of hydraulic element systems with 3 elements.
// ones with only "middle" in the name which should have 4 flow paths (all evenly distributed along the slope),
// and ones with "middle" and "bottom" in the name which should have 3 flow paths (two in middle, one at bottom).
if (hydElemPtr.startsWith("3")) {
if ((hydElemPtr.contains("middle")) && (!hydElemPtr.contains("bottom"))) {
return 4;
} else // These should have middle and bottom
{
return 3;
}
}
// Should not get here.
return 0;
}
double[] DetermineFlowPathDistribution(String hydElemPtr) {
hydElemPtr = hydElemPtr.substring(hydElemPtr.lastIndexOf("\\") + 1);
// This rediumentary algorithm for determining the hyd elem flow path position relative to slope length for
// a hydaulic element system is based on conversation with Jack Carlson in late 03/2016
if (hydElemPtr.substring(hydElemPtr.lastIndexOf("\\") + 1).startsWith("1")) {
if (hydElemPtr.contains("middle")) {
return new double[]{.5, 1};
} else {
return new double[]{1};
}
}
// presently there are only 2 kinds of hydraulic element systems with 2 elements.
// ones with only "middle" in the name which should have 3 flow paths (all evenly distributed along the slope),
// and ones with "middle" and "bottom" in the name which should have 2 flow paths (one in middle, one at bottom).
//
// presently there is one hydraulic element with "along" instead of "middle" in the name
// "2 Water and Sediment Control Basins along RUSLE slope.xml" This should be treated the same as middle.
//
if (hydElemPtr.startsWith("2")) {
if (((hydElemPtr.contains("middle")) || (hydElemPtr.contains("along"))) && (!hydElemPtr.contains("bottom"))) {
return new double[]{.333, .666, 1};
} else // These should have middle and bottom
{
return new double[]{.5, 1};
}
}
// presently there are only 2 kinds of hydraulic element systems with 3 elements.
// ones with only "middle" in the name which should have 4 flow paths (all evenly distributed along the slope),
// and ones with "middle" and "bottom" in the name which should have 3 flow paths (two in middle, one at bottom).
if (hydElemPtr.startsWith("3")) {
if ((hydElemPtr.contains("middle")) && (!hydElemPtr.contains("bottom"))) {
return new double[]{.25, .5, .75, 1};
} else // These should have middle and bottom
{
return new double[]{.333, .666, 1};
}
}
// Should not get here...
return new double[]{0};
}
// Generic File Preparation routine
// Downloads, and prepares a file for use in Rusle2 Pyrome
//
// fileType: the type of file to process
// Valid fileType(s) include: "contour",
//
// fileDir: the dir of the filename specified in the <Filename> tag in the R2 XML file
// Valid fileDir(s) include: "countour-systems"
//
// idx: An index value, if there are multiple items of the same type for slope segments
// @Deprecated
// int prepareFile(String httpPtr, File outputFile, String fileType, String fileDir, String idx) throws IOException
// {
// ProcessComponent pcPrepare = new ProcessComponent();
// // Generate shell script to prepare --fileType-- file for pyrome
// LOG.info("***********************************************************************************the " + fileType + " file name=" + outputFile.getName());
// String tmpFilename = outputFile.getName().substring(0, outputFile.getName().length()-4) + ".tmp";
// LOG.info("***********************************************************************************the " + fileType + " tmp file name=" + tmpFilename);
// File prepare = new File(outputFile.getParent() + "/prepare" + fileType + ".sh");
// String prep = "#! /bin/bash\n" ;
// prep += "wget \"" + httpPtr + "\" -O " + tmpFilename + "\n";
// //prep += "echo \"<?xml version=\\\"1.0\\\"?>\" > " + workingDir.getName() + "\n";
// prep += "echo \"<Obj>\" >> " + outputFile.getName() + "\n";
// //prep += "echo \"<Type>" + fileType.toUpperCase() + "</Type>\" >> " + workingDir.getName() + "\n";
// prep += "echo \"<Filename>" + fileDir + "\\\\aaa" + idx + "</Filename>\" >> " + outputFile.getName() + "\n";
// //prep += "echo \"<Science>20030415</Science>\" >> " + workingDir.getName() + "\n";
// prep += "tail -n +2 " + tmpFilename + " >> " + outputFile.getName() + "\n";
// FileUtils.writeStringToFile(prepare, prep);
// prepare.setExecutable(true);
// LOG.info(fileType + "--HttpPtr=" + httpPtr);
// LOG.info("the pc-exe is=" + pcPrepare.exe);
// pcPrepare.working_dir = outputFile.getParent();
// pcPrepare.exe = "./prepare" + fileType + ".sh";
// pcPrepare.args = new String[]{};
// pcPrepare.execute();
// stdout += "\n" + pcPrepare.stdout;
// stderr += "\n" + pcPrepare.stderr;
// return pcPrepare.exitValue;
// }
void prepareFileJ(String httpPtr, File outputFile, String fileType, String fileDir, String basefilename, boolean prepareSoilForPyrome) throws IOException {
BufferedReader br = null;
BufferedWriter bw = null;
String fn = (((basefilename != null) & (basefilename.length() > 0)) ? "\\" + basefilename + "1" : "\\aaa");
try {
// Generate shell script to prepare --fileType-- file for pyrome
LOG.info("***********************************************************************************the " + fileType + " file name=" + outputFile.getName());
String tmpFilename = outputFile.getName().substring(0, outputFile.getName().length() - 4) + ".tmp";
LOG.info("***********************************************************************************the " + fileType + " tmp file name=" + tmpFilename);
getFile(httpPtr, outputFile.getParent(), tmpFilename);
FileOutputStream fos = new FileOutputStream(outputFile);
bw = new BufferedWriter(new OutputStreamWriter(fos));
File origFile = new File(outputFile.getParent() + "/" + tmpFilename);
FileInputStream fis = new FileInputStream(origFile);
br = new BufferedReader(new InputStreamReader(fis));
if ((fileType.contentEquals("CLIMATE")) || (fileType.contentEquals("SOIL")) || (prepareSoilForPyrome)) {
bw.write("<?xml version=\"1.0\"?>\n");
}
if (!fileType.contentEquals("SOIL")) {
bw.write("<Obj>\n");
if ((fileType != null) && (fileType.length() > 1)) {
bw.write("<Type>" + fileType + "</Type>\n");
}
// if an incrementing index is needed, replace "0" with counter variable
bw.write("<Filename>" + fileDir + fn + "</Filename>\n");
}
int i = 0;
String inputLine;
while ((inputLine = br.readLine()) != null) {
// skip the first line of the file, except for soil files which only have 1 line
if ((i > 0) || (fileType.contentEquals("SOIL") && (i == 0) && (inputLine.startsWith("<Obj>")))) {
bw.write(inputLine + "\n");
}
i++;
}
fis.close();
} catch (IOException ioe) {
LOG.info("IO Exception while preparing flie=" + outputFile.getName() + "---" + ioe.toString());
} finally {
if (br != null) {
br.close();
}
if (bw != null) {
bw.close();
}
}
}
// TO DO
// Consider moving to a helper class since this is a generally applicable function
private void getFile(String url, String destDir, String filename) {
FileOutputStream fos = null;
String escapedUrl = XMLUtils.escapeURL(url);
try {
LOG.info("*************************************\n\n\n\nTRYING TO GET FILE=" + url + "\n");
LOG.info("Where the URI is =");
LOG.info(escapedUrl + "\n\n\n\n\n*************************************************************");
HttpClient client = new DefaultHttpClient();
HttpGet httpget = new HttpGet(escapedUrl);
HttpResponse response = client.execute((HttpUriRequest) httpget);
byte[] soilData = IOUtils.toByteArray(response.getEntity().getContent());
fos = new FileOutputStream(new File(destDir + "/" + filename));
fos.write(soilData);
fos.close();
} catch (IOException ie) {
LOG.log(Level.SEVERE, "ERROR GETTING SOILS IFC FILE!:" + ie.toString());
throw new RuntimeException(ie);
} finally {
if (fos != null) {
try {
fos.close();
} catch (Exception fe) {
}
}
}
}
/**
* Gets results returned from RomeShell
*
* @param key
* @return
*/
protected String getResult(String key) {
String sPattern = "RomeFileGetAttrValue " + key;
//LOG.info("seeking='" + sPattern + "'");
// Check if attr is available via the GetAttrValue cmd and return if so
if (stdout.contains(sPattern)) {
int start = stdout.indexOf(sPattern) + sPattern.length() + 2;
int end = stdout.toString().indexOf('\r', start);
//LOG.info("returning='" + stdout.substring(start, end).trim() + "'");
return stdout.substring(start, end).trim();
}
// Check if attr is available via the TestAttrValue cmd and return if so
sPattern = "RomeFileTestAttrValue " + key;
//LOG.info("seeking='" + sPattern + "'");
if (stdout.contains(sPattern)) {
int start = stdout.indexOf(sPattern) + sPattern.length() + 2;
int end = stdout.toString().indexOf('\r', start);
//LOG.info("returning='" + stdout.substring(start, end).trim() + "'");
return stdout.substring(start, end).trim();
}
//String key2 = "\"#RD:MAN_PTR:#RD:MAN_IRRIG_SUB_OBJ_PTR:" + key.substring(1);
sPattern = ":" + removeFirstLastChar(key) + "\"";
//LOG.info("seeking='" + sPattern + "'");
if (stdout.contains(sPattern)) {
int start = stdout.indexOf(sPattern) + sPattern.length() + 2;
int end = stdout.toString().indexOf('\r', start);
String output = stdout.substring(start, end).trim();
if ((output == null) || (output.length() <= 0)) {
output = "null";
}
//LOG.info("returning='" + output + "'");
return output;
}
// If attr is not available return null
LOG.info("returning='null'");
return "null";
}
/**
* Gets results returned from Pyrome
*
* @param key
* @return
*/
protected String getResultPyrome(String key) {
String sPattern = key + "=";
if (stdout.contains(key)) {
int start = stdout.indexOf(key) + key.length() + 1;
int end = stdout.toString().indexOf('\r', start);
//LOG.info("returning='" + stdout.substring(start, end).trim() + "'");
return stdout.substring(start, end).trim();
}
LOG.info("returning='null'");
return "null";
}
/**
* Gets results returned from Pyrome
*
* @param key
* @return
*/
protected String getResultPyromeArray(String key, Boolean bQuoted, Boolean bEscape, Boolean bIndexed) {
String result = "[";
String sPattern = "";
String text = "";
int idx = 0;
do {
sPattern = bIndexed ? (key + ":" + idx) : key;
System.out.println("Searching for key=" + sPattern);
text = getResultPyrome(sPattern);
System.out.println("Result of search=" + text);
if (!text.contentEquals("null")) {
if (idx > 0) {
result += ",";
}
if (bQuoted) {
result += "\"" + (bEscape ? StringEscapeUtils.escapeJava(text) : text) + "\"";
} else {
result += (bEscape ? StringEscapeUtils.escapeJava(text) : text);
}
idx++;
}
} while (!text.contentEquals("null"));
result += "]";
return result;
}
public boolean isUrlReachable(String targetUrl) throws IOException {
String r2db = Config.getString("r2.db", "http://oms-db.engr.colostate.edu/r2");
String testUrl = r2db + "/" + targetUrl;
testUrl = XMLUtils.escapeXMLFileURL(testUrl);
System.out.println("Testing URL=" + testUrl);
URL url = new URL(testUrl);
HttpURLConnection httpUrlConnection = (HttpURLConnection) url.openConnection();
//httpUrlConnection.setRequestMethod("HEAD");
httpUrlConnection.setRequestMethod("GET");
try {
int responseCode = httpUrlConnection.getResponseCode();
System.out.println("response code=" + responseCode);
return responseCode == HttpURLConnection.HTTP_OK;
} catch (UnknownHostException noInternetConnection) {
return false;
}
}
protected static String escapeJavaNoFwdSlash(String text) {
String javaEsc = StringEscapeUtils.escapeJava(text);
return javaEsc.replace("\\/", "/");
}
public static String removeFirstLastChar(String text) {
return text.substring(1, text.length() - 1);
}
}