Package org.persvr.util

Source Code of org.persvr.util.Console

package org.persvr.util;

import java.io.PrintWriter;
import java.io.StringWriter;
import java.security.PrivilegedAction;
import java.util.List;

import jline.ConsoleReader;

import org.apache.commons.logging.LogFactory;
import org.mozilla.javascript.Context;
import org.mozilla.javascript.Function;
import org.mozilla.javascript.NativeObject;
import org.mozilla.javascript.RhinoException;
import org.mozilla.javascript.ScriptRuntime;
import org.mozilla.javascript.Scriptable;
import org.mozilla.javascript.ScriptableObject;
import org.mozilla.javascript.Undefined;
import org.persvr.data.DataSourceManager;
import org.persvr.data.GlobalData;
import org.persvr.data.PersistableObject;
import org.persvr.data.Transaction;
import org.persvr.javascript.PersevereContextFactory;
import org.persvr.javascript.PersevereNativeFunction;
import org.persvr.remote.Client;
import org.persvr.security.UserSecurity;

/**
* Provides a console for interaction with the JavaScript environment on the server
* @author Kris
*
*/
public class Console extends Thread {
  public Console() {
    super("Persevere Console");
  }
  Context context;
  Scriptable global;
  Scriptable consoleScope;
  public static void main(String[] args){
    DataSourceManager.getDataSources(); // fire up the sources/DBs
    new Console().run();
  }
 
  @Override
  public void run() {
    try {
      // wait a little while so that the prompt can come after Jetty's messages about being started
      Thread.sleep(300);
    } catch (InterruptedException e) {
      e.printStackTrace();
    }
    UserSecurity.doPriviledgedAction(new PrivilegedAction(){
      Object output;
      public Object run() {
          Client connection = new Client("console");
          // give this thread a context/user
          Client.registerThisConnection(connection.getIndividualRequest(null, null));
          context = PersevereContextFactory.getContext();
          global = GlobalData.getGlobalScope();
          consoleScope = new NativeObject();
          // we may want to make this a prototype, so you can create unscoped variables without errors. Downside is it might mislead users as to what they can do in methods
          consoleScope.setParentScope(global);
          ((NativeObject) consoleScope).setGetterOrSetter("help", 0, new PersevereNativeFunction(){

            @Override
            public Object call(Context cx, Scriptable scope, Scriptable thisObj, Object[] args) {
              String help = "The full Persevere API is available at the console as described in http://docs.persvr.org/documentation/server-side-js\n";
              help += "Additionally there are the following special properties available at the console:\n";
              help += "autocommit - This indicate whether or not each command should be committed immediately (otherwise you must manually commit with commit())\n";
              help += "shutdown - Shuts down Persevere\n";
              return help;
            }
           
          }, false);
          ((NativeObject) consoleScope).setGetterOrSetter("shutdown", 0, new PersevereNativeFunction(){
            @Override
            public Object call(Context cx, Scriptable scope, Scriptable thisObj, Object[] args) {
              System.exit(0);
              return null;
            }
          }, false);
          Transaction.startTransaction();
          consoleScope.put("autocommit", consoleScope, true);
          PersistableObject.enableSecurity(true);
         
          try {
            ConsoleReader reader = new ConsoleReader();
            StringBuffer sb = new StringBuffer();
            reader.setBellEnabled(false);
            System.out.println("Type \"help\" at the console for more information");
            do {
              String prompt = (sb.length() > 0) ? "   " : "js>"; // no prompt if we're on a multiline
              String line = reader.readLine(prompt);
              if(line == null){
                // in eclipse jline doesn't work, so we have to resort standard System.in
                char c;
                do{
                  c = (char) System.in.read();
                  if (c == (char) -1){
                    System.out.println("Console not available (no valid input stream is present)");
                    return null;
                  }
                  sb.append(c);
                }while(c != '\n');
              }
              else
                sb.append(line);
              if (context.stringIsCompilableUnit(sb.toString()))
              {
                // if it is syntactically finished, we evaluate
                System.out.println(evaluate(sb.toString()));
                sb = new StringBuffer();
              }
            } while(true);
          } catch (Throwable e1) {
            LogFactory.getLog(Console.class).warn("Console not available: " + e1.getMessage());
          }
        return null;
      }
    });
  }
  /**
   * Evaluates an expression within a transaction and returns the result
   * @param expression
   * @return
   */
  String evaluate(String expression){
    try {
      Object value = context.evaluateString(consoleScope, expression, "console", 0, null);
      if (ScriptRuntime.toBoolean(consoleScope.get("autocommit", consoleScope))) {
        try{
          Transaction.currentTransaction().commit();
        }
        finally{
          Transaction.startTransaction();
        }
      }
      if(value == Undefined.instance)
        return "";
      if(value instanceof List){
        return "[object Array of " + ((List)value).size() + " elements]";
      }
      return ScriptRuntime.toString(value);
    } catch (Throwable e) {
      if (ScriptRuntime.toBoolean(consoleScope.get("autocommit", consoleScope))) {
        Transaction.currentTransaction().abort();
        Transaction.startTransaction();
      }
      if(e instanceof RhinoException)
        return ((RhinoException)e).details() + '\n' + ((RhinoException)e).getScriptStackTrace();
      else {
        StringWriter sw = new StringWriter();
        e.printStackTrace(new PrintWriter(sw));
        return sw.toString();
      }
    }

  }
    static String uneval(Context cx, Scriptable scope, Object value)
    {
        if (value == null) {
            return "null";
        }
        if (value == Undefined.instance) {
            return "undefined";
        }
        if (value instanceof String) {
            String escaped = ScriptRuntime.escapeString((String)value);
            StringBuffer sb = new StringBuffer(escaped.length() + 2);
            sb.append('\"');
            sb.append(escaped);
            sb.append('\"');
            return sb.toString();
        }
        if (value instanceof Number) {
            double d = ((Number)value).doubleValue();
            if (d == 0 && 1 / d < 0) {
        return "-0";
            }
            return ScriptRuntime.toString(d);
        }
        if (value instanceof Boolean) {
            return ScriptRuntime.toString(value);
        }
        if (value instanceof Scriptable) {
            Scriptable obj = (Scriptable)value;
            // Wrapped Java objects won't have "toSource" and will report
            // errors for get()s of nonexistent name, so use has() first
            if (ScriptableObject.hasProperty(obj, "toSource")) {
        Object v = ScriptableObject.getProperty(obj, "toSource");
        if (v instanceof Function) {
            Function f = (Function)v;
            return ScriptRuntime.toString(f.call(cx, scope, obj, ScriptRuntime.emptyArgs));
        }
            }
            return ScriptRuntime.toString(value);
        }
        return value.toString();
    }

}
TOP

Related Classes of org.persvr.util.Console

TOP
Copyright © 2018 www.massapi.com. All rights reserved.
All source code are property of their respective owners. Java is a trademark of Sun Microsystems, Inc and owned by ORACLE Inc. Contact coftware#gmail.com.