If you suspect sys.path is incorrect, you could

1) pass a property defining python.path to PySystemState.initialize,
2) or modify sys.path for each PySystemState instance.  I do this
by passing a script to new interpreters.

      String initScript =
        "import sys,java\n" +
        "sys.path.insert(0,'"+userScriptHome+"')\n" +
        "sys.path.append('"+jarFilePath+"')\n" +
        "sys.path.append('"+jarFilePath+"/Lib')\n" +
        "java.lang.System.out.println(sys.path)\n" + ...

      _interp = new PythonInterpreter();

      _interp.exec(initScript);

PySystemState.path is public, so you could modify it directly
with Java code.

   _interp.getSystemState().path.append(Py.newString(userScriptHome));

Interpreters can share system states, so you ought to check whether the
path includes your additions already before adding them.




On 11/26/2012 10:46 AM, Mason Wardle wrote:
In looking at Jeff's snippets, if I'm not mistaken, they are searching all the available bundles for classes and I'm trying to understand if it applies to my issue at hand. I only have two plugins (I'm running with Equinox in Eclipse) -- one contains jython.jar and the other contains all my Jython code and the Java class that's trying to instantiate a Jython class, so I'm not certain this is related to bundle loading.

Let me give you some more background.

It works as a normal Java app so I think I have the code right, but it doesn't work in the OSGi context. I'm using the JythonObjectFactory described in chapter 10 of the Jython book on jython.org The name of my Jython module is FileValidatorJ and it contains a class FileValidatorJ which implements a Java interface called FileValidator.

Let me give you the key pieces of code. First, here is the object factory.

public class JythonObjectFactoryEfficient {

 private final PyObject klass;

 public JythonObjectFactoryEfficient(PySystemState state, 
Class<?> interfaceType, 
String moduleName, 
String className) 
 {
     PyObject importer = state.getBuiltins().__getitem__(Py.newString("__import__"));

     PyObject module = importer.__call__(Py.newString(moduleName));
     klass = module.__getattr__(className);
     System.out.println("module =\n" + module + "\nclass =\n" + klass);
 }

 public Object createObject() {
     return klass.__call__().__tojava__(interfaceType);
 }
}

And here is a snippet of code I'm using to import my Jython class into Java:
JythonObjectFactoryEfficient validateFactory = new JythonObjectFactoryEfficient(
new PySystemState(),
FileValidator.class,
"GeolocationFileValidatorJ",
"GeolocationFileValidatorJ");
System.out.println(validateFactory.createObject().getClass().getName());
FileValidator joe = (FileValidator) validateFactory.createObject();



Here is the output when I run the snippet as a Java app (the first four lines are from the factory constructor and the final line is from the snippet):
module =
<module 'FileValidatorJ' from '__pyclasspath__/FileValidatorJ.py'>
class =
<class 'FileValidatorJ.FileValidatorJ'>
org.python.proxies.FileValidatorJ$FileValidatorJ$0

When I run in an OSGi context, I get the following output:
module =
<module 'FileValidatorJ' from '/home/mbw/eclipse-3.8.1/workspace/org.myorg.files/src/FileValidatorJ$py.class'>
class =
<class 'FileValidatorJ.FileValidatorJ'>
org.python.core.PySingleton

<SNIP>

org.python.core.PySingleton cannot be cast to org.myorg.files.interfaces.FileValidator
!STACK 0
java.lang.ClassCastException: org.python.core.PySingleton cannot be cast to org.myorg.files.interfaces.FileValidator

<SNIP>

It seems like it's more along the lines properly setting up my paths in my bundle. I have modified my Run Configuration to define CLASSPATH and JYTHONPATH. Once I do that, I get past most of my errors. (I would prefer to be able to set it up in a product configuration...but I think that may be a little off subject as of yet). 

Adding the CLASSPATH and JYTHONPATH to the Run Configuration allows me to import the Jython class with errors and in turn, import the Java interface inside of Jython without errors. I'm now getting tripped up because my PySystemState doesn't seem to be configured properly.

I could be barking up the wrong tree...but if any have seen these issues, I would love to know how to address them.


Best Regards and Thanks for your time,
Mason


On Wed, Nov 21, 2012 at 9:32 AM, Benoît Thiébault <thiebault@artenum.com> wrote:
Thanks Jeff, that's exactly what I was looking for!
... and it works!

Le 21/11/2012 17:00, Jeff Emanuel a écrit :
I've included code snippets below.  getBundles() returns the Bundles that
I want to allow access to from Jython.  I don't deal with Bundle
unloading or reloading. 


    Bundle[] bundles = getBundles(context);
    savePackageNames(bundles);
    _bundlesClassLoader = new BundlesClassLoader(bundles,
                                                 getClass().getClassLoader());

    // Later for each required interpreter:

      PySystemState.initialize(System.getProperties(),postProps,
                               new String[]{""}, bundlesClassLoader);

      _interp = new PythonInterpreter();

      // Add packages from plugin to interpreter.  These are packages available
      // to the bundlesClassLoader.
      String[] packageNames = plugin.getPackageNames();  // _packageNames below.
      for (int i=0;i<packageNames.length;++i) {
        PySystemState.add_package(packageNames[i]);
      }




  private String[] _packageNames;
  private void savePackageNames(Bundle[] bundles) {
    ArrayList<String> names = new ArrayList<String>();
    for (int i=0;i<bundles.length;++i) {
      Dictionary headers = bundles[i].getHeaders();
      String packages=(String)headers.get("Provide-Package");
      addPackageNames(packages,names);
      packages=(String)headers.get("Export-Package");
      addPackageNames(packages,names);
    }
    _packageNames = names.toArray(new String[names.size()]);
  }


class BundlesClassLoader extends ClassLoader {

  private Bundle[] _bundles;
  public BundlesClassLoader(Bundle[] bundles, ClassLoader parent) {
    super(parent);
    _bundles=bundles;
  }
  protected Class findClass(String className)
    throws ClassNotFoundException {
    try {
      return super.findClass(className);
    } catch (ClassNotFoundException e) {
      // Look for the class from the bundles.
      for (int i=0;i<_bundles.length;++i) {
        try {
          return _bundles[i].loadClass(className);
        } catch (ClassNotFoundException e2) {         
        }
      }
      // Didn't find the class anywhere, rethrow e.
      throw e;
    }
  }
}


------------------------------------------------------------------------------
Monitor your physical, virtual and cloud infrastructure from a single
web console. Get in-depth insight into apps, servers, databases, vmware,
SAP, cloud infrastructure, etc. Download 30-day Free Trial.
Pricing starts from $795 for 25 servers or applications!
http://p.sf.net/sfu/zoho_dev2dev_nov
_______________________________________________
Jython-users mailing list
Jython-users@lists.sourceforge.net
https://lists.sourceforge.net/lists/listinfo/jython-users




------------------------------------------------------------------------------
Monitor your physical, virtual and cloud infrastructure from a single
web console. Get in-depth insight into apps, servers, databases, vmware,
SAP, cloud infrastructure, etc. Download 30-day Free Trial.
Pricing starts from $795 for 25 servers or applications!
http://p.sf.net/sfu/zoho_dev2dev_nov


_______________________________________________
Jython-users mailing list
Jython-users@lists.sourceforge.net
https://lists.sourceforge.net/lists/listinfo/jython-users