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 static jdk.nashorn.internal.codegen.CompilerConstants.RUN_SCRIPT;
29 import static jdk.nashorn.internal.codegen.CompilerConstants.STRICT_MODE;
30 import static jdk.nashorn.internal.lookup.Lookup.MH;
31 import static jdk.nashorn.internal.runtime.ECMAErrors.typeError;
32 import static jdk.nashorn.internal.runtime.ScriptRuntime.UNDEFINED;
33
34 import java.io.File;
35 import java.io.IOException;
36 import java.io.PrintWriter;
37 import java.lang.invoke.MethodHandle;
38 import java.lang.invoke.MethodHandles;
39 import java.lang.reflect.Modifier;
40 import java.net.MalformedURLException;
41 import java.net.URL;
42 import java.security.AccessControlContext;
43 import java.security.AccessController;
44 import java.security.CodeSigner;
45 import java.security.CodeSource;
46 import java.security.Permissions;
47 import java.security.PrivilegedAction;
48 import java.security.ProtectionDomain;
49 import java.util.Map;
50 import java.util.concurrent.atomic.AtomicLong;
51 import jdk.internal.org.objectweb.asm.ClassReader;
52 import jdk.internal.org.objectweb.asm.util.CheckClassAdapter;
53 import jdk.nashorn.api.scripting.ScriptObjectMirror;
54 import jdk.nashorn.internal.codegen.Compiler;
55 import jdk.nashorn.internal.codegen.ObjectClassGenerator;
56 import jdk.nashorn.internal.ir.FunctionNode;
57 import jdk.nashorn.internal.ir.debug.ASTWriter;
58 import jdk.nashorn.internal.ir.debug.PrintVisitor;
59 import jdk.nashorn.internal.objects.Global;
60 import jdk.nashorn.internal.parser.Parser;
61 import jdk.nashorn.internal.runtime.options.Options;
62
63 /**
64 * This class manages the global state of execution. Context is immutable.
65 */
66 public final class Context {
67 // nashorn specific security runtime access permission names
68 /**
138 public void verify(final byte[] code) {
139 context.verify(code);
140 }
141
142 @Override
143 public long getUniqueScriptId() {
144 return context.getUniqueScriptId();
145 }
146
147 @Override
148 public long getUniqueEvalId() {
149 return context.getUniqueEvalId();
150 }
151 }
152
153 /** Is Context global debug mode enabled ? */
154 public static final boolean DEBUG = Options.getBooleanProperty("nashorn.debug");
155
156 private static final ThreadLocal<ScriptObject> currentGlobal = new ThreadLocal<>();
157
158 /**
159 * Get the current global scope
160 * @return the current global scope
161 */
162 public static ScriptObject getGlobal() {
163 // This class in a package.access protected package.
164 // Trusted code only can call this method.
165 return getGlobalTrusted();
166 }
167
168 /**
169 * Set the current global scope
170 * @param global the global scope
171 */
172 public static void setGlobal(final ScriptObject global) {
173 if (global != null && !(global instanceof Global)) {
174 throw new IllegalArgumentException("global is not an instance of Global!");
175 }
176
177 setGlobalTrusted(global);
331 } else {
332 this.scriptLoader = createNewLoader();
333 this.uniqueScriptId = new AtomicLong();
334 }
335 this.errors = errors;
336 this.uniqueEvalId = new AtomicLong();
337
338 // if user passed -classpath option, make a class loader with that and set it as
339 // thread context class loader so that script can access classes from that path.
340 final String classPath = options.getString("classpath");
341 if (! env._compile_only && classPath != null && !classPath.isEmpty()) {
342 // make sure that caller can create a class loader.
343 if (sm != null) {
344 sm.checkPermission(new RuntimePermission("createClassLoader"));
345 }
346 this.classPathLoader = NashornLoader.createClassLoader(classPath);
347 } else {
348 this.classPathLoader = null;
349 }
350
351 // print version info if asked.
352 if (env._version) {
353 getErr().println("nashorn " + Version.version());
354 }
355
356 if (env._fullversion) {
357 getErr().println("nashorn full version " + Version.fullVersion());
358 }
359 }
360
361 /**
362 * Get the error manager for this context
363 * @return error manger
364 */
365 public ErrorManager getErrorManager() {
366 return errors;
367 }
368
369 /**
370 * Get the script environment for this context
642 public static void checkPackageAccess(final Class<?> clazz) {
643 final SecurityManager sm = System.getSecurityManager();
644 if (sm != null) {
645 Class<?> bottomClazz = clazz;
646 while (bottomClazz.isArray()) {
647 bottomClazz = bottomClazz.getComponentType();
648 }
649 checkPackageAccess(sm, bottomClazz.getName());
650 }
651 }
652
653 /**
654 * Checks that the given package name can be accessed from no permissions context.
655 *
656 * @param pkgName package name
657 * @throw SecurityException if not accessible
658 */
659 public static void checkPackageAccess(final String pkgName) {
660 final SecurityManager sm = System.getSecurityManager();
661 if (sm != null) {
662 checkPackageAccess(sm, pkgName.endsWith(".")? pkgName : pkgName + ".");
663 }
664 }
665
666 /**
667 * Checks that the given package can be accessed from no permissions context.
668 *
669 * @param sm current security manager instance
670 * @param fullName fully qualified package name
671 * @throw SecurityException if not accessible
672 */
673 private static void checkPackageAccess(final SecurityManager sm, final String fullName) {
674 sm.getClass(); // null check
675 final int index = fullName.lastIndexOf('.');
676 if (index != -1) {
677 final String pkgName = fullName.substring(0, index);
678 AccessController.doPrivileged(new PrivilegedAction<Void>() {
679 @Override
680 public Void run() {
681 sm.checkPackageAccess(pkgName);
682 return null;
908 boolean strict;
909
910 try {
911 strict = script.getField(STRICT_MODE.symbolName()).getBoolean(null);
912 } catch (final NoSuchFieldException | SecurityException | IllegalArgumentException | IllegalAccessException e) {
913 strict = false;
914 }
915
916 // Package as a JavaScript function and pass function back to shell.
917 return ((GlobalObject)Context.getGlobalTrusted()).newScriptFunction(RUN_SCRIPT.symbolName(), runMethodHandle, scope, strict);
918 }
919
920 private ScriptFunction compileScript(final Source source, final ScriptObject scope, final ErrorManager errMan) {
921 return getRunScriptFunction(compile(source, errMan, this._strict), scope);
922 }
923
924 private synchronized Class<?> compile(final Source source, final ErrorManager errMan, final boolean strict) {
925 // start with no errors, no warnings.
926 errMan.reset();
927
928 GlobalObject global = null;
929 Class<?> script;
930
931 if (env._class_cache_size > 0) {
932 global = (GlobalObject)Context.getGlobalTrusted();
933 script = global.findCachedClass(source);
934 if (script != null) {
935 Compiler.LOG.fine("Code cache hit for ", source, " avoiding recompile.");
936 return script;
937 }
938 }
939
940 final FunctionNode functionNode = new Parser(env, source, errMan, strict).parse();
941 if (errors.hasErrors()) {
942 return null;
943 }
944
945 if (env._print_ast) {
946 getErr().println(new ASTWriter(functionNode));
947 }
948
949 if (env._print_parse) {
950 getErr().println(new PrintVisitor(functionNode));
951 }
952
953 if (env._parse_only) {
954 return null;
955 }
956
957 final URL url = source.getURL();
958 final ScriptLoader loader = env._loader_per_compile ? createNewLoader() : scriptLoader;
959 final CodeSource cs = new CodeSource(url, (CodeSigner[])null);
960 final CodeInstaller<ScriptEnvironment> installer = new ContextCodeInstaller(this, loader, cs);
961
962 final Compiler compiler = new Compiler(installer, strict);
963
964 final FunctionNode newFunctionNode = compiler.compile(functionNode);
965 script = compiler.install(newFunctionNode);
966
967 if (global != null) {
968 global.cacheClass(source, script);
969 }
970
971 return script;
972 }
973
974 private ScriptLoader createNewLoader() {
975 return AccessController.doPrivileged(
976 new PrivilegedAction<ScriptLoader>() {
977 @Override
978 public ScriptLoader run() {
979 return new ScriptLoader(appLoader, Context.this);
980 }
981 }, CREATE_LOADER_ACC_CTXT);
982 }
983
984 private long getUniqueEvalId() {
985 return uniqueEvalId.getAndIncrement();
986 }
987
988 private long getUniqueScriptId() {
989 return uniqueScriptId.getAndIncrement();
990 }
991 }
|
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 static jdk.nashorn.internal.codegen.CompilerConstants.RUN_SCRIPT;
29 import static jdk.nashorn.internal.codegen.CompilerConstants.STRICT_MODE;
30 import static jdk.nashorn.internal.lookup.Lookup.MH;
31 import static jdk.nashorn.internal.runtime.ECMAErrors.typeError;
32 import static jdk.nashorn.internal.runtime.ScriptRuntime.UNDEFINED;
33
34 import java.io.File;
35 import java.io.IOException;
36 import java.io.PrintWriter;
37 import java.lang.invoke.MethodHandle;
38 import java.lang.invoke.MethodHandles;
39 import java.lang.ref.ReferenceQueue;
40 import java.lang.ref.SoftReference;
41 import java.lang.reflect.Modifier;
42 import java.net.MalformedURLException;
43 import java.net.URL;
44 import java.security.AccessControlContext;
45 import java.security.AccessController;
46 import java.security.CodeSigner;
47 import java.security.CodeSource;
48 import java.security.Permissions;
49 import java.security.PrivilegedAction;
50 import java.security.ProtectionDomain;
51 import java.util.LinkedHashMap;
52 import java.util.Map;
53 import java.util.concurrent.atomic.AtomicLong;
54 import jdk.internal.org.objectweb.asm.ClassReader;
55 import jdk.internal.org.objectweb.asm.util.CheckClassAdapter;
56 import jdk.nashorn.api.scripting.ScriptObjectMirror;
57 import jdk.nashorn.internal.codegen.Compiler;
58 import jdk.nashorn.internal.codegen.ObjectClassGenerator;
59 import jdk.nashorn.internal.ir.FunctionNode;
60 import jdk.nashorn.internal.ir.debug.ASTWriter;
61 import jdk.nashorn.internal.ir.debug.PrintVisitor;
62 import jdk.nashorn.internal.objects.Global;
63 import jdk.nashorn.internal.parser.Parser;
64 import jdk.nashorn.internal.runtime.options.Options;
65
66 /**
67 * This class manages the global state of execution. Context is immutable.
68 */
69 public final class Context {
70 // nashorn specific security runtime access permission names
71 /**
141 public void verify(final byte[] code) {
142 context.verify(code);
143 }
144
145 @Override
146 public long getUniqueScriptId() {
147 return context.getUniqueScriptId();
148 }
149
150 @Override
151 public long getUniqueEvalId() {
152 return context.getUniqueEvalId();
153 }
154 }
155
156 /** Is Context global debug mode enabled ? */
157 public static final boolean DEBUG = Options.getBooleanProperty("nashorn.debug");
158
159 private static final ThreadLocal<ScriptObject> currentGlobal = new ThreadLocal<>();
160
161 // class cache
162 private ClassCache classCache;
163
164 /**
165 * Get the current global scope
166 * @return the current global scope
167 */
168 public static ScriptObject getGlobal() {
169 // This class in a package.access protected package.
170 // Trusted code only can call this method.
171 return getGlobalTrusted();
172 }
173
174 /**
175 * Set the current global scope
176 * @param global the global scope
177 */
178 public static void setGlobal(final ScriptObject global) {
179 if (global != null && !(global instanceof Global)) {
180 throw new IllegalArgumentException("global is not an instance of Global!");
181 }
182
183 setGlobalTrusted(global);
337 } else {
338 this.scriptLoader = createNewLoader();
339 this.uniqueScriptId = new AtomicLong();
340 }
341 this.errors = errors;
342 this.uniqueEvalId = new AtomicLong();
343
344 // if user passed -classpath option, make a class loader with that and set it as
345 // thread context class loader so that script can access classes from that path.
346 final String classPath = options.getString("classpath");
347 if (! env._compile_only && classPath != null && !classPath.isEmpty()) {
348 // make sure that caller can create a class loader.
349 if (sm != null) {
350 sm.checkPermission(new RuntimePermission("createClassLoader"));
351 }
352 this.classPathLoader = NashornLoader.createClassLoader(classPath);
353 } else {
354 this.classPathLoader = null;
355 }
356
357 final int cacheSize = env._class_cache_size;
358 if (cacheSize > 0) {
359 classCache = new ClassCache(cacheSize);
360 }
361
362 // print version info if asked.
363 if (env._version) {
364 getErr().println("nashorn " + Version.version());
365 }
366
367 if (env._fullversion) {
368 getErr().println("nashorn full version " + Version.fullVersion());
369 }
370 }
371
372 /**
373 * Get the error manager for this context
374 * @return error manger
375 */
376 public ErrorManager getErrorManager() {
377 return errors;
378 }
379
380 /**
381 * Get the script environment for this context
653 public static void checkPackageAccess(final Class<?> clazz) {
654 final SecurityManager sm = System.getSecurityManager();
655 if (sm != null) {
656 Class<?> bottomClazz = clazz;
657 while (bottomClazz.isArray()) {
658 bottomClazz = bottomClazz.getComponentType();
659 }
660 checkPackageAccess(sm, bottomClazz.getName());
661 }
662 }
663
664 /**
665 * Checks that the given package name can be accessed from no permissions context.
666 *
667 * @param pkgName package name
668 * @throw SecurityException if not accessible
669 */
670 public static void checkPackageAccess(final String pkgName) {
671 final SecurityManager sm = System.getSecurityManager();
672 if (sm != null) {
673 checkPackageAccess(sm, pkgName.endsWith(".") ? pkgName : pkgName + ".");
674 }
675 }
676
677 /**
678 * Checks that the given package can be accessed from no permissions context.
679 *
680 * @param sm current security manager instance
681 * @param fullName fully qualified package name
682 * @throw SecurityException if not accessible
683 */
684 private static void checkPackageAccess(final SecurityManager sm, final String fullName) {
685 sm.getClass(); // null check
686 final int index = fullName.lastIndexOf('.');
687 if (index != -1) {
688 final String pkgName = fullName.substring(0, index);
689 AccessController.doPrivileged(new PrivilegedAction<Void>() {
690 @Override
691 public Void run() {
692 sm.checkPackageAccess(pkgName);
693 return null;
919 boolean strict;
920
921 try {
922 strict = script.getField(STRICT_MODE.symbolName()).getBoolean(null);
923 } catch (final NoSuchFieldException | SecurityException | IllegalArgumentException | IllegalAccessException e) {
924 strict = false;
925 }
926
927 // Package as a JavaScript function and pass function back to shell.
928 return ((GlobalObject)Context.getGlobalTrusted()).newScriptFunction(RUN_SCRIPT.symbolName(), runMethodHandle, scope, strict);
929 }
930
931 private ScriptFunction compileScript(final Source source, final ScriptObject scope, final ErrorManager errMan) {
932 return getRunScriptFunction(compile(source, errMan, this._strict), scope);
933 }
934
935 private synchronized Class<?> compile(final Source source, final ErrorManager errMan, final boolean strict) {
936 // start with no errors, no warnings.
937 errMan.reset();
938
939 Class<?> script = findCachedClass(source);
940 if (script != null) {
941 Compiler.LOG.fine("Code cache hit for ", source, " avoiding recompile.");
942 return script;
943 }
944
945 final FunctionNode functionNode = new Parser(env, source, errMan, strict).parse();
946 if (errors.hasErrors()) {
947 return null;
948 }
949
950 if (env._print_ast) {
951 getErr().println(new ASTWriter(functionNode));
952 }
953
954 if (env._print_parse) {
955 getErr().println(new PrintVisitor(functionNode));
956 }
957
958 if (env._parse_only) {
959 return null;
960 }
961
962 final URL url = source.getURL();
963 final ScriptLoader loader = env._loader_per_compile ? createNewLoader() : scriptLoader;
964 final CodeSource cs = new CodeSource(url, (CodeSigner[])null);
965 final CodeInstaller<ScriptEnvironment> installer = new ContextCodeInstaller(this, loader, cs);
966
967 final Compiler compiler = new Compiler(installer, strict);
968
969 final FunctionNode newFunctionNode = compiler.compile(functionNode);
970 script = compiler.install(newFunctionNode);
971 cacheClass(source, script);
972
973 return script;
974 }
975
976 private ScriptLoader createNewLoader() {
977 return AccessController.doPrivileged(
978 new PrivilegedAction<ScriptLoader>() {
979 @Override
980 public ScriptLoader run() {
981 return new ScriptLoader(appLoader, Context.this);
982 }
983 }, CREATE_LOADER_ACC_CTXT);
984 }
985
986 private long getUniqueEvalId() {
987 return uniqueEvalId.getAndIncrement();
988 }
989
990 private long getUniqueScriptId() {
991 return uniqueScriptId.getAndIncrement();
992 }
993
994 /**
995 * Cache for compiled script classes.
996 */
997 @SuppressWarnings("serial")
998 private static class ClassCache extends LinkedHashMap<Source, ClassReference> {
999 private final int size;
1000 private final ReferenceQueue<Class<?>> queue;
1001
1002 ClassCache(int size) {
1003 super(size, 0.75f, true);
1004 this.size = size;
1005 this.queue = new ReferenceQueue<>();
1006 }
1007
1008 void cache(final Source source, final Class<?> clazz) {
1009 put(source, new ClassReference(clazz, queue, source));
1010 }
1011
1012 @Override
1013 protected boolean removeEldestEntry(final Map.Entry<Source, ClassReference> eldest) {
1014 return size() > size;
1015 }
1016
1017 @Override
1018 public ClassReference get(Object key) {
1019 for (ClassReference ref; (ref = (ClassReference)queue.poll()) != null; ) {
1020 remove(ref.source);
1021 }
1022 return super.get(key);
1023 }
1024
1025 }
1026
1027 private static class ClassReference extends SoftReference<Class<?>> {
1028 private final Source source;
1029
1030 ClassReference(final Class<?> clazz, final ReferenceQueue<Class<?>> queue, final Source source) {
1031 super(clazz, queue);
1032 this.source = source;
1033 }
1034 }
1035
1036 // Class cache management
1037 private Class<?> findCachedClass(final Source source) {
1038 ClassReference ref = classCache == null ? null : classCache.get(source);
1039 return ref != null ? ref.get() : null;
1040 }
1041
1042 private void cacheClass(final Source source, final Class<?> clazz) {
1043 if (classCache != null) {
1044 classCache.cache(source, clazz);
1045 }
1046 }
1047
1048
1049 }
|