Package jep

Source Code of jep.Jep

package jep;

import java.io.File;
import java.util.ArrayList;

import jep.python.PyModule;
import jep.python.PyObject;


/**
* <pre>
* Jep.java - Embeds CPython in Java.
*
* Copyright (c) 2004 - 2011 Mike Johnson.
*
* This file is licenced under the the zlib/libpng License.
*
* This software is provided 'as-is', without any express or implied
* warranty. In no event will the authors be held liable for any
* damages arising from the use of this software.
*
* Permission is granted to anyone to use this software for any
* purpose, including commercial applications, and to alter it and
* redistribute it freely, subject to the following restrictions:
*
*     1. The origin of this software must not be misrepresented; you
*     must not claim that you wrote the original software. If you use
*     this software in a product, an acknowledgment in the product
*     documentation would be appreciated but is not required.
*
*     2. Altered source versions must be plainly marked as such, and
*     must not be misrepresented as being the original software.
*
*     3. This notice may not be removed or altered from any source
*     distribution.
*
* Created: Fri Apr 30 10:35:03 2004
*
* </pre>
*
* @author [mrjohnson0 at sourceforge.net] Mike Johnson
* @version $Id$
*/
public final class Jep {
   
    private boolean closed = false;
    private long    tstate = 0;
    // all calls must originate from same thread
    private Thread thread = null;
   
    // used by default if not passed/set by caller
    private ClassLoader classLoader = null;
   
    // eval() storage.
    private StringBuffer evalLines   = null;
    private boolean      interactive = false;
   
    // windows requires this as unix newline...
    private static final String LINE_SEP = "\n";

    /*
     * keep track of objects that we create. do this to prevent
     * crashes in userland if jep is closed.
     *
     */
    private ArrayList<PyObject> pythonObjects = new ArrayList<PyObject>();
   
   
    // -------------------------------------------------- constructors
   
    /**
     * Creates a new <code>Jep</code> instance.
     *
     * @exception JepException if an error occurs
     */
    public Jep() throws JepException {
        this(false, null, null);
    }

   
    /**
     * Creates a new <code>Jep</code> instance.
     *
     * @param interactive a <code>boolean</code> value
     * @exception JepException if an error occurs
     */
    public Jep(boolean interactive) throws JepException {
        this(interactive, null, null);
    }
   
   
    /**
     * Creates a new <code>Jep</code> instance.
     *
     * @param interactive a <code>boolean</code> value
     * @param includePath a ':' delimited <code>String</code> of directories
     * @exception JepException if an error occurs
     */
    public Jep(boolean interactive, String includePath) throws JepException {
        this(interactive, includePath, null);
    }
   
   
    /**
     * Creates a new <code>Jep</code> instance.
     *
     * @param interactive a <code>boolean</code> value
     * @param includePath a path separated by File.pathSeparator
     * @param cl a <code>ClassLoader</code> value
     * @exception JepException if an error occurs
     */
    public Jep(boolean interactive,
               String includePath,
               ClassLoader cl) throws JepException {
       
        if(cl == null)
            this.classLoader = this.getClass().getClassLoader();
        else
            this.classLoader = cl;
       
        this.interactive = interactive;
        this.tstate = init(this.classLoader);
        this.thread = Thread.currentThread();
       
        // why write C code if you don't have to? :-)
        if(includePath != null) {
            eval("import sys");
            eval("sys.path += '" + includePath + "'.split('" +
                 File.pathSeparator + "')");
        }

        eval("import jep");
    }
   
   
    // load shared library
    static {
        System.loadLibrary("jep");
    }
   
   
    private native long init(ClassLoader classloader) throws JepException;
   
   
    /**
     * <pre>
     * all calls must check thread
     *
     * <b>Internal Only</b>
     * </pre>
     *
     * @exception JepException if an error occurs
     */
    public void isValidThread() throws JepException {
        if(this.thread != Thread.currentThread())
            throw new JepException("Invalid thread access.");
        if(this.tstate == 0)
            throw new JepException("Initialization failed.");
    }


    /**
     * run a python script.
     *
     * @param script a <code>String</code> absolute path to script file.
     * @exception JepException if an error occurs
     */
    public void runScript(String script) throws JepException {
        runScript(script, null);
    }


    /**
     * run a python script.
     *
     * @param script a <code>String</code> absolute path to script file.
     * @param cl a <code>ClassLoader</code> value, may be null.
     * @exception JepException if an error occurs
     */
    public void runScript(String script, ClassLoader cl) throws JepException {
        if(this.closed)
            throw new JepException("Jep has been closed.");
        isValidThread();
       
        if(script == null)
            throw new JepException("Script filename cannot be null.");
       
        File file = new File(script);
        if(!file.exists() || !file.canRead())
            throw new JepException("Invalid file: " + file.getAbsolutePath());

        setClassLoader(cl);
        run(this.tstate, script);
    }
   

    private native void run(long tstate,
                            String script) throws JepException;
   

    /**
     * Invoke a Python function.
     *
     * @param name must be a valid Python function name in globals dict.
     * @return an <code>Object</code> value
     * @exception JepException if an error occurs
     */
    public Object invoke(String name, Object... args) throws JepException {
        if(name == null || name.trim().equals(""))
            throw new JepException("Invalid function name.");

        int[] types = new int[args.length];

        for(int i = 0; i < args.length; i++)
            types[i] = Util.getTypeId(args[i]);

        return invoke(this.tstate, name, args, types);
    }


    private native Object invoke(long tstate,
                                 String name,
                                 Object[] args,
                                 int[] types);


    /**
     * <pre>
     * Evaluate python statements.
     *
     * In interactive mode, Jep may not immediately execute the given lines of code.
     * In that case, eval() returns false and the statement is stored and
     * is appended to the next incoming string.
     *
     * If you're running an unknown number of statements, finish with
     * <code>eval(null)</code> to flush the statement buffer.
     *
     * Interactive mode is slower than a straight eval call since it has to
     * compile the code strings to detect the end of the block.
     * Non-interactive mode is faster, but code blocks must be complete.
     *
     * For Example:
     * <blockquote>eval("if(Test):\n\tprint 'w00t'")</blockquote>
     * This is a limitation on the Python interpreter and unlikely to change.
     *
     * Also, Python does not readly return object values from eval(). Use
     * {@link #getValue(java.lang.String)} instead.
     *
     * @param str a <code>String</code> value
     * @return true if statement complete and was executed.
     * @exception JepException if an error occurs
     */
    public boolean eval(String str) throws JepException {
        if(this.closed)
            throw new JepException("Jep has been closed.");
        isValidThread();
       
        try {
            // trim windows \r\n
            if(str != null)
                str = str.replaceAll("\r", "");
           
            if(str == null || str.trim().equals("")) {
                if(!this.interactive)
                    return false;
                if(this.evalLines == null)
                    return true; // nothing to eval

                // null means we send lines, whether or not it compiles.
                eval(this.tstate, this.evalLines.toString());
                this.evalLines = null;
                return true;
            }
            else {
                // first check if it compiles by itself
                if(!this.interactive ||
                   (this.evalLines == null &&
                    compileString(this.tstate, str) == 1)) {
                   
                    eval(this.tstate, str);
                    return true;
                }
               
                // doesn't compile on it's own, append to eval
                if(this.evalLines == null)
                    this.evalLines = new StringBuffer();
                else
                    evalLines.append(LINE_SEP);
                evalLines.append(str);
            }
           
            return false;
        }
        catch(JepException e) {
            this.evalLines = null;
            throw new JepException(e);
        }
    }


    private native int compileString(long tstate,
                                     String str) throws JepException;

   
    private native void eval(long tstate,
                             String str) throws JepException;


    /**
     * <pre>
     * Retrieves a value from python. If the result is not a java object,
     * the implementation currently returns a String.
     *
     * Python is pretty picky about what it excepts here. The general syntax:
     * <blockquote>eval("a = 5")
     *String a = (String) getValue("a")</blockquote>
     * will work.
     * </pre>
     *
     * @param str a <code>String</code> value
     * @return an <code>Object</code> value
     * @exception JepException if an error occurs
     */
    public Object getValue(String str) throws JepException {
        if(this.closed)
            throw new JepException("Jep has been closed.");
        isValidThread();
       
        return getValue(this.tstate, str);
    }

   
    private native Object getValue(long tstate,
                                   String str) throws JepException;


    /**
     * <pre>
     * Retrieves a python string object as a java array.
     *
     * @param str a <code>String</code>
     * @return an <code>Object</code> array
     * @exception JepException if an error occurs
     */

    public float[] getValue_floatarray(String str) throws JepException {
        if(this.closed)
            throw new JepException("Jep has been closed.");
        isValidThread();
       
        return getValue_floatarray(this.tstate, str);
    }

    private native float[] getValue_floatarray(long tstate,
                                   String str) throws JepException;


    /**
     * <pre>
     * Retrieves a python string object as a java array.
     *
     * @param str a <code>String</code>
     * @return an <code>Object</code> array
     * @exception JepException if an error occurs
     */
    public byte [] getValue_bytearray(String str) throws JepException {
        if(this.closed)
            throw new JepException("Jep has been closed.");
        isValidThread();
       
        return getValue_bytearray(this.tstate, str);
    }
   
    private native byte[] getValue_bytearray(long tstate,
                                   String str) throws JepException;

   
    /**
     * <pre>
     * Track Python objects we create so they can be smoothly shutdown
     * with no risk of crashes due to bad reference counting.
     *
     * <b>Internal use only.</b>
     * </pre>
     *
     * @param obj a <code>PyObject</code> value
     * @return same object, for inlining stuff
     * @exception JepException if an error occurs
     */
    public PyObject trackObject(PyObject obj) throws JepException {
        return trackObject(obj, true);
    }


    /**
     * <pre>
     * Track Python objects we create so they can be smoothly shutdown
     * with no risk of crashes due to bad reference counting.
     *
     * <b>Internal use only.</b>
     * </pre>
     *
     * @param obj a <code>PyObject</code> value
     * @param inc should trackObject incref()
     * @return same object, for inlining stuff
     * @exception JepException if an error occurs
     */
    public PyObject trackObject(PyObject obj, boolean inc) throws JepException {
        // make sure python doesn't close it
        if(inc)
            obj.incref();

        this.pythonObjects.add(obj);
        return obj;
    }


    /**
     * Create a python module on the interpreter. If the given name is
     * valid, imported module, this method will return that module.
     *
     * @param name a <code>String</code> value
     * @return a <code>PyModule</code> value
     * @exception JepException if an error occurs
     */
    public PyModule createModule(String name) throws JepException {
        return (PyModule) trackObject(new PyModule(
                                          this.tstate,
                                          createModule(this.tstate,
                                                       name),
                                          this));
    }


    private native long createModule(long tstate,
                                     String name) throws JepException;


    // -------------------------------------------------- set things
   
    /**
     * set default classloader
     *
     * @param cl a <code>ClassLoader</code> value
     */
    public void setClassLoader(ClassLoader cl) {
        if(cl != null && cl != this.classLoader) {
            this.classLoader = cl;
            // call native set
            setClassLoader(this.tstate, cl);
        }
    }
   
   
    private native void setClassLoader(long tstate, ClassLoader cl);
   
   
    /**
     * changes behavior of eval()
     *
     * @param v a <code>boolean</code> value
     */
    public void setInteractive(boolean v) {
        this.interactive = v;
    }
   
   
    /**
     * get interactive
     *
     * @return a <code>boolean</code> value
     */
    public boolean isInteractive() {
        return this.interactive;
    }

   
    /**
     * Describe <code>set</code> method here.
     *
     * @param name a <code>String</code> value
     * @param v an <code>Object</code> value
     * @exception JepException if an error occurs
     */
    public void set(String name, Object v) throws JepException {
        if(this.closed)
            throw new JepException("Jep has been closed.");
        isValidThread();
       
        if(v instanceof Class)
            set(tstate, name, (Class) v);
        else
            set(tstate, name, v);
    }

    private native void set(long tstate, String name, Object v)
        throws JepException;

    private native void set(long tstate, String name, Class v)
        throws JepException;

    /**
     * Describe <code>set</code> method here.
     *
     * @param name a <code>String</code> value
     * @param v a <code>String</code> value
     * @exception JepException if an error occurs
     */
    public void set(String name, String v) throws JepException {
        if(this.closed)
            throw new JepException("Jep has been closed.");
        isValidThread();
       
        set(tstate, name, v);
    }

    private native void set(long tstate, String name, String v)
        throws JepException;



    /**
     * Describe <code>set</code> method here.
     *
     * @param name a <code>String</code> value
     * @param v a <code>boolean</code> value
     * @exception JepException if an error occurs
     */
    public void set(String name, boolean v) throws JepException {
        // there's essentially no difference between int and bool...
        if(v)
            set(name, 1);
        else
            set(name, 0);
    }


    /**
     * Describe <code>set</code> method here.
     *
     * @param name a <code>String</code> value
     * @param v an <code>int</code> value
     * @exception JepException if an error occurs
     */
    public void set(String name, int v) throws JepException {
        if(this.closed)
            throw new JepException("Jep has been closed.");
        isValidThread();
       
        set(tstate, name, v);
    }
   
    /**
     * Describe <code>set</code> method here.
     *
     * @param name a <code>String</code> value
     * @param v an <code>int</code> value
     * @exception JepException if an error occurs
     */
    public void set(String name, short v) throws JepException {
        if(this.closed)
            throw new JepException("Jep has been closed.");
        isValidThread();
       
        set(tstate, name, (int) v);
    }
   
    private native void set(long tstate, String name, int v)
        throws JepException;

   
    /**
     * Describe <code>set</code> method here.
     *
     * @param name a <code>String</code> value
     * @param v a <code>char[]</code> value
     * @exception JepException if an error occurs
     */
    public void set(String name, char[] v) throws JepException {
        if(this.closed)
            throw new JepException("Jep has been closed.");
        isValidThread();
       
        set(tstate, name, new String(v));
    }


    /**
     * Describe <code>set</code> method here.
     *
     * @param name a <code>String</code> value
     * @param v a <code>char</code> value
     * @exception JepException if an error occurs
     */
    public void set(String name, char v) throws JepException {
        if(this.closed)
            throw new JepException("Jep has been closed.");
        isValidThread();
       
        set(tstate, name, new String(new char[] { v }));
    }


    /**
     * Describe <code>set</code> method here.
     *
     * @param name a <code>String</code> value
     * @param b a <code>byte</code> value
     * @exception JepException if an error occurs
     */
    public void set(String name, byte b) throws JepException {
        if(this.closed)
            throw new JepException("Jep has been closed.");
        isValidThread();
       
        set(tstate, name, (int) b);
    }

   
    /**
     * Describe <code>set</code> method here.
     *
     * @param name a <code>String</code> value
     * @param v a <code>long</code> value
     * @exception JepException if an error occurs
     */
    public void set(String name, long v) throws JepException {
        if(this.closed)
            throw new JepException("Jep has been closed.");
        isValidThread();

        set(tstate, name, v);
    }
   
    private native void set(long tstate, String name, long v)
        throws JepException;
   
   
    /**
     * Describe <code>set</code> method here.
     *
     * @param name a <code>String</code> value
     * @param v a <code>double</code> value
     * @exception JepException if an error occurs
     */
    public void set(String name, double v) throws JepException {
        if(this.closed)
            throw new JepException("Jep has been closed.");
        isValidThread();

        set(tstate, name, v);
    }
   
    private native void set(long tstate, String name, double v)
        throws JepException;


    /**
     * Describe <code>set</code> method here.
     *
     * @param name a <code>String</code> value
     * @param v a <code>float</code> value
     * @exception JepException if an error occurs
     */
    public void set(String name, float v) throws JepException {
        if(this.closed)
            throw new JepException("Jep has been closed.");
        isValidThread();
       
        set(tstate, name, v);
    }
   
    private native void set(long tstate, String name, float v)
        throws JepException;


    // -------------------------------------------------- set arrays

    /**
     * Describe <code>set</code> method here.
     *
     * @param name a <code>String</code> value
     * @param v a <code>boolean[]</code> value
     * @exception JepException if an error occurs
     */
    public void set(String name, boolean[] v) throws JepException {
        if(this.closed)
            throw new JepException("Jep has been closed.");
        isValidThread();
       
        set(tstate, name, v);
    }

    private native void set(long tstate, String name, boolean[] v)
        throws JepException;


    /**
     * Describe <code>set</code> method here.
     *
     * @param name a <code>String</code> value
     * @param v an <code>int[]</code> value
     * @exception JepException if an error occurs
     */
    public void set(String name, int[] v) throws JepException {
        if(this.closed)
            throw new JepException("Jep has been closed.");
        isValidThread();
       
        set(tstate, name, v);
    }

    private native void set(long tstate, String name, int[] v)
        throws JepException;


    /**
     * Describe <code>set</code> method here.
     *
     * @param name a <code>String</code> value
     * @param v a <code>short[]</code> value
     * @exception JepException if an error occurs
     */
    public void set(String name, short[] v) throws JepException {
        if(this.closed)
            throw new JepException("Jep has been closed.");
        isValidThread();
       
        set(tstate, name, v);
    }

    private native void set(long tstate, String name, short[] v)
        throws JepException;


    /**
     * Describe <code>set</code> method here.
     *
     * @param name a <code>String</code> value
     * @param v a <code>byte[]</code> value
     * @exception JepException if an error occurs
     */
    public void set(String name, byte[] v) throws JepException {
        if(this.closed)
            throw new JepException("Jep has been closed.");
        isValidThread();
       
        set(tstate, name, v);
    }

    private native void set(long tstate, String name, byte[] v)
        throws JepException;


    /**
     * Describe <code>set</code> method here.
     *
     * @param name a <code>String</code> value
     * @param v a <code>long[]</code> value
     * @exception JepException if an error occurs
     */
    public void set(String name, long[] v) throws JepException {
        if(this.closed)
            throw new JepException("Jep has been closed.");
        isValidThread();
       
        set(tstate, name, v);
    }

    private native void set(long tstate, String name, long[] v)
        throws JepException;


    /**
     * Describe <code>set</code> method here.
     *
     * @param name a <code>String</code> value
     * @param v a <code>double[]</code> value
     * @exception JepException if an error occurs
     */
    public void set(String name, double[] v) throws JepException {
        if(this.closed)
            throw new JepException("Jep has been closed.");
        isValidThread();
       
        set(tstate, name, v);
    }

    private native void set(long tstate, String name, double[] v)
        throws JepException;


    /**
     * Describe <code>set</code> method here.
     *
     * @param name a <code>String</code> value
     * @param v a <code>float[]</code> value
     * @exception JepException if an error occurs
     */
    public void set(String name, float[] v) throws JepException {
        if(this.closed)
            throw new JepException("Jep has been closed.");
        isValidThread();
       
        set(tstate, name, v);
    }

    private native void set(long tstate, String name, float[] v)
        throws JepException;


    // -------------------------------------------------- close me

    /**
     * Shutdown python interpreter. Make sure you call this.
     *
     */
    public synchronized void close() {
        if(this.closed)
            return;
       
        // close all the PyObjects we created
        for(int i = 0; i < this.pythonObjects.size(); i++)
            pythonObjects.get(i).close();

        this.closed = true;
        this.close(tstate);
        this.tstate = 0;
    }

    private native void close(long tstate);
   
   
    /**
     * Describe <code>finalize</code> method here.
     *
     */
    protected void finalize() {
        this.close();
    }
}
TOP

Related Classes of jep.Jep

TOP
Copyright © 2018 www.massapi.com. All rights reserved.
All source code are property of their respective owners. Java is a trademark of Sun Microsystems, Inc and owned by ORACLE Inc. Contact coftware#gmail.com.