net.autosauler.ballance.server.model.Scripts.java Source code

Java tutorial

Introduction

Here is the source code for net.autosauler.ballance.server.model.Scripts.java

Source

/*******************************************************************************
 * Copyright 2011 Alex 'Ript' Malyshev <alexript@gmail.com>
 * 
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 * 
 *   http://www.apache.org/licenses/LICENSE-2.0
 * 
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 ******************************************************************************/

package net.autosauler.ballance.server.model;

import java.io.IOException;
import java.util.HashMap;
import java.util.Hashtable;
import java.util.Iterator;
import java.util.List;
import java.util.Set;

import javax.script.ScriptException;

import net.autosauler.ballance.server.mongodb.Database;
import net.autosauler.ballance.server.util.Base64;
import net.autosauler.ballance.server.vm.VM;
import net.autosauler.ballance.shared.datatypes.DataTypes;

import org.w3c.dom.Element;
import org.w3c.dom.NodeList;

import com.allen_sauer.gwt.log.client.Log;
import com.mongodb.BasicDBObject;
import com.mongodb.DB;
import com.mongodb.DBCollection;
import com.mongodb.DBCursor;
import com.mongodb.DBObject;

/**
 * The Class Scripts.
 * 
 * @author alexript
 */
public class Scripts {

    /** The Constant TABLENAME. */
    private final static String TABLENAME = "scripts";

    /**
     * Dump.
     * 
     * @param domain
     *            the domain
     * @return the string
     */
    public static String dump(String domain) {
        StringBuilder sb = new StringBuilder();
        sb.append("<scripts>\n");
        DB db = Database.get(domain);
        if (db != null) {
            Database.retain();
            DBCollection coll = db.getCollection(TABLENAME);
            BasicDBObject q = new BasicDBObject();

            q.put("domain", domain);

            DBCursor cur = coll.find(q);
            while (cur.hasNext()) {
                DBObject myDoc = cur.next();

                String txt;
                try {
                    txt = Base64.encodeBytes(((String) myDoc.get("text")).getBytes("UTF-8"));
                    sb.append("<script name=\"");
                    sb.append((String) myDoc.get("name"));
                    sb.append("\">");
                    sb.append(txt);
                    sb.append("</script>\n");
                } catch (IOException e) {
                    Log.error(e.getMessage());
                }

            }
            Database.release();
        }
        sb.append("</scripts>\n");
        return sb.toString();
    }

    /** The domain. */
    private final String domain;

    /** The name. */
    private String name;

    /** The text. */
    private String text;

    /** The vm. */
    private VM vm = null;

    /** The caller. */
    private final IScriptableObject caller;

    private final String username;

    public Scripts(IScriptableObject obj, String domain, String username, String name) {
        this(obj, domain, username, name, null);
    }

    /**
     * Instantiates a new scripts.
     * 
     * @param obj
     *            the obj
     * @param domain
     *            the domain
     * @param name
     *            the name
     */
    public Scripts(IScriptableObject obj, String domain, String username, String name, VM vm2) {
        this.name = name;
        this.domain = domain;
        this.username = username;
        caller = obj;
        initVM(vm2);

        initStruct();

        loadText();

        if (vm != null) {
            if (text != null) {
                try {
                    vm.eval(text);
                } catch (Exception e) {
                    Log.error(e.getMessage());
                }

            } else {
                Log.error("There is no text for script " + name);
            }
        } else {
            Log.error("My vm is null!!!!");
        }

    }

    /**
     * Instantiates a new scripts. WARNING: only for database restore case
     * 
     * @param domain
     *            the domain
     */
    public Scripts(String domain, String username) {
        name = "";
        this.domain = domain;
        this.username = username;
        caller = null;
        initStruct();
    }

    public Scripts(String domain, String username, String name) {
        this(domain, username, name, null);
    }

    /**
     * Instantiates a new scripts.
     * 
     * @param domain
     *            the domain
     * @param name
     *            the name
     */
    public Scripts(String domain, String username, String name, VM vm2) {
        this.name = name;
        this.domain = domain;
        this.username = username;
        caller = null;
        initVM(vm2);
        initStruct();
        loadText();

        if (vm != null) {

            if (text != null) {
                try {

                    vm.eval(text);
                } catch (Exception e) {
                    Log.error(e.getMessage());
                }

            } else {
                Log.error("There is no text for script " + name);
            }
        }

    }

    /**
     * Call.
     * 
     * @param funcname
     *            the funcname
     * @param args
     *            the args
     * @return the object
     * @throws ScriptException
     *             the script exception
     * @throws NoSuchMethodException
     *             the no such method exception
     */
    public Object call(String funcname, final Object... args) throws ScriptException, NoSuchMethodException {
        Object result = null;

        if (vm != null) {
            result = vm.call(funcname, args);
        }
        return result;
    }

    /**
     * Eval.
     * 
     * @param cmd
     *            the cmd
     * @return the object
     */
    public Object eval(String cmd) {

        if (vm != null) {
            try {
                return vm.eval(cmd);
            } catch (ScriptException e) {
                Log.error(e.getMessage());
            }
        }
        return null;
    }

    /**
     * Eval.
     * 
     * @param evalstring
     *            the evalstring
     * @param params
     *            the params
     * @param types
     *            the types
     * @return the hash map
     * @throws ScriptException
     *             the script exception
     * @throws NoSuchMethodException
     *             the no such method exception
     */
    public HashMap<String, String> eval(String evalstring, HashMap<String, String> params,
            HashMap<String, Integer> types) throws ScriptException, NoSuchMethodException {

        Hashtable<String, Object> input = new Hashtable<String, Object>();
        Set<String> names = params.keySet();
        Iterator<String> i = names.iterator();
        while (i.hasNext()) {
            String name = i.next();
            if (types.containsKey(name)) {
                input.put(name, DataTypes.fromString(types.get(name), params.get(name)));
            }
        }
        HashMap<String, String> result = new HashMap<String, String>();

        Object eval = null;
        if (vm != null) {

            eval = vm.call(evalstring, input);

        }
        // ---------------------
        if (eval != null) {
            if (Hashtable.class.isInstance(eval)) {
                @SuppressWarnings("unchecked")
                Hashtable<String, Object> output = (Hashtable<String, Object>) eval;

                if ((output != null) && !output.isEmpty()) {
                    Set<String> cnames = output.keySet();
                    Iterator<String> j = cnames.iterator();
                    while (j.hasNext()) {
                        String name = new String(j.next());
                        if (types.containsKey(name)) {
                            result.put(name, DataTypes.toString(types.get(name), output.get(name)));
                        }
                    }
                } else {
                    Log.error("Empty eval's result");
                }
            } else {
                Log.error("Eval result is not HashMap: " + eval.getClass().getCanonicalName());
            }
        }

        return result;
    }

    public HashMap<String, String> eval(String evalstring, String changedfield, HashMap<String, String> params,
            HashMap<String, Integer> types) throws ScriptException, NoSuchMethodException {
        Hashtable<String, Object> input = new Hashtable<String, Object>();
        Set<String> names = params.keySet();
        Iterator<String> i = names.iterator();
        while (i.hasNext()) {
            String name = i.next();
            if (types.containsKey(name)) {
                input.put(name, DataTypes.fromString(types.get(name), params.get(name)));
            }
        }
        HashMap<String, String> result = new HashMap<String, String>();

        Object eval = null;
        if (vm != null) {

            eval = vm.call(evalstring, changedfield, input);

        }
        // ---------------------
        if (eval != null) {
            if (Hashtable.class.isInstance(eval)) {
                @SuppressWarnings("unchecked")
                Hashtable<String, Object> output = (Hashtable<String, Object>) eval;

                if ((output != null) && !output.isEmpty()) {
                    Set<String> cnames = output.keySet();
                    Iterator<String> j = cnames.iterator();
                    while (j.hasNext()) {
                        String name = new String(j.next());
                        if (types.containsKey(name)) {
                            result.put(name, DataTypes.toString(types.get(name), output.get(name)));
                        }
                    }
                } else {
                    Log.error("Empty eval's result");
                }
            } else {
                Log.error("Eval result is not HashMap: " + eval.getClass().getCanonicalName());
            }
        }

        return result;

    }

    /**
     * @param evalstring
     * @param tablename
     * @param changedfield
     * @param params
     * @param types
     * @return
     * @throws ScriptException
     * @throws NoSuchMethodException
     */
    public HashMap<String, String> eval(String evalstring, String tablename, String changedfield,
            HashMap<String, String> params, HashMap<String, Integer> types)
            throws ScriptException, NoSuchMethodException {
        Hashtable<String, Object> input = new Hashtable<String, Object>();
        Set<String> names = params.keySet();
        Iterator<String> i = names.iterator();
        while (i.hasNext()) {
            String name = i.next();
            if (types.containsKey(name)) {
                input.put(name, DataTypes.fromString(types.get(name), params.get(name)));
            }
        }
        HashMap<String, String> result = new HashMap<String, String>();

        Object eval = null;
        if (vm != null) {

            eval = vm.call(evalstring, tablename, changedfield, input);

        }
        // ---------------------
        if (eval != null) {
            if (Hashtable.class.isInstance(eval)) {
                @SuppressWarnings("unchecked")
                Hashtable<String, Object> output = (Hashtable<String, Object>) eval;

                if ((output != null) && !output.isEmpty()) {
                    Set<String> cnames = output.keySet();
                    Iterator<String> j = cnames.iterator();
                    while (j.hasNext()) {
                        String name = new String(j.next());
                        if (types.containsKey(name)) {
                            result.put(name, DataTypes.toString(types.get(name), output.get(name)));
                        }
                    }
                } else {
                    Log.error("Empty eval's result");
                }
            } else {
                Log.error("Eval result is not HashMap: " + eval.getClass().getCanonicalName());
            }
        }

        return result;

    }

    /**
     * Gets the text.
     * 
     * @return the text
     */
    public String getText() {
        return text;
    }

    /**
     * Inits the struct.
     */
    private void initStruct() {
        DB db = Database.get(domain);
        if (db != null) {
            Database.retain();
            DBCollection coll = db.getCollection(TABLENAME);
            List<DBObject> indexes = coll.getIndexInfo();
            if (indexes.size() < 1) {
                BasicDBObject i = new BasicDBObject();

                i.put("domain", 1);
                i.put("name", 1);
                coll.createIndex(i);

            }
            Database.release();
        }
    }

    /**
     * Inits the vm.
     */
    private void initVM(VM parentvm) {
        Log.trace("init vm");
        if (parentvm == null) {
            vm = new VM(domain, username);
        } else {
            vm = parentvm;
        }
        if (!name.equals("global")) {
            Scripts global = new Scripts(domain, username, "global", vm);
            global.nop();
        }

    }

    /**
     * Load text.
     */
    private void loadText() {
        String txt = "";

        DBObject doc = null;
        DB db = Database.get(domain);
        if (db != null) {
            Database.retain();
            DBCollection coll = db.getCollection(TABLENAME);
            BasicDBObject query = new BasicDBObject();
            query.put("domain", domain);
            query.put("name", name);

            doc = coll.findOne(query);
            Database.release();
            if (doc != null) {
                txt = (String) doc.get("text");
            }
        }

        if ((txt == null) || txt.isEmpty()) {
            if (!domain.equals("127.0.0.1")) {
                Scripts s = new Scripts(caller, "127.0.0.1", username, name, vm);
                txt = s.getText();
            }

        }

        if ((txt == null) || txt.isEmpty()) {
            if (domain.equals("127.0.0.1") && name.equals("global")) {
                txt = "import java.lang\nLog.error('Global script evaluated')\n";
            }
            if (caller != null) {
                txt = caller.generateDefaultScript();

            }

            setText(txt, true);

            return;
        }

        setText(txt, false);

    }

    /**
     * Nop. (no operations)
     */
    private void nop() {
        return;
    }

    /**
     * Restore.
     * 
     * @param vals
     *            the vals
     */
    public void restore(Element vals) {
        NodeList nodes = vals.getElementsByTagName("script");
        for (int i = 0; i < nodes.getLength(); i++) {
            Element val = (Element) nodes.item(i);
            String name = val.getAttribute("name");
            String b64 = val.getTextContent();
            try {
                String text = new String(Base64.decode(b64), "UTF-8");
                this.name = name;
                setText(text, true);
            } catch (IOException e) {
                Log.error(e.getMessage());
            }

        }

    }

    /**
     * Sets the text.
     * 
     * @param txt
     *            the new text
     */
    public void setText(String txt) {
        setText(txt, true);
    }

    /**
     * Sets the text.
     * 
     * @param txt
     *            the txt
     * @param andstore
     *            the andstore
     */
    public void setText(String txt, boolean andstore) {
        text = txt;
        if (andstore) {
            DBObject doc = null;
            DB db = Database.get(domain);
            if (db != null) {
                Database.retain();
                DBCollection coll = db.getCollection(TABLENAME);
                BasicDBObject query = new BasicDBObject();
                query.put("domain", domain);
                query.put("name", name);

                doc = coll.findOne(query);

                if (doc != null) {
                    doc.put("text", text);
                    coll.save(doc);
                } else {
                    doc = new BasicDBObject();
                    doc.put("domain", domain);
                    doc.put("name", name);
                    doc.put("text", text);
                    coll.insert(doc);
                }

                Database.release();

                initVM(null);

            }
        }
    }
}