![JAR search and dependency download from the Maven repository](/logo.png)
org.mvel2.sh.ShellSession Maven / Gradle / Ivy
Go to download
Show more of this group Show more artifacts with this name
Show all versions of tbel Show documentation
Show all versions of tbel Show documentation
TBEL is a powerful expression language for ThingsBoard platform user-defined functions.
Original implementation is based on MVEL.
/**
* MVEL 2.0
* Copyright (C) 2007 The Codehaus
* Mike Brock, Dhanji Prasanna, John Graham, Mark Proctor
*
* 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 org.mvel2.sh;
import org.mvel2.MVELInterpretedRuntime;
import org.mvel2.ParserContext;
import org.mvel2.integration.VariableResolverFactory;
import org.mvel2.integration.impl.MapVariableResolverFactory;
import org.mvel2.sh.command.basic.BasicCommandSet;
import org.mvel2.sh.command.file.FileCommandSet;
import org.mvel2.templates.TemplateRuntime;
import org.mvel2.util.StringAppender;
import org.mvel2.util.PropertyTools;
import java.io.*;
import java.util.*;
import static java.lang.Boolean.parseBoolean;
import static java.lang.Runtime.getRuntime;
import static java.lang.System.arraycopy;
import static java.lang.System.getProperty;
import static java.util.ResourceBundle.getBundle;
import static org.mvel2.MVEL.compileExpression;
import static org.mvel2.MVEL.executeExpression;
import static org.mvel2.util.PropertyTools.contains;
/**
* A shell session.
*/
public class ShellSession {
public static final String PROMPT_VAR = "$PROMPT";
private static final String[] EMPTY = new String[0];
private final Map commands = new HashMap();
private Map variables;
private Map env;
private Object ctxObject;
ParserContext pCtx = new ParserContext();
VariableResolverFactory lvrf;
private int depth;
private int cdepth;
private boolean multi = false;
private int multiIndentSize = 0;
private PrintStream out = System.out;
private String prompt;
private String commandBuffer;
StringAppender inBuffer = new StringAppender();
final BufferedReader readBuffer = new BufferedReader(new InputStreamReader(System.in));
public ShellSession() {
System.out.println("Starting session...");
variables = new HashMap();
env = new HashMap();
commands.putAll(new BasicCommandSet().load());
commands.putAll(new FileCommandSet().load());
env.put(PROMPT_VAR, DefaultEnvironment.PROMPT);
env.put("$OS_NAME", getProperty("os.name"));
env.put("$OS_VERSION", getProperty("os.version"));
env.put("$JAVA_VERSION", PropertyTools.getJavaVersion());
env.put("$CWD", new File(".").getAbsolutePath());
env.put("$COMMAND_PASSTRU", "false");
env.put("$PRINTOUTPUT", "true");
env.put("$ECHO", "false");
env.put("$SHOW_TRACES", "true");
env.put("$USE_OPTIMIZER_ALWAYS", "false");
env.put("$PATH", "");
try {
ResourceBundle bundle = getBundle(".mvelsh.properties");
Enumeration enumer = bundle.getKeys();
String key;
while (enumer.hasMoreElements()) {
env.put(key = enumer.nextElement(), bundle.getString(key));
}
}
catch (MissingResourceException e) {
System.out.println("No config file found. Loading default config.");
if (!contains(getProperty("os.name").toLowerCase(), "windows")) {
env.put("$PATH", "/bin:/usr/bin:/sbin:/usr/sbin");
}
}
lvrf = new MapVariableResolverFactory(variables, new MapVariableResolverFactory(env));
}
public ShellSession(String init) {
this();
exec(init);
}
private void _exec() {
String[] inTokens;
Object outputBuffer;
final PrintStream sysPrintStream = System.out;
final PrintStream sysErrorStream = System.err;
final InputStream sysInputStream = System.in;
File execFile;
if ("true".equals(env.get("$ECHO"))) {
out.println(">" + commandBuffer);
out.flush();
}
inTokens = inBuffer.append(commandBuffer).toString().split("\\s");
if (inTokens.length != 0 && commands.containsKey(inTokens[0])) {
commandBuffer = null;
String[] passParameters;
if (inTokens.length > 1) {
arraycopy(inTokens, 1, passParameters = new String[inTokens.length - 1], 0, passParameters.length);
}
else {
passParameters = EMPTY;
}
try {
commands.get(inTokens[0]).execute(this, passParameters);
}
catch (CommandException e) {
out.append("Error: ").append(e.getMessage()).append("\n");
}
}
else {
commandBuffer = null;
try {
if (shouldDefer(inBuffer)) {
multi = true;
return;
}
else {
multi = false;
}
if (parseBoolean(env.get("$USE_OPTIMIZER_ALWAYS"))) {
outputBuffer = executeExpression(compileExpression(inBuffer.toString()), ctxObject, lvrf);
}
else {
MVELInterpretedRuntime runtime = new MVELInterpretedRuntime(inBuffer.toString(), ctxObject, lvrf, pCtx);
outputBuffer = runtime.parse();
}
}
catch (Exception e) {
if ("true".equals(env.get("$COMMAND_PASSTHRU"))) {
String[] paths;
String s;
if ((s = inTokens[0]).startsWith("./")) {
s = new File(env.get("$CWD")).getAbsolutePath() + s.substring(s.indexOf('/'));
paths = new String[]{s};
}
else {
paths = env.get("$PATH").split("(:|;)");
}
boolean successfulExec = false;
for (String execPath : paths) {
if ((execFile = new File(execPath + "/" + s)).exists() && execFile.isFile()) {
successfulExec = true;
String[] execString = new String[inTokens.length];
execString[0] = execFile.getAbsolutePath();
System.arraycopy(inTokens, 1, execString, 1, inTokens.length - 1);
try {
final Process p = getRuntime().exec(execString);
final OutputStream outStream = p.getOutputStream();
final InputStream inStream = p.getInputStream();
final InputStream errStream = p.getErrorStream();
final RunState runState = new RunState(this);
final Thread pollingThread = new Thread(new Runnable() {
public void run() {
byte[] buf = new byte[25];
int read;
while (true) {
try {
while ((read = inStream.read(buf)) > 0) {
for (int i = 0; i < read; i++) {
sysPrintStream.print((char) buf[i]);
}
sysPrintStream.flush();
}
if (!runState.isRunning()) break;
}
catch (Exception e) {
break;
}
}
sysPrintStream.flush();
if (!multi) {
multiIndentSize = (prompt = String.valueOf(TemplateRuntime.eval(env.get("$PROMPT"), variables))).length();
out.append(prompt);
}
else {
out.append(">").append(indent((multiIndentSize - 1) + (depth * 4)));
}
}
});
final Thread watchThread = new Thread(new Runnable() {
public void run() {
Thread runningThread = new Thread(new Runnable() {
public void run() {
try {
String read;
while (runState.isRunning()) {
while ((read = readBuffer.readLine()) != null) {
if (runState.isRunning()) {
for (char c : read.toCharArray()) {
outStream.write((byte) c);
}
}
else {
runState.getSession().setCommandBuffer(read);
break;
}
}
}
outStream.write((byte) '\n');
outStream.flush();
}
catch (Exception e2) {
}
}
});
runningThread.setPriority(Thread.MIN_PRIORITY);
runningThread.start();
try {
p.waitFor();
}
catch (InterruptedException e) {
// nothing;
}
sysPrintStream.flush();
runState.setRunning(false);
try {
runningThread.join();
}
catch (InterruptedException e) {
// nothing;�
}
}
});
pollingThread.setPriority(Thread.MIN_PRIORITY);
pollingThread.start();
watchThread.setPriority(Thread.MIN_PRIORITY);
watchThread.start();
watchThread.join();
try {
pollingThread.notify();
}
catch (Exception ne) {
}
}
catch (Exception e2) {
// fall through;
}
}
}
if (successfulExec) {
inBuffer.reset();
return;
}
}
ByteArrayOutputStream stackTraceCap = new ByteArrayOutputStream();
PrintStream capture = new PrintStream(stackTraceCap);
e.printStackTrace(capture);
capture.flush();
env.put("$LAST_STACK_TRACE", new String(stackTraceCap.toByteArray()));
if (parseBoolean(env.get("$SHOW_TRACE"))) {
out.println(env.get("$LAST_STACK_TRACE"));
}
else {
out.println(e.toString());
}
inBuffer.reset();
return;
}
if (outputBuffer != null && "true".equals(env.get("$PRINTOUTPUT"))) {
if (outputBuffer.getClass().isArray()) {
out.println(Arrays.toString((Object[]) outputBuffer));
}
else {
out.println(String.valueOf(outputBuffer));
}
}
}
inBuffer.reset();
}
//todo: fix this
public void run() {
final BufferedReader readBuffer = new BufferedReader(new InputStreamReader(System.in));
try {
//noinspection InfiniteLoopStatement
while (true) {
printPrompt();
if (commandBuffer == null) {
commandBuffer = readBuffer.readLine();
}
_exec();
}
}
catch (Exception e) {
e.printStackTrace();
System.out.println("unexpected exception. exiting.");
}
}
public void printPrompt() {
if (!multi) {
multiIndentSize = (prompt = String.valueOf(TemplateRuntime.eval(env.get("$PROMPT"), variables))).length();
out.append(prompt);
}
else {
out.append(">").append(indent((multiIndentSize - 1) + (depth * 4)));
}
}
public boolean shouldDefer(StringAppender inBuf) {
char[] buffer = new char[inBuf.length()];
inBuf.getChars(0, inBuf.length(), buffer, 0);
depth = cdepth = 0;
for (int i = 0; i < buffer.length; i++) {
switch (buffer[i]) {
case '/':
if (i + 1 < buffer.length && buffer[i + 1] == '*') {
cdepth++;
}
break;
case '*':
if (i + 1 < buffer.length && buffer[i + 1] == '/') {
cdepth--;
}
break;
case '{':
depth++;
break;
case '}':
depth--;
break;
}
}
return depth + cdepth > 0;
}
public String indent(int size) {
StringBuffer sbuf = new StringBuffer();
for (int i = 0; i < size; i++) sbuf.append(" ");
return sbuf.toString();
}
public Map getCommands() {
return commands;
}
public Map getVariables() {
return variables;
}
public Map getEnv() {
return env;
}
public Object getCtxObject() {
return ctxObject;
}
public void setCtxObject(Object ctxObject) {
this.ctxObject = ctxObject;
}
public String getCommandBuffer() {
return commandBuffer;
}
public void setCommandBuffer(String commandBuffer) {
this.commandBuffer = commandBuffer;
}
public void exec(String command) {
for (String c : command.split("\n")) {
inBuffer.append(c);
_exec();
}
}
public static final class RunState {
private boolean running = true;
private ShellSession session;
public RunState(ShellSession session) {
this.session = session;
}
public ShellSession getSession() {
return session;
}
public void setSession(ShellSession session) {
this.session = session;
}
public boolean isRunning() {
return running;
}
public void setRunning(boolean running) {
this.running = running;
}
}
}
© 2015 - 2025 Weber Informatics LLC | Privacy Policy