# HG changeset patch # User igerasim # Date 1420551550 -10800 # Node ID 7d82c3d2d8fe00194abe461608c81e403eb73ff2 # Parent 9acaa4f57b0b9e3757a7b4576ca9418a75ea8287 [mq]: 8067951-System.loadLibrary.cannot.find.library.when.path.contains.quoted.entry diff --git a/src/java.base/macosx/classes/java/lang/ClassLoaderHelper.java b/src/java.base/macosx/classes/java/lang/ClassLoaderHelper.java --- a/src/java.base/macosx/classes/java/lang/ClassLoaderHelper.java +++ b/src/java.base/macosx/classes/java/lang/ClassLoaderHelper.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2012, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2012, 2015 Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -31,6 +31,11 @@ private ClassLoaderHelper() {} /** + * Indicates, whether PATH env variable is allowed to contain quoted entries. + */ + static final boolean allowsQuotedPathElements = false; + + /** * Returns an alternate path name for the given file * such that if the original pathname did not exist, then the * file may be located at the alternate location. diff --git a/src/java.base/share/classes/java/lang/ClassLoader.java b/src/java.base/share/classes/java/lang/ClassLoader.java --- a/src/java.base/share/classes/java/lang/ClassLoader.java +++ b/src/java.base/share/classes/java/lang/ClassLoader.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2013, 2014 Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2013, 2015 Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -1747,35 +1747,47 @@ private static String usr_paths[]; private static String sys_paths[]; - private static String[] initializePath(String propname) { - String ldpath = System.getProperty(propname, ""); - String ps = File.pathSeparator; - int ldlen = ldpath.length(); - int i, j, n; - // Count the separators in the path - i = ldpath.indexOf(ps); - n = 0; - while (i >= 0) { - n++; - i = ldpath.indexOf(ps, i + 1); + private static String[] initializePath(String propName) { + String ldPath = System.getProperty(propName, ""); + int ldLen = ldPath.length(); + char ps = File.pathSeparatorChar; + + if (ClassLoaderHelper.allowsQuotedPathElements && + ldPath.indexOf('\"') >= 0) { + char[] buf = new char[ldLen]; + int bufLen = 0; + for (int i = 0; i < ldLen; ++i) { + char ch = ldPath.charAt(i); + if (ch == '\"') { + while (++i < ldLen && + (ch = ldPath.charAt(i)) != '\"') { + buf[bufLen++] = ch; + } + } else { + buf[bufLen++] = (ch == ps) ? '\0' : ch; + } + } + ldPath = new String(buf, 0, bufLen); + ldLen = bufLen; + ps = '\0'; } - // allocate the array of paths - n :'s = n + 1 path elements - String[] paths = new String[n + 1]; + int psCount = 0; + for (int i = ldPath.indexOf(ps); i >= 0; + i = ldPath.indexOf(ps, i + 1)) { + psCount++; + } - // Fill the array with paths from the ldpath - n = i = 0; - j = ldpath.indexOf(ps); - while (j >= 0) { - if (j - i > 0) { - paths[n++] = ldpath.substring(i, j); - } else if (j - i == 0) { - paths[n++] = "."; - } - i = j + 1; - j = ldpath.indexOf(ps, i); + String[] paths = new String[psCount + 1]; + int pathStart = 0; + for (int j = 0; j < psCount; ++j) { + int pathEnd = ldPath.indexOf(ps, pathStart); + paths[j] = (pathStart < pathEnd) ? + ldPath.substring(pathStart, pathEnd) : "."; + pathStart = pathEnd + 1; } - paths[n] = ldpath.substring(i, ldlen); + paths[psCount] = (pathStart < ldLen) ? + ldPath.substring(pathStart, ldLen) : "."; return paths; } diff --git a/src/java.base/unix/classes/java/lang/ClassLoaderHelper.java b/src/java.base/unix/classes/java/lang/ClassLoaderHelper.java --- a/src/java.base/unix/classes/java/lang/ClassLoaderHelper.java +++ b/src/java.base/unix/classes/java/lang/ClassLoaderHelper.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2012, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2012, 2015 Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -31,6 +31,11 @@ private ClassLoaderHelper() {} /** + * Indicates, whether PATH env variable is allowed to contain quoted entries. + */ + static final boolean allowsQuotedPathElements = false; + + /** * Returns an alternate path name for the given file * such that if the original pathname did not exist, then the * file may be located at the alternate location. diff --git a/src/java.base/windows/classes/java/lang/ClassLoaderHelper.java b/src/java.base/windows/classes/java/lang/ClassLoaderHelper.java --- a/src/java.base/windows/classes/java/lang/ClassLoaderHelper.java +++ b/src/java.base/windows/classes/java/lang/ClassLoaderHelper.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2012, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2012, 2015 Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -31,6 +31,11 @@ private ClassLoaderHelper() {} /** + * Indicates, whether PATH env variable is allowed to contain quoted entries. + */ + static final boolean allowsQuotedPathElements = true; + + /** * Returns an alternate path name for the given file * such that if the original pathname did not exist, then the * file may be located at the alternate location. diff --git a/test/java/lang/ClassLoader/LibraryPathProperty.java b/test/java/lang/ClassLoader/LibraryPathProperty.java new file mode 100644 --- /dev/null +++ b/test/java/lang/ClassLoader/LibraryPathProperty.java @@ -0,0 +1,84 @@ +/* + * Copyright (c) 2015, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ + +/* + * @test + * @bug 8067951 + * @summary Unit test for internal ClassLoader#initializePath(). + * Quoted entries should get unquoted on Windows. + * Empty entries should be replaced with dot. + * @library /lib/testlibrary + * @build jdk.testlibrary.Platform + * @run main LibraryPathProperty + */ + +import java.lang.reflect.Method; +import java.io.File; +import java.util.Arrays; +import jdk.testlibrary.Platform; + +public class LibraryPathProperty { + + static final String propName = "test.property.name"; + static final String SP = File.pathSeparator; + static Method method; + + public static void main(String[] args) throws Throwable { + method = ClassLoader.class + .getDeclaredMethod("initializePath", + String.class); + method.setAccessible(true); + + test("", "."); + test(SP, ".", "."); + test("a" + SP, "a", "."); + test(SP + "b", ".", "b"); + test("a" + SP + SP + "b", "a", ".", "b"); + + if (Platform.isWindows()) { + // on Windows parts of paths may be quoted + test("\"\"", "."); + test("\"\"" + SP, ".", "."); + test(SP + "\"\"", ".", "."); + test("a" + SP + "\"b\"" + SP, "a", "b", "."); + test(SP + "\"a\"" + SP + SP + "b", ".", "a", ".", "b"); + test("\"a\"" + SP + "\"b\"", "a", "b"); + test("\"/a/\"b" + SP + "c", "/a/b", "c"); + test("\"/a;b\"" + SP + "c", "/a;b", "c"); + test("\"/a:b\"" + SP + "c", "/a:b", "c"); + test("\"/a" + SP + "b\"" + SP + "c", "/a" + SP + "b", "c"); + test("/\"a\"\";\"\"b\"" + SP + "\"c\"", "/a;b", "c"); + test("/\"a:\"b" + SP + "c", "/a:b", "c"); + } + } + + static void test(String s, String... expected) throws Throwable { + System.setProperty(propName, s); + String[] res = (String[])method.invoke(null, propName); + if (!Arrays.asList(res).equals(Arrays.asList(expected))) { + throw new RuntimeException("Parsing [" + s + "] " + + " result " + Arrays.asList(res) + + " doesn't match " + Arrays.asList(expected)); + } + } +}