package geniusweb.pythonadapter; import org.python.core.Py; import org.python.core.PyObject; import org.python.core.PySystemState; import org.python.util.PythonInterpreter; import geniusweb.actions.Action; import geniusweb.connection.ConnectionEnd; import geniusweb.inform.Inform; import geniusweb.party.Capabilities; import geniusweb.party.DefaultParty; import geniusweb.party.Party; import tudelft.utilities.listener.Listener; /** * An adapter that allows you to put a python-based Party into a jar file and * use it with Genius2. This adapter supports the jython dialect. The reason * this adapter is needed is that you can not directly use the .py file in java, * we have to load a python interpreter and connect it to your file. * *

Usage

* * * *

Working principle

* * The created jar file contains a full python interpreter plus some glue code. * The glue code runs your party inside the python interpreter and routes the * calls through the Geniuseb java structures. */ public abstract class PythonPartyAdapter implements Party, Listener { private final PythonInterpreter interpreter = new PythonInterpreter(); private final DefaultParty pyparty; public PythonPartyAdapter() { /** * Normally Party does not have a constructor. However this is a special * case where we need to initialize Python and connect the python class. */ interpreter.exec("import sys"); addPath(""); System.out.println("code is at " + getClass().getProtectionDomain() .getCodeSource().getLocation().getPath()); // point to sources. Should include all dependencies. // should work both in Eclipse and when using the compiled jar. addPath(getClass().getProtectionDomain().getCodeSource().getLocation() .getPath()); PySystemState state = new PySystemState(); PyObject importer = state.getBuiltins() .__getitem__(Py.newString("__import__")); PyObject module = importer.__call__(Py.newString(getPythonClass())); PyObject klass = module.__getattr__(getPythonClass()); pyparty = (DefaultParty) klass.__call__() .__tojava__(DefaultParty.class); } /** * @return the class/modulename of both your python module filename (eg, * X.py) and your python class (eg class X) inside that file that * implements {@link DefaultParty}. This file must be in the root of * the jar file/working directory. The name is without an extension. */ abstract public String getPythonClass(); @Override public Capabilities getCapabilities() { return pyparty.getCapabilities(); } @Override public String getDescription() { return pyparty.getDescription(); } @Override public void notifyChange(Inform data) { pyparty.notifyChange(data); } @Override public void disconnect() { pyparty.disconnect(); } @Override public void terminate() { pyparty.terminate(); } @Override public void connect(ConnectionEnd connection) { pyparty.connect(connection); } private void addPath(String relpath) { String path = System.getProperty("user.dir") + "/" + relpath + "/"; System.out.println("adding python path " + path); interpreter.exec("sys.path.insert(0, '" + path + "')"); } }