NashornLoader.java revision 1643:133ea8746b37
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 26package jdk.nashorn.internal.runtime; 27 28import java.io.File; 29import java.io.IOException; 30import java.net.MalformedURLException; 31import java.net.URL; 32import java.net.URLClassLoader; 33import java.lang.reflect.Module; 34import java.security.CodeSource; 35import java.security.Permission; 36import java.security.PermissionCollection; 37import java.security.Permissions; 38import java.security.SecureClassLoader; 39import java.util.HashSet; 40import java.util.Set; 41import jdk.internal.module.Modules; 42 43/** 44 * Superclass for Nashorn class loader classes. 45 */ 46abstract class NashornLoader extends SecureClassLoader { 47 protected static final String OBJECTS_PKG = "jdk.nashorn.internal.objects"; 48 protected static final String RUNTIME_PKG = "jdk.nashorn.internal.runtime"; 49 protected static final String RUNTIME_ARRAYS_PKG = "jdk.nashorn.internal.runtime.arrays"; 50 protected static final String RUNTIME_LINKER_PKG = "jdk.nashorn.internal.runtime.linker"; 51 protected static final String SCRIPTS_PKG = "jdk.nashorn.internal.scripts"; 52 protected static final String OBJECTS_PKG_INTERNAL = "jdk/nashorn/internal/objects"; 53 protected static final String RUNTIME_PKG_INTERNAL = "jdk/nashorn/internal/runtime"; 54 protected static final String RUNTIME_ARRAYS_PKG_INTERNAL = "jdk/nashorn/internal/runtime/arrays"; 55 protected static final String RUNTIME_LINKER_PKG_INTERNAL = "jdk/nashorn/internal/runtime/linker"; 56 protected static final String SCRIPTS_PKG_INTERNAL = "jdk/nashorn/internal/scripts"; 57 58 protected static final Module nashornModule = NashornLoader.class.getModule(); 59 60 private static final Permission[] SCRIPT_PERMISSIONS; 61 62 private static final Set<String> scriptsPkgSet = new HashSet<>(); 63 64 static { 65 scriptsPkgSet.add(SCRIPTS_PKG); 66 67 /* 68 * Generated classes get access to runtime, runtime.linker, objects, scripts packages. 69 * Note that the actual scripts can not access these because Java.type, Packages 70 * prevent these restricted packages. And Java reflection and JSR292 access is prevented 71 * for scripts. In other words, nashorn generated portions of script classes can access 72 * classes in these implementation packages. 73 */ 74 SCRIPT_PERMISSIONS = new Permission[] { 75 new RuntimePermission("accessClassInPackage." + RUNTIME_PKG), 76 new RuntimePermission("accessClassInPackage." + RUNTIME_LINKER_PKG), 77 new RuntimePermission("accessClassInPackage." + OBJECTS_PKG), 78 new RuntimePermission("accessClassInPackage." + SCRIPTS_PKG), 79 new RuntimePermission("accessClassInPackage." + RUNTIME_ARRAYS_PKG) 80 }; 81 } 82 83 NashornLoader(final ClassLoader parent) { 84 super(parent); 85 } 86 87 protected static Module defineModule(final String moduleName, final ClassLoader loader) { 88 return Modules.defineModule(loader, moduleName, scriptsPkgSet); 89 } 90 91 protected static void addReadsModule(final Module from, final Module to) { 92 Modules.addReads(from, to); 93 } 94 95 protected static void addModuleExports(final Module from, final String pkg, final Module to) { 96 if (to == null) { 97 Modules.addExportsToAll(from, pkg); 98 } else { 99 Modules.addExports(from, pkg, to); 100 } 101 } 102 103 protected static void checkPackageAccess(final String name) { 104 final int i = name.lastIndexOf('.'); 105 if (i != -1) { 106 final SecurityManager sm = System.getSecurityManager(); 107 if (sm != null) { 108 final String pkgName = name.substring(0, i); 109 switch (pkgName) { 110 case RUNTIME_PKG: 111 case RUNTIME_ARRAYS_PKG: 112 case RUNTIME_LINKER_PKG: 113 case OBJECTS_PKG: 114 case SCRIPTS_PKG: 115 // allow it. 116 break; 117 default: 118 sm.checkPackageAccess(pkgName); 119 } 120 } 121 } 122 } 123 124 @Override 125 protected PermissionCollection getPermissions(final CodeSource codesource) { 126 final Permissions permCollection = new Permissions(); 127 for (final Permission perm : SCRIPT_PERMISSIONS) { 128 permCollection.add(perm); 129 } 130 return permCollection; 131 } 132 133 /** 134 * Create a secure URL class loader for the given classpath 135 * @param classPath classpath for the loader to search from 136 * @param parent the parent class loader for the new class loader 137 * @return the class loader 138 */ 139 static ClassLoader createClassLoader(final String classPath, final ClassLoader parent) { 140 final URL[] urls = pathToURLs(classPath); 141 return URLClassLoader.newInstance(urls, parent); 142 } 143 144 /* 145 * Utility method for converting a search path string to an array 146 * of directory and JAR file URLs. 147 * 148 * @param path the search path string 149 * @return the resulting array of directory and JAR file URLs 150 */ 151 private static URL[] pathToURLs(final String path) { 152 final String[] components = path.split(File.pathSeparator); 153 URL[] urls = new URL[components.length]; 154 int count = 0; 155 while(count < components.length) { 156 final URL url = fileToURL(new File(components[count])); 157 if (url != null) { 158 urls[count++] = url; 159 } 160 } 161 if (urls.length != count) { 162 final URL[] tmp = new URL[count]; 163 System.arraycopy(urls, 0, tmp, 0, count); 164 urls = tmp; 165 } 166 return urls; 167 } 168 169 /* 170 * Returns the directory or JAR file URL corresponding to the specified 171 * local file name. 172 * 173 * @param file the File object 174 * @return the resulting directory or JAR file URL, or null if unknown 175 */ 176 private static URL fileToURL(final File file) { 177 String name; 178 try { 179 name = file.getCanonicalPath(); 180 } catch (final IOException e) { 181 name = file.getAbsolutePath(); 182 } 183 name = name.replace(File.separatorChar, '/'); 184 if (!name.startsWith("/")) { 185 name = "/" + name; 186 } 187 // If the file does not exist, then assume that it's a directory 188 if (!file.isFile()) { 189 name += "/"; 190 } 191 try { 192 return new URL("file", "", name); 193 } catch (final MalformedURLException e) { 194 throw new IllegalArgumentException("file"); 195 } 196 } 197} 198 199