1 /* 2 * Copyright (c) 2010, 2013, Oracle and/or its affiliates. All rights reserved. 3 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. 4 * 5 * This code is free software; you can redistribute it and/or modify it 6 * under the terms of the GNU General Public License version 2 only, as 7 * published by the Free Software Foundation. Oracle designates this 8 * particular file as subject to the "Classpath" exception as provided 9 * by Oracle in the LICENSE file that accompanied this code. 10 * 11 * This code is distributed in the hope that it will be useful, but WITHOUT 12 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or 13 * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License 14 * version 2 for more details (a copy is included in the LICENSE file that 15 * accompanied this code). 16 * 17 * You should have received a copy of the GNU General Public License version 18 * 2 along with this work; if not, write to the Free Software Foundation, 19 * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. 20 * 21 * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA 22 * or visit www.oracle.com if you need additional information or have any 23 * questions. 24 */ 25 26 package jdk.nashorn.internal.runtime; 27 28 import java.lang.module.ModuleDescriptor; 29 import java.lang.module.ModuleDescriptor.Modifier; 30 import java.security.CodeSource; 31 import java.util.Objects; 32 import java.util.Set; 33 34 /** 35 * Responsible for loading script generated classes. 36 * 37 */ 38 final class ScriptLoader extends NashornLoader { 39 private static final String NASHORN_PKG_PREFIX = "jdk.nashorn.internal."; 40 41 private volatile boolean structureAccessAdded; 42 private final Context context; 43 private final Module scriptModule; 44 45 /*package-private*/ Context getContext() { 46 return context; 47 } 48 49 /** 50 * Constructor. 51 */ 52 ScriptLoader(final Context context) { 53 super(context.getStructLoader()); 54 this.context = context; 55 56 // new scripts module, it's specific exports and read-edges 57 scriptModule = createModule("jdk.scripting.nashorn.scripts"); 58 59 // specific exports from nashorn to new scripts module 60 NASHORN_MODULE.addExports(OBJECTS_PKG, scriptModule); 61 NASHORN_MODULE.addExports(RUNTIME_PKG, scriptModule); 62 NASHORN_MODULE.addExports(RUNTIME_ARRAYS_PKG, scriptModule); 63 NASHORN_MODULE.addExports(RUNTIME_LINKER_PKG, scriptModule); 64 NASHORN_MODULE.addExports(SCRIPTS_PKG, scriptModule); 65 66 // nashorn needs to read scripts module methods,fields 67 NASHORN_MODULE.addReads(scriptModule); 68 } 69 70 private Module createModule(final String moduleName) { 71 final Module structMod = context.getStructLoader().getModule(); 72 final ModuleDescriptor.Builder builder = 73 ModuleDescriptor.newModule(moduleName, Set.of(Modifier.SYNTHETIC)) 74 .requires("java.logging") 75 .requires(NASHORN_MODULE.getName()) 76 .requires(structMod.getName()) 77 .packages(Set.of(SCRIPTS_PKG)); 78 79 if (Context.javaSqlFound) { 80 builder.requires("java.sql"); 81 } 82 83 if (Context.javaSqlRowsetFound) { 84 builder.requires("java.sql.rowset"); 85 } 86 87 final ModuleDescriptor descriptor = builder.build(); 88 89 final Module mod = Context.createModuleTrusted(structMod.getLayer(), descriptor, this); 90 loadModuleManipulator(); 91 return mod; 92 } 93 94 @Override 95 protected Class<?> loadClass(final String name, final boolean resolve) throws ClassNotFoundException { 96 checkPackageAccess(name); 97 final Class<?> cl = super.loadClass(name, resolve); 98 if (!structureAccessAdded) { 99 final StructureLoader structLoader = context.getStructLoader(); 100 if (cl.getClassLoader() == structLoader) { 101 structureAccessAdded = true; 102 structLoader.addModuleExport(scriptModule); 103 } 104 } 105 return cl; 106 } 107 108 @Override 109 protected Class<?> findClass(final String name) throws ClassNotFoundException { 110 final ClassLoader appLoader = context.getAppLoader(); 111 112 /* 113 * If the appLoader is null, don't bother side-delegating to it! 114 * Bootloader has been already attempted via parent loader 115 * delegation from the "loadClass" method. 116 * 117 * Also, make sure that we don't delegate to the app loader 118 * for nashorn's own classes or nashorn generated classes! 119 */ 120 if (appLoader == null || name.startsWith(NASHORN_PKG_PREFIX)) { 121 throw new ClassNotFoundException(name); 122 } 123 124 /* 125 * This split-delegation is used so that caller loader 126 * based resolutions of classes would work. For example, 127 * java.sql.DriverManager uses caller's class loader to 128 * get Driver instances. Without this split-delegation 129 * a script class evaluating DriverManager.getDrivers() 130 * will not get back any JDBC driver! 131 */ 132 return appLoader.loadClass(name); 133 } 134 135 // package-private and private stuff below this point 136 137 /** 138 * Install a class for use by the Nashorn runtime 139 * 140 * @param name Binary name of class. 141 * @param data Class data bytes. 142 * @param cs CodeSource code source of the class bytes. 143 * 144 * @return Installed class. 145 */ 146 synchronized Class<?> installClass(final String name, final byte[] data, final CodeSource cs) { 147 return defineClass(name, data, 0, data.length, Objects.requireNonNull(cs)); 148 } 149 }