Package com.blazebit.cdi.exception

Source Code of com.blazebit.cdi.exception.ExceptionWrappingInterceptor

/*
* Copyright 2011 Blazebit
*/
package com.blazebit.cdi.exception;

import com.blazebit.annotation.AnnotationUtils;
import com.blazebit.cdi.exception.annotation.ExceptionWrap;
import com.blazebit.cdi.exception.annotation.ExceptionWrapping;
import com.blazebit.exception.ExceptionUtils;
import java.io.Serializable;
import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;
import java.util.logging.Level;
import java.util.logging.Logger;
import javax.interceptor.AroundInvoke;
import javax.interceptor.Interceptor;
import javax.interceptor.InvocationContext;

/**
* This interceptor simply wraps exceptions which are declared as sources in the
* ExceptionWrap annotations into the exception type "wrapper" which is also
* declared in the ExceptionWrap annotation. It ignores exceptions which are
* declared in the throws clause of the method for which this interceptor runs.
*
* <pre>
* <code>
* public class Bean implements Serializable {
*
*   @ExceptionWrapping(value = {
*       @ExceptionWrap(source = RuntimeExceptionA.class, wrapper = MyExceptionA.class),
*       @ExceptionWrap(source = RuntimeExceptionB.class, wrapper = MyExceptionB.class),
*       @ExceptionWrap(wrapper = MyExceptionC.class) })
*   public void example() throws MyExceptionA, MyExceptionB, MyExceptionC {
*     // code
*   }
* }
* </code>
* </pre>
*
* RuntimeExceptionA will be wrapped into MyExceptionA RuntimeExceptionB will be
* wrapped into MyExceptionB Every other Exception, that is not instance of
* MyExceptionA, MyExceptionB or MyExceptionC, will be wrapped into MyExceptionC
*
* The order of ExceptionWrap annotations within the ExceptionWrapping
* annotation is important and should be declared from specific to general.
*
* If you would specify <code>@ExceptionWrap( wrapper=MyExceptionC.class)</code>
* as the first element of the ExceptionWrapping annotation, then every
* exception that is not declared in the throws clause will be wrapped into a
* MyExceptionC!
*
* @since 0.1.2
* @author Christian Beikov
* @see ExceptionWrapping
* @see ExceptionWrap
*
*/
@Interceptor
@ExceptionWrapping(value = {})
public class ExceptionWrappingInterceptor implements Serializable {

  private static final long serialVersionUID = 1L;

  @AroundInvoke
  public Object errorLogging(InvocationContext ic) throws Exception {
    /* Retrieve the logger for the intercepted class */
    Logger log = Logger.getLogger(ic.getTarget().getClass().getName());
    Method m = ic.getMethod();
    Object targetObject = ic.getTarget();
    Class<?> targetClass = targetObject == null ? m.getDeclaringClass()
        : targetObject.getClass();
    /*
     * Retrieve the exceptions declared in the throws clause of the
     * intercepted method
     */
    Class<?>[] declaredExceptions = m.getExceptionTypes();
    ExceptionWrapping wrappingAnnotation = AnnotationUtils.findAnnotation(
        m, targetClass, ExceptionWrapping.class);
    ExceptionWrap[] wraps = null;
    Object ret;
    boolean doWrapping = true;

    if (wrappingAnnotation == null) {
      throw new IllegalStateException(
          "The interceptor annotation can not be determined!");
    }

    wraps = wrappingAnnotation.value();

    /* Only try to do wrapping when exceptionWrap elements are available */
    doWrapping = wraps != null && wraps.length > 0;

    try {
      ret = ic.proceed();
    } catch (Throwable t) {
      /*
       * Check if the throwable is an instance of
       * InvocationTargetException and if so, unwrap the cause. OWB did
       * not unwrap exceptions that have been thrown in decorators in some
       * versions so we need to do this to be able to handle the right
       * exception
       */
      Throwable t1 = ExceptionUtils.unwrap(t,
          InvocationTargetException.class);

      if (doWrapping) {
        /*
         * Check if the exception that was thrown is declared in the
         * throws clause and if so, don't apply exception wrapping
         */
        for (Class<?> declaredException : declaredExceptions) {
          if (declaredException.isInstance(t1)) {
            /* Do this so no exception wrapper is applied */
            doWrapping = false;
            break;
          }
        }

        if (doWrapping) {
          /*
           * If a wrapping should be applied, iterate through
           * exception wraps and check if the thrown exception is an
           * instance of a declared source class.
           */
          for (ExceptionWrap wrap : wraps) {
            Class<? extends Throwable>[] sourceClasses = wrap
                .sources();
            Class<? extends Exception> wrapperClass = wrap
                .wrapper();
            Exception e = null;

            /*
             * Only do wrapping if the exception isn't already a
             * instance of the wrapper exceptionF
             */
            if (!wrapperClass.isInstance(t1)) {
              for (Class<? extends Throwable> source : sourceClasses) {
                /*
                 * When the thrown exception is instance of an
                 * exception wrap source class, create a new
                 * exception instance with the thrown exception
                 * as cause
                 */
                if (source.isInstance(t1)) {
                  try {
                    e = wrapperClass.getConstructor(
                        Throwable.class)
                        .newInstance(t1);
                  } catch (Throwable t2) {
                    /*
                     * Declared wrapper exception has no
                     * constructor with a throwable as param
                     */
                    Exception ex1 = null;

                    /*
                     * Cast to or wrap the throwable into a
                     * new exception because we may not
                     * throw Throwable instances within here
                     */
                    if (t2 instanceof Exception) {
                      ex1 = (Exception) t2;
                    } else {
                      ex1 = new Exception(t2);
                    }

                    log.log(Level.WARNING,
                        "The applied wrapper exception on the method "
                            + m.getName()
                            + " has no constructor for type Throwable!",
                        ex1);
                  }

                  if (e != null) {
                    throw e;
                  }
                }
              }
            }
          }
        }
      }

      /*
       * No exception wrapping was applied, so cast to or wrap the
       * throwable into a new exception and throw it
       */
      if (t1 instanceof Exception) {
        throw (Exception) t1;
      }

      throw new Exception(t1);
    }

    return ret;
  }
}
TOP

Related Classes of com.blazebit.cdi.exception.ExceptionWrappingInterceptor

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.