package com.laytonsmith.core; import com.laytonsmith.PureUtilities.ExecutionQueue; import com.laytonsmith.core.constructs.CString; import com.laytonsmith.core.constructs.CVoid; import com.laytonsmith.core.constructs.Target; import com.laytonsmith.core.environments.Environment; import com.laytonsmith.core.environments.GlobalEnv; import com.laytonsmith.core.exceptions.CancelCommandException; import com.laytonsmith.core.exceptions.ConfigRuntimeException; import com.laytonsmith.core.exceptions.FunctionReturnException; import com.laytonsmith.core.functions.Echoes; /** * A subclass of ExecutionQueue, which knows how to handle uncaught exceptions * in a MethodScript specific way. * */ public class MethodScriptExecutionQueue extends ExecutionQueue { GlobalEnv env; public MethodScriptExecutionQueue(String threadPrefix, String defaultQueueName) { super(threadPrefix, defaultQueueName, null); } public void setEnvironment(GlobalEnv env){ this.env = env; super.setUncaughtExceptionHandler(getExceptionHandler()); } private Thread.UncaughtExceptionHandler getExceptionHandler(){ Thread.UncaughtExceptionHandler uceh = new Thread.UncaughtExceptionHandler() { @Override public void uncaughtException(Thread t, Throwable e) { Environment env = Environment.createEnvironment(MethodScriptExecutionQueue.this.env); if(e instanceof ConfigRuntimeException){ //This should be handled by the default UEH ConfigRuntimeException.HandleUncaughtException(((ConfigRuntimeException)e), env); } else if(e instanceof FunctionReturnException){ //If they return void, fine, but if they return any other value, it will be //ignored, so we want to warn them, but not trigger a flat out error. if(!(((FunctionReturnException)e).getReturn() instanceof CVoid)){ ConfigRuntimeException.DoWarning("Closure is returning a value in an execution queue task," + " which is unexpected behavior. It may return void however, which will" + " simply stop that one task. " + ((FunctionReturnException)e).getTarget().toString()); } } else if(e instanceof CancelCommandException){ //Ok. If there's a message, echo it to console. String msg = ((CancelCommandException)e).getMessage().trim(); if(!"".equals(msg)){ Target tt = ((CancelCommandException)e).getTarget(); new Echoes.console().exec(tt, env, new CString(msg, tt)); } } else { //Well, we tried to deal with it, but this is beyond our ability to //handle, so let it bubble up further. throw new RuntimeException(e); } } }; return uceh; } }