use of com.laytonsmith.core.profiler.ProfilePoint in project CommandHelper by EngineHub.
the class Script method eval.
/**
* Given the parse tree and environment, executes the tree.
*
* @param c
* @param env
* @return
* @throws CancelCommandException
*/
public Construct eval(ParseTree c, final Environment env) throws CancelCommandException {
if (env.getEnv(GlobalEnv.class).IsInterrupted()) {
// unconditionally.
throw new CancelCommandException("", Target.UNKNOWN);
}
final Construct m = c.getData();
CurrentEnv = env;
if (m.getCType() != ConstructType.FUNCTION) {
if (m.getCType() == ConstructType.VARIABLE) {
return new CString(m.val(), m.getTarget());
} else {
return m;
}
}
StackTraceManager stManager = env.getEnv(GlobalEnv.class).GetStackTraceManager();
boolean addedRootStackElement = false;
try {
// If it's an unknown target, this is not user generated code, and we want to skip adding the element here.
if (stManager.isStackEmpty() && !m.getTarget().equals(Target.UNKNOWN)) {
stManager.addStackTraceElement(new ConfigRuntimeException.StackTraceElement("<<main code>>", m.getTarget()));
addedRootStackElement = true;
}
stManager.setCurrentTarget(c.getTarget());
env.getEnv(GlobalEnv.class).SetScript(this);
if (m.val().charAt(0) == '_' && m.val().charAt(1) != '_') {
// Not really a function, so we can't put it in Function.
Procedure p = getProc(m.val());
if (p == null) {
throw new CREInvalidProcedureException("Unknown procedure \"" + m.val() + "\"", m.getTarget());
}
Environment newEnv = env;
try {
newEnv = env.clone();
} catch (CloneNotSupportedException e) {
}
ProfilePoint pp = env.getEnv(GlobalEnv.class).GetProfiler().start(m.val() + " execution", LogLevel.INFO);
Construct ret;
try {
ret = p.cexecute(c.getChildren(), newEnv, m.getTarget());
} finally {
pp.stop();
}
return ret;
}
final Function f;
try {
f = (Function) FunctionList.getFunction(m);
} catch (ConfigCompileException e) {
// Turn it into a config runtime exception. This shouldn't ever happen though.
throw ConfigRuntimeException.CreateUncatchableException("Unable to find function " + m.val(), m.getTarget());
}
ArrayList<Construct> args = new ArrayList<>();
try {
if (f.isRestricted() && !Static.hasCHPermission(f.getName(), env)) {
throw new CREInsufficientPermissionException("You do not have permission to use the " + f.getName() + " function.", m.getTarget());
}
if (f.useSpecialExec()) {
ProfilePoint p = null;
if (f.shouldProfile() && env.getEnv(GlobalEnv.class).GetProfiler() != null && env.getEnv(GlobalEnv.class).GetProfiler().isLoggable(f.profileAt())) {
p = env.getEnv(GlobalEnv.class).GetProfiler().start(f.profileMessageS(c.getChildren()), f.profileAt());
}
Construct ret;
try {
ret = f.execs(m.getTarget(), env, this, c.getChildren().toArray(new ParseTree[] {}));
} finally {
if (p != null) {
p.stop();
}
}
return ret;
}
for (ParseTree c2 : c.getChildren()) {
args.add(eval(c2, env));
}
Object[] a = args.toArray();
Construct[] ca = new Construct[a.length];
for (int i = 0; i < a.length; i++) {
ca[i] = (Construct) a[i];
// CArray, CBoolean, CDouble, CInt, CNull, CString, CVoid, CEntry, CLabel (only to sconcat).
if (!(ca[i] instanceof CArray || ca[i] instanceof CBoolean || ca[i] instanceof CDouble || ca[i] instanceof CInt || ca[i] instanceof CNull || ca[i] instanceof CString || ca[i] instanceof CVoid || ca[i] instanceof IVariable || ca[i] instanceof CEntry || ca[i] instanceof CLabel) && (!f.getName().equals("__autoconcat__") && (ca[i] instanceof CLabel))) {
throw new CRECastException("Invalid Construct (" + ca[i].getClass() + ") being passed as an argument to a function (" + f.getName() + ")", m.getTarget());
}
while (f.preResolveVariables() && ca[i] instanceof IVariable) {
IVariable cur = (IVariable) ca[i];
ca[i] = env.getEnv(GlobalEnv.class).GetVarList().get(cur.getVariableName(), cur.getTarget()).ival();
}
}
{
// It takes a moment to generate the toString of some things, so lets not do it
// if we actually aren't going to profile
ProfilePoint p = null;
if (f.shouldProfile() && env.getEnv(GlobalEnv.class).GetProfiler() != null && env.getEnv(GlobalEnv.class).GetProfiler().isLoggable(f.profileAt())) {
p = env.getEnv(GlobalEnv.class).GetProfiler().start(f.profileMessage(ca), f.profileAt());
}
Construct ret;
try {
ret = f.exec(m.getTarget(), env, ca);
} finally {
if (p != null) {
p.stop();
}
}
return ret;
}
// We want to catch and rethrow the ones we know how to catch, and then
// catch and report anything else.
} catch (ConfigRuntimeException | ProgramFlowManipulationException e) {
if (e instanceof AbstractCREException) {
((AbstractCREException) e).freezeStackTraceElements(stManager);
}
throw e;
} catch (InvalidEnvironmentException e) {
if (!e.isDataSet()) {
e.setData(f.getName());
}
throw e;
} catch (Exception e) {
String brand = Implementation.GetServerType().getBranding();
SimpleVersion version = Static.getVersion();
String culprit = brand;
outer: for (ExtensionTracker tracker : ExtensionManager.getTrackers().values()) {
for (FunctionBase b : tracker.getFunctions()) {
if (b.getName().equals(f.getName())) {
// name instead of the core plugin's name.
for (Extension extension : tracker.getExtensions()) {
culprit = extension.getName();
break outer;
}
}
}
}
String emsg = TermColors.RED + "Uh oh! You've found an error in " + TermColors.CYAN + culprit + TermColors.RED + ".\n" + "This happened while running your code, so you may be able to find a workaround," + " but is ultimately an issue in " + culprit + ".\n" + "The following code caused the error:\n" + TermColors.WHITE;
List<String> args2 = new ArrayList<>();
Map<String, String> vars = new HashMap<>();
for (Construct cc : args) {
if (cc instanceof IVariable) {
Construct ccc = env.getEnv(GlobalEnv.class).GetVarList().get(((IVariable) cc).getVariableName(), cc.getTarget()).ival();
String vval = ccc.val();
if (ccc instanceof CString) {
vval = ccc.asString().getQuote();
}
vars.put(((IVariable) cc).getVariableName(), vval);
}
if (cc == null) {
args2.add("java-null");
} else if (cc instanceof CString) {
args2.add(cc.asString().getQuote());
} else if (cc instanceof IVariable) {
args2.add(((IVariable) cc).getVariableName());
} else {
args2.add(cc.val());
}
}
if (!vars.isEmpty()) {
emsg += StringUtils.Join(vars, " = ", "\n") + "\n";
}
emsg += f.getName() + "(";
emsg += StringUtils.Join(args2, ", ");
emsg += ")\n";
emsg += TermColors.RED + "on or around " + TermColors.YELLOW + m.getTarget().file() + TermColors.WHITE + ":" + TermColors.CYAN + m.getTarget().line() + TermColors.RED + ".\n";
// Server might not be available in this platform, so let's be sure to ignore those exceptions
String modVersion;
try {
modVersion = StaticLayer.GetConvertor().GetServer().getAPIVersion();
} catch (Exception ex) {
modVersion = Implementation.GetServerType().name();
}
String extensionData = "";
for (ExtensionTracker tracker : ExtensionManager.getTrackers().values()) {
for (Extension extension : tracker.getExtensions()) {
try {
extensionData += TermColors.CYAN + extension.getName() + TermColors.RED + " (" + TermColors.RESET + extension.getVersion() + TermColors.RED + ")\n";
} catch (AbstractMethodError ex) {
// This happens with an old style extensions. Just skip it.
extensionData += TermColors.CYAN + "Unknown Extension" + TermColors.RED + "\n";
}
}
}
if (extensionData.isEmpty()) {
extensionData = "NONE\n";
}
emsg += "Please report this to the developers, and be sure to include the version numbers:\n" + TermColors.CYAN + "Server" + TermColors.RED + " version: " + TermColors.RESET + modVersion + TermColors.RED + ";\n" + TermColors.CYAN + brand + TermColors.RED + " version: " + TermColors.RESET + version + TermColors.RED + ";\n" + "Loaded extensions and versions:\n" + extensionData + "Here's the stacktrace:\n" + TermColors.RESET + Static.GetStacktraceString(e);
Static.getLogger().log(Level.SEVERE, emsg);
throw new CancelCommandException(null, Target.UNKNOWN);
}
} finally {
if (addedRootStackElement && stManager.isStackSingle()) {
stManager.popStackTraceElement();
}
}
}
use of com.laytonsmith.core.profiler.ProfilePoint in project CommandHelper by EngineHub.
the class BoundEvent method trigger.
/**
* When the event actually occurs, this should be run, after translating the original event object (of whatever type
* it may be) into a standard map, which contains the event object data. It is converted into a CArray here, and
* then the script is executed with the driver's execute function.
*
* @param activeEvent
*/
public void trigger(ActiveEvent activeEvent) throws EventException {
try {
// GenericTree<Construct> root = new GenericTree<Construct>();
// root.setRoot(tree);
Environment env = originalEnv.clone();
CArray ca = CArray.GetAssociativeArray(Target.UNKNOWN);
for (Map.Entry<String, Construct> entry : activeEvent.parsedEvent.entrySet()) {
ca.set(new CString(entry.getKey(), Target.UNKNOWN), entry.getValue(), Target.UNKNOWN);
}
env.getEnv(GlobalEnv.class).GetVarList().set(new IVariable(CArray.TYPE, eventObjName, ca, Target.UNKNOWN));
env.getEnv(GlobalEnv.class).SetEvent(activeEvent);
activeEvent.addHistory("Triggering bound event: " + this);
try {
ProfilePoint p = env.getEnv(GlobalEnv.class).GetProfiler().start("Executing event handler for " + this.getEventName() + " defined at " + this.getTarget(), LogLevel.ERROR);
try {
this.execute(env, activeEvent);
} finally {
p.stop();
}
} catch (ConfigRuntimeException e) {
// We don't know how to handle this, but we need to set the env,
// then pass it up the chain
e.setEnv(env);
throw e;
}
} catch (CloneNotSupportedException ex) {
Logger.getLogger(BoundEvent.class.getName()).log(Level.SEVERE, null, ex);
}
}
use of com.laytonsmith.core.profiler.ProfilePoint in project CommandHelper by EngineHub.
the class AliasCore method alias.
/**
* This is the workhorse function. It takes a given command, then converts it into the actual command(s). If the
* command maps to a defined alias, it will run the specified alias. It will search through the global list of
* aliases, as well as the aliases defined for that specific player. This function doesn't handle the /alias command
* however.
*
* @param command
* @return
*/
public boolean alias(String command, final MCCommandSender player) {
if (scripts == null) {
throw ConfigRuntimeException.CreateUncatchableException("Cannot run alias commands, no config file is loaded", Target.UNKNOWN);
}
boolean match = false;
try {
// actually add the player to the array.
if (player != null && player instanceof MCPlayer && echoCommand.contains(((MCPlayer) player).getName())) {
// we are running one of the expanded commands, so exit with false
return false;
}
for (Script s : scripts) {
try {
if (s.match(command)) {
this.addPlayerReference(player);
if (Prefs.ConsoleLogCommands() && s.doLog()) {
StringBuilder b = new StringBuilder("CH: Running original command ");
if (player instanceof MCPlayer) {
b.append("on player ").append(((MCPlayer) player).getName());
} else {
b.append("from a MCCommandSender");
}
b.append(" ----> ").append(command);
Static.getLogger().log(Level.INFO, b.toString());
}
GlobalEnv gEnv = new GlobalEnv(parent.executionQueue, parent.profiler, parent.persistenceNetwork, MethodScriptFileLocations.getDefault().getConfigDirectory(), parent.profiles, new TaskManager());
CommandHelperEnvironment cEnv = new CommandHelperEnvironment();
cEnv.SetCommandSender(player);
Environment env = Environment.createEnvironment(gEnv, cEnv);
try {
env.getEnv(CommandHelperEnvironment.class).SetCommand(command);
ProfilePoint alias = env.getEnv(GlobalEnv.class).GetProfiler().start("Global Alias - \"" + command + "\"", LogLevel.ERROR);
try {
s.run(s.getVariables(command), env, new MethodScriptComplete() {
@Override
public void done(String output) {
try {
if (output != null) {
if (!output.trim().isEmpty() && output.trim().startsWith("/")) {
if (Prefs.DebugMode()) {
if (player instanceof MCPlayer) {
Static.getLogger().log(Level.INFO, "[CommandHelper]: Executing command on " + ((MCPlayer) player).getName() + ": " + output.trim());
} else {
Static.getLogger().log(Level.INFO, "[CommandHelper]: Executing command from console equivalent: " + output.trim());
}
}
if (player instanceof MCPlayer) {
((MCPlayer) player).chat(output.trim());
} else {
Static.getServer().dispatchCommand(player, output.trim().substring(1));
}
}
}
} catch (Throwable e) {
StreamUtils.GetSystemErr().println(e.getMessage());
player.sendMessage(MCChatColor.RED + e.getMessage());
} finally {
Static.getAliasCore().removePlayerReference(player);
}
}
});
} finally {
alias.stop();
}
} catch (ConfigRuntimeException ex) {
ex.setEnv(env);
ConfigRuntimeException.HandleUncaughtException(ex, env);
} catch (Throwable e) {
// This is not a simple user script error, this is a deeper problem, so we always handle this.
StreamUtils.GetSystemErr().println("An unexpected exception occured: " + e.getClass().getSimpleName());
player.sendMessage("An unexpected exception occured: " + MCChatColor.RED + e.getClass().getSimpleName());
e.printStackTrace();
} finally {
Static.getAliasCore().removePlayerReference(player);
}
match = true;
break;
}
} catch (Exception e) {
StreamUtils.GetSystemErr().println("An unexpected exception occured inside the command " + s.toString());
e.printStackTrace();
}
}
} catch (Throwable e) {
// Not only did an error happen, an error happened in our error handler
throw new InternalException(TermColors.RED + "An unexpected error occured in the CommandHelper plugin. " + "Further, this is likely an error with the error handler, so it may be caused by your script, " + "however, there is no more information at this point. Check your script, but also report this " + "as a bug in CommandHelper. Also, it's possible that some commands will no longer work. As a temporary " + "workaround, restart the server, and avoid doing whatever it is you did to make this happen.\nThe error is as follows: " + e.toString() + "\n" + TermColors.reset() + "Stack Trace:\n" + StringUtils.Join(Arrays.asList(e.getStackTrace()), "\n"));
}
return match;
}
use of com.laytonsmith.core.profiler.ProfilePoint in project CommandHelper by EngineHub.
the class Interpreter method execute.
/**
* This executes an entire script. The cmdline_prompt_event is first triggered (if used) and if the event is
* cancelled, nothing happens.
*
* @param script
* @param args
* @param fromFile
* @throws ConfigCompileException
* @throws IOException
*/
public void execute(String script, List<String> args, File fromFile) throws ConfigCompileException, IOException, ConfigCompileGroupException {
CmdlineEvents.cmdline_prompt_input.CmdlinePromptInput input = new CmdlineEvents.cmdline_prompt_input.CmdlinePromptInput(script, inShellMode);
EventUtils.TriggerListener(Driver.CMDLINE_PROMPT_INPUT, "cmdline_prompt_input", input);
if (input.isCancelled()) {
return;
}
ctrlCcount = 0;
if ("exit".equals(script)) {
if (inShellMode) {
inShellMode = false;
return;
}
pl(YELLOW + "Use exit() if you wish to exit.");
return;
}
if ("help".equals(script)) {
pl(getHelpMsg());
return;
}
if (fromFile == null) {
fromFile = new File("Interpreter");
}
boolean localShellMode = false;
if (!inShellMode && script.startsWith("$$")) {
localShellMode = true;
script = script.substring(2);
}
if (inShellMode || localShellMode) {
// Wrap this in shell_adv
if (doBuiltin(script)) {
return;
}
List<String> shellArgs = StringUtils.ArgParser(script);
List<String> escapedArgs = new ArrayList<>();
for (String arg : shellArgs) {
escapedArgs.add(new CString(arg, Target.UNKNOWN).getQuote());
}
script = "shell_adv(" + "array(" + StringUtils.Join(escapedArgs, ",") + ")," + "array(" + "'stdout':closure(@l){sys_out(@l);}," + "'stderr':closure(@l){sys_err(@l);})" + ");";
}
isExecuting = true;
ProfilePoint compile = env.getEnv(GlobalEnv.class).GetProfiler().start("Compilation", LogLevel.VERBOSE);
final ParseTree tree;
try {
TokenStream stream = MethodScriptCompiler.lex(script, fromFile, true);
tree = MethodScriptCompiler.compile(stream);
} finally {
compile.stop();
}
// Environment env = Environment.createEnvironment(this.env.getEnv(GlobalEnv.class));
final List<Variable> vars = new ArrayList<>();
if (args != null) {
// Build the @arguments variable, the $ vars, and $ itself. Note that
// we have special handling for $0, that is the script name, like bash.
// However, it doesn't get added to either $ or @arguments, due to the
// uncommon use of it.
StringBuilder finalArgument = new StringBuilder();
CArray arguments = new CArray(Target.UNKNOWN);
{
// Set the $0 argument
Variable v = new Variable("$0", "", Target.UNKNOWN);
v.setVal(fromFile.toString());
v.setDefault(fromFile.toString());
vars.add(v);
}
for (int i = 0; i < args.size(); i++) {
String arg = args.get(i);
if (i > 0) {
finalArgument.append(" ");
}
Variable v = new Variable("$" + Integer.toString(i + 1), "", Target.UNKNOWN);
v.setVal(new CString(arg, Target.UNKNOWN));
v.setDefault(arg);
vars.add(v);
finalArgument.append(arg);
arguments.push(new CString(arg, Target.UNKNOWN), Target.UNKNOWN);
}
Variable v = new Variable("$", "", false, true, Target.UNKNOWN);
v.setVal(new CString(finalArgument.toString(), Target.UNKNOWN));
v.setDefault(finalArgument.toString());
vars.add(v);
env.getEnv(GlobalEnv.class).GetVarList().set(new IVariable(CArray.TYPE, "@arguments", arguments, Target.UNKNOWN));
}
try {
ProfilePoint p = this.env.getEnv(GlobalEnv.class).GetProfiler().start("Interpreter Script", LogLevel.ERROR);
try {
final MutableObject<Throwable> wasThrown = new MutableObject<>();
scriptThread = new Thread(new Runnable() {
@Override
public void run() {
try {
MethodScriptCompiler.execute(tree, env, new MethodScriptComplete() {
@Override
public void done(String output) {
if (System.console() != null && !"".equals(output.trim())) {
StreamUtils.GetSystemOut().println(output);
}
}
}, null, vars);
} catch (CancelCommandException e) {
// Nothing, though we could have been Ctrl+C cancelled, so we need to reset
// the interrupt flag. But we do that unconditionally below, in the finally,
// in the other thread.
} catch (ConfigRuntimeException e) {
ConfigRuntimeException.HandleUncaughtException(e, env);
// No need for the full stack trace
if (System.console() == null) {
System.exit(1);
}
} catch (NoClassDefFoundError e) {
StreamUtils.GetSystemErr().println(RED + Main.getNoClassDefFoundErrorMessage(e) + reset());
StreamUtils.GetSystemErr().println("Since you're running from standalone interpreter mode, this is not a fatal error, but one of the functions you just used required" + " an actual backing engine that isn't currently loaded. (It still might fail even if you load the engine though.) You simply won't be" + " able to use that function here.");
if (System.console() == null) {
System.exit(1);
}
} catch (InvalidEnvironmentException ex) {
StreamUtils.GetSystemErr().println(RED + ex.getMessage() + " " + ex.getData() + "() cannot be used in this context.");
if (System.console() == null) {
System.exit(1);
}
} catch (RuntimeException e) {
pl(RED + e.toString());
e.printStackTrace(StreamUtils.GetSystemErr());
if (System.console() == null) {
System.exit(1);
}
}
}
}, "MethodScript-Main");
scriptThread.start();
try {
scriptThread.join();
} catch (InterruptedException ex) {
//
}
} finally {
p.stop();
}
} finally {
env.getEnv(GlobalEnv.class).SetInterrupt(false);
isExecuting = false;
}
}
use of com.laytonsmith.core.profiler.ProfilePoint in project CommandHelper by EngineHub.
the class AbstractEvent method execute.
/**
* This function is run when the actual event occurs.
*
* @param tree The compiled parse tree
* @param b The bound event
* @param env The operating environment
* @param activeEvent The active event being executed
*/
@Override
public final void execute(ParseTree tree, BoundEvent b, Environment env, BoundEvent.ActiveEvent activeEvent) throws ConfigRuntimeException {
preExecution(env, activeEvent);
// Various events have a player to put into the env.
// Do this after preExcecution() in case the particular event needs to inject the player first.
Construct c = activeEvent.getParsedEvent().get("player");
if (c != null) {
try {
MCPlayer p = Static.GetPlayer(c, Target.UNKNOWN);
env.getEnv(CommandHelperEnvironment.class).SetPlayer(p);
} catch (CREPlayerOfflineException e) {
// Set env CommandSender to prevent incorrect inherited player from being used in a player event.
if (env.getEnv(CommandHelperEnvironment.class).GetPlayer() != null) {
env.getEnv(CommandHelperEnvironment.class).SetCommandSender(Static.getServer().getConsole());
}
}
}
ProfilePoint event = null;
if (env.getEnv(GlobalEnv.class).GetProfiler() != null) {
event = env.getEnv(GlobalEnv.class).GetProfiler().start("Event " + b.getEventName() + " (defined at " + b.getTarget().toString() + ")", LogLevel.ERROR);
}
try {
try {
// Get the label from the bind time environment, and put it in the current environment.
String label = b.getEnvironment().getEnv(GlobalEnv.class).GetLabel();
if (label == null) {
// Set the permission to global if it's null, since that means
// it wasn't set, and so we aren't in a secured environment anyways.
label = Static.GLOBAL_PERMISSION;
}
env.getEnv(GlobalEnv.class).SetLabel(label);
MethodScriptCompiler.execute(tree, env, null, null);
} catch (CancelCommandException ex) {
if (ex.getMessage() != null && !ex.getMessage().isEmpty()) {
StreamUtils.GetSystemOut().println(ex.getMessage());
}
} catch (FunctionReturnException ex) {
// We simply allow this to end the event execution
} catch (ProgramFlowManipulationException ex) {
ConfigRuntimeException.HandleUncaughtException(new CREFormatException("Unexpected control flow operation used.", ex.getTarget()), env);
}
} finally {
if (event != null) {
event.stop();
}
// Finally, among other things, we need to clean-up injected players and entities
postExecution(env, activeEvent);
}
}
Aggregations