/*
This file is part of the software framework JStatCom,
a library for building applications for data based analysis.
Copyright (C) 2000-2005 Markus Kraetzig
This library is free software; you can redistribute it and/or modify
it under the terms of the GNU Lesser General Public License as
published by the Free Software Foundation; either version 2.1 of the
License, or (at your option) any later version.
This library 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
Lesser General Public License for more details.
You should have received a copy of the GNU Lesser General Public
License along with this library; if not, write to the Free Software
Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307
USA
*/
package com.jstatcom.engine.gauss;
import java.io.BufferedWriter;
import java.io.File;
import java.io.FileInputStream;
import java.io.FileWriter;
import java.io.IOException;
import java.util.ArrayList;
import java.util.Iterator;
import java.util.List;
import java.util.StringTokenizer;
import javolution37.javolution.xml.ObjectReader;
import org.apache.log4j.Logger;
import com.jstatcom.engine.ConfigHolder;
import com.jstatcom.engine.Engine;
import com.jstatcom.engine.EngineTypes;
import com.jstatcom.engine.LoadTypes;
import com.jstatcom.model.JSCConstants;
import com.jstatcom.model.JSCData;
import com.jstatcom.model.JSCInt;
import com.jstatcom.model.JSCNArray;
import com.jstatcom.model.JSCNumber;
import com.jstatcom.model.JSCSArray;
import com.jstatcom.model.JSCString;
import com.jstatcom.model.JSCTypes;
import com.jstatcom.util.FArg;
import com.jstatcom.util.UString;
/**
* Links to an instance of the software package Gauss (www.aptech.com). This
* object performs the whole communication with Gauss and has control over it,
* i.e. it starts, commands, and ends Gauss.
*
* This class enforces the Singleton property by a static initializer. Currently
* it runs only on the Windows OS.
*
* @author Markus Kraetzig
*/
public final class GaussEngine implements Engine {
private static final Logger log = Logger.getLogger(GaussEngine.class);
private static String sysSuffix = ".dll";
static {
// check whether not windows, assume so
if (System.getProperty("os.name", "Windows").toUpperCase().indexOf(
"WIN") < 0)
sysSuffix = ".so";
}
private volatile boolean stopped = false;
private volatile boolean isRunning = false;
private static GaussEngine gauss = null;
private static ConfigHolder cf = null;
private List libList = new ArrayList();
private StringBuffer libBuffer = new StringBuffer();
private List dlibList = null;
private StringBuffer dlibBuffer = null;
private String gaussLibName = null;
private static String tmpDir = null;
/**
* GaussEngine constructor comment.
*/
private GaussEngine() {
super();
}
/**
* Compiles the source files defined in the XML file for compilation.
*
* @return null if ok, error string otherwise
*/
public String compileGCG() {
String failed = "GAUSS gcg compilation failed:\n";
String error = null;
// Create tmp file.
File tmpFile = null;
try {
tmpFile = GaussEngineType.INSTANCE.getTempFile();
} catch (RuntimeException ex) {
error = failed + ex.getMessage();
return error;
}
GCGSet gcgSet = null;
ObjectReader constructor = new ObjectReader();
try {
gcgSet = (GCGSet) constructor.read(new FileInputStream(new File(
EngineTypes.GAUSS.DIR_NAME + "/"
+ cf.getConfig(GaussConfigKeys.COMPILE_CFG))));
} catch (Throwable ex) {
error = failed + ex.getMessage();
return error;
}
// Write to tmp file.
BufferedWriter out = null;
try {
out = new BufferedWriter(new FileWriter(tmpFile));
for (Iterator it = gcgSet.iterator(); it.hasNext();) {
String fName = it.next() + "";
File srcFile = new File(EngineTypes.GAUSS.DIR_NAME + "/"
+ fName);
out
.write("#include \"" + srcFile.getAbsolutePath()
+ "\";\r\n");
}
out.close();
} catch (IOException e) {
error = failed + e.getMessage();
return error;
}
if (!isRunning)
start(true);
// Run compilation.
File gcgFile = new File(EngineTypes.GAUSS.DIR_NAME + "/"
+ gcgSet.GCG_NAME);
gcgFile.delete();
StringBuffer execBuffer = new StringBuffer();
String libraries = gcgSet.LIBS;
if (libraries != null) {
libraries = libraries.trim();
if (libraries.length() > 0)
execBuffer.append("library " + libraries + ";\n");
}
execBuffer.append("compile \"" + tmpFile.getAbsolutePath() + "\" \""
+ gcgFile.getAbsolutePath() + "\";\n");
String exec = UString.replaceAllSubStrings(execBuffer.toString(), "\\",
"\\\\");
log.info("\nGAUSS gcg compilation:\n" + exec);
if ((error = executeCommandEx(exec)) != null)
return failed + error;
return null;
}
/**
* Creates the GAUSS libraries defined in the respective XML file
*
* @return null if ok, error string otherwise
*/
public String createLibs() {
String failed = "GAUSS library generation failed:\n";
String error = null;
LIBSet libSet = null;
ObjectReader constructor = new ObjectReader();
try {
libSet = (LIBSet) constructor.read(new FileInputStream(new File(
EngineTypes.GAUSS.DIR_NAME + "/"
+ cf.getConfig(GaussConfigKeys.LIB_CFG))));
} catch (Throwable ex) {
error = failed + ex.getMessage();
return error;
}
// Run library creation.
String libraries = libSet.LIBS;
if (libraries != null) {
libraries = libraries.trim();
if (libraries.length() > 0)
load(libraries, GaussLoadTypes.LIB);
}
log.info("\nGAUSS library generation:\n");
for (Iterator it = libSet.iterator(); it.hasNext();) {
LIBSet.SRCLibPair pair = (LIBSet.SRCLibPair) it.next();
File srcFile = new File(EngineTypes.GAUSS.DIR_NAME + "/"
+ pair.srcFile);
String exec = "lib "
+ pair.libraryName
+ " \""
+ UString.replaceAllSubStrings(srcFile.getAbsolutePath(),
"\\", "\\\\") + "\"";
log.info(exec);
if ((error = executeCommandEx(exec)) != null) {
return failed + error;
}
log.info(" ... ok");
}
return null;
}
/**
* Executes a GAUSS command. If this engine is in debug mode, the command is
* also printed to System.out.
*
* @param command
* string with GAUSS code, for example "y=rndn(100,1)"
* @throws IllegalArgumentException
* if (command == null)
* @throws RuntimeException
* if execution of command failed, use
* getMessage to retrieve the error string
*/
public void execute(String command) {
if (command == null)
throw new IllegalArgumentException("Command was null.");
if (!isRunning)
start(true);
command = command.trim();
if (command.length() == 0)
return;
// Ending ";" is taken care of by jgauss library.
if (command.charAt(command.length() - 1) == ';')
command = command.substring(0, command.length() - 1);
log.debug("command:\n" + command + ";\n");
String error = null;
if ((error = executeCommandEx(command)) != null)
throw new RuntimeException(error);
checkStopped();
}
/**
* Executes a procedure with input and return parameters specified. The
* results are set to the data objects specified in retData.
* Listeners registered to these data objects receive notifications if
* something changed.
*
* Please note:
* If a data object of type JSCTypes.INT is specified as
* return, then any double scalar will silently be cast to an int. It may
* happen that information is lost during that operation.
*
* @param procName
* procedure name to be executed by this engine
* @param args
* the data to be used as input, can be null or
* emtpy if no arguments needed
* @param retData
* the data array to store results can be null or
* emtpy if no returns needed
* @throws IllegalArgumentException
* if args or retData contain
* elements that are null
* @throws RuntimeException
* if return types are not compatible with returns
*/
public void call(String procName, JSCData[] args, JSCData[] retData) {
if (args == null)
args = new JSCData[0];
if (retData == null)
retData = new JSCData[0];
String names[] = new String[retData.length];
JSCTypes retTypes[] = new JSCTypes[retData.length];
StringBuffer exec = new StringBuffer();
for (int i = 0; i < retData.length; i++) {
if (i == 0)
exec.append("{");
if (retData[i] == null)
throw new IllegalArgumentException("Return at array position ["
+ i + "] is null.");
names[i] = retData[i].name();
retTypes[i] = retData[i].type();
if (i > 0)
exec.append(", ");
exec.append(names[i]);
if (i == retData.length - 1)
exec.append("} = ");
}
exec.append(procName);
for (int i = 0; i < args.length; i++) {
if (i == 0)
exec.append("(");
if (args[i] == null)
throw new IllegalArgumentException(
"Argument at array position [" + i + "] is null.");
if (i > 0)
exec.append(", ");
exec.append(args[i].name());
if (i == args.length - 1)
exec.append(")");
}
write(args);
checkStopped();
execute(exec.toString());
checkStopped();
read(retData);
}
/**
* Low level command execution for a GAUSS command.
*
* @param command
* string with GAUSS code, for example "y=rndn(100,1)"
* @return null if execution completed ok, otherwise error
* message
*/
private native String executeCommandEx(String command);
/**
* Returns an instance of the GaussEngine that is a
* Singleton. Whenever this method is called, the respective system library
* is loaded.
*
* @return initialized GAUSS instance, not yet started
* @throws RuntimeException
* if operating system is not supported or if something went
* wrong during the init process
* @throws UnsatisfiedLinkError
* if system libraries cannot be found
*/
public static GaussEngine getInstance() {
if (gauss != null)
return gauss;
gauss = new GaussEngine();
cf = ConfigHolder.valueOf(EngineTypes.GAUSS);
// Collect the necessary information from ConfigHolder and OS
// for loading the correct library.
String osName = System.getProperty("os.name");
if (osName == null)
throw new RuntimeException("OS name is null.");
if (osName.indexOf("Win") > -1) {
String dllName = null;
if (cf.getConfig(GaussConfigKeys.GAUSS_VERSION).equals("3.2")) {
gauss.gaussLibName = "glm1.dll";
dllName = "jgauss1.dll";
} else {
gauss.gaussLibName = "glm2.dll";
dllName = "jgauss2.dll";
}
String loadName = EngineTypes.GAUSS.DIR_NAME + "/"
+ gauss.gaussLibName;
File sysFile = new File(loadName);
String sysPath = sysFile.getAbsolutePath();
if (!sysFile.isFile())
throw new RuntimeException("System library " + sysPath
+ " does not exist.");
gauss.dlibList = new ArrayList();
gauss.dlibList.add(sysPath);
gauss.dlibBuffer = new StringBuffer(sysPath);
System.load(new File(EngineTypes.GAUSS.DIR_NAME + "/" + dllName)
.getAbsolutePath());
} else
throw new RuntimeException("OS " + osName + " is not supported.");
// Temp dir. Use system temp if empty or does not exist.
tmpDir = cf.getConfig(GaussConfigKeys.TEMP_DIR);
if (!new File(tmpDir).isDirectory())
tmpDir = JSCConstants.getSystemTemp();
// Shared mem.
int memSize = Integer.parseInt(cf
.getConfig(GaussConfigKeys.SHARED_MEM_SIZE));
// Init environment.
String error = gauss.initializeGaussEx(cf
.getConfig(GaussConfigKeys.EXE_LOCATION), tmpDir, memSize, cf
.getConfig(GaussConfigKeys.GAUSS_VERSION));
if (error != null)
throw new RuntimeException(error);
return gauss;
}
/**
* Gets the instance name of the associateted GAUSS program.
*
* @return the name of this instance
*/
// private native String getInstanceNameEx();
/**
* Gets whether GAUSS is currently busy.
*
* @return true if GAUSS is busy, false
* otherwise
*/
private native boolean isExecutingEx();
/**
* Initializes Gauss environment. Needs to be called before Gauss can be
* started.
*
* @param gaussExeDir
* the directory of the gauss executable
* @param tempDir
* the temporary directory
* @param sharedMemSize
* the size of the shared memory area
* @return null if ok, otherwise error string
*/
private native String initializeGaussEx(String gaussExeDir, String tempDir,
int sharedMemSize, String versString);
/**
* @see com.jstatcom.engine.Engine
*/
public boolean isValid(JSCTypes type) {
if (type == JSCTypes.NARRAY || type == JSCTypes.NUMBER
|| type == JSCTypes.INT || type == JSCTypes.SARRAY
|| type == JSCTypes.STRING)
return true;
return false;
}
/**
* Loads a module according to the load type. All filenames must be
* specified relative to the resource directory for the GAUSS engine. The
* args argument is ignored.
*
* @throws IllegalArgumentException
* if (loadName == null || loadType == null) or
* if (loadName.length() == 0) or if
* loadName is not valid
* @see com.jstatcom.engine.Engine
*/
public void load(String loadName, LoadTypes loadType, JSCData... args) {
if (loadName == null || loadType == null)
throw new IllegalArgumentException("Argument was null.");
if (loadName.length() == 0)
throw new IllegalArgumentException("Module name was empty.");
if (!isRunning)
start(true);
// Loads GCG file if not in debug mode.
if (loadType == GaussLoadTypes.GCG)
loadGCG(loadName);
// Loads libraries if in debug mode.
if (loadType == GaussLoadTypes.LIB)
loadLIB(loadName);
// Loads system libraries.
if (loadType == GaussLoadTypes.SYS)
loadSYS(loadName);
// Sets a global symbol.
if (loadType == GaussLoadTypes.GLOBAL) {
if (args == null)
throw new IllegalArgumentException(
"Global symbol agument missing.");
if (args.length != 1)
throw new IllegalArgumentException(
"Global symbol agument length was " + args.length
+ " instead of 1.");
JSCConstants.checkNameThrowEx(loadName);
write(args);
execute(loadName + " = " + args[0].name());
}
checkStopped();
}
/**
* Loads GCG.
*
* @param toLoad
* String
*/
private void loadGCG(String toLoad) {
if (JSCConstants.DEBUG)
return;
String loadName = EngineTypes.GAUSS.DIR_NAME + "/" + toLoad.trim();
String error = null;
File gcgFile = new File(loadName);
if (!gcgFile.isFile())
if ((error = compileGCG()) != null) // Compilation.
throw new RuntimeException(error);
gcgFile = new File(loadName);
if (!gcgFile.isFile())
throw new RuntimeException("File " + gcgFile.getAbsolutePath()
+ " could not be created.");
String exec = UString.replaceAllSubStrings(gcgFile.getAbsolutePath(),
"\\", "\\\\");
log.debug("\nload gcg file:\nuse " + exec + ";\n");
if ((error = executeCommandEx("use " + exec)) != null) // Use gcg.
if ((error = compileGCG()) != null) // Compile gcg.
throw new RuntimeException(error);
// Try to use gcg again.
if ((error = executeCommandEx("use " + exec)) != null)
throw new RuntimeException(error);
}
/**
* Loads LIB.
*
* @param toLoad
* String
*/
private void loadLIB(String toLoad) {
if (!JSCConstants.DEBUG)
return;
String loadName = toLoad.toLowerCase().trim();
List oldList = new ArrayList(libList);
StringBuffer oldBuffer = new StringBuffer(libBuffer.toString());
StringTokenizer st = new StringTokenizer(loadName, ",");
while (st.hasMoreTokens()) {
String toPut = st.nextToken().trim();
if (!libList.contains(toPut) && toPut.length() > 0) {
libList.add(toPut);
if (libBuffer.length() > 0)
libBuffer.append(", " + toPut);
else
libBuffer.append(toPut);
}
}
String error = null;
log.debug("\nload libraries: " + libBuffer.toString());
if ((error = executeCommandEx("library " + libBuffer.toString())) != null) {
libBuffer = oldBuffer;
libList = oldList;
throw new RuntimeException(error);
}
}
/**
* Loads SYS.
*
* @param toLoad
* the name of the library file relative to the resource dir
* @throws RuntimeException
* if GAUSS is busy or if the system library does not exist or
* if GAUSS gives a load errorD
*/
private void loadSYS(String toLoad) {
if (isExecutingEx())
throw new RuntimeException("Gauss is busy.");
List oldList = new ArrayList(dlibList);
StringBuffer oldBuffer = new StringBuffer(dlibBuffer.toString());
String error = null;
StringTokenizer st = new StringTokenizer(toLoad, ",");
while (st.hasMoreTokens()) {
String toPut = st.nextToken().trim();
if (!toPut.toLowerCase().endsWith(sysSuffix))
toPut = toPut + sysSuffix;
String loadName = EngineTypes.GAUSS.DIR_NAME + "/" + toPut;
File sysFile = new File(loadName);
String sysPath = sysFile.getAbsolutePath();
if (!sysFile.isFile())
throw new RuntimeException("System library " + sysPath
+ " does not exist.");
if (!dlibList.contains(sysPath)) {
dlibList.add(sysPath);
if (dlibBuffer.length() > 0)
dlibBuffer.append(", " + sysPath);
else
dlibBuffer.append(sysPath);
}
}
// Gauss needs to be restarted before new dlibs can be loaded.
// This is to make sure that every dll is unloaded.
// isRunning = false;
/*
* if ((error = terminateGaussEx()) != null) throw new
* RuntimeException(error);
*/
// start();
String exec = "dlibrary " + dlibBuffer.toString();
exec = UString.replaceAllSubStrings(exec, "\\", "\\\\");
log.debug("\nload system library:\n" + exec + ";\n");
if ((error = executeCommandEx(exec)) != null) {
dlibBuffer = oldBuffer;
dlibList = oldList;
throw new RuntimeException(error);
}
}
/**
* Reads all variables defined in varNames from GAUSS. The
* varTypes are necessary to enforce type savety.
*
* @param rtArray
* the data to be read
* @throws IllegalArgumentException
* if (rtArray == nul) or if rtArray
* contains null elements
* @throws RuntimeException
* if the variable could not be read or if an invalid type was
* specified or if the read variable does not match with the
* respective type
*/
public void read(JSCData[] rtArray) {
if (rtArray == null)
throw new IllegalArgumentException("Argument was null.");
if (!isRunning)
start(true);
for (int i = 0; i < rtArray.length; i++) {
if (rtArray[i] == null)
throw new IllegalArgumentException("Return at array position ["
+ i + "] was null");
JSCTypes type = rtArray[i].type();
String name = rtArray[i].name();
log.debug("read: name=" + name + ", type=" + type);
if (!isValid(type))
throw new IllegalArgumentException("Return type " + type
+ " at array position [" + i
+ "] cannot be handled by GAUSS");
Object readObj = null;
try {
readObj = readDataEx(name);
} catch (Throwable ex) {
throw new RuntimeException("Reading variable " + name
+ " failed with error message:\n\n" + ex.getMessage());
}
checkStopped();
if (readObj == null)
rtArray[i].clear();
else if (type == JSCTypes.NARRAY) {
if (!(readObj instanceof double[][]))
throw new RuntimeException("Values for variable " + name
+ " do not match with type " + type + ".");
((JSCNArray) rtArray[i]).setVal((double[][]) readObj);
} else if (type == JSCTypes.SARRAY) {
if (!(readObj instanceof String[][])
&& !(readObj instanceof String))
throw new RuntimeException("Values for variable " + name
+ " do not match with type " + type + ".");
if (readObj instanceof String[][])
((JSCSArray) rtArray[i]).setVal((String[][]) readObj);
else
((JSCSArray) rtArray[i])
.setVal(new String[][] { { (String) readObj } });
} else if (type == JSCTypes.NUMBER || type == JSCTypes.INT) {
if (!(readObj instanceof double[][]))
throw new RuntimeException("Values for variable " + name
+ " do not match with type " + type + ".");
double[][] ret = (double[][]) readObj;
if (ret.length < 1 || ret[0].length < 1 || ret.length > 1
|| ret[0].length > 1)
throw new RuntimeException("Variable " + name
+ " is not a 1x1 scalar for type " + type + ".");
if (type == JSCTypes.NUMBER)
((JSCNumber) rtArray[i]).setVal(ret[0][0]);
else
((JSCInt) rtArray[i]).setVal(new Double(ret[0][0])
.intValue());
} else if (type == JSCTypes.STRING) {
if (!(readObj instanceof String))
throw new RuntimeException("Values for variable " + name
+ " do not match with type " + type + ".");
((JSCString) rtArray[i]).setVal((String) readObj);
}
}
return;
}
/**
* Reads symbols from Gauss if the argument is a variable in Gauss.
*
* @param arg
* name of the variable in the Gauss program
* @return the data array from GAUSS
*/
private native Object readDataEx(String arg);
/**
* Starts an instance of GAUSS. If in DEBUG mode, then it uses the library
* system, otherwise the specified .gcg file is loaded. If the load of the
* .gcg file fails then a compilation of the source files is carried out.
*
* Nothing happens if GAUSS is already running.
*
* @param compileIfNecessary
* compiles gcg file if it cannot be loaded
* @throws RuntimeException
* if start fails
*/
public void start(boolean compileIfNecessary) {
// GAUSS is already running.
if (isRunning)
return;
String error = null;
if ((error = startGaussEx()) != null)
throw new RuntimeException(error);
isRunning = true;
try {
log.info(FArg.sprintf("%-20s%s", new FArg("GAUSS version:").add(cf
.getConfig(GaussConfigKeys.GAUSS_VERSION))));
log.info(FArg.sprintf("%-20s%s", new FArg("GAUSS tempdir:").add(cf
.getConfig(GaussConfigKeys.TEMP_DIR))));
log.info(FArg.sprintf("%-20s%s", new FArg("GAUSS executable:")
.add(cf.getConfig(GaussConfigKeys.EXE_LOCATION))));
checkStopped();
if (!JSCConstants.DEBUG && compileIfNecessary)
load(cf.getConfig(GaussConfigKeys.GCG_FILENAME),
GaussLoadTypes.GCG);
else
load("jgauss, pgraph", GaussLoadTypes.LIB);
Thread outPut = new Thread() {
public void run() {
startGaussOutEx();
return;
}
};
outPut.start();
} catch (RuntimeException ex) { // Clean up.
terminateGaussEx();
isRunning = false;
throw ex;
}
}
/**
* Start new instance of GAUSS program and attach to this object.
*
* @return null if ok, otherwise error string
*/
private native String startGaussEx();
/**
* Only for Gauss version >= 3.5. Starts the GaussOut thread that reads all
* output from Gauss and writes it to System.out.
*/
private native void startGaussOutEx();
/**
* @see com.jstatcom.engine.Engine
*/
public void stop() {
String error = null;
stopped = true;
if ((error = stopExecutionEx()) != null)
throw new RuntimeException(error);
}
/**
* Low level stop method. It stops a running GAUSS program.
*
* @return null if ok, otherwise error string
*/
private native String stopExecutionEx();
/**
* Only for Gauss version >= 3.5. Stops the GaussOut thread that reads all
* output from Gauss and writes it to the applications
* System.out.
*/
private native void stopGaussOutEx();
/**
* @see com.jstatcom.engine.Engine
*/
public void shutdown() {
String error = null;
if ((error = terminateGaussEx()) != null)
throw new RuntimeException(error);
stopGaussOutEx();
}
/**
* Low level termination method. It finishes GAUSS without checking for
* running program execution and waiting calls in the worker queue.
*
* @return null if ok, otherwise error string
*/
private native String terminateGaussEx();
/**
* Write a data array to GAUSS. If GAUSS is not yet running, the
* start method is called.
*
* @param engineData
* the data array to be written to GAUSS
* @throws IllegalArgumentException
* if one of the data types cannot be handled by the GAUSS
* engine or if (engineData == null) or if one
* element of engineData is null
* @throws RuntimeException
* if write failed of if GAUSS could not be started if it was
* not running before
*
* @see com.jstatcom.engine.Engine
*/
public void write(JSCData[] engineData) {
if (engineData == null)
throw new IllegalArgumentException("Argument was null.");
if (!isRunning)
start(true);
String error = null;
for (int i = 0; i < engineData.length; i++) {
checkStopped();
JSCData data = engineData[i];
if (data == null)
throw new IllegalArgumentException(
"Argument at array position [" + i + "] was null.");
log.debug("write: " + data);
JSCTypes type = data.type();
if (!isValid(type))
throw new IllegalArgumentException("Argument type " + type
+ " at array position [" + i
+ "] cannot be handled by GAUSS.");
// Empty
if (data.isEmpty()) {
if ((error = executeCommandEx(data.name() + "=0;\n"
+ data.name() + "={}")) != null)
throw new RuntimeException(error);
}
// Number array
else if (type == JSCTypes.NARRAY) {
double[][] dataVal = ((JSCNArray) data).doubleArray();
if ((error = writeDoubleArrayEx(data.name(), dataVal)) != null)
throw new RuntimeException(error);
}
// Number
else if (type == JSCTypes.NUMBER || type == JSCTypes.INT) {
double number;
if (type == JSCTypes.NUMBER)
number = ((Double) data.value()).doubleValue();
else
number = ((Integer) data.value()).doubleValue();
if ((error = writeDoubleArrayEx(data.name(),
new double[][] { { number } })) != null)
throw new RuntimeException(error);
}
// String array
else if (type == JSCTypes.SARRAY) {
if ((error = writeStringArrayEx(data.name(), (String[][]) data
.value())) != null)
throw new RuntimeException(error);
}
// String
else if (type == JSCTypes.STRING) {
String val = "\"" + (String) data.value() + "\"";
if ((error = executeCommandEx(data.name() + " = " + val)) != null)
throw new RuntimeException(error);
}
}
}
/**
* Checks whether stop was called and throws exception to notify caller. The
* flag is reset.
*/
private void checkStopped() {
if (stopped) {
stopped = false;
throw new RuntimeException(Thread.currentThread().getName()
+ " was interrupted.");
}
}
/**
* Low level write method that writes a number array to Gauss.
*
* @param name
* the name of the variable to write
* @param arg
* number array that should be written to Gauss
* @return null if ok, otherwise error message
*/
private native String writeDoubleArrayEx(String name, double[][] arg);
/**
* Low level write method that writes a string array to Gauss.
*
* @param name
* the name of the variable to write
* @param arg
* string array that should be written to Gauss
* @return null if ok, otherwise error message
*/
private native String writeStringArrayEx(String name, String[][] arg);
}
Ads help maintain this website.