/* * JBoss, Home of Professional Open Source * Copyright 2011, Red Hat, Inc., and individual contributors * by the @authors tag. See the copyright.txt in the distribution for a * full listing of individual contributors. * * 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.jboss.solder.exception.control; /** * Payload for an exception to be handled. This object is not immutable as small pieces of the state may be set by the * handler. * * @param <T> Exception type this event represents */ @SuppressWarnings({"unchecked"}) public class CaughtException<T extends Throwable> { /** * Flow control enum. Used in the dispatcher to determine how to markHandled. */ protected enum ExceptionHandlingFlow { HANDLED, MARK_HANDLED, DROP_CAUSE, ABORT, RETHROW, THROW } private final ExceptionStack exceptionStack; private final T exception; private boolean unmute; private ExceptionHandlingFlow flow; private Throwable throwNewException; private final boolean breadthFirstTraversal; private final boolean depthFirstTraversal; private final boolean markedHandled; /** * Initial state constructor. * * @param exceptionStack Information about the current exception and cause chain. * @param breadthFirstTraversal flag indicating the direction of the cause chain traversal * @param handled flag indicating the exception has already been handled by a previous handler * @throws IllegalArgumentException if exceptionStack is null */ public CaughtException(final ExceptionStack exceptionStack, final boolean breadthFirstTraversal, final boolean handled) { if (exceptionStack == null) { throw new IllegalArgumentException("null is not valid for exceptionStack"); } this.exception = (T) exceptionStack.getCurrent(); this.exceptionStack = exceptionStack; this.breadthFirstTraversal = breadthFirstTraversal; this.depthFirstTraversal = !breadthFirstTraversal; this.markedHandled = handled; this.flow = ExceptionHandlingFlow.MARK_HANDLED; } public T getException() { return this.exception; } /** * Instructs the dispatcher to abort further processing of handlers. */ public void abort() { this.flow = ExceptionHandlingFlow.ABORT; } /** * Instructs the dispatcher to rethrow the event exception after handler processing. */ public void rethrow() { this.flow = ExceptionHandlingFlow.RETHROW; } /** * Instructs the dispatcher to terminate additional handler processing and mark the event as handled. */ public void handled() { this.flow = ExceptionHandlingFlow.HANDLED; } /** * Default instruction to dispatcher, continues handler processing. */ public void markHandled() { this.flow = ExceptionHandlingFlow.MARK_HANDLED; } /** * Similar to {@link CaughtException#markHandled()}, but instructs the dispatcher to markHandled to the next element * in the cause chain without processing additional handlers for this cause chain element. */ public void dropCause() { this.flow = ExceptionHandlingFlow.DROP_CAUSE; } /** * Instructs the dispatcher to allow this handler to be invoked again. */ public void unmute() { this.unmute = true; } public boolean isBreadthFirstTraversal() { return breadthFirstTraversal; } public boolean isDepthFirstTraversal() { return depthFirstTraversal; } protected boolean isUnmute() { return this.unmute; } public ExceptionStack getExceptionStack() { return this.exceptionStack; } protected ExceptionHandlingFlow getFlow() { return this.flow; } public boolean isMarkedHandled() { return this.markedHandled; } /** * Rethrow the exception, but use the given exception instead of the original. * * @param t Exception to be thrown in place of the original. */ public void rethrow(Throwable t) { this.throwNewException = t; this.flow = ExceptionHandlingFlow.THROW; } protected Throwable getThrowNewException() { return throwNewException; } }