diff --git a/core/src/main/java/org/elasticsearch/bootstrap/JarHell.java b/core/src/main/java/org/elasticsearch/bootstrap/JarHell.java index 90621407b23..a5c71e3aa67 100644 --- a/core/src/main/java/org/elasticsearch/bootstrap/JarHell.java +++ b/core/src/main/java/org/elasticsearch/bootstrap/JarHell.java @@ -26,6 +26,7 @@ import org.elasticsearch.common.logging.ESLogger; import org.elasticsearch.common.logging.Loggers; import java.io.IOException; +import java.net.MalformedURLException; import java.net.URL; import java.net.URLClassLoader; import java.nio.file.FileVisitResult; @@ -70,21 +71,43 @@ public class JarHell { } /** - * Checks the current classloader for duplicate classes + * Checks the current classpath for duplicate classes * @throws IllegalStateException if jar hell was found */ public static void checkJarHell() throws Exception { ClassLoader loader = JarHell.class.getClassLoader(); - if (loader instanceof URLClassLoader == false) { - return; - } ESLogger logger = Loggers.getLogger(JarHell.class); if (logger.isDebugEnabled()) { logger.debug("java.class.path: {}", System.getProperty("java.class.path")); logger.debug("sun.boot.class.path: {}", System.getProperty("sun.boot.class.path")); - logger.debug("classloader urls: {}", Arrays.toString(((URLClassLoader)loader).getURLs())); + if (loader instanceof URLClassLoader ) { + logger.debug("classloader urls: {}", Arrays.toString(((URLClassLoader)loader).getURLs())); + } } - checkJarHell(((URLClassLoader) loader).getURLs()); + checkJarHell(parseClassPath()); + } + + /** + * Parses the classpath into a set of URLs + */ + @SuppressForbidden(reason = "resolves against CWD because that is how classpaths work") + public static URL[] parseClassPath() { + String elements[] = System.getProperty("java.class.path").split(System.getProperty("path.separator")); + URL urlElements[] = new URL[elements.length]; + for (int i = 0; i < elements.length; i++) { + String element = elements[i]; + // empty classpath element behaves like CWD. + if (element.isEmpty()) { + element = System.getProperty("user.dir"); + } + try { + urlElements[i] = PathUtils.get(element).toUri().toURL(); + } catch (MalformedURLException e) { + // should not happen, as we use the filesystem API + throw new RuntimeException(e); + } + } + return urlElements; } /** diff --git a/core/src/main/java/org/elasticsearch/bootstrap/Security.java b/core/src/main/java/org/elasticsearch/bootstrap/Security.java index 47e0100e210..a6bcb2f3732 100644 --- a/core/src/main/java/org/elasticsearch/bootstrap/Security.java +++ b/core/src/main/java/org/elasticsearch/bootstrap/Security.java @@ -24,7 +24,6 @@ import org.elasticsearch.env.Environment; import java.io.*; import java.net.URL; -import java.net.URLClassLoader; import java.nio.file.AccessMode; import java.nio.file.FileAlreadyExistsException; import java.nio.file.Files; @@ -133,27 +132,21 @@ final class Security { */ @SuppressForbidden(reason = "proper use of URL") static void setCodebaseProperties() { - ClassLoader loader = Security.class.getClassLoader(); - if (loader instanceof URLClassLoader) { - for (URL url : ((URLClassLoader)loader).getURLs()) { - for (Map.Entry e : SPECIAL_JARS.entrySet()) { - if (e.getKey().matcher(url.getPath()).matches()) { - String prop = e.getValue(); - if (System.getProperty(prop) != null) { - throw new IllegalStateException("property: " + prop + " is unexpectedly set: " + System.getProperty(prop)); - } - System.setProperty(prop, url.toString()); + for (URL url : JarHell.parseClassPath()) { + for (Map.Entry e : SPECIAL_JARS.entrySet()) { + if (e.getKey().matcher(url.getPath()).matches()) { + String prop = e.getValue(); + if (System.getProperty(prop) != null) { + throw new IllegalStateException("property: " + prop + " is unexpectedly set: " + System.getProperty(prop)); } + System.setProperty(prop, url.toString()); } } - for (String prop : SPECIAL_JARS.values()) { - if (System.getProperty(prop) == null) { - System.setProperty(prop, "file:/dev/null"); // no chance to be interpreted as "all" - } + } + for (String prop : SPECIAL_JARS.values()) { + if (System.getProperty(prop) == null) { + System.setProperty(prop, "file:/dev/null"); // no chance to be interpreted as "all" } - } else { - // we could try to parse the classpath or something, but screw it for now. - throw new UnsupportedOperationException("Unsupported system classloader type: " + loader.getClass()); } } diff --git a/core/src/main/java/org/elasticsearch/plugins/PluginManager.java b/core/src/main/java/org/elasticsearch/plugins/PluginManager.java index ee9e6b392e0..3eded07712f 100644 --- a/core/src/main/java/org/elasticsearch/plugins/PluginManager.java +++ b/core/src/main/java/org/elasticsearch/plugins/PluginManager.java @@ -41,7 +41,6 @@ import java.io.IOException; import java.io.OutputStream; import java.net.MalformedURLException; import java.net.URL; -import java.net.URLClassLoader; import java.nio.file.*; import java.nio.file.attribute.BasicFileAttributes; import java.nio.file.attribute.PosixFileAttributeView; @@ -315,10 +314,7 @@ public class PluginManager { private void jarHellCheck(Path candidate, boolean isolated) throws IOException { // create list of current jars in classpath final List jars = new ArrayList<>(); - ClassLoader loader = PluginManager.class.getClassLoader(); - if (loader instanceof URLClassLoader) { - Collections.addAll(jars, ((URLClassLoader) loader).getURLs()); - } + jars.addAll(Arrays.asList(JarHell.parseClassPath())); // read existing bundles. this does some checks on the installation too. List bundles = PluginsService.getPluginBundles(environment.pluginsFile()); diff --git a/core/src/main/java/org/elasticsearch/plugins/PluginsService.java b/core/src/main/java/org/elasticsearch/plugins/PluginsService.java index c70349f9bf8..5834efc398d 100644 --- a/core/src/main/java/org/elasticsearch/plugins/PluginsService.java +++ b/core/src/main/java/org/elasticsearch/plugins/PluginsService.java @@ -47,6 +47,7 @@ import java.nio.file.DirectoryStream; import java.nio.file.Files; import java.nio.file.Path; import java.util.ArrayList; +import java.util.Arrays; import java.util.Collection; import java.util.Collections; import java.util.HashMap; @@ -331,12 +332,7 @@ public class PluginsService extends AbstractComponent { // pluginmanager does it, but we do it again, in case lusers mess with jar files manually try { final List jars = new ArrayList<>(); - ClassLoader parentLoader = getClass().getClassLoader(); - if (parentLoader instanceof URLClassLoader) { - for (URL url : ((URLClassLoader) parentLoader).getURLs()) { - jars.add(url); - } - } + jars.addAll(Arrays.asList(JarHell.parseClassPath())); jars.addAll(bundle.urls); JarHell.checkJarHell(jars.toArray(new URL[0])); } catch (Exception e) { diff --git a/core/src/test/java/org/elasticsearch/bootstrap/BootstrapForTesting.java b/core/src/test/java/org/elasticsearch/bootstrap/BootstrapForTesting.java index 34bba38d18a..e31fc7d8b35 100644 --- a/core/src/test/java/org/elasticsearch/bootstrap/BootstrapForTesting.java +++ b/core/src/test/java/org/elasticsearch/bootstrap/BootstrapForTesting.java @@ -86,7 +86,7 @@ public class BootstrapForTesting { // initialize paths the same exact way as bootstrap. Permissions perms = new Permissions(); // add permissions to everything in classpath - for (URL url : ((URLClassLoader)BootstrapForTesting.class.getClassLoader()).getURLs()) { + for (URL url : JarHell.parseClassPath()) { Path path = PathUtils.get(url.toURI()); // resource itself perms.add(new FilePermission(path.toString(), "read,readlink"));