diff options
| author | Andrew Branson <andrew.branson@cern.ch> | 2013-02-14 22:54:45 +0100 |
|---|---|---|
| committer | Andrew Branson <andrew.branson@cern.ch> | 2013-02-14 22:54:45 +0100 |
| commit | 65ed02984f004ce736744e56540bc04324f311c4 (patch) | |
| tree | 6cbdc7f8f2975301042f07ef37ff4743c51a6c4e | |
| parent | 48027b943a833f6639ddce33178a5694529ac91a (diff) | |
Fold script console environment into Script.
Add support for 'textFiles/consoleScript.lang.txt' console function
declarations in kernel and modules.
Use that context for ScriptConsole network consoles and new ShellConsole
client process.
| -rw-r--r-- | bin/eclipse/Cristal Kernel Console.launch | 19 | ||||
| -rw-r--r-- | src/main/java/com/c2kernel/process/ClientShell.java | 82 | ||||
| -rw-r--r-- | src/main/java/com/c2kernel/scripting/Script.java | 83 | ||||
| -rw-r--r-- | src/main/java/com/c2kernel/scripting/ScriptConsole.java | 50 | ||||
| -rw-r--r-- | src/main/resources/textFiles/consoleHelp.txt | 15 | ||||
| -rw-r--r-- | src/main/resources/textFiles/consoleScript.javascript.txt | 19 |
6 files changed, 211 insertions, 57 deletions
diff --git a/bin/eclipse/Cristal Kernel Console.launch b/bin/eclipse/Cristal Kernel Console.launch new file mode 100644 index 0000000..b8bae26 --- /dev/null +++ b/bin/eclipse/Cristal Kernel Console.launch @@ -0,0 +1,19 @@ +<?xml version="1.0" encoding="UTF-8" standalone="no"?>
+<launchConfiguration type="org.eclipse.jdt.launching.localJavaApplication">
+<listAttribute key="org.eclipse.debug.core.MAPPED_RESOURCE_PATHS">
+<listEntry value="/cristal-kernel/src/main/java/com/c2kernel/process/ClientShell.java"/>
+</listAttribute>
+<listAttribute key="org.eclipse.debug.core.MAPPED_RESOURCE_TYPES">
+<listEntry value="1"/>
+</listAttribute>
+<stringAttribute key="org.eclipse.debug.ui.ATTR_CONSOLE_ENCODING" value="UTF-8"/>
+<listAttribute key="org.eclipse.debug.ui.favoriteGroups">
+<listEntry value="org.eclipse.debug.ui.launchGroup.debug"/>
+<listEntry value="org.eclipse.debug.ui.launchGroup.run"/>
+</listAttribute>
+<stringAttribute key="org.eclipse.jdt.launching.CLASSPATH_PROVIDER" value="org.eclipse.m2e.launchconfig.classpathProvider"/>
+<stringAttribute key="org.eclipse.jdt.launching.MAIN_TYPE" value="com.c2kernel.process.ClientShell"/>
+<stringAttribute key="org.eclipse.jdt.launching.PROGRAM_ARGUMENTS" value="-config bin/conf/client.conf -connect ${file_prompt}"/>
+<stringAttribute key="org.eclipse.jdt.launching.PROJECT_ATTR" value="cristal-kernel"/>
+<stringAttribute key="org.eclipse.jdt.launching.SOURCE_PATH_PROVIDER" value="org.eclipse.m2e.launchconfig.sourcepathProvider"/>
+</launchConfiguration>
diff --git a/src/main/java/com/c2kernel/process/ClientShell.java b/src/main/java/com/c2kernel/process/ClientShell.java new file mode 100644 index 0000000..5bb1246 --- /dev/null +++ b/src/main/java/com/c2kernel/process/ClientShell.java @@ -0,0 +1,82 @@ +/*
+ * ClientShell.java
+ *
+ * Copyright (c) 2013, The CRISTAL Consortium. All rights reserved.
+ *
+ * CRISTAL kernel is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 3 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library. If not, see:
+ * http://www.gnu.org/licenses/
+ */
+
+package com.c2kernel.process;
+
+import java.util.Scanner;
+
+import com.c2kernel.entity.proxy.AgentProxy;
+import com.c2kernel.scripting.Script;
+
+public class ClientShell extends StandardClient {
+
+ AgentProxy user;
+ Script console;
+
+ public ClientShell(String username, String pass) throws Exception {
+ user = Gateway.connect(username, pass);
+ console = new Script("javascript", user, System.out);
+ }
+
+ public void run() {
+ Scanner scan = new Scanner(System.in);
+ System.out.print("> ");
+ while (scan.hasNextLine()) {
+ String command = scan.nextLine();
+ console.setScript(command);
+ try {
+ Object response = console.execute();
+ if (response == null)
+ System.out.println("Ok");
+ else
+ System.out.println(response);
+ } catch (Throwable ex) {
+ ex.printStackTrace();
+ }
+ System.out.print("> ");
+ }
+ close();
+ }
+
+ public static void main(String[] args) throws Exception {
+ Gateway.init(readC2KArgs(args));
+ Scanner scan = new Scanner(System.in);
+ int loginAttempts = 0;
+ ClientShell shell = null;
+ while (shell == null && loginAttempts++ < 3) {
+ System.out.print("User:");
+ String username = scan.nextLine();
+ System.out.print("Password:");
+ String pass = scan.nextLine();
+ try {
+ shell = new ClientShell(username, pass);
+ } catch (Exception ex) {
+ System.err.println(ex.getMessage());
+ }
+ }
+ if (shell == null) {
+ System.err.println("Bye");
+ System.exit(0);
+ }
+ shell.run();
+
+ }
+
+}
diff --git a/src/main/java/com/c2kernel/scripting/Script.java b/src/main/java/com/c2kernel/scripting/Script.java index ed86696..98ab8cf 100644 --- a/src/main/java/com/c2kernel/scripting/Script.java +++ b/src/main/java/com/c2kernel/scripting/Script.java @@ -1,13 +1,18 @@ package com.c2kernel.scripting;
+import java.io.PrintStream;
+import java.io.PrintWriter;
import java.io.StringReader;
import java.util.ArrayList;
import java.util.HashMap;
import javax.script.Bindings;
+import javax.script.ScriptContext;
import javax.script.ScriptEngine;
import javax.script.ScriptEngineFactory;
import javax.script.ScriptEngineManager;
+import javax.script.ScriptException;
+import javax.script.SimpleScriptContext;
import javax.xml.parsers.DocumentBuilder;
import javax.xml.parsers.DocumentBuilderFactory;
@@ -21,8 +26,10 @@ import com.c2kernel.common.ObjectNotFoundException; import com.c2kernel.entity.agent.Job;
import com.c2kernel.entity.proxy.AgentProxy;
import com.c2kernel.entity.proxy.ItemProxy;
+import com.c2kernel.process.Gateway;
import com.c2kernel.utils.LocalObjectLoader;
import com.c2kernel.utils.Logger;
+import com.c2kernel.utils.Resource;
/**************************************************************************
*
@@ -42,7 +49,7 @@ public class Script HashMap<String, Parameter> mOutputParams = new HashMap<String, Parameter>();
ArrayList<Script> mIncludes = new ArrayList<Script>();
ScriptEngine engine;
- Bindings beans;
+ ScriptContext context;
/**
* Loads script xml and parses it for script source, parameters and output specifications.
@@ -55,11 +62,10 @@ public class Script * @param scriptVersion - named version of the script (must be numbered viewpoint)
* @throws ScriptParsingException - when script not found (ScriptLoadingException) or xml is invalid (ScriptParsingException)
*/
- public Script(String scriptName, int scriptVersion, Bindings context) throws ScriptingEngineException
+ public Script(String scriptName, int scriptVersion, ScriptContext context) throws ScriptingEngineException
{
this(scriptName, scriptVersion);
- beans = context;
-
+ this.context = context;
}
public Script(String scriptName, int scriptVersion) throws ScriptingEngineException
@@ -67,7 +73,7 @@ public class Script mName = scriptName;
mVersion = String.valueOf(scriptVersion);
if (!scriptName.equals(""))
- setScript(mName, mVersion);
+ loadScript(mName, mVersion);
}
/**
@@ -91,7 +97,7 @@ public class Script public Script(ItemProxy object, AgentProxy subject, Job job) throws ScriptingEngineException
{
this(job.getActPropString("ScriptName"), job.getActPropString("ScriptVersion") == null ? -1 : Integer.parseInt(job.getActPropString("ScriptVersion")));
- // set enviroment - this needs to be well documented for script developers
+ // set environment - this needs to be well documented for script developers
if (!mInputParams.containsKey("item"))
addInputParam("item", ItemProxy.class);
setInputParamValue("item", object);
@@ -107,13 +113,49 @@ public class Script if (!mOutputParams.containsKey("errors"))
addOutput("errors", ErrorInfo.class);
}
+
+ /**
+ * For consoles
+ *
+ * @param lang - script language
+ * @param agent - AgentProxy of the console user
+ * @param out - the output PrintStream for reporting results that don't go to the log
+ */
+ public Script(String lang, AgentProxy agent, PrintStream out) throws Exception {
+ setScriptEngine(lang);
+ Bindings beans = context.getBindings(ScriptContext.ENGINE_SCOPE);
+ beans.put("storage", Gateway.getStorage());
+ beans.put("db", Gateway.getStorage().getDb());
+ beans.put("proxy", Gateway.getProxyManager());
+ beans.put("lookup", Gateway.getLDAPLookup());
+ beans.put("orb", Gateway.getORB());
+ beans.put("agent", agent);
+ beans.put("output", out);
+ PrintWriter output = new PrintWriter(out);
+ context.setWriter(output);
+ context.setErrorWriter(output);
+ HashMap<String, String> consoleScripts = Resource.getAllTextResources("textFiles/consoleScript."+lang+".txt");
+ for (String ns : consoleScripts.keySet()) {
+ try {
+ engine.eval(consoleScripts.get(ns));
+ } catch (ScriptException ex) {
+ out.println("Exception parsing console script for "+(ns==null?"kernel":ns+" module"));
+ ex.printStackTrace(out);
+ }
+ }
+ addOutput(null, Object.class);
+
+ }
public void setScriptEngine(String lang) {
engine = new ScriptEngineManager().getEngineByName(lang);
- beans = engine.createBindings();
+ Bindings beans = engine.createBindings();
+ context = new SimpleScriptContext();
+ context.setBindings(beans, ScriptContext.ENGINE_SCOPE);
+ engine.setContext(context);
}
- public void setScript(String scriptName, String scriptVersion) throws ScriptingEngineException
+ public void loadScript(String scriptName, String scriptVersion) throws ScriptingEngineException
{
try
{
@@ -194,7 +236,7 @@ public class Script String includeName = currentParam.getAttribute("name");
String includeVersion = currentParam.getAttribute("version");
try {
- Script includedScript = new Script(includeName, Integer.parseInt(includeVersion), beans);
+ Script includedScript = new Script(includeName, Integer.parseInt(includeVersion), context);
mIncludes.add(includedScript);
for (Parameter includeParam : includedScript.getInputParams().values()) {
addIncludedInputParam(includeParam.getName(), includeParam.getType());
@@ -205,7 +247,6 @@ public class Script throw new ScriptParsingException("Error parsing imported script '"+includeName+"', version '"+includeVersion+"': "+e.getMessage());
}
-
}
//load Script
else if (paramName.equals("script"))
@@ -336,7 +377,7 @@ public class Script if (value.getClass() != param.getType())
throw new ParameterException(
"Parameter " + name + " is wrong type \n" + "Required: " + param.getType().toString() + "\n" + "Supplied: " + value.getClass().toString());
- beans.put(name, value);
+ context.getBindings(ScriptContext.ENGINE_SCOPE).put(name, value);
Logger.msg(7, "Script.setInputParamValue() - " + name + ": " + value.toString());
param.setInitialised(true);
}
@@ -381,7 +422,7 @@ public class Script } catch (Exception e) {
emptyObject = null;
}
- beans.put(outputParam.getName(), emptyObject);
+ context.getBindings(ScriptContext.ENGINE_SCOPE).put(outputParam.getName(), emptyObject);
}
@@ -402,7 +443,7 @@ public class Script if (engine == null)
throw new ScriptingEngineException("Script engine not set. Cannot execute scripts.");
- returnValue = engine.eval(mScript, beans);
+ returnValue = engine.eval(mScript);
Logger.msg(7, "Script.execute() - script returned \"" + returnValue + "\"");
}
catch (Throwable ex)
@@ -424,7 +465,7 @@ public class Script if (outputName == null)
outputValue = returnValue;
else
- outputValue = beans.get(outputParam.getName());
+ outputValue = context.getBindings(ScriptContext.ENGINE_SCOPE).get(outputParam.getName());
Logger.msg(4, "Script.execute() - Output parameter "+outputName+"="+(outputValue==null?"null":outputValue.toString()));
// check the class
@@ -442,20 +483,14 @@ public class Script return outputs;
}
-
- /**
- * Resets the scripting enviroment, clearing all state and parameters for another execution.
- */
- public void reset()
- {
- for (Parameter parameter : mInputParams.values())
- parameter.setInitialised(false);
- beans = engine.createBindings();
+
+ public void setScript(String script) {
+ mScript = script;
}
static public void main(String[] args) {
for(ScriptEngineFactory sef: new ScriptEngineManager().getEngineFactories()) {
- System.out.println(sef.getEngineName()+" v"+sef.getEngineVersion()+" using "+sef.getLanguageName()+" v"+sef.getLanguageVersion());
+ System.out.println(sef.getEngineName()+" v"+sef.getEngineVersion()+" using "+sef.getLanguageName()+" v"+sef.getLanguageVersion()+" "+sef.getNames());
}
}
}
diff --git a/src/main/java/com/c2kernel/scripting/ScriptConsole.java b/src/main/java/com/c2kernel/scripting/ScriptConsole.java index 826ab88..9b70641 100644 --- a/src/main/java/com/c2kernel/scripting/ScriptConsole.java +++ b/src/main/java/com/c2kernel/scripting/ScriptConsole.java @@ -13,13 +13,12 @@ import java.util.StringTokenizer; import javax.script.Bindings;
import javax.script.ScriptEngine;
-import javax.script.ScriptEngineManager;
import org.tanukisoftware.wrapper.WrapperManager;
+import com.c2kernel.entity.proxy.AgentProxy;
import com.c2kernel.process.Gateway;
import com.c2kernel.utils.Logger;
-import com.c2kernel.utils.Resource;
import com.c2kernel.utils.server.SocketHandler;
/**************************************************************************
@@ -139,19 +138,21 @@ public class ScriptConsole implements SocketHandler { // get system objects
try {
Logger.addLogStream(output, 0);
-
- engine = new ScriptEngineManager().getEngineByName("JavaScript");
- beans = engine.createBindings();
- beans.put("storage", Gateway.getStorage());
- beans.put("db", Gateway.getStorage().getDb());
- beans.put("proxy", Gateway.getProxyManager());
- beans.put("lookup", Gateway.getLDAPLookup());
- beans.put("orb", Gateway.getORB());
+ AgentProxy user = Gateway.getCurrentUser();
try {
- beans.put("system", Gateway.getProxyManager().getProxy(
- Gateway.getLDAPLookup().getRoleManager().getAgentPath("system")));
+ if (user == null) user = (AgentProxy)Gateway.getProxyManager().getProxy(
+ Gateway.getLDAPLookup().getRoleManager().getAgentPath("system"));
+ } catch (Exception ex) {
+ output.println("System agent unavailable");
+ }
+ Script context;
+ try {
+ context = new Script("javascript", user, output);
} catch (Exception ex) {
- output.println("System agent unavailable");
+ output.println("Error initializing console script context");
+ ex.printStackTrace(output);
+ shutdown();
+ return;
}
StringBuffer commandBuffer = new StringBuffer();
@@ -176,24 +177,6 @@ public class ScriptConsole implements SocketHandler { shutdown();
continue;
}
- else if(command.startsWith("log")) {
- try {
- int newLogLevel = Integer.parseInt(command.substring(4));
- Logger.removeLogStream(output);
- Logger.addLogStream(output, newLogLevel);
- Logger.msg("Log level for "+socket.getInetAddress()+" set to "+newLogLevel);
- continue;
- } catch (NumberFormatException ex) { }
- }
- else if(command.equals("help")) {
- output.println(Resource.findTextResource("textFiles/consoleHelp.txt"));
- continue;
- }
- else if(command.equals("version")) {
- output.println("Kernel version: "+Resource.getKernelVersion());
- output.println("Modules loaded: "+Gateway.getModuleManager().getModuleVersions());
- continue;
- }
try {
if (command.endsWith("\\")) {
commandBuffer.append(command.substring(0,command.length()-1));
@@ -206,10 +189,11 @@ public class ScriptConsole implements SocketHandler { // process control
if (command.equals("shutdown")) {
- WrapperManager.stop(0);
+ WrapperManager.stop(0);
}
else {
- Object response = engine.eval(command, beans);
+ context.setScript(command);
+ Object response = context.execute();
if (response == null)
output.println("Ok");
else
diff --git a/src/main/resources/textFiles/consoleHelp.txt b/src/main/resources/textFiles/consoleHelp.txt new file mode 100644 index 0000000..57a0655 --- /dev/null +++ b/src/main/resources/textFiles/consoleHelp.txt @@ -0,0 +1,15 @@ +Cristal console
+---------------
+Commands entered here are directly parsed by the beanshell engine. You can call methods directly on these pre-loaded objects:
+proxy - the EntityProxyManager
+storage - the TransactionManager
+db - the ClusterStorageManager
+lookup - the LDAPLookup (server context)
+orb - the ORB
+user - the current logged in user, or the system user if connected to the server console
+
+Built-in commands:
+log(level) - Change the log level of your stream.
+help() - View this message.
+version() - View kernel and module versions.
+shutdown() - Stop this CRISTAL instance.
diff --git a/src/main/resources/textFiles/consoleScript.javascript.txt b/src/main/resources/textFiles/consoleScript.javascript.txt new file mode 100644 index 0000000..9c68553 --- /dev/null +++ b/src/main/resources/textFiles/consoleScript.javascript.txt @@ -0,0 +1,19 @@ +function log(level) { + com.c2kernel.utils.Logger.removeLogStream(output); + com.c2kernel.utils.Logger.addLogStream(output, level); +} +function help() { + var help = com.c2kernel.utils.Resource.getAllTextResources("textFiles/consoleHelp.txt").values().iterator(); + while (help.hasNext()) + println(help.next()); +} +function version() { + print("Kernel version: "+com.c2kernel.utils.Resource.getKernelVersion()); + print("Modules loaded: "+com.c2kernel.process.Gateway.getModuleManager().getModuleVersions()); +} +function shutdown() { + if (com.c2kernel.process.AbstractMain.runningAsWrapper) + org.tanukisoftware.wrapper.WrapperManager.stop(0); + else + com.c2kernel.process.StandardClient.close(); +} |
