Package st.gravel.support.jvm.runtime

Source Code of st.gravel.support.jvm.runtime.ExceptionStack$ExceptionHandler

package st.gravel.support.jvm.runtime;

import st.gravel.support.jvm.NonLocalReturn;

public class ExceptionStack {
  public static class ExceptionHandler {

    private final Object exceptionSelector;
    private final Object exBlock;
    private final ExceptionHandler previous;
    private final Object marker;
    private final Object protectedBlock;

    public ExceptionHandler(Object protectedBlock,
        Object exceptionSelector, Object exBlock,
        ExceptionHandler previous, Object marker) {
      this.protectedBlock = protectedBlock;
      this.exceptionSelector = exceptionSelector;
      this.exBlock = exBlock;
      this.previous = previous;
      this.marker = marker;
    }

    public void handle(Object exception) throws Throwable {
      setCurrentHandler(exception, this);
      Object value = MethodTools.perform(exBlock, "value:", exception);
      throw new NonLocalReturn(value, marker);
    }

    public boolean handles(Object exception) throws Throwable {
      Object res = MethodTools.perform(exceptionSelector, "handles:",
          exception);
      return res == Boolean.TRUE;
    }

    public Object marker() {
      return marker;
    }

    public ExceptionHandler previous() {
      return previous;
    }

  }

  private static final ThreadLocal<ExceptionStack> currentStack = new ThreadLocal<ExceptionStack>() {
    @Override
    protected ExceptionStack initialValue() {
      return new ExceptionStack();
    }
  };

  public static ExceptionHandler addHandler(Object protectedBlock,
      Object exceptionSelector, Object exBlock, Object marker) {
    return currentStack.get().pvtAddHandler(protectedBlock,
        exceptionSelector, exBlock, marker);
  }

  private static ExceptionHandler currentHandler(Object exception) {
    return (ExceptionHandler) MethodTools.safePerform(exception,
        "currentHandler");
  }

  public static void handle(Object exception, Object resumeMarker)
      throws Throwable {
    currentStack.get().pvtHandle(exception, resumeMarker);
  }

  public static void handlePass(Object exception) throws Throwable {
    currentStack.get().pvtHandlePass(exception);
  }

  public static void handleResume_(Object exception, Object returnValue) {
    currentStack.get().pvtHandleResume(exception, returnValue);
  }

  public static Object handleRetry(Object exception) throws Throwable {
    return currentStack.get().pvtHandleRetry(exception);
  }

  public static Object handleRetryUsing_(Object exception, Object value)
      throws Throwable {
    return currentStack.get().pvtHandleRetryUsing_(exception, value);
  }

  public static Object handleReturn(Object exception, Object value) {
    return currentStack.get().pvtHandleReturn(exception, value);
  }

  private static ExceptionHandler initialHandler(Object exception) {
    return (ExceptionHandler) MethodTools.safePerform(exception,
        "initialHandler");
  }

  public static boolean isNested(Object exception) throws Throwable {
    return currentStack.get().pvtIsNested(exception);
  }

  public static void removeHandler(ExceptionHandler handler) {
    currentStack.get().pvtRemoveHandler(handler);
  }

  private static void setCurrentHandler(Object exception,
      ExceptionHandler value) {
    MethodTools.safePerform(exception, "currentHandler:", value);
  }

  private static void setInitialHandler(Object exception,
      ExceptionHandler value) {
    MethodTools.safePerform(exception, "initialHandler:", value);
  }

  private ExceptionHandler current;

  private void executeDefaultAction(Object exception) {
    MethodTools.safePerform(exception, "defaultAction");
  }

  public void handleFrom(Object exception, ExceptionHandler handler)
      throws Throwable {
    while (handler != null) {
      if (handler.handles(exception)) {
        handler.handle(exception);
        return;
      }
      handler = handler.previous();
    }
    executeDefaultAction(exception);
  }

  private ExceptionHandler pvtAddHandler(Object protectedBlock,
      Object exceptionSelector, Object exBlock, Object marker) {
    current = new ExceptionHandler(protectedBlock, exceptionSelector,
        exBlock, current, marker);
    return current;
  }

  private void pvtHandle(Object exception, Object resumeMarker)
      throws Throwable {
    setResumeMarker(exception, resumeMarker);
    ExceptionHandler handler = initialHandler(exception);
    if (handler == null)
      handler = current;
    if (handler == null) {
      executeDefaultAction(exception);
      return;
    }
    setInitialHandler(exception, handler);
    current = handler.previous();
    handleFrom(exception, handler);
    current = handler;
  }

  private void pvtHandlePass(Object exception) throws Throwable {
    handleFrom(exception, currentHandler(exception).previous());
  }

  private void pvtHandleResume(Object exception, Object returnValue) {
    Object resumeMarker = resumeMarker(exception);
    throw new NonLocalReturn(returnValue, resumeMarker);
  }

  private Object pvtHandleRetry(Object exception) throws Throwable {
    ExceptionHandler handler = currentHandler(exception);
    return pvtHandleRetryUsing_(exception, handler.protectedBlock);
  }

  private Object pvtHandleRetryUsing_(Object exception, Object value)
      throws Throwable {
    Object result = MethodTools.perform(value, "value");
    return pvtHandleReturn(exception, result);
  }

  private Object pvtHandleReturn(Object exception, Object value) {
    throw new NonLocalReturn(value, currentHandler(exception).marker());
  }

  private boolean pvtIsNested(Object exception) throws Throwable {
    ExceptionHandler handler = initialHandler(exception);
    if (handler == null)
      return false;
    while (handler != null) {
      if (handler.handles(exception)) {
        return true;
      }
      handler = handler.previous();
    }
    return false;
  }

  private void pvtRemoveHandler(ExceptionHandler handler) {
    if (current == handler) {
      current = handler.previous();
    }
  }

  private Object resumeMarker(Object exception) {
    return MethodTools.safePerform(exception, "resumeMarker");
  }

  private void setResumeMarker(Object exception, Object resumeMarker) {
    MethodTools.safePerform(exception, "resumeMarker:", resumeMarker);
  }

}
TOP

Related Classes of st.gravel.support.jvm.runtime.ExceptionStack$ExceptionHandler

TOP
Copyright © 2018 www.massapi.com. All rights reserved.
All source code are property of their respective owners. Java is a trademark of Sun Microsystems, Inc and owned by ORACLE Inc. Contact coftware#gmail.com.