# HG changeset patch # User igerasim # Date 1421683931 -10800 # Node ID b86e910f3310facbb6e1cf89e65438bdcd2674db # Parent 178ac8a1fbded37ae87d0ac1e5ee308a5a056240 8067951: System.loadLibrary cannot find library when path contains quoted entry Reviewed-by: sherman, rriggs, alanb diff -r 178ac8a1fbde -r b86e910f3310 jdk/src/java.base/macosx/classes/java/lang/ClassLoaderHelper.java --- a/jdk/src/java.base/macosx/classes/java/lang/ClassLoaderHelper.java Mon Jan 19 09:05:50 2015 +0100 +++ b/jdk/src/java.base/macosx/classes/java/lang/ClassLoaderHelper.java Mon Jan 19 19:12:11 2015 +0300 @@ -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 -r 178ac8a1fbde -r b86e910f3310 jdk/src/java.base/share/classes/java/lang/ClassLoader.java --- a/jdk/src/java.base/share/classes/java/lang/ClassLoader.java Mon Jan 19 09:05:50 2015 +0100 +++ b/jdk/src/java.base/share/classes/java/lang/ClassLoader.java Mon Jan 19 19:12:11 2015 +0300 @@ -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,54 @@ 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; + int psCount = 0; + + if (ClassLoaderHelper.allowsQuotedPathElements && + ldPath.indexOf('\"') >= 0) { + // First, remove quotes put around quoted parts of paths. + // Second, use a quotation mark as a new path separator. + // This will preserve any quoted old path separators. + 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 { + if (ch == ps) { + psCount++; + ch = '\"'; + } + buf[bufLen++] = ch; + } + } + ldPath = new String(buf, 0, bufLen); + ldLen = bufLen; + ps = '\"'; + } else { + for (int i = ldPath.indexOf(ps); i >= 0; + i = ldPath.indexOf(ps, i + 1)) { + psCount++; + } } - // allocate the array of paths - n :'s = n + 1 path elements - String[] paths = new String[n + 1]; - - // 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 -r 178ac8a1fbde -r b86e910f3310 jdk/src/java.base/unix/classes/java/lang/ClassLoaderHelper.java --- a/jdk/src/java.base/unix/classes/java/lang/ClassLoaderHelper.java Mon Jan 19 09:05:50 2015 +0100 +++ b/jdk/src/java.base/unix/classes/java/lang/ClassLoaderHelper.java Mon Jan 19 19:12:11 2015 +0300 @@ -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 -r 178ac8a1fbde -r b86e910f3310 jdk/src/java.base/windows/classes/java/lang/ClassLoaderHelper.java --- a/jdk/src/java.base/windows/classes/java/lang/ClassLoaderHelper.java Mon Jan 19 09:05:50 2015 +0100 +++ b/jdk/src/java.base/windows/classes/java/lang/ClassLoaderHelper.java Mon Jan 19 19:12:11 2015 +0300 @@ -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 -r 178ac8a1fbde -r b86e910f3310 jdk/test/java/lang/ClassLoader/LibraryPathProperty.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/jdk/test/java/lang/ClassLoader/LibraryPathProperty.java Mon Jan 19 19:12:11 2015 +0300 @@ -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)); + } + } +}