Example #1
0
  @Override
  public synchronized Object call(Context cx, Scriptable scope, Scriptable thisObj, Object[] args) {
    Transaction previousTransaction = Transaction.currentTransaction();
    Transaction.startTransaction();
    String filename = (String) args[0];
    if (filename.startsWith(".")) filename = currentJslibPath + filename;
    filename = Pattern.compile("\\.\\./[^.]*/").matcher(filename).replaceAll("/");
    filename = filename.replace("./", "");
    InputStream inStream;
    ScriptableObject exportObject;
    String oldJsLibPath = currentJslibPath;
    try {
      File jslibFile = jslibFiles.get(filename);
      if (jslibFile == null && !filename.endsWith(".js")) {
        filename += ".js";
        jslibFile = jslibFiles.get(filename);
      }
      if (jslibFile == null)
        throw ScriptRuntime.constructError("Error", "File not found " + filename);
      exportObject = exports.get(filename);
      Long lastTimeStamp = lastTimeStamps.get(filename);
      if (lastTimeStamp == null || lastTimeStamp < jslibFile.lastModified()) {
        lastTimeStamps.put(filename, jslibFile.lastModified());
        inStream = new FileInputStream(jslibFile);
        exportObject = new NativeObject();
        ScriptRuntime.setObjectProtoAndParent((ScriptableObject) exportObject, global);
        // setup the module scope
        ScriptableObject moduleScope = new NativeObject();
        moduleScope.setParentScope(global);
        int lastSlash = filename.lastIndexOf('/');
        currentJslibPath = lastSlash == -1 ? "" : filename.substring(0, lastSlash + 1);
        moduleScope.put("exports", moduleScope, exportObject);
        // memoize
        exports.put(filename, exportObject);
        // evaluate the script
        try {
          cx.evaluateString(moduleScope, IOUtils.toString(inStream, "UTF-8"), filename, 1, null);
        } catch (RuntimeException e) {
          // revert
          exports.remove(filename);
          jslibFiles.put(filename, jslibFile);
          throw e;
        }
        // re-retrieve it in case the library changed it
        exportObject = (ScriptableObject) moduleScope.get("exports", moduleScope);
        exports.put(filename, exportObject);

        if ("jsgi-app.js".equals(filename)) {
          // handle jackconfig.js, setting up the app if it is there
          global.put("app", global, exportObject.get("app", exportObject));
        }
        // freeze it
        // exportObject.sealObject();
      }
      Transaction.currentTransaction().commit();
    } catch (IOException e) {
      throw ScriptRuntime.constructError("Error", e.getMessage());
    } finally {
      currentJslibPath = oldJsLibPath;
      previousTransaction.enterTransaction();
    }
    return exportObject;
  }