Blob Blame History Raw
From 41fba27ce8728722076f1c0c9f81db215c7b494a Mon Sep 17 00:00:00 2001
From: Mat Booth <mat.booth@redhat.com>
Date: Thu, 28 Sep 2017 16:13:50 +0100
Subject: [PATCH] Better support system installed versions of Jython for Linux
 distros

---
 .../debug/ui/launching/PythonRunnerConfig.java     |  4 ++-
 .../python/pydev/runners/SimpleJythonRunner.java   | 33 ++++++++++++++++---
 .../ui/interpreters/JythonInterpreterManager.java  | 21 ++++++++++++
 .../AbstractInterpreterProviderFactory.java        |  2 +-
 .../pydev/ui/pythonpathconf/InterpreterInfo.java   |  8 ++---
 .../JythonInterpreterProviderFactory.java          | 37 +++++++++++++++++++---
 6 files changed, 89 insertions(+), 16 deletions(-)

diff --git a/plugins/org.python.pydev.debug/src/org/python/pydev/debug/ui/launching/PythonRunnerConfig.java b/plugins/org.python.pydev.debug/src/org/python/pydev/debug/ui/launching/PythonRunnerConfig.java
index ae4202094..6aa827837 100644
--- a/plugins/org.python.pydev.debug/src/org/python/pydev/debug/ui/launching/PythonRunnerConfig.java
+++ b/plugins/org.python.pydev.debug/src/org/python/pydev/debug/ui/launching/PythonRunnerConfig.java
@@ -40,6 +40,7 @@ import org.python.pydev.plugin.PydevPlugin;
 import org.python.pydev.ast.interpreter_managers.InterpreterInfo;
 import org.python.pydev.ast.interpreter_managers.InterpreterManagersAPI;
 import org.python.pydev.ast.listing_utils.JavaVmLocationFinder;
+import org.python.pydev.ast.runners.SimpleJythonRunner;
 import org.python.pydev.ast.runners.SimpleRunner;
 import org.python.pydev.core.ExtensionHelper;
 import org.python.pydev.core.IInterpreterInfo;
@@ -716,7 +717,8 @@ public class PythonRunnerConfig {
             //            if (project.getNature(Constants.JAVA_NATURE) != null){
             //                cpath  = getClasspath(JavaCore.create(project));
             //            } else {
-            cpath = interpreter + SimpleRunner.getPythonPathSeparator() + pythonpathUsed;
+            cpath = SimpleJythonRunner.generateClasspath(interpreter.toString()) + SimpleRunner.getPythonPathSeparator()
+                    + pythonpathUsed;
             //            }
             cmdArgs.add(cpath);
             cmdArgs.add("-Dpython.path=" + pythonpathUsed); //will be added to the env variables in the run (check if this works on all platforms...)
diff --git a/plugins/org.python.pydev.ast/src/org/python/pydev/ast/runners/SimpleJythonRunner.java b/plugins/org.python.pydev.ast/src/org/python/pydev/ast/runners/SimpleJythonRunner.java
index 1b3d84c2b..f5552ce68 100644
--- a/plugins/org.python.pydev.ast/src/org/python/pydev/ast/runners/SimpleJythonRunner.java
+++ b/plugins/org.python.pydev.ast/src/org/python/pydev/ast/runners/SimpleJythonRunner.java
@@ -11,9 +11,13 @@ package org.python.pydev.runners;
 
 import java.io.File;
 import java.io.IOException;
+import java.nio.file.Files;
+import java.nio.file.Path;
+import java.nio.file.Paths;
 import java.util.ArrayList;
 import java.util.Arrays;
 import java.util.List;
+import java.util.stream.Collectors;
 
 import org.eclipse.core.resources.IProject;
 import org.eclipse.core.runtime.AssertionFailedException;
@@ -81,15 +85,15 @@ public class SimpleJythonRunner extends SimpleRunner {
             //In Jython 2.5b0, if we don't set python.home, it won't be able to calculate the correct PYTHONPATH
             //(see http://bugs.jython.org/issue1214 )
 
+            String classpath = generateClasspath(jythonJar);
             String pythonHome = new File(jythonJar).getParent().toString();
 
             if (additionalPythonpath != null) {
-                jythonJar += SimpleRunner.getPythonPathSeparator();
-                jythonJar += additionalPythonpath;
+                classpath += SimpleRunner.getPythonPathSeparator() + additionalPythonpath;
                 s = new String[] { javaLoc, "-Dpython.path=" + additionalPythonpath, "-Dpython.home=" + pythonHome,
-                        "-classpath", jythonJar, "org.python.util.jython", script };
+                        "-classpath", classpath, "org.python.util.jython", script };
             } else {
-                s = new String[] { javaLoc, "-Dpython.home=" + pythonHome, "-classpath", jythonJar,
+                s = new String[] { javaLoc, "-Dpython.home=" + pythonHome, "-classpath", classpath,
                         "org.python.util.jython", script };
             }
 
@@ -147,6 +151,8 @@ public class SimpleJythonRunner extends SimpleRunner {
         }
         jythonPath.append(libs);
 
+        String classpath = generateClasspath(jythonJar);
+
         //may have the dir or be null
         String cacheDir = null;
         try {
@@ -174,7 +180,7 @@ public class SimpleJythonRunner extends SimpleRunner {
         String[] s = new String[] {
                 "-Dpython.path=" + jythonPath.toString(),
                 "-classpath",
-                jythonJar + pathSeparator + jythonPath,
+                classpath + pathSeparator + jythonPath,
                 "org.python.util.jython",
                 script
         };
@@ -190,4 +196,21 @@ public class SimpleJythonRunner extends SimpleRunner {
         return asList.toArray(new String[0]);
     }
 
+    public static String generateClasspath(String jythonJar) {
+        Path jythonPath = Paths.get(jythonJar);
+        String separator = SimpleRunner.getPythonPathSeparator();
+        try {
+            String javalibs = Files.list(jythonPath.getParent().resolve("javalib"))
+                    .filter(Files::isRegularFile)
+                    .map(Path::toString)
+                    .collect(Collectors.joining(separator));
+            String classpath = jythonPath.toString();
+            if (javalibs != null && !javalibs.isEmpty()) {
+                classpath += separator + javalibs;
+            }
+            return classpath;
+        } catch (IOException e) {
+            return jythonPath.toString();
+        }
+    }
 }
diff --git a/plugins/org.python.pydev.ast/src/org/python/pydev/ast/interpreter_managers/JythonInterpreterManager.java b/plugins/org.python.pydev.ast/src/org/python/pydev/ast/interpreter_managers/JythonInterpreterManager.java
index e9f3333d1..6970c0854 100644
--- a/plugins/org.python.pydev.ast/src/org/python/pydev/ast/interpreter_managers/JythonInterpreterManager.java
+++ b/plugins/org.python.pydev.ast/src/org/python/pydev/ast/interpreter_managers/JythonInterpreterManager.java
@@ -12,6 +12,10 @@
 package org.python.pydev.ast.interpreter_managers;
 
 import java.io.File;
+import java.io.IOException;
+import java.nio.file.Files;
+import java.nio.file.Path;
+import java.nio.file.Paths;
 import java.util.List;
 
 import org.eclipse.core.runtime.CoreException;
@@ -70,6 +74,23 @@ public class JythonInterpreterManager extends AbstractInterpreterManager {
         }
         File script = getInterpreterInfoPy();
 
+        Path path = Paths.get(executable);
+        try {
+            if (executable.endsWith(".jar")) {
+                path = path.getParent().toRealPath();
+            } else {
+                path = path.toRealPath().getParent().getParent();
+            }
+            if (Files.isRegularFile(path.resolve("jython.jar")) && Files.isDirectory(path.resolve("Lib"))) {
+                executable = path.resolve("jython.jar").toString();
+            } else if (Files.isRegularFile(path.resolve("jython-dev.jar"))
+                    && Files.isDirectory(path.resolve("Lib"))) {
+                executable = path.resolve("jython-dev.jar").toString();
+            }
+        } catch (IOException e) {
+            executable = path.toString();
+        }
+
         //gets the info for the python side
         Tuple<String, String> outTup = new SimpleJythonRunner().runAndGetOutputWithJar(
                 FileUtils.getFileAbsolutePath(script),
diff --git a/plugins/org.python.pydev/src/org/python/pydev/ui/pythonpathconf/AbstractInterpreterProviderFactory.java b/plugins/org.python.pydev/src/org/python/pydev/ui/pythonpathconf/AbstractInterpreterProviderFactory.java
index 0e012a9c9..7f10e3b4f 100644
--- a/plugins/org.python.pydev/src/org/python/pydev/ui/pythonpathconf/AbstractInterpreterProviderFactory.java
+++ b/plugins/org.python.pydev/src/org/python/pydev/ui/pythonpathconf/AbstractInterpreterProviderFactory.java
@@ -73,7 +73,7 @@ public abstract class AbstractInterpreterProviderFactory implements IInterpreter
                     if (available != null) {
                         for (File afile : available) {
                             int priority = matchesPattern(patterns, afile);
-                            if (priority != INVALID) {
+                            if (priority != INVALID && !afile.isDirectory()) {
                                 if (pathSetsByPriority[priority] == null) {
                                     pathSetsByPriority[priority] = new LinkedHashSet<String>();
                                 }
diff --git a/plugins/org.python.pydev.ast/src/org/python/pydev/ast/interpreter_managers/InterpreterInfo.java b/plugins/org.python.pydev.ast/src/org/python/pydev/ast/interpreter_managers/InterpreterInfo.java
index 17145cf46..c8c051bb9 100644
--- a/plugins/org.python.pydev.ast/src/org/python/pydev/ast/interpreter_managers/InterpreterInfo.java
+++ b/plugins/org.python.pydev.ast/src/org/python/pydev/ast/interpreter_managers/InterpreterInfo.java
@@ -14,6 +14,7 @@ package org.python.pydev.ui.pythonpathconf;
 import java.io.File;
 import java.io.FilenameFilter;
 import java.io.StringReader;
+import java.nio.file.Paths;
 import java.util.ArrayList;
 import java.util.Arrays;
 import java.util.Collection;
@@ -1494,10 +1495,8 @@ public class InterpreterInfo implements IInterpreterInfo {
      * @return if the executable is the jython jar.
      */
     public static boolean isJythonExecutable(String executable) {
-        if (executable.endsWith("\"")) {
-            return executable.endsWith(".jar\"");
-        }
-        return executable.endsWith(".jar");
+        java.nio.file.Path p = Paths.get(executable);
+        return p.endsWith(Paths.get("bin", "jython")) || p.getFileName().toString().endsWith(".jar");
     }
 
     /**
diff --git a/plugins/org.python.pydev/src/org/python/pydev/ui/pythonpathconf/JythonInterpreterProviderFactory.java b/plugins/org.python.pydev/src/org/python/pydev/ui/pythonpathconf/JythonInterpreterProviderFactory.java
index dc2586ce3..6b397f22d 100644
--- a/plugins/org.python.pydev/src/org/python/pydev/ui/pythonpathconf/JythonInterpreterProviderFactory.java
+++ b/plugins/org.python.pydev/src/org/python/pydev/ui/pythonpathconf/JythonInterpreterProviderFactory.java
@@ -12,6 +12,10 @@
 ******************************************************************************/
 package org.python.pydev.ui.pythonpathconf;
 
+import java.io.IOException;
+import java.nio.file.Files;
+import java.nio.file.Path;
+import java.nio.file.Paths;
 import java.util.Arrays;
 import java.util.LinkedHashSet;
 import java.util.List;
@@ -57,13 +61,36 @@ public class JythonInterpreterProviderFactory extends AbstractInterpreterProvide
         } catch (CoreException e) {
             Log.log(e);
         }
+        // The jython home location for linux packaged versions of jython
+        pathsToSearch.add("/usr/share/jython");
+        // The standard location for jars on linux distros
         pathsToSearch.add("/usr/share/java");
-        pathsToSearch.add("/usr/bin");
-        pathsToSearch.add("/usr/local/bin");
 
-        String[] searchResults = searchPaths(pathsToSearch, Arrays.asList("jython.jar"));
-        if (searchResults.length > 0) {
-            return AlreadyInstalledInterpreterProvider.create("jython", searchResults);
+        String[] searchResults = searchPaths(pathsToSearch, Arrays.asList("jython.jar", "jython-dev.jar", "jython"),
+                false);
+
+        LinkedHashSet<String> paths = new LinkedHashSet<>();
+        for (String result : searchResults) {
+            Path path = Paths.get(result);
+            try {
+                if (result.endsWith(".jar")) {
+                    path = path.getParent().toRealPath();
+                } else {
+                    path = path.toRealPath().getParent().getParent();
+                }
+                if (Files.isRegularFile(path.resolve("jython.jar")) && Files.isDirectory(path.resolve("Lib"))) {
+                    paths.add(path.resolve("jython.jar").toString());
+                } else if (Files.isRegularFile(path.resolve("jython-dev.jar"))
+                        && Files.isDirectory(path.resolve("Lib"))) {
+                    paths.add(path.resolve("jython-dev.jar").toString());
+                }
+            } catch (IOException e) {
+                continue;
+            }
+        }
+
+        if (paths.size() > 0) {
+            return AlreadyInstalledInterpreterProvider.create("jython", paths.toArray(new String[paths.size()]));
         }
 
         return null;
-- 
2.13.5