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.api.scripting; 27 28 import java.util.Arrays; 29 import java.util.Collections; 30 import java.util.List; 31 import java.util.Objects; 32 import javax.script.ScriptEngine; 33 import javax.script.ScriptEngineFactory; 34 import jdk.nashorn.internal.runtime.Context; 35 import jdk.nashorn.internal.runtime.Version; 36 37 /** 38 * JSR-223 compliant script engine factory for Nashorn. The engine answers for: 39 * <ul> 40 * <li>names {@code "nashorn"}, {@code "Nashorn"}, {@code "js"}, {@code "JS"}, {@code "JavaScript"}, 41 * {@code "javascript"}, {@code "ECMAScript"}, and {@code "ecmascript"};</li> 42 * <li>MIME types {@code "application/javascript"}, {@code "application/ecmascript"}, {@code "text/javascript"}, and 43 * {@code "text/ecmascript"};</li> 44 * <li>as well as for the extension {@code "js"}.</li> 45 * </ul> 46 * Programs executing in engines created using {@link #getScriptEngine(String[])} will have the passed arguments 47 * accessible as a global variable named {@code "arguments"}. 48 * 49 * @deprecated Nashorn JavaScript script engine and APIs, and the jjs tool 50 * are deprecated with the intent to remove them in a future release. 51 * 52 * @since 1.8u40 53 */ 54 @Deprecated(since="11", forRemoval=true) 55 public final class NashornScriptEngineFactory implements ScriptEngineFactory { 56 @Override 57 public String getEngineName() { 58 return (String) getParameter(ScriptEngine.ENGINE); 59 } 60 61 @Override 62 public String getEngineVersion() { 63 return (String) getParameter(ScriptEngine.ENGINE_VERSION); 64 } 65 66 @Override 67 public List<String> getExtensions() { 68 return Collections.unmodifiableList(extensions); 69 } 70 71 @Override 72 public String getLanguageName() { 73 return (String) getParameter(ScriptEngine.LANGUAGE); 74 } 75 76 @Override 77 public String getLanguageVersion() { 78 return (String) getParameter(ScriptEngine.LANGUAGE_VERSION); 79 } 80 81 @Override 82 public String getMethodCallSyntax(final String obj, final String method, final String... args) { 83 final StringBuilder sb = new StringBuilder(). 84 append(Objects.requireNonNull(obj)).append('.'). 85 append(Objects.requireNonNull(method)).append('('); 86 final int len = args.length; 87 88 if (len > 0) { 89 sb.append(Objects.requireNonNull(args[0])); 90 } 91 for (int i = 1; i < len; i++) { 92 sb.append(',').append(Objects.requireNonNull(args[i])); 93 } 94 sb.append(')'); 95 96 return sb.toString(); 97 } 98 99 @Override 100 public List<String> getMimeTypes() { 101 return Collections.unmodifiableList(mimeTypes); 102 } 103 104 @Override 105 public List<String> getNames() { 106 return Collections.unmodifiableList(names); 107 } 108 109 @Override 110 public String getOutputStatement(final String toDisplay) { 111 return "print(" + toDisplay + ")"; 112 } 113 114 @Override 115 public Object getParameter(final String key) { 116 switch (key) { 117 case ScriptEngine.NAME: 118 return "javascript"; 119 case ScriptEngine.ENGINE: 120 return "Oracle Nashorn"; 121 case ScriptEngine.ENGINE_VERSION: 122 return Version.version(); 123 case ScriptEngine.LANGUAGE: 124 return "ECMAScript"; 125 case ScriptEngine.LANGUAGE_VERSION: 126 return "ECMA - 262 Edition 5.1"; 127 case "THREADING": 128 // The engine implementation is not thread-safe. Can't be 129 // used to execute scripts concurrently on multiple threads. 130 return null; 131 default: 132 return null; 133 } 134 } 135 136 @Override 137 public String getProgram(final String... statements) { 138 Objects.requireNonNull(statements); 139 final StringBuilder sb = new StringBuilder(); 140 141 for (final String statement : statements) { 142 sb.append(Objects.requireNonNull(statement)).append(';'); 143 } 144 145 return sb.toString(); 146 } 147 148 // default options passed to Nashorn script engine 149 private static final String[] DEFAULT_OPTIONS = new String[] { "-doe" }; 150 151 @Override 152 public ScriptEngine getScriptEngine() { 153 try { 154 return new NashornScriptEngine(this, DEFAULT_OPTIONS, getAppClassLoader(), null); 155 } catch (final RuntimeException e) { 156 if (Context.DEBUG) { 157 e.printStackTrace(); 158 } 159 throw e; 160 } 161 } 162 163 /** 164 * Create a new Script engine initialized with the given class loader. 165 * 166 * @param appLoader class loader to be used as script "app" class loader. 167 * @return newly created script engine. 168 * @throws SecurityException 169 * if the security manager's {@code checkPermission} 170 * denies {@code RuntimePermission("nashorn.setConfig")} 171 */ 172 public ScriptEngine getScriptEngine(final ClassLoader appLoader) { 173 return newEngine(DEFAULT_OPTIONS, appLoader, null); 174 } 175 176 /** 177 * Create a new Script engine initialized with the given class filter. 178 * 179 * @param classFilter class filter to use. 180 * @return newly created script engine. 181 * @throws NullPointerException if {@code classFilter} is {@code null} 182 * @throws SecurityException 183 * if the security manager's {@code checkPermission} 184 * denies {@code RuntimePermission("nashorn.setConfig")} 185 */ 186 public ScriptEngine getScriptEngine(final ClassFilter classFilter) { 187 return newEngine(DEFAULT_OPTIONS, getAppClassLoader(), Objects.requireNonNull(classFilter)); 188 } 189 190 /** 191 * Create a new Script engine initialized with the given arguments. 192 * 193 * @param args arguments array passed to script engine. 194 * @return newly created script engine. 195 * @throws NullPointerException if {@code args} is {@code null} 196 * @throws SecurityException 197 * if the security manager's {@code checkPermission} 198 * denies {@code RuntimePermission("nashorn.setConfig")} 199 */ 200 public ScriptEngine getScriptEngine(final String... args) { 201 return newEngine(Objects.requireNonNull(args), getAppClassLoader(), null); 202 } 203 204 /** 205 * Create a new Script engine initialized with the given arguments and the given class loader. 206 * 207 * @param args arguments array passed to script engine. 208 * @param appLoader class loader to be used as script "app" class loader. 209 * @return newly created script engine. 210 * @throws NullPointerException if {@code args} is {@code null} 211 * @throws SecurityException 212 * if the security manager's {@code checkPermission} 213 * denies {@code RuntimePermission("nashorn.setConfig")} 214 */ 215 public ScriptEngine getScriptEngine(final String[] args, final ClassLoader appLoader) { 216 return newEngine(Objects.requireNonNull(args), appLoader, null); 217 } 218 219 /** 220 * Create a new Script engine initialized with the given arguments, class loader and class filter. 221 * 222 * @param args arguments array passed to script engine. 223 * @param appLoader class loader to be used as script "app" class loader. 224 * @param classFilter class filter to use. 225 * @return newly created script engine. 226 * @throws NullPointerException if {@code args} or {@code classFilter} is {@code null} 227 * @throws SecurityException 228 * if the security manager's {@code checkPermission} 229 * denies {@code RuntimePermission("nashorn.setConfig")} 230 */ 231 public ScriptEngine getScriptEngine(final String[] args, final ClassLoader appLoader, final ClassFilter classFilter) { 232 return newEngine(Objects.requireNonNull(args), appLoader, Objects.requireNonNull(classFilter)); 233 } 234 235 private ScriptEngine newEngine(final String[] args, final ClassLoader appLoader, final ClassFilter classFilter) { 236 checkConfigPermission(); 237 try { 238 return new NashornScriptEngine(this, args, appLoader, classFilter); 239 } catch (final RuntimeException e) { 240 if (Context.DEBUG) { 241 e.printStackTrace(); 242 } 243 throw e; 244 } 245 } 246 247 // -- Internals only below this point 248 249 private static void checkConfigPermission() { 250 final SecurityManager sm = System.getSecurityManager(); 251 if (sm != null) { 252 sm.checkPermission(new RuntimePermission(Context.NASHORN_SET_CONFIG)); 253 } 254 } 255 256 private static final List<String> names; 257 private static final List<String> mimeTypes; 258 private static final List<String> extensions; 259 260 static { 261 names = immutableList( 262 "nashorn", "Nashorn", 263 "js", "JS", 264 "JavaScript", "javascript", 265 "ECMAScript", "ecmascript" 266 ); 267 268 mimeTypes = immutableList( 269 "application/javascript", 270 "application/ecmascript", 271 "text/javascript", 272 "text/ecmascript" 273 ); 274 275 extensions = immutableList("js"); 276 } 277 278 private static List<String> immutableList(final String... elements) { 279 return Collections.unmodifiableList(Arrays.asList(elements)); 280 } 281 282 private static ClassLoader getAppClassLoader() { 283 // Revisit: script engine implementation needs the capability to 284 // find the class loader of the context in which the script engine 285 // is running so that classes will be found and loaded properly 286 final ClassLoader ccl = Thread.currentThread().getContextClassLoader(); 287 return (ccl == null)? NashornScriptEngineFactory.class.getClassLoader() : ccl; 288 } 289 }