e4cd93c
From 41fba27ce8728722076f1c0c9f81db215c7b494a Mon Sep 17 00:00:00 2001
e4cd93c
From: Mat Booth <mat.booth@redhat.com>
e4cd93c
Date: Thu, 28 Sep 2017 16:13:50 +0100
e4cd93c
Subject: [PATCH] Better support system installed versions of Jython for Linux
e4cd93c
 distros
e4cd93c
e4cd93c
---
e4cd93c
 .../debug/ui/launching/PythonRunnerConfig.java     |  4 ++-
e4cd93c
 .../python/pydev/runners/SimpleJythonRunner.java   | 33 ++++++++++++++++---
e4cd93c
 .../ui/interpreters/JythonInterpreterManager.java  | 21 ++++++++++++
e4cd93c
 .../AbstractInterpreterProviderFactory.java        |  2 +-
e4cd93c
 .../pydev/ui/pythonpathconf/InterpreterInfo.java   |  8 ++---
e4cd93c
 .../JythonInterpreterProviderFactory.java          | 37 +++++++++++++++++++---
e4cd93c
 6 files changed, 89 insertions(+), 16 deletions(-)
e4cd93c
e4909f6
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
e4cd93c
index ae4202094..6aa827837 100644
e4909f6
--- a/plugins/org.python.pydev.debug/src/org/python/pydev/debug/ui/launching/PythonRunnerConfig.java
e4909f6
+++ b/plugins/org.python.pydev.debug/src/org/python/pydev/debug/ui/launching/PythonRunnerConfig.java
e4cd93c
@@ -59,6 +59,7 @@ import org.python.pydev.plugin.PydevPlugin;
266987d
 import org.python.pydev.ast.interpreter_managers.InterpreterInfo;
266987d
 import org.python.pydev.ast.interpreter_managers.InterpreterManagersAPI;
266987d
 import org.python.pydev.ast.listing_utils.JavaVmLocationFinder;
266987d
+import org.python.pydev.ast.runners.SimpleJythonRunner;
266987d
 import org.python.pydev.ast.runners.SimpleRunner;
266987d
 import org.python.pydev.core.ExtensionHelper;
266987d
 import org.python.pydev.core.IInterpreterInfo;
b299fc1
@@ -701,7 +702,8 @@ public class PythonRunnerConfig {
e4cd93c
             //            if (project.getNature(Constants.JAVA_NATURE) != null){
e4cd93c
             //                cpath  = getClasspath(JavaCore.create(project));
e4cd93c
             //            } else {
e4cd93c
-            cpath = interpreter + SimpleRunner.getPythonPathSeparator() + pythonpathUsed;
e4cd93c
+            cpath = SimpleJythonRunner.generateClasspath(interpreter.toString()) + SimpleRunner.getPythonPathSeparator()
e4cd93c
+                    + pythonpathUsed;
10a1404
             //            }
10a1404
             cmdArgs.add(cpath);
e4909f6
             cmdArgs.add("-Dpython.path=" + pythonpathUsed); //will be added to the env variables in the run (check if this works on all platforms...)
266987d
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
e4cd93c
index 1b3d84c2b..f5552ce68 100644
266987d
--- a/plugins/org.python.pydev.ast/src/org/python/pydev/ast/runners/SimpleJythonRunner.java
266987d
+++ b/plugins/org.python.pydev.ast/src/org/python/pydev/ast/runners/SimpleJythonRunner.java
e4cd93c
@@ -11,9 +11,13 @@ package org.python.pydev.runners;
e4cd93c
 
e4cd93c
 import java.io.File;
e4cd93c
 import java.io.IOException;
e4cd93c
+import java.nio.file.Files;
e4cd93c
+import java.nio.file.Path;
e4cd93c
+import java.nio.file.Paths;
e4cd93c
 import java.util.ArrayList;
e4cd93c
 import java.util.Arrays;
e4cd93c
 import java.util.List;
e4cd93c
+import java.util.stream.Collectors;
9dcbece
 
e4cd93c
 import org.eclipse.core.resources.IProject;
266987d
 import org.eclipse.core.runtime.AssertionFailedException;
266987d
@@ -81,15 +85,15 @@ public class SimpleJythonRunner extends SimpleRunner {
e4cd93c
             //In Jython 2.5b0, if we don't set python.home, it won't be able to calculate the correct PYTHONPATH
e4cd93c
             //(see http://bugs.jython.org/issue1214 )
e4cd93c
 
e4cd93c
+            String classpath = generateClasspath(jythonJar);
e4cd93c
             String pythonHome = new File(jythonJar).getParent().toString();
e4cd93c
 
e4cd93c
             if (additionalPythonpath != null) {
9dcbece
-                jythonJar += SimpleRunner.getPythonPathSeparator();
9dcbece
-                jythonJar += additionalPythonpath;
e4cd93c
+                classpath += SimpleRunner.getPythonPathSeparator() + additionalPythonpath;
e4cd93c
                 s = new String[] { javaLoc, "-Dpython.path=" + additionalPythonpath, "-Dpython.home=" + pythonHome,
9dcbece
-                        "-classpath", jythonJar, "org.python.util.jython", script };
e4cd93c
+                        "-classpath", classpath, "org.python.util.jython", script };
9dcbece
             } else {
9dcbece
-                s = new String[] { javaLoc, "-Dpython.home=" + pythonHome, "-classpath", jythonJar,
e4cd93c
+                s = new String[] { javaLoc, "-Dpython.home=" + pythonHome, "-classpath", classpath,
e4cd93c
                         "org.python.util.jython", script };
9dcbece
             }
9dcbece
 
266987d
@@ -147,6 +151,8 @@ public class SimpleJythonRunner extends SimpleRunner {
e4909f6
         }
e4cd93c
         jythonPath.append(libs);
e4909f6
 
e4cd93c
+        String classpath = generateClasspath(jythonJar);
e4909f6
+
e4cd93c
         //may have the dir or be null
e4cd93c
         String cacheDir = null;
e4cd93c
         try {
e4cd93c
@@ -162,7 +168,7 @@ public class SimpleJythonRunner extends SimpleRunner {
e4909f6
         String[] s = new String[] {
e4909f6
                 "-Dpython.path=" + jythonPath.toString(),
e4cd93c
                 "-classpath",
e4cd93c
-                jythonJar + pathSeparator + jythonPath,
e4cd93c
+                classpath + pathSeparator + jythonPath,
e4cd93c
                 "org.python.util.jython",
e4cd93c
                 script
e4cd93c
         };
e4cd93c
@@ -178,4 +184,21 @@ public class SimpleJythonRunner extends SimpleRunner {
e4cd93c
         return asList.toArray(new String[0]);
e4cd93c
     }
e4cd93c
 
e4cd93c
+    public static String generateClasspath(String jythonJar) {
e4cd93c
+        Path jythonPath = Paths.get(jythonJar);
e4cd93c
+        String separator = SimpleRunner.getPythonPathSeparator();
e4cd93c
+        try {
e4cd93c
+            String javalibs = Files.list(jythonPath.getParent().resolve("javalib"))
e4cd93c
+                    .filter(Files::isRegularFile)
e4cd93c
+                    .map(Path::toString)
e4cd93c
+                    .collect(Collectors.joining(separator));
e4cd93c
+            String classpath = jythonPath.toString();
e4cd93c
+            if (javalibs != null && !javalibs.isEmpty()) {
e4cd93c
+                classpath += separator + javalibs;
e4cd93c
+            }
e4cd93c
+            return classpath;
e4cd93c
+        } catch (IOException e) {
e4cd93c
+            return jythonPath.toString();
e4cd93c
+        }
e4cd93c
+    }
e4cd93c
 }
266987d
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
e4cd93c
index e9f3333d1..6970c0854 100644
266987d
--- a/plugins/org.python.pydev.ast/src/org/python/pydev/ast/interpreter_managers/JythonInterpreterManager.java
266987d
+++ b/plugins/org.python.pydev.ast/src/org/python/pydev/ast/interpreter_managers/JythonInterpreterManager.java
e4cd93c
@@ -12,6 +12,10 @@
266987d
 package org.python.pydev.ast.interpreter_managers;
e4cd93c
 
e4cd93c
 import java.io.File;
e4cd93c
+import java.io.IOException;
e4cd93c
+import java.nio.file.Files;
e4cd93c
+import java.nio.file.Path;
e4cd93c
+import java.nio.file.Paths;
e4cd93c
 import java.util.List;
e4cd93c
 
e4cd93c
 import org.eclipse.core.runtime.CoreException;
e4cd93c
@@ -71,6 +75,23 @@ public class JythonInterpreterManager extends AbstractInterpreterManager {
e4cd93c
         }
e4cd93c
         File script = getInterpreterInfoPy();
e4cd93c
 
e4cd93c
+        Path path = Paths.get(executable);
e4cd93c
+        try {
e4cd93c
+            if (executable.endsWith(".jar")) {
e4cd93c
+                path = path.getParent().toRealPath();
e4cd93c
+            } else {
e4cd93c
+                path = path.toRealPath().getParent().getParent();
e4cd93c
+            }
e4cd93c
+            if (Files.isRegularFile(path.resolve("jython.jar")) && Files.isDirectory(path.resolve("Lib"))) {
e4cd93c
+                executable = path.resolve("jython.jar").toString();
e4cd93c
+            } else if (Files.isRegularFile(path.resolve("jython-dev.jar"))
e4cd93c
+                    && Files.isDirectory(path.resolve("Lib"))) {
e4cd93c
+                executable = path.resolve("jython-dev.jar").toString();
e4cd93c
+            }
e4cd93c
+        } catch (IOException e) {
e4cd93c
+            executable = path.toString();
e4cd93c
+        }
e4cd93c
+
e4cd93c
         //gets the info for the python side
e4cd93c
         Tuple<String, String> outTup = new SimpleJythonRunner().runAndGetOutputWithJar(
e4cd93c
                 FileUtils.getFileAbsolutePath(script),
e4cd93c
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
e4cd93c
index 0e012a9c9..7f10e3b4f 100644
e4cd93c
--- a/plugins/org.python.pydev/src/org/python/pydev/ui/pythonpathconf/AbstractInterpreterProviderFactory.java
e4cd93c
+++ b/plugins/org.python.pydev/src/org/python/pydev/ui/pythonpathconf/AbstractInterpreterProviderFactory.java
e4cd93c
@@ -72,7 +72,7 @@ public abstract class AbstractInterpreterProviderFactory implements IInterpreter
e4cd93c
                     if (available != null) {
e4cd93c
                         for (File afile : available) {
e4cd93c
                             int priority = matchesPattern(patterns, afile);
e4cd93c
-                            if (priority != INVALID) {
e4cd93c
+                            if (priority != INVALID && !afile.isDirectory()) {
e4cd93c
                                 if (pathSetsByPriority[priority] == null) {
e4cd93c
                                     pathSetsByPriority[priority] = new LinkedHashSet<String>();
e4cd93c
                                 }
266987d
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
e4cd93c
index 17145cf46..c8c051bb9 100644
266987d
--- a/plugins/org.python.pydev.ast/src/org/python/pydev/ast/interpreter_managers/InterpreterInfo.java
266987d
+++ b/plugins/org.python.pydev.ast/src/org/python/pydev/ast/interpreter_managers/InterpreterInfo.java
b299fc1
@@ -14,6 +14,7 @@ package org.python.pydev.ui.pythonpathconf;
e4cd93c
 import java.io.File;
e4cd93c
 import java.io.FilenameFilter;
e4cd93c
 import java.io.StringReader;
e4cd93c
+import java.nio.file.Paths;
e4cd93c
 import java.util.ArrayList;
e4cd93c
 import java.util.Arrays;
e4cd93c
 import java.util.Collection;
b299fc1
@@ -1479,10 +1481,8 @@ public class InterpreterInfo implements IInterpreterInfo {
e4cd93c
      * @return if the executable is the jython jar.
9dcbece
      */
9dcbece
     public static boolean isJythonExecutable(String executable) {
e4cd93c
-        if (executable.endsWith("\"")) {
9dcbece
-            return executable.endsWith(".jar\"");
e4cd93c
-        }
9dcbece
-        return executable.endsWith(".jar");
b299fc1
+        java.nio.file.Path p = Paths.get(executable);
e4cd93c
+        return p.endsWith(Paths.get("bin", "jython")) || p.getFileName().toString().endsWith(".jar");
9dcbece
     }
9dcbece
 
9dcbece
     /**
e4cd93c
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
e4cd93c
index dc2586ce3..6b397f22d 100644
e4cd93c
--- a/plugins/org.python.pydev/src/org/python/pydev/ui/pythonpathconf/JythonInterpreterProviderFactory.java
e4cd93c
+++ b/plugins/org.python.pydev/src/org/python/pydev/ui/pythonpathconf/JythonInterpreterProviderFactory.java
e4cd93c
@@ -12,6 +12,10 @@
e4cd93c
 ******************************************************************************/
e4cd93c
 package org.python.pydev.ui.pythonpathconf;
e4cd93c
 
e4cd93c
+import java.io.IOException;
e4cd93c
+import java.nio.file.Files;
e4cd93c
+import java.nio.file.Path;
e4cd93c
+import java.nio.file.Paths;
e4cd93c
 import java.util.Arrays;
e4cd93c
 import java.util.LinkedHashSet;
e4cd93c
 import java.util.List;
266987d
@@ -57,13 +61,36 @@ public class JythonInterpreterProviderFactory extends AbstractInterpreterProvide
e4cd93c
         } catch (CoreException e) {
e4cd93c
             Log.log(e);
e4cd93c
         }
e4cd93c
+        // The jython home location for linux packaged versions of jython
e4cd93c
+        pathsToSearch.add("/usr/share/jython");
e4cd93c
+        // The standard location for jars on linux distros
e4cd93c
         pathsToSearch.add("/usr/share/java");
e4cd93c
-        pathsToSearch.add("/usr/bin");
e4cd93c
-        pathsToSearch.add("/usr/local/bin");
e4cd93c
 
e4cd93c
-        String[] searchResults = searchPaths(pathsToSearch, Arrays.asList("jython.jar"));
e4cd93c
-        if (searchResults.length > 0) {
e4cd93c
-            return AlreadyInstalledInterpreterProvider.create("jython", searchResults);
e4cd93c
+        String[] searchResults = searchPaths(pathsToSearch, Arrays.asList("jython.jar", "jython-dev.jar", "jython"),
e4cd93c
+                false);
e4cd93c
+
e4cd93c
+        LinkedHashSet<String> paths = new LinkedHashSet<>();
e4cd93c
+        for (String result : searchResults) {
e4cd93c
+            Path path = Paths.get(result);
e4cd93c
+            try {
e4cd93c
+                if (result.endsWith(".jar")) {
e4cd93c
+                    path = path.getParent().toRealPath();
e4cd93c
+                } else {
e4cd93c
+                    path = path.toRealPath().getParent().getParent();
e4cd93c
+                }
e4cd93c
+                if (Files.isRegularFile(path.resolve("jython.jar")) && Files.isDirectory(path.resolve("Lib"))) {
e4cd93c
+                    paths.add(path.resolve("jython.jar").toString());
e4cd93c
+                } else if (Files.isRegularFile(path.resolve("jython-dev.jar"))
e4cd93c
+                        && Files.isDirectory(path.resolve("Lib"))) {
e4cd93c
+                    paths.add(path.resolve("jython-dev.jar").toString());
e4cd93c
+                }
e4cd93c
+            } catch (IOException e) {
e4cd93c
+                continue;
e4cd93c
+            }
e4cd93c
+        }
e4cd93c
+
e4cd93c
+        if (paths.size() > 0) {
e4cd93c
+            return AlreadyInstalledInterpreterProvider.create("jython", paths.toArray(new String[paths.size()]));
e4cd93c
         }
e4cd93c
 
e4cd93c
         return null;
e4cd93c
-- 
e4cd93c
2.13.5
e4cd93c