# HG changeset patch # User sundar # Date 1379070911 -19800 # Node ID 8b0914b25430d882526da828b8cd1c64eedbd1c6 # Parent 917b16e509bd15d6bb1e46c4b084b812105c36c2 8024619: JDBC java.sql.DriverManager is not usable from JS script Reviewed-by: jlaskey, lagergren, attila diff -r 917b16e509bd -r 8b0914b25430 make/build.xml --- a/make/build.xml Thu Sep 12 22:16:40 2013 +0530 +++ b/make/build.xml Fri Sep 13 16:45:11 2013 +0530 @@ -230,6 +230,10 @@ + + + + @@ -238,6 +242,7 @@ + diff -r 917b16e509bd -r 8b0914b25430 src/jdk/nashorn/internal/runtime/Context.java --- a/src/jdk/nashorn/internal/runtime/Context.java Thu Sep 12 22:16:40 2013 +0530 +++ b/src/jdk/nashorn/internal/runtime/Context.java Fri Sep 13 16:45:11 2013 +0530 @@ -236,6 +236,10 @@ private static final ClassLoader myLoader = Context.class.getClassLoader(); private static final StructureLoader sharedLoader; + /*package-private*/ ClassLoader getSharedLoader() { + return sharedLoader; + } + private static AccessControlContext createNoPermAccCtxt() { return new AccessControlContext(new ProtectionDomain[] { new ProtectionDomain(null, new Permissions()) }); } @@ -254,7 +258,7 @@ sharedLoader = AccessController.doPrivileged(new PrivilegedAction() { @Override public StructureLoader run() { - return new StructureLoader(myLoader, null); + return new StructureLoader(myLoader); } }, CREATE_LOADER_ACC_CTXT); } @@ -599,7 +603,7 @@ * @throws ClassNotFoundException if structure class cannot be resolved */ public static Class forStructureClass(final String fullName) throws ClassNotFoundException { - if (System.getSecurityManager() != null && !NashornLoader.isStructureClass(fullName)) { + if (System.getSecurityManager() != null && !StructureLoader.isStructureClass(fullName)) { throw new ClassNotFoundException(fullName); } return Class.forName(fullName, true, sharedLoader); @@ -792,12 +796,11 @@ static Context fromClass(final Class clazz) { final ClassLoader loader = clazz.getClassLoader(); - Context context = null; - if (loader instanceof NashornLoader) { - context = ((NashornLoader)loader).getContext(); + if (loader instanceof ScriptLoader) { + return ((ScriptLoader)loader).getContext(); } - return (context != null) ? context : Context.getContextTrusted(); + return Context.getContextTrusted(); } private Object evaluateSource(final Source source, final ScriptObject scope, final ScriptObject thiz) { @@ -899,7 +902,7 @@ new PrivilegedAction() { @Override public ScriptLoader run() { - return new ScriptLoader(sharedLoader, Context.this); + return new ScriptLoader(appLoader, Context.this); } }, CREATE_LOADER_ACC_CTXT); } diff -r 917b16e509bd -r 8b0914b25430 src/jdk/nashorn/internal/runtime/NashornLoader.java --- a/src/jdk/nashorn/internal/runtime/NashornLoader.java Thu Sep 12 22:16:40 2013 +0530 +++ b/src/jdk/nashorn/internal/runtime/NashornLoader.java Fri Sep 13 16:45:11 2013 +0530 @@ -38,10 +38,7 @@ import jdk.nashorn.tools.Shell; /** - * Superclass for Nashorn class loader classes. This stores Context - * instance as an instance field. The current context can be - * efficiently accessed from a given Class via it's ClassLoader. - * + * Superclass for Nashorn class loader classes. */ abstract class NashornLoader extends SecureClassLoader { private static final String OBJECTS_PKG = "jdk.nashorn.internal.objects"; @@ -69,27 +66,8 @@ }; } - private final Context context; - - final Context getContext() { - return context; - } - - NashornLoader(final ClassLoader parent, final Context context) { + NashornLoader(final ClassLoader parent) { super(parent); - this.context = context; - } - - - /** - * Called by subclass after package access check is done - * @param name name of the class to be loaded - * @param resolve whether the class should be resolved or not - * @return Class object - * @throws ClassNotFoundException if class cannot be loaded - */ - protected final Class loadClassTrusted(final String name, final boolean resolve) throws ClassNotFoundException { - return super.loadClass(name, resolve); } protected static void checkPackageAccess(final String name) { @@ -122,10 +100,6 @@ return permCollection; } - static boolean isStructureClass(final String fullName) { - return fullName.startsWith(SCRIPTS_PKG); - } - /** * Create a secure URL class loader for the given classpath * @param classPath classpath for the loader to search from diff -r 917b16e509bd -r 8b0914b25430 src/jdk/nashorn/internal/runtime/ScriptLoader.java --- a/src/jdk/nashorn/internal/runtime/ScriptLoader.java Thu Sep 12 22:16:40 2013 +0530 +++ b/src/jdk/nashorn/internal/runtime/ScriptLoader.java Fri Sep 13 16:45:11 2013 +0530 @@ -33,17 +33,42 @@ * */ final class ScriptLoader extends NashornLoader { + private static final String NASHORN_PKG_PREFIX = "jdk.nashorn.internal."; + + private final Context context; + + /*package-private*/ Context getContext() { + return context; + } + /** * Constructor. */ - ScriptLoader(final StructureLoader parent, final Context context) { - super(parent, context); + ScriptLoader(final ClassLoader parent, final Context context) { + super(parent); + this.context = context; } @Override protected Class loadClass(String name, boolean resolve) throws ClassNotFoundException { checkPackageAccess(name); - return super.loadClassTrusted(name, resolve); + try { + return super.loadClass(name, resolve); + } catch (final ClassNotFoundException | SecurityException e) { + // We'll get ClassNotFoundException for Nashorn 'struct' classes. + // Also, we'll get SecurityException for jdk.nashorn.internal.* + // classes. So, load these using to context's 'shared' loader. + // All these classes start with "jdk.nashorn.internal." prefix. + try { + if (name.startsWith(NASHORN_PKG_PREFIX)) { + return context.getSharedLoader().loadClass(name); + } + } catch (final ClassNotFoundException ignored) { + } + + // throw the original exception from here + throw e; + } } // package-private and private stuff below this point diff -r 917b16e509bd -r 8b0914b25430 src/jdk/nashorn/internal/runtime/StructureLoader.java --- a/src/jdk/nashorn/internal/runtime/StructureLoader.java Thu Sep 12 22:16:40 2013 +0530 +++ b/src/jdk/nashorn/internal/runtime/StructureLoader.java Fri Sep 13 16:45:11 2013 +0530 @@ -34,7 +34,6 @@ /** * Responsible for on the fly construction of structure classes. - * */ final class StructureLoader extends NashornLoader { private static final String JS_OBJECT_PREFIX_EXTERNAL = binaryName(SCRIPTS_PACKAGE) + '.' + JS_OBJECT_PREFIX.symbolName(); @@ -42,27 +41,17 @@ /** * Constructor. */ - StructureLoader(final ClassLoader parent, final Context context) { - super(parent, context); + StructureLoader(final ClassLoader parent) { + super(parent); } - @Override - protected synchronized Class loadClass(final String name, final boolean resolve) throws ClassNotFoundException { - // check the cache first - final Class loadedClass = findLoadedClass(name); - if (loadedClass != null) { - if (resolve) { - resolveClass(loadedClass); - } - return loadedClass; - } - - return super.loadClassTrusted(name, resolve); + static boolean isStructureClass(final String name) { + return name.startsWith(JS_OBJECT_PREFIX_EXTERNAL); } @Override protected Class findClass(final String name) throws ClassNotFoundException { - if (name.startsWith(JS_OBJECT_PREFIX_EXTERNAL)) { + if (isStructureClass(name)) { return generateClass(name, name.substring(JS_OBJECT_PREFIX_EXTERNAL.length())); } return super.findClass(name); @@ -75,11 +64,7 @@ * @return Generated class. */ private Class generateClass(final String name, final String descriptor) { - Context context = getContext(); - - if (context == null) { - context = Context.getContextTrusted(); - } + final Context context = Context.getContextTrusted(); final byte[] code = new ObjectClassGenerator(context).generate(descriptor); return defineClass(name, code, 0, code.length, new ProtectionDomain(null, getPermissions(null))); diff -r 917b16e509bd -r 8b0914b25430 test/script/basic/JDK-8024619.js --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/test/script/basic/JDK-8024619.js Fri Sep 13 16:45:11 2013 +0530 @@ -0,0 +1,46 @@ +/* + * Copyright (c) 2010, 2013, 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. + */ + +/** + * JDK-8024619: JDBC java.sql.DriverManager is not usable from JS script + * + * @test + * @run + */ + +var DriverManager = Java.type("java.sql.DriverManager"); +var e = DriverManager.getDrivers(); + +var driverFound = false; +// check for Nashorn SQL driver +while (e.hasMoreElements()) { + var driver = e.nextElement(); + if (driver.acceptsURL("jdbc:nashorn:")) { + driverFound = true; + break; + } +} + +if (! driverFound) { + fail("Nashorn JDBC Driver not found!"); +} diff -r 917b16e509bd -r 8b0914b25430 test/src/META-INF/services/java.sql.Driver --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/test/src/META-INF/services/java.sql.Driver Fri Sep 13 16:45:11 2013 +0530 @@ -0,0 +1,1 @@ +jdk.nashorn.api.NashornSQLDriver diff -r 917b16e509bd -r 8b0914b25430 test/src/jdk/nashorn/api/NashornSQLDriver.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/test/src/jdk/nashorn/api/NashornSQLDriver.java Fri Sep 13 16:45:11 2013 +0530 @@ -0,0 +1,79 @@ +/* + * Copyright (c) 2010, 2013, 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. Oracle designates this + * particular file as subject to the "Classpath" exception as provided + * by Oracle in the LICENSE file that accompanied this code. + * + * 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. + */ + +package jdk.nashorn.api; + +import java.sql.*; +import java.util.Properties; +import java.util.logging.Logger; + +/** + * A dummy SQL driver for testing purpose. + */ +public final class NashornSQLDriver implements Driver { + static { + try { + DriverManager.registerDriver(new NashornSQLDriver(), null); + } catch (SQLException se) { + throw new RuntimeException(se); + } + } + + @Override + public boolean acceptsURL(String url) { + return url.startsWith("jdbc:nashorn:"); + } + + @Override + public Connection connect(String url, Properties info) { + throw new UnsupportedOperationException("I am a dummy!!"); + } + + @Override + public int getMajorVersion() { + return -1; + } + + @Override + public int getMinorVersion() { + return -1; + } + + @Override + public DriverPropertyInfo[] getPropertyInfo(String url, Properties info) { + return new DriverPropertyInfo[0]; + } + + @Override + public boolean jdbcCompliant() { + // no way! + return false; + } + + @Override + public Logger getParentLogger() throws SQLFeatureNotSupportedException { + throw new SQLFeatureNotSupportedException(); + } +}