package me.chenyi.jython;
import java.io.*;
import java.net.URL;
import java.net.URLDecoder;
import java.util.Map;
import org.python.core.*;
import org.python.util.PythonInterpreter;
/**
* Class description goes here
*
* @author $Author:$
* @version $Revision:$
*/
public class ScriptInterpreter extends PythonInterpreter
{
private static final String ROUTINES = "me/chenyi/jython/jython_rules.py";
private Map sharedCache;
private static final String[] MODULES =
{
"string.py", // Ties in jython-lib.jar
"me/chenyi/jython/jython_rules.py"
};
static
{
PySystemState.initialize();
// Look up each module in MODULES and add its containing jar file to sys.path
for (int i = 0; i < MODULES.length; i++)
{
String moduleName = MODULES[i];
String jarPath = findJarContaining(moduleName);
if (jarPath == null)
{
System.out.println("Unable to find jar file containing " + moduleName + " ");
}
else
{
File baseFile = new File(jarPath);
String nestedPath = "";
while(!baseFile.exists())
{
nestedPath = (nestedPath.equals(""))? baseFile.getName() : baseFile.getName()+"/"+nestedPath;
baseFile = baseFile.getParentFile();
}
try
{
SyspathArchive archive = new SyspathArchive(jarPath);
System.out.println("Creating SyspathArchiveHack("+jarPath+")");
Py.getSystemState().path.append(archive);
System.out.println("Added "+jarPath+" to the Jython classpath");
}
catch (IOException e)
{
System.out.println("Unable to create SyspathArchive for " + moduleName);
System.out.println("try to add it as path");
try
{
Py.getSystemState().path.append(new PyString(jarPath));
}
catch(Exception e1)
{
System.out.println("fail to to add as path again, ignore it: " + jarPath);
e1.printStackTrace();
}
// e.printStackTrace();
}
}
}
//Py.getSystemState().callExitFunc();
}
/**
* Default constructor
*/
protected ScriptInterpreter(Map sharedCache)
{
this.sharedCache = sharedCache;
loadLibrary(ROUTINES);
}
public boolean loadLibrary(String libraryResource) throws IllegalArgumentException
{
try
{
PyCode libraryCode = (PyCode) sharedCache.get(libraryResource);
if (libraryCode == null)
{
synchronized (sharedCache)
{
libraryCode = (PyCode) sharedCache.get(libraryResource);
if (libraryCode == null)
{
// load the resource
ClassLoader classLoader = getClass().getClassLoader();
BufferedReader br = new BufferedReader(new InputStreamReader(classLoader.getResourceAsStream(libraryResource)));
int length = 0;
char[] cbuf = new char[1024];
StringBuffer buffer = new StringBuffer();
while ((length = br.read(cbuf)) != -1)
buffer.append(cbuf, 0, length);
libraryCode = compile(buffer.toString());
//System.out.println("** Interpreter.store library cache value");
sharedCache.put(libraryResource, libraryCode);
}
}
}
super.exec(libraryCode);
return true;
}
catch (Exception e)
{
e.printStackTrace();
throw new IllegalArgumentException("Interpreter library '" + libraryResource + "' could not be loaded: " + e.getMessage());
}
}
/**
* Allows code to be compile and cached without having to run the code.
*
* @param script the script to be pre-compiled and stored
*/
public void doCompile(String script)
{
// check to see if we have a cache defined for this code
PyCode scriptCode = (PyCode) sharedCache.get(script);
if (scriptCode == null)
{
synchronized (sharedCache)
{
scriptCode = (PyCode) sharedCache.get(script);
if (scriptCode == null)
{
scriptCode = compile(script);
sharedCache.put(script, scriptCode);
}
}
}
}
/**
* Called to execute a generic script that can be used by all columns.
* This script does not return any values, but instead it is assummed that
* all those that reference the code will know about the script variables.
*
* @param script the script to be run.
*/
public void exec(String script)
throws UnsupportedOperationException, IllegalStateException
{
try
{
// check to see if we have a cache defined for this code
PyCode scriptCode = (PyCode) sharedCache.get(script);
if (scriptCode == null)
{
synchronized (sharedCache)
{
scriptCode = (PyCode) sharedCache.get(script);
if (scriptCode == null)
{
// System.out.println("Compiling rule " + script);
scriptCode = compile(script);
sharedCache.put(script, scriptCode);
}
}
}
super.exec(scriptCode);
}
catch (PyException pye)
{
StringBuffer errorBuffer = new StringBuffer("\n** Problem parsing following python script: **\n");
errorBuffer.append(script);
errorBuffer.append("\n");
errorBuffer.append("** ------------------------- **\n");
errorBuffer.append(pye.toString());
errorBuffer.append("** ------------------------- **\n");
throw new UnsupportedOperationException(errorBuffer.toString());
}
catch(Exception e)
{
System.out.println("Interpreter.exec exception " + e.getMessage());
System.out.println("** Script = " + script);
System.out.println("-----------------------");
}
}
/**
* Parses the equation and returns a result as either an Object based on PyObject
* or null if there was no value. This method should be called when an arbitrary
* value of unknown type is returned.
*
* @param eqn the equation to be interpreted.
* @return an Object representing the results of the equation or null if there was
* no result. The value returned will be based on PyObject.
*/
public Object parse(String eqn)
throws UnsupportedOperationException
{
StringBuffer eqnBuffer = new StringBuffer("result = ")
.append(eqn);
try
{
exec(eqnBuffer.toString());
PyObject result = get("result");
if (result instanceof PyNone)
return null;
else
return result;
}
catch (PyException pye)
{
throw new UnsupportedOperationException("Error parsing results");
}
}
public static String findJarContaining(String item)
{
String header = "jar:file:";
String header2 = "vfszip:";
String header3 = "file:";
String trailer = "!/" + item;
String trailer2 = "/" + item;
String trailer3 = "/" + item;
URL url = ScriptInterpreter.class.getResource("/" + item);
// We should get something like
// "jar:file:/C:/Documents and Settings/kejohnson/.javaws/cache/http/Dlocalhost/P80/DMdemo/DMlib/RMmyjython.jar!/__run__.py"
// or "vfszip:/D:/iICE/Server/jboss-5.1.0.GA/server/iICE/deploy/iMercury-test.ear/lib/InnovationCommon.jar/resource/rules.py"
if (url == null)
{
System.out.println("Main: getResource failed for " + item);
return null;
}
String path = url.toString();
try
{
path = URLDecoder.decode(url.toString(), "UTF-8");
}
catch (UnsupportedEncodingException e)
{
System.out.println("Interpreter: " + e.getMessage());
}
System.out.println(path);
if (!path.startsWith(header) || !path.endsWith(trailer))
{
if (!path.startsWith(header2) || !path.endsWith(trailer2))
{
if(!path.startsWith(header3) || !path.endsWith(trailer3))
{
System.out.println("Interpreter: Can't interpret URL for " + item + ": " + path);
return null;
}
}
}
if (path.startsWith(header))
{
// Strip header and trailer
path = path.substring(header.length(), path.length() - trailer.length());
}
else if (path.startsWith(header2))
{
// Strip header2 and trailer2
path = path.substring(header2.length(), path.length() - trailer2.length());
}
else if (path.startsWith(header3))
{
// Strip header2 and trailer2
path = path.substring(header3.length(), path.length() - trailer3.length());
}
// path is in local drive windows
if (path.matches("/[a-zA-Z]:.*"))
{
path = path.substring(1);
}
// path is in the network
else if (path.matches("//.*"))
{
// does nothing
}
// path is linux
else
{
// does nothing
}
System.out.println("Path for " + item + ": " + path);
return path;
}
}