All Downloads are FREE. Search and download functionalities are using the official Maven repository.

nl.weeaboo.lua2.LuaException Maven / Gradle / Ivy

package nl.weeaboo.lua2;

import java.util.List;

import nl.weeaboo.lua2.io.LuaSerializable;
import nl.weeaboo.lua2.stdlib.DebugTrace;
import nl.weeaboo.lua2.vm.LuaNil;
import nl.weeaboo.lua2.vm.LuaStackTraceElement;
import nl.weeaboo.lua2.vm.LuaString;
import nl.weeaboo.lua2.vm.LuaValue;

/**
 * Represents an error thrown by the Lua VM.
 */
@LuaSerializable
public final class LuaException extends RuntimeException {

    private static final long serialVersionUID = 1L;

    private static final int MAX_LEVELS = 8;

    private final LuaValue message;

    public LuaException(String message) {
        this(LuaString.valueOf(message));
    }

    public LuaException(LuaValue message) {
        this(message, null, 0);
    }

    public LuaException(LuaValue message, Throwable cause, int level) {
        super(cause);

        this.message = (message != null ? message : LuaNil.NIL);

        if (level >= 0) {
            initStackTrace(cause, level);
        }
    }

    private void initStackTrace(Throwable cause, int level) {
        LuaRunState lrs = LuaRunState.getCurrent();
        if (lrs == null) {
            return; // No Lua context is current
        }

        List stack = DebugTrace.stackTrace(lrs.getRunningThread(), level, MAX_LEVELS);
        if (cause != null) {
            setStackTrace(prefixLuaStackTrace(cause, stack));
        } else {
            setStackTrace(prefixLuaStackTrace(this, stack));
        }
    }

    /**
     * Converts an arbitrary exception to an equivalent {@link LuaException}.
     */
    public static LuaException wrap(String message, Throwable ex) {
        LuaException le;
        if (ex instanceof LuaException) {
            if (ex.getMessage() != null) {
                message += ": " + ex.toString();
            }
            le = new LuaException(LuaString.valueOf(message), ex.getCause(), 0);

            // Copy stacktrace and cause from the existing exception
            le.setStackTrace(ex.getStackTrace());
        } else {
            // For non-Lua exceptions, add the original exception as a cause
            le = new LuaException(LuaString.valueOf(message), ex, 0);
        }

        return le;
    }

    private static StackTraceElement[] prefixLuaStackTrace(Throwable t, List luaStack) {
        StackTraceElement[] javaStack = t.getStackTrace();
        StackTraceElement[] newStack = new StackTraceElement[luaStack.size() + javaStack.length];

        int joff = 0;
        for (int n = 0; n < javaStack.length; n++) {
            StackTraceElement ste = javaStack[n];
            if (ste.getClassName().contains("LuaInterpreter") && ste.getMethodName().equals("resume")) {
                joff = n;
                break;
            }
        }
        System.arraycopy(javaStack, 0, newStack, 0, joff);
        for (int n = 0; n < luaStack.size(); n++) {
            newStack[joff + n] = luaStack.get(n).toJavaStackTraceElement();
        }
        System.arraycopy(javaStack, joff, newStack, joff + luaStack.size(), javaStack.length - joff);
        return newStack;
    }

    @Override
    public String getMessage() {
        return String.valueOf(message);
    }

    /** Retuns the error message for this exception as a Lua object. */
    public LuaValue getMessageObject() {
        return message;
    }

}




© 2015 - 2024 Weber Informatics LLC | Privacy Policy