View Javadoc

1   /**
2    * 2010, Digitalis Informatica. All rights reserved. Distribuicao e Gestao de Informatica, Lda. Estrada de Paco de Arcos
3    * num.9 - Piso -1 2780-666 Paco de Arcos Telefone: (351) 21 4408990 Fax: (351) 21 4408999 http://www.digitalis.pt
4    */
5   
6   package pt.digitalis.dif.controller;
7   
8   import java.util.HashMap;
9   import java.util.Map;
10  
11  import javax.servlet.ServletException;
12  
13  import pt.digitalis.dif.controller.interfaces.IDIFContext;
14  import pt.digitalis.dif.controller.interfaces.IDispatcherErrorHandler;
15  import pt.digitalis.dif.controller.objects.ExceptionHandlerData;
16  
17  /**
18   * Exception Handler stages registry class. Allows registering of all stages that declare to handle specific exceptions.
19   * 
20   * @author Pedro Viegas <a href="mailto:pviegas@digitalis.pt">pviegas@digitalis.pt</a><br/>
21   * @created 2010/05/04
22   */
23  public class ExceptionHandlers {
24  
25      /** Exception Handler Stages map */
26      static private Map<String, ExceptionHandlerData> handlers = new HashMap<String, ExceptionHandlerData>();
27  
28      /** Attribute ID to save the raised exception caught by the exception handler */
29      static public final String RAISED_EXCEPTION_ATTRIBUTE = "RaisedExceptionCaghtInHandler";
30  
31      /**
32       * Registers a new Exception handler
33       * 
34       * @param exceptionClass
35       *            the exception class to register
36       * @param stageID
37       *            the ID for the handler stage
38       */
39      static public void addExceptionHandler(Class<Throwable> exceptionClass, String stageID)
40      {
41          handlers.put(exceptionClass.getCanonicalName(), new ExceptionHandlerData(exceptionClass, stageID));
42      }
43  
44      /**
45       * Registers a new Exception handler
46       * 
47       * @param exceptionClassName
48       *            the exception class name to register
49       * @param stageID
50       *            the ID for the handler stage
51       */
52      @SuppressWarnings("unchecked")
53      static public void addExceptionHandler(String exceptionClassName, String stageID)
54      {
55          try
56          {
57              Class<Throwable> clazz = (Class<Throwable>) Class.forName(exceptionClassName);
58              addExceptionHandler(clazz, stageID);
59          }
60          catch (ClassNotFoundException e)
61          {
62              e.printStackTrace();
63          }
64      }
65  
66      /**
67       * Gets the ID of the handler stage for the given exception
68       * 
69       * @param exceptionClass
70       *            the class of the exception
71       * @return the handler stage ID
72       */
73      static public String getExceptionHandler(Class<? extends Throwable> exceptionClass)
74      {
75          ExceptionHandlerData handler = handlers.get(exceptionClass.getCanonicalName());
76  
77          // No direct hit. Search for inheritance match
78          if (handler == null)
79          {
80              for (ExceptionHandlerData currentHandler: handlers.values())
81                  if (currentHandler.getExceptionClass().isAssignableFrom(exceptionClass))
82                  {
83                      handler = currentHandler;
84                      break;
85                  }
86          }
87  
88          if (handler == null)
89              return null;
90          else
91              return handler.getHandlerStageID();
92      }
93  
94      /**
95       * Gets the ID of the handler stage for the given exception
96       * 
97       * @param exceptionClassName
98       *            the class name of the exception
99       * @return the handler stage ID
100      */
101     static public String getExceptionHandler(String exceptionClassName)
102     {
103         ExceptionHandlerData handler = handlers.get(exceptionClassName);
104 
105         // No direct hit. Search for inheritance match. Must have a class object
106         if (handler == null)
107         {
108             try
109             {
110                 @SuppressWarnings("unchecked")
111                 Class<Throwable> clazz = (Class<Throwable>) Class.forName(exceptionClassName);
112 
113                 return getExceptionHandler(clazz);
114             }
115             catch (ClassNotFoundException e)
116             {
117                 e.printStackTrace();
118                 return null;
119             }
120         }
121         else
122             return handler.getHandlerStageID();
123     }
124 
125     /**
126      * Gets the ID of the handler stage for the given exception
127      * 
128      * @param exception
129      *            the exception
130      * @return the handler stage ID
131      */
132     static public String getExceptionHandler(Throwable exception)
133     {
134         String result = null;
135         result = getExceptionHandler(exception.getClass());
136 
137         while (result == null && exception != null)
138         {
139             if (exception.getCause() instanceof Exception)
140                 exception = exception.getCause();
141             else if (exception instanceof ServletException)
142                 exception = ((ServletException) exception).getRootCause();
143             else
144                 break;
145 
146             if (exception != null)
147                 result = getExceptionHandler(exception.getClass());
148         }
149 
150         return result;
151     }
152 
153     /**
154      * Handles redirection actions for a given exsception. Will determine the correct handler, add the necessary
155      * information to the request and redirect to the handler stage.
156      * 
157      * @param context
158      *            the current running stage context
159      * @param exception
160      *            the exception raised to handle
161      */
162     static public void handleException(IDIFContext context, Exception exception)
163     {
164         String stageToRedirectTo = getExceptionHandler(exception);
165 
166         if (stageToRedirectTo != null)
167         {
168             context.addStageResult(IDispatcherErrorHandler.ORIGINAL_REQUEST, context.getRequest());
169             context.addStageResult(IDispatcherErrorHandler.EXCEPTION, exception);
170             context.getRequest().addAttribute(RAISED_EXCEPTION_ATTRIBUTE, exception);
171             context.redirectTo(stageToRedirectTo, true);
172         }
173     }
174 
175     /**
176      * Inspector for a given exception. Will determine of the given exception has a handler defined
177      * 
178      * @param exceptionClass
179      *            the exception class
180      * @return T if the exception has a registered handler
181      */
182     static public boolean hasHandler(Class<? extends Throwable> exceptionClass)
183     {
184         return (getExceptionHandler(exceptionClass) != null);
185     }
186 
187     /**
188      * Inspector for a given exception. Will determine of the given exception has a handler defined
189      * 
190      * @param exception
191      *            the exception
192      * @return T if the exception has a registered handler
193      */
194     static public boolean hasHandler(Exception exception)
195     {
196         return (getExceptionHandler(exception) != null);
197     }
198 
199     /**
200      * Inspector for a given exception. Will determine of the given exception has a handler defined
201      * 
202      * @param exceptionClassName
203      *            the exception class name
204      * @return T if the exception has a registered handler
205      */
206     static public boolean hasHandler(String exceptionClassName)
207     {
208         return (getExceptionHandler(exceptionClassName) != null);
209     }
210 
211     /**
212      * Removes a registered exception handler
213      * 
214      * @param key
215      */
216     public static void removeExceptionHandler(String key)
217     {
218         handlers.remove(key);
219     }
220 }