weka.core.scripting.Jython Maven / Gradle / Ivy
Go to download
Show more of this group Show more artifacts with this name
Show all versions of weka-stable Show documentation
Show all versions of weka-stable Show documentation
The Waikato Environment for Knowledge Analysis (WEKA), a machine
learning workbench. This is the stable version. Apart from bugfixes, this version
does not receive any other updates.
/*
* 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 .
*/
/*
* Jython.java
* Copyright (C) 2007-2012 University of Waikato, Hamilton, New Zealand
*/
package weka.core.scripting;
import java.io.File;
import java.io.InputStream;
import java.io.Serializable;
import java.lang.reflect.Constructor;
import java.lang.reflect.Method;
import java.util.HashSet;
import weka.core.RevisionHandler;
import weka.core.RevisionUtils;
/**
* A helper class for Jython.
*
* @author fracpete (fracpete at waikato dot ac dot nz)
* @version $Revision: 10203 $
*/
public class Jython implements Serializable, RevisionHandler {
/** for serialization */
private static final long serialVersionUID = -6972298704460209252L;
/** the classname of the Python interpreter */
public final static String CLASS_PYTHONINERPRETER = "org.python.util.PythonInterpreter";
/** the classname of the Python ObjectInputStream */
public final static String CLASS_PYTHONOBJECTINPUTSTREAM = "org.python.util.PythonObjectInputStream";
/** whether the Jython classes are in the Classpath */
protected static boolean m_Present = false;
static {
try {
Class.forName(CLASS_PYTHONINERPRETER);
m_Present = true;
} catch (Exception e) {
m_Present = false;
}
}
/** the interpreter */
protected Object m_Interpreter;
/**
* default constructor, tries to instantiate a Python Interpreter
*/
public Jython() {
m_Interpreter = newInterpreter();
}
/**
* returns the currently used Python Interpreter
*
* @return the interpreter, can be null
*/
public Object getInterpreter() {
return m_Interpreter;
}
/**
* executes the specified method on the current interpreter and returns the
* result, if any.
*
* @param methodName the name of the method
* @param paramClasses the classes of the parameters
* @param paramValues the values of the parameters
* @return the return value of the method, if any (in that case null)
*/
public Object invoke(String methodName, Class[] paramClasses,
Object[] paramValues) {
Object result;
result = null;
if (getInterpreter() != null) {
result = invoke(getInterpreter(), methodName, paramClasses, paramValues);
}
return result;
}
/**
* returns whether the Jython classes are present or not, i.e. whether the
* classes are in the classpath or not
*
* @return whether the Jython classes are available
*/
public static boolean isPresent() {
return m_Present;
}
/**
* initializes and returns a Python Interpreter
*
* @return the interpreter or null if Jython classes not present
*/
public static Object newInterpreter() {
Object result;
result = null;
if (isPresent()) {
try {
result = Class.forName(CLASS_PYTHONINERPRETER).newInstance();
} catch (Exception e) {
e.printStackTrace();
result = null;
}
}
return result;
}
/**
* loads the module and returns a new instance of it as instance of the
* provided Java class template.
*
* @param file the Jython module file
* @param template the template for the returned Java object
* @return the Jython object
*/
public static Object newInstance(File file, Class template) {
return newInstance(file, template, new File[0]);
}
/**
* loads the module and returns a new instance of it as instance of the
* provided Java class template. The paths are added to 'sys.path' - can be
* used if the module depends on other Jython modules.
*
* @param file the Jython module file
* @param template the template for the returned Java object
* @param paths additional paths to add to "sys.path"
* @return the Jython object
*/
public static Object newInstance(File file, Class template, File[] paths) {
Object result;
String tempName;
String instanceName;
String javaClassName;
String objectDef;
int i;
String[] tmpPaths;
HashSet currentPaths;
String filename;
Object interpreter;
result = null;
if (!isPresent()) {
return result;
}
interpreter = newInterpreter();
if (interpreter == null) {
return result;
}
// add paths to sys.path
if (paths.length > 0) {
invoke(interpreter, "exec", new Class[] { String.class },
new Object[] { "import sys" });
// determine currently set paths
instanceName = "syspath";
invoke(interpreter, "exec", new Class[] { String.class },
new Object[] { instanceName + " = sys.path" });
currentPaths = new HashSet();
try {
tmpPaths = (String[]) invoke(interpreter, "get", new Class[] {
String.class, Class.class }, new Object[] { instanceName,
String[].class });
for (i = 0; i < tmpPaths.length; i++) {
currentPaths.add(tmpPaths[i]);
}
} catch (Exception ex) {
ex.printStackTrace();
}
// add only new paths
for (i = 0; i < paths.length; i++) {
if (!currentPaths.contains(paths[i].getAbsolutePath())) {
invoke(interpreter, "exec", new Class[] { String.class },
new Object[] { "sys.path.append('" + paths[i].getAbsolutePath()
+ "')" });
}
}
}
// get object
filename = file.getAbsolutePath();
invoke(interpreter, "execfile", new Class[] { String.class },
new Object[] { filename });
tempName = filename.substring(filename.lastIndexOf("/") + 1);
tempName = tempName.substring(0, tempName.indexOf("."));
instanceName = tempName.toLowerCase();
javaClassName = tempName.substring(0, 1).toUpperCase()
+ tempName.substring(1);
objectDef = "=" + javaClassName + "()";
invoke(interpreter, "exec", new Class[] { String.class },
new Object[] { instanceName + objectDef });
try {
result = invoke(interpreter, "get", new Class[] { String.class,
Class.class }, new Object[] { instanceName, template });
} catch (Exception ex) {
ex.printStackTrace();
}
return result;
}
/**
* executes the specified method and returns the result, if any
*
* @param o the object the method should be called from, e.g., a Python
* Interpreter
* @param methodName the name of the method
* @param paramClasses the classes of the parameters
* @param paramValues the values of the parameters
* @return the return value of the method, if any (in that case null)
*/
public static Object invoke(Object o, String methodName,
Class[] paramClasses, Object[] paramValues) {
Method m;
Object result;
result = null;
try {
m = o.getClass().getMethod(methodName, paramClasses);
result = m.invoke(o, paramValues);
} catch (Exception e) {
e.printStackTrace();
result = null;
}
return result;
}
/**
* deserializes the Python Object from the stream
*
* @param in the stream to use
* @return the deserialized object
*/
public static Object deserialize(InputStream in) {
Class cls;
Class[] paramTypes;
Constructor constr;
Object[] arglist;
Object obj;
Object result;
result = null;
try {
cls = Class.forName(CLASS_PYTHONOBJECTINPUTSTREAM);
paramTypes = new Class[] { InputStream.class };
constr = cls.getConstructor(paramTypes);
arglist = new Object[] { in };
obj = constr.newInstance(arglist);
result = invoke(obj, "readObject", new Class[] {}, new Object[] {});
} catch (Exception e) {
e.printStackTrace();
}
return result;
}
/**
* Returns the revision string.
*
* @return the revision
*/
@Override
public String getRevision() {
return RevisionUtils.extract("$Revision: 10203 $");
}
/**
* If no arguments are given, it just prints the presence of the Jython
* classes, otherwise it expects a Jython filename to execute.
*
* @param args commandline arguments
*/
public static void main(String[] args) {
if (args.length == 0) {
System.out.println("Jython present: " + isPresent());
} else {
Jython jython = new Jython();
if (jython.getInterpreter() == null) {
System.err.println("Cannot instantiate Python Interpreter!");
} else {
jython.invoke("execfile", new Class[] { String.class },
new Object[] { args[0] });
}
}
}
}