View Javadoc
1   /*
2    * Copyright (c) MuleSoft, Inc.  All rights reserved.  http://www.mulesoft.com
3    * The software in this package is published under the terms of the CPAL v1.0
4    * license, a copy of which has been included with this distribution in the
5    * LICENSE.txt file.
6    */
7   package org.mule.tck.testmodels.mule;
8   
9   import org.mule.api.MuleEvent;
10  import org.mule.api.exception.SystemExceptionHandler;
11  import org.mule.exception.AbstractMessagingExceptionStrategy;
12  
13  import java.util.ArrayList;
14  import java.util.LinkedList;
15  import java.util.List;
16  
17  import org.apache.commons.logging.Log;
18  import org.apache.commons.logging.LogFactory;
19  
20  /**
21   * <code>TestExceptionStrategy</code> is used by the Mule test cases as a direct
22   * replacement of the {@link org.mule.exception.AbstractMessagingExceptionStrategy}.
23   * This is used to test that overriding the default Exception strategy works.
24   */
25  public class TestExceptionStrategy extends AbstractMessagingExceptionStrategy
26      implements SystemExceptionHandler
27  {
28      /**
29       * logger used by this class
30       */
31      protected final Log logger = LogFactory.getLog(getClass());
32  
33      /**
34       * This is the lock that protect both the storage of {@link #callback} and
35       * modifications of {@link #unhandled}.
36       */
37      private Object callbackLock = new Object();
38  
39      // @GuardedBy("callbackLock")
40      private ExceptionCallback callback;
41      // @GuardedBy("callbackLock")
42      private List<Exception> unhandled = new LinkedList<Exception>();
43  
44      private volatile String testProperty;
45  
46      public String getTestProperty()
47      {
48          return testProperty;
49      }
50  
51      public void setTestProperty(String testProperty)
52      {
53          this.testProperty = testProperty;
54      }
55  
56      @Override
57      public MuleEvent handleException(Exception exception, MuleEvent event)
58      {
59          ExceptionCallback callback = null;
60          synchronized (callbackLock)
61          {
62              if (this.callback != null)
63              {
64                  callback = this.callback;
65              }
66              else
67              {
68                  unhandled.add(exception);
69              }
70          }
71          // It is important that the call to the callback is done outside
72          // synchronization since we don't control that code and
73          // we could have liveness problems.
74          logger.info("Handling exception: " + exception.getClass().getName());
75          if (callback != null)
76          {
77              logger.info("Exception caught on TestExceptionStrategy and was sent to callback.", exception);
78              callback.onException(exception);
79          }
80          else
81          {
82              logger.info("Exception caught on TestExceptionStrategy but there was no callback set.", exception);
83          }
84          return event;
85      }
86  
87      public void handleException(Exception exception)
88      {
89          handleException(exception, null);
90      }
91  
92      public interface ExceptionCallback
93      {
94          void onException(Throwable t);
95      }
96  
97      public void setExceptionCallback(ExceptionCallback exceptionCallback)
98      {
99          synchronized (callbackLock)
100         {
101             this.callback = exceptionCallback;
102         }
103         processUnhandled();
104     }
105 
106     protected void processUnhandled()
107     {
108         List<Exception> unhandledCopies = null;
109         ExceptionCallback callback = null;
110         synchronized (callbackLock)
111         {
112             if (this.callback != null)
113             {
114                 callback = this.callback;
115                 unhandledCopies = new ArrayList<Exception>(unhandled);
116                 unhandled.clear();
117             }
118         }
119         // It is important that the call to the callback is done outside
120         // synchronization since we don't control that code and
121         // we could have liveness problems.
122         if (callback != null && unhandledCopies != null)
123         {
124             for (Exception exception : unhandledCopies)
125             {
126                 logger.info("Handling exception after setting the callback.", exception);
127                 callback.onException(exception);
128             }
129         }
130     }
131 }