From c4a1c1412da246071af6dcf5a9969e1b79f9fcbc Mon Sep 17 00:00:00 2001
From: felmer <felmer>
Date: Thu, 30 Jun 2016 09:47:20 +0000
Subject: [PATCH] SSDM-3745: Jython27: Execute everything with the right
 context class loader otherwise python xml module wouldn't work

SVN: 36769
---
 .../cisd/common/jython/v27/Evaluator27.java   |  2 +-
 .../cisd/common/jython/v27/JythonUtils.java   | 37 +++++++++++++++-
 .../jython/v27/PythonInterpreter27.java       | 42 ++++++++++++++++++-
 3 files changed, 77 insertions(+), 4 deletions(-)

diff --git a/common/source/java/ch/systemsx/cisd/common/jython/v27/Evaluator27.java b/common/source/java/ch/systemsx/cisd/common/jython/v27/Evaluator27.java
index 8d527f6971c..9a9c6f05cb0 100644
--- a/common/source/java/ch/systemsx/cisd/common/jython/v27/Evaluator27.java
+++ b/common/source/java/ch/systemsx/cisd/common/jython/v27/Evaluator27.java
@@ -190,7 +190,7 @@ public final class Evaluator27 implements IJythonEvaluator
             {
                 pyArgs[i] = translateToPython(args[i]);
             }
-            PyObject result = func.__call__(pyArgs);
+            PyObject result = JythonUtils.invokeFunction(func, pyArgs);
             return translateToJava(result);
         } catch (PyException ex)
         {
diff --git a/common/source/java/ch/systemsx/cisd/common/jython/v27/JythonUtils.java b/common/source/java/ch/systemsx/cisd/common/jython/v27/JythonUtils.java
index 19a75bf2ba9..f7fbf811367 100644
--- a/common/source/java/ch/systemsx/cisd/common/jython/v27/JythonUtils.java
+++ b/common/source/java/ch/systemsx/cisd/common/jython/v27/JythonUtils.java
@@ -18,6 +18,7 @@ package ch.systemsx.cisd.common.jython.v27;
 
 import java.util.HashMap;
 import java.util.Map;
+import java.util.concurrent.Callable;
 
 import org.python27.core.Py;
 import org.python27.core.PyDictionary;
@@ -25,6 +26,8 @@ import org.python27.core.PyFunction;
 import org.python27.core.PyObject;
 import org.python27.core.PySequenceList;
 
+import ch.systemsx.cisd.base.exceptions.CheckedExceptionTunnel;
+
 /**
  * Jython utility methods.
  * 
@@ -76,7 +79,39 @@ class JythonUtils
         {
             pyArgs[i] = Py.java2py(args[i]);
         }
-        return function.__call__(pyArgs);
+        return invokeFunction(function, pyArgs);
+    }
+
+    static PyObject invokeFunction(final PyFunction function, final PyObject[] pyArgs)
+    {
+        return executeWithContextClassLoader(function, new Callable<PyObject>()
+            {
+                @Override
+                public PyObject call() throws Exception
+                {
+                    return function.__call__(pyArgs);
+                }
+            });
+    }
+    
+    static final <V> V executeWithContextClassLoader(Object object, Callable<V> action)
+    {
+        Thread thread = Thread.currentThread();
+        ClassLoader originalContextClassLoader = thread.getContextClassLoader();
+        try
+        {
+            thread.setContextClassLoader(object.getClass().getClassLoader());
+            try
+            {
+                return action.call();
+            } catch (Exception ex)
+            {
+                throw CheckedExceptionTunnel.wrapIfNecessary(ex);
+            }
+        } finally
+        {
+            thread.setContextClassLoader(originalContextClassLoader);
+        }
     }
 
 }
diff --git a/common/source/java/ch/systemsx/cisd/common/jython/v27/PythonInterpreter27.java b/common/source/java/ch/systemsx/cisd/common/jython/v27/PythonInterpreter27.java
index 62f0a229873..e6b85e5c9a8 100644
--- a/common/source/java/ch/systemsx/cisd/common/jython/v27/PythonInterpreter27.java
+++ b/common/source/java/ch/systemsx/cisd/common/jython/v27/PythonInterpreter27.java
@@ -16,6 +16,8 @@
 
 package ch.systemsx.cisd.common.jython.v27;
 
+import java.util.concurrent.Callable;
+
 import org.apache.log4j.Logger;
 import org.python27.core.CompileMode;
 import org.python27.core.Py;
@@ -131,7 +133,35 @@ class PythonInterpreter27 extends org.python27.util.PythonInterpreter
         return new PythonInterpreter27();
     }
 
-    public void exec(String data, String filename)
+    @Override
+    public void exec(final String s)
+    {
+        JythonUtils.executeWithContextClassLoader(this, new Callable<Void>()
+            {
+                @Override
+                public Void call() throws Exception
+                {
+                    PythonInterpreter27.super.exec(s);
+                    return null;
+                }
+            });
+    }
+
+    @Override
+    public void exec(final PyObject code)
+    {
+        JythonUtils.executeWithContextClassLoader(this, new Callable<Void>()
+            {
+                @Override
+                public Void call() throws Exception
+                {
+                    PythonInterpreter27.super.exec(code);
+                    return null;
+                }
+            });
+    }
+
+    public void exec(final String data, final String filename)
     {
         String[] pythonPath = ch.systemsx.cisd.common.jython.JythonUtils.getScriptDirectoryPythonPath(filename);
 
@@ -143,7 +173,15 @@ class PythonInterpreter27 extends org.python27.util.PythonInterpreter
 
             setSystemState();
 
-            Py.exec(Py.compile_flags(data, filename, CompileMode.exec, cflags), getLocals(), null);
+            JythonUtils.executeWithContextClassLoader(this, new Callable<Void>()
+                {
+                    @Override
+                    public Void call() throws Exception
+                    {
+                        Py.exec(Py.compile_flags(data, filename, CompileMode.exec, cflags), getLocals(), null);
+                        return null;
+                    }
+                });
             Py.flushLine();
         } finally
         {
-- 
GitLab