source: tags/MetisMQIDemo/src/main/java/weka/core/scripting/Jython.java

Last change on this file was 29, checked in by gnappo, 15 years ago

Taggata versione per la demo e aggiunto branch.

File size: 8.9 KB
Line 
1/*
2 *    This program is free software; you can redistribute it and/or modify
3 *    it under the terms of the GNU General Public License as published by
4 *    the Free Software Foundation; either version 2 of the License, or
5 *    (at your option) any later version.
6 *
7 *    This program is distributed in the hope that it will be useful,
8 *    but WITHOUT ANY WARRANTY; without even the implied warranty of
9 *    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
10 *    GNU General Public License for more details.
11 *
12 *    You should have received a copy of the GNU General Public License
13 *    along with this program; if not, write to the Free Software
14 *    Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
15 */
16
17/*
18 * Jython.java
19 * Copyright (C) 2007 University of Waikato, Hamilton, New Zealand
20 */
21
22package weka.core.scripting;
23
24import weka.core.RevisionHandler;
25import weka.core.RevisionUtils;
26
27import java.io.File;
28import java.io.InputStream;
29import java.io.Serializable;
30import java.lang.reflect.Constructor;
31import java.lang.reflect.Method;
32import java.util.HashSet;
33
34/**
35 * A helper class for <a href="http://www.jython.org/" target="_blank">Jython</a>.
36 *
37 * @author  fracpete (fracpete at waikato dot ac dot nz)
38 * @version $Revision: 5953 $
39 */
40public class Jython
41  implements Serializable, RevisionHandler {
42
43  /** for serialization */
44  private static final long serialVersionUID = -6972298704460209252L;
45
46  /** the classname of the Python interpreter */
47  public final static String CLASS_PYTHONINERPRETER = "org.python.util.PythonInterpreter";
48 
49  /** the classname of the Python ObjectInputStream */
50  public final static String CLASS_PYTHONOBJECTINPUTSTREAM = "org.python.util.PythonObjectInputStream";
51 
52  /** whether the Jython classes are in the Classpath */
53  protected static boolean m_Present = false;
54  static {
55    try {
56      Class.forName(CLASS_PYTHONINERPRETER);
57      m_Present = true;
58    }
59    catch (Exception e) {
60      m_Present = false;
61    }
62  }
63 
64  /** the interpreter */
65  protected Object m_Interpreter;
66 
67  /**
68   * default constructor, tries to instantiate a Python Interpreter
69   */
70  public Jython() {
71    m_Interpreter = newInterpreter();
72  }
73 
74  /**
75   * returns the currently used Python Interpreter
76   *
77   * @return            the interpreter, can be null
78   */
79  public Object getInterpreter() {
80    return m_Interpreter;
81  }
82 
83  /**
84   * executes the specified method on the current interpreter and returns the
85   * result, if any.
86   *
87   * @param methodName          the name of the method
88   * @param paramClasses        the classes of the parameters
89   * @param paramValues         the values of the parameters
90   * @return                    the return value of the method, if any (in that case null)
91   */
92  public Object invoke(String methodName, Class[] paramClasses, Object[] paramValues) {
93    Object      result;
94   
95    result = null;
96    if (getInterpreter() != null)
97      result = invoke(getInterpreter(), methodName, paramClasses, paramValues);
98   
99    return result;
100  }
101 
102  /**
103   * returns whether the Jython classes are present or not, i.e. whether the
104   * classes are in the classpath or not
105   *
106   * @return                    whether the Jython classes are available
107   */
108  public static boolean isPresent() {
109    return m_Present;
110  }
111
112  /**
113   * initializes and returns a Python Interpreter
114   *
115   * @return                    the interpreter or null if Jython classes not present
116   */
117  public static Object newInterpreter() {
118    Object      result;
119   
120    result = null;
121   
122    if (isPresent()) {
123      try {
124        result = Class.forName(CLASS_PYTHONINERPRETER).newInstance();
125      }
126      catch (Exception e) {
127        e.printStackTrace();
128        result = null;
129      }
130    }
131
132    return result;
133  }
134
135  /**
136   * loads the module and returns a new instance of it as instance of the
137   * provided Java class template.
138   *
139   * @param file                the Jython module file
140   * @param template            the template for the returned Java object
141   * @return                    the Jython object
142   */
143  public static Object newInstance(File file, Class template) {
144    return newInstance(file, template, new File[0]);
145  }
146
147  /**
148   * loads the module and returns a new instance of it as instance of the
149   * provided Java class template. The paths are added to 'sys.path' - can
150   * be used if the module depends on other Jython modules.
151   *
152   * @param file                the Jython module file
153   * @param template            the template for the returned Java object
154   * @param paths               additional paths to add to "sys.path"
155   * @return                    the Jython object
156   */
157  public static Object newInstance(File file, Class template, File[] paths) {
158    Object              result;
159    String              tempName;
160    String              instanceName;
161    String              javaClassName;
162    String              objectDef;
163    int                 i;
164    String[]            tmpPaths;
165    HashSet<String>     currentPaths;
166    String              filename;
167    Object              interpreter;
168
169    result = null;
170
171    if (!isPresent())
172      return result;
173   
174    interpreter = newInterpreter();
175    if (interpreter == null)
176      return result;
177   
178    // add paths to sys.path
179    if (paths.length > 0) {
180      invoke(interpreter, "exec", new Class[]{String.class}, new Object[]{"import sys"});
181
182      // determine currently set paths
183      instanceName = "syspath";
184      invoke(interpreter, "exec", new Class[]{String.class}, new Object[]{instanceName + " = sys.path"});
185      currentPaths = new HashSet<String>();
186      try {
187        tmpPaths = (String[]) invoke(interpreter, "get", new Class[]{String.class, Class.class}, new Object[]{instanceName, String[].class});
188        for (i = 0; i < tmpPaths.length; i++)
189          currentPaths.add(tmpPaths[i]);
190      }
191      catch (Exception ex) {
192        ex.printStackTrace();
193      }
194
195      // add only new paths
196      for (i = 0; i < paths.length; i++) {
197        if (!currentPaths.contains(paths[i].getAbsolutePath()))
198          invoke(interpreter, "exec", new Class[]{String.class}, new Object[]{"sys.path.append('" + paths[i].getAbsolutePath() + "')"});
199      }
200    }
201
202    // get object
203    filename      = file.getAbsolutePath();
204    invoke(interpreter, "execfile", new Class[]{String.class}, new Object[]{filename});
205    tempName      = filename.substring(filename.lastIndexOf("/") + 1);
206    tempName      = tempName.substring(0, tempName.indexOf("."));
207    instanceName  = tempName.toLowerCase();
208    javaClassName = tempName.substring(0,1).toUpperCase() + tempName.substring(1);
209    objectDef     = "=" + javaClassName + "()";
210    invoke(interpreter, "exec", new Class[]{String.class}, new Object[]{instanceName + objectDef});
211    try {
212      result = invoke(interpreter, "get", new Class[]{String.class, Class.class}, new Object[]{instanceName, template});
213    }
214    catch (Exception ex) {
215      ex.printStackTrace();
216    }
217
218    return result;
219  }
220 
221  /**
222   * executes the specified method and returns the result, if any
223   *
224   * @param o                   the object the method should be called from,
225   *                            e.g., a Python Interpreter
226   * @param methodName          the name of the method
227   * @param paramClasses        the classes of the parameters
228   * @param paramValues         the values of the parameters
229   * @return                    the return value of the method, if any (in that case null)
230   */
231  public static Object invoke(Object o, String methodName, Class[] paramClasses, Object[] paramValues) {
232    Method      m;
233    Object      result;
234   
235    result = null;
236   
237    try {
238      m      = o.getClass().getMethod(methodName, paramClasses);
239      result = m.invoke(o, paramValues);
240    }
241    catch (Exception e) {
242      e.printStackTrace();
243      result = null;
244    }
245   
246    return result;
247  }
248
249  /**
250   * deserializes the Python Object from the stream
251   *
252   * @param in                  the stream to use
253   * @return                    the deserialized object
254   */
255  public static Object deserialize(InputStream in) {
256    Class<?>            cls;
257    Class[]             paramTypes;
258    Constructor         constr;
259    Object[]            arglist;
260    Object              obj;
261    Object              result;
262
263    result = null;
264
265    try {
266      cls        = Class.forName(CLASS_PYTHONOBJECTINPUTSTREAM);
267      paramTypes = new Class[]{InputStream.class};
268      constr     = cls.getConstructor(paramTypes);
269      arglist    = new Object[]{in};
270      obj        = constr.newInstance(arglist);
271      result     = invoke(obj, "readObject", new Class[]{}, new Object[]{});
272    }
273    catch (Exception e) {
274      e.printStackTrace();
275    }
276   
277    return result;
278  }
279 
280  /**
281   * Returns the revision string.
282   *
283   * @return            the revision
284   */
285  public String getRevision() {
286    return RevisionUtils.extract("$Revision: 5953 $");
287  }
288 
289  /**
290   * If no arguments are given, it just prints the presence of the Jython
291   * classes, otherwise it expects a Jython filename to execute.
292   *
293   * @param args                commandline arguments
294   */
295  public static void main(String[] args) {
296    if (args.length == 0) {
297      System.out.println("Jython present: " + isPresent());
298    }
299    else {
300      Jython jython = new Jython();
301      if (jython.getInterpreter() == null)
302        System.err.println("Cannot instantiate Python Interpreter!");
303      else
304        jython.invoke("execfile", new Class[]{String.class}, new Object[]{args[0]});
305    }
306  }
307}
Note: See TracBrowser for help on using the repository browser.