| Classes in this File | Line Coverage | Branch Coverage | Complexity | ||||
| ExceptionMappingAdvice | 
 | 
 | 2.142857142857143;2.143 | 
| 1 |  /** | |
| 2 |   * Copyright 2010 The Kuali Foundation Licensed under the | |
| 3 |   * Educational Community License, Version 2.0 (the "License"); you may | |
| 4 |   * not use this file except in compliance with the License. You may | |
| 5 |   * obtain a copy of the License at | |
| 6 |   * | |
| 7 |   * http://www.osedu.org/licenses/ECL-2.0 | |
| 8 |   * | |
| 9 |   * Unless required by applicable law or agreed to in writing, | |
| 10 |   * software distributed under the License is distributed on an "AS IS" | |
| 11 |   * BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express | |
| 12 |   * or implied. See the License for the specific language governing | |
| 13 |   * permissions and limitations under the License. | |
| 14 |   */ | |
| 15 | ||
| 16 |  package org.kuali.student.common.util; | |
| 17 | ||
| 18 |  import java.io.PrintWriter; | |
| 19 |  import java.io.StringWriter; | |
| 20 |  import java.lang.reflect.Constructor; | |
| 21 |  import java.util.Map; | |
| 22 | ||
| 23 |  import org.apache.log4j.Logger; | |
| 24 |  import org.springframework.aop.ThrowsAdvice; | |
| 25 |  import org.springframework.core.Ordered; | |
| 26 | ||
| 27 |  /** | |
| 28 |   * @author Daniel Epstein | |
| 29 |   *         <p> | |
| 30 |   *         Use this Advice to map one exception to another for use when other | |
| 31 |   *         advice eats your runtime exceptions outside of your code. This happens in | |
| 32 |   *         Transactions when commit is not called until outside of your DAO | |
| 33 |   *         layer. | |
| 34 |   *         </p> | |
| 35 |   *  | |
| 36 |   * <p> | |
| 37 |   * Set the property "exceptionMapping" as a map that maps an exception class to | |
| 38 |   * your own exception class | |
| 39 |   * </p> | |
| 40 |   *  | |
| 41 |   * <p> | |
| 42 |   * Remember that aspect order is important and that this bean will always be | |
| 43 |   * order "500" | |
| 44 |   * </p> | |
| 45 |   *  | |
| 46 |   * Example: | |
| 47 |   *  | |
| 48 |   * <pre> | |
| 49 |   * <tx:annotation-driven transaction-manager="JtaTxManager" order="1000"/> | |
| 50 |   * lt;bean id="mapExceptionAdvisor" | |
| 51 |   * class="org.myfoo.ExceptionMappingAdvice"> | |
| 52 |   * <property name="exceptionMapping"> | |
| 53 |   *         <map> | |
| 54 |   *                 <entry key="javax.persistence.EntityExistsException" | |
| 55 |   *                         value="org.myfoo.exceptions.AlreadyExistsException" /> | |
| 56 |   *         </map> | |
| 57 |   * </property> | |
| 58 |   * lt;/bean> | |
| 59 |   * lt;aop:config> | |
| 60 |   * <aop:aspect id="dataAccessToBusinessException" | |
| 61 |   *         ref="mapExceptionAdvisor"> | |
| 62 |   *         <aop:after-throwing | |
| 63 |   *                 pointcut="execution(* org.myfoo.service.*.*(..))" | |
| 64 |   *                 method="afterThrowing" throwing="ex" /> | |
| 65 |   * </aop:aspect> | |
| 66 |   * lt;/aop:config> | |
| 67 |   * </pre> | |
| 68 |   */ | |
| 69 | 0 |  public class ExceptionMappingAdvice implements ThrowsAdvice, Ordered { | 
| 70 | 0 |          private int order = 500; | 
| 71 | private static final long serialVersionUID = 1L; | |
| 72 | private Map<Class<? extends Exception>, Class<? extends Exception>> exceptionMapping; | |
| 73 | private Class<? extends Exception> defaultException; | |
| 74 | 0 |          final Logger logger = Logger.getLogger(ExceptionMappingAdvice.class); | 
| 75 | ||
| 76 |          /** | |
| 77 |           * This method will use the real exception thrown and look up the exception | |
| 78 |           * that should be thrown | |
| 79 |           *  | |
| 80 |           * @param ex | |
| 81 |           * @throws Exception | |
| 82 |           */ | |
| 83 | public void afterThrowing(Exception ex) throws Exception { | |
| 84 | 0 |                  Class<? extends Exception> mappedExceptionClass = exceptionMapping | 
| 85 | .get(ex.getClass()); | |
| 86 | ||
| 87 | 0 |                  if (mappedExceptionClass != null) { | 
| 88 | 0 |                  logger.debug("Mapping exception "+ex.getClass()+" to "+mappedExceptionClass); | 
| 89 | 0 |                  Constructor<? extends Exception> c = mappedExceptionClass | 
| 90 |                                          .getConstructor(String.class); | |
| 91 | 0 |                          Exception mappedException = c.newInstance(ex.getMessage()); | 
| 92 | 0 |                          throw mappedException; | 
| 93 | } | |
| 94 | ||
| 95 |                  //Throw a default exception if this is a runtime exception | |
| 96 | 0 |                  if(ex instanceof RuntimeException){ | 
| 97 | 0 |                          logger.trace("No mapping available, throwing default exception "+defaultException); | 
| 98 | 0 |                          if (defaultException != null) { | 
| 99 |                                  //Log the error | |
| 100 | 0 |                                  StringWriter traceWriter = new StringWriter(); | 
| 101 | 0 |                                  PrintWriter printWriter = new PrintWriter(traceWriter, false); | 
| 102 | 0 |                                  logger.error(printWriter, ex); | 
| 103 | 0 |                                  printWriter.close(); | 
| 104 | 0 |                                  String faultMessage = traceWriter.getBuffer().toString(); | 
| 105 | 0 |                                  logger.error(faultMessage); | 
| 106 |                                  //Throw the default exception | |
| 107 |                                  try{ | |
| 108 | 0 |                                          Constructor<? extends Exception> c = defaultException | 
| 109 | .getConstructor(String.class, Throwable.class); | |
| 110 | 0 |                                          throw c.newInstance(ex.getMessage(), ex); | 
| 111 | 0 |                                  }catch(NoSuchMethodException e){ | 
| 112 | 0 |                                          Constructor<? extends Exception> c = defaultException | 
| 113 |                                                          .getConstructor(String.class); | |
| 114 | 0 |                                          throw c.newInstance(ex.getMessage()); | 
| 115 | } | |
| 116 | } | |
| 117 |                          //Check if no default was defined | |
| 118 | 0 |                          logger.debug("No mapping or default exception available. Exception "+ex.getClass()); | 
| 119 | 0 |                          throw new RuntimeException("Could Not Map Exception: " + ex.toString()); | 
| 120 | } | |
| 121 | 0 |          } | 
| 122 | ||
| 123 | @Override | |
| 124 | public int getOrder() { | |
| 125 | 0 |                  return order; | 
| 126 | } | |
| 127 | ||
| 128 |          /** | |
| 129 |           * @param order | |
| 130 |           *            the order to set | |
| 131 |           */ | |
| 132 | public void setOrder(int order) { | |
| 133 | 0 |                  this.order = order; | 
| 134 | 0 |          } | 
| 135 | ||
| 136 |          /** | |
| 137 |           * @return the exceptionMapping | |
| 138 |           */ | |
| 139 | public Map<Class<? extends Exception>, Class<? extends Exception>> getExceptionMapping() { | |
| 140 | 0 |                  return exceptionMapping; | 
| 141 | } | |
| 142 | ||
| 143 |          /** | |
| 144 |           * @param exceptionMapping | |
| 145 |           *            the exceptionMapping to set | |
| 146 |           */ | |
| 147 | public void setExceptionMapping( | |
| 148 | Map<Class<? extends Exception>, Class<? extends Exception>> exceptionMapping) { | |
| 149 | 0 |                  this.exceptionMapping = exceptionMapping; | 
| 150 | 0 |          } | 
| 151 | ||
| 152 |          /** | |
| 153 |           * @return the defaultException | |
| 154 |           */ | |
| 155 | public Class<? extends Exception> getDefaultException() { | |
| 156 | 0 |                  return defaultException; | 
| 157 | } | |
| 158 | ||
| 159 |          /** | |
| 160 |           * @param defaultException | |
| 161 |           *            the defaultException to set | |
| 162 |           */ | |
| 163 | public void setDefaultException(Class<? extends Exception> defaultException) { | |
| 164 | 0 |                  this.defaultException = defaultException; | 
| 165 | 0 |          } | 
| 166 | ||
| 167 | } |