/** * Invoke a script from the command line. * * @param scriptResource the script resource of path * @param scriptArgs an array of command line arguments * @return the return value * @throws IOException an I/O related error occurred * @throws JavaScriptException the script threw an error during compilation or execution */ public Object runScript(Object scriptResource, String... scriptArgs) throws IOException, JavaScriptException { Resource resource; if (scriptResource instanceof Resource) { resource = (Resource) scriptResource; } else if (scriptResource instanceof String) { resource = findResource((String) scriptResource, null, null); } else { throw new IOException("Unsupported script resource: " + scriptResource); } if (!resource.exists()) { throw new FileNotFoundException(scriptResource.toString()); } Context cx = contextFactory.enterContext(); try { Object retval; Map<Trackable, ReloadableScript> scripts = getScriptCache(cx); commandLineArgs = Arrays.asList(scriptArgs); ReloadableScript script = new ReloadableScript(resource, this); scripts.put(resource, script); mainScope = new ModuleScope(resource.getModuleName(), resource, globalScope, mainWorker); retval = mainWorker.evaluateScript(cx, script, mainScope); mainScope.updateExports(); return retval instanceof Wrapper ? ((Wrapper) retval).unwrap() : retval; } finally { Context.exit(); } }
private void evaluateBootstrapScripts(Context cx) throws IOException { List<String> bootstrapScripts = config.getBootstrapScripts(); if (bootstrapScripts != null) { for (String script : bootstrapScripts) { Resource resource = new FileResource(script); // not found, attempt to resolve the file relative to ringo home if (!resource.exists()) { resource = getRingoHome().getResource(script); } if (resource == null || !resource.exists()) { throw new FileNotFoundException("Bootstrap script " + script + " not found"); } mainWorker.evaluateScript(cx, new ReloadableScript(resource, this), globalScope); } } }
/** * Evaluate an expression from the command line. * * @param expr the JavaScript expression to evaluate * @return the return value * @throws IOException an I/O related error occurred * @throws JavaScriptException the script threw an error during compilation or execution */ public Object evaluateExpression(String expr) throws IOException, JavaScriptException { Context cx = contextFactory.enterContext(); cx.setOptimizationLevel(-1); try { Object retval; Repository repository = repositories.get(0); Scriptable parentScope = mainScope != null ? mainScope : globalScope; ModuleScope scope = new ModuleScope("<expr>", repository, parentScope, mainWorker); Resource res = new StringResource("<expr>", expr, 1); ReloadableScript script = new ReloadableScript(res, this); retval = mainWorker.evaluateScript(cx, script, scope); return retval instanceof Wrapper ? ((Wrapper) retval).unwrap() : retval; } finally { Context.exit(); } }
/** * Create a RhinoEngine with the given configuration. If <code>globals</code> is not null, its * contents are added as properties on the global object. * * @param config the configuration used to initialize the engine. * @param globals an optional map of global properties * @throws Exception if the engine can't be created */ public RhinoEngine(RingoConfig config, Map<String, Object> globals) throws Exception { this.config = config; workers = new LinkedBlockingDeque<RingoWorker>(); currentWorker = new ThreadLocal<RingoWorker>(); mainWorker = new RingoWorker(this); compiledScripts = new ConcurrentHashMap<Trackable, ReloadableScript>(); interpretedScripts = new ConcurrentHashMap<Trackable, ReloadableScript>(); singletons = new HashMap<Singleton, Singleton>(); contextFactory = new RingoContextFactory(this, config); repositories = config.getRepositories(); wrapFactory = config.getWrapFactory(); loaders = new ModuleLoader[] {new JsModuleLoader(), new JsonModuleLoader(), new ClassModuleLoader()}; RingoDebugger debugger = null; if (config.getDebug()) { debugger = new RingoDebugger(config); debugger.setScopeProvider(this); debugger.attachTo(contextFactory); debugger.setBreakOnExceptions(true); } // create and initialize global scope Context cx = contextFactory.enterContext(); try { boolean sealed = config.isSealed(); globalScope = new RingoGlobal(cx, this, sealed); Class<Scriptable>[] classes = config.getHostClasses(); if (classes != null) { for (Class<Scriptable> clazz : classes) { defineHostClass(clazz); } } ScriptableList.init(globalScope); ScriptableMap.init(globalScope); ScriptableObject.defineClass(globalScope, ScriptableWrapper.class); ScriptableObject.defineClass(globalScope, ModuleObject.class); if (globals != null) { for (Map.Entry<String, Object> entry : globals.entrySet()) { ScriptableObject.defineProperty( globalScope, entry.getKey(), entry.getValue(), ScriptableObject.DONTENUM); } } mainWorker.evaluateScript(cx, getScript("globals"), globalScope); evaluateBootstrapScripts(cx); if (sealed) { globalScope.sealObject(); } if (debugger != null) { debugger.setBreak(); } try { Runtime.getRuntime() .addShutdownHook( new Thread() { public void run() { shutdown(); } }); } catch (java.security.AccessControlException e) { log.log(Level.WARNING, "Could not register shutdown hook due to security exception", e); } } finally { Context.exit(); } }
/** * Load a Javascript module into a module scope. This checks if the module has already been loaded * in the current context and if so returns the existing module scope. * * @param cx the current context * @param moduleName the module name * @param loadingScope the scope requesting the module * @return the loaded module's scope * @throws IOException indicates that in input/output related error occurred */ public Scriptable loadModule(Context cx, String moduleName, Scriptable loadingScope) throws IOException { return mainWorker.loadModule(cx, moduleName, loadingScope); }
/** * Get the list of errors encountered by the main worker. * * @return a list of errors, may be null. */ public List<ScriptError> getMainErrors() { return mainWorker.getErrors(); }
/** * Return a worker, returning it to the worker pool. * * @param worker the worker to be released */ void returnWorker(RingoWorker worker) { if (!workers.offerFirst(worker)) { worker.shutdown(); } }
/** * Invoke a javascript function. This enters a JavaScript context, creates a new per-thread scope, * calls the function, exits the context and returns the return value of the invocation. * * @param module the module name or object, or null for the main module * @param method the method name to call in the script * @param args the arguments to pass to the method * @return the return value of the invocation * @throws NoSuchMethodException the method is not defined * @throws IOException an I/O related error occurred */ public Object invoke(Object module, String method, Object... args) throws IOException, NoSuchMethodException, ExecutionException, InterruptedException { return mainWorker.invoke(module, method, args); }