View Javadoc

1   /*
2    * $Id: SimpleRetryPolicy.java 22088 2011-06-03 10:07:47Z dirk.olmes $
3    * --------------------------------------------------------------------------------------
4    * Copyright (c) MuleSoft, Inc.  All rights reserved.  http://www.mulesoft.com
5    *
6    * The software in this package is published under the terms of the CPAL v1.0
7    * license, a copy of which has been included with this distribution in the
8    * LICENSE.txt file.
9    */
10  
11  package org.mule.retry.policies;
12  
13  import java.util.concurrent.atomic.AtomicInteger;
14  
15  import org.apache.commons.logging.Log;
16  import org.apache.commons.logging.LogFactory;
17  import org.mule.api.retry.RetryPolicy;
18  import org.mule.retry.PolicyStatus;
19  
20  /**
21   * Allows to configure how many times a retry should be attempted and how long to wait between retries.
22   */
23  public class SimpleRetryPolicy implements RetryPolicy
24  {
25      protected static final Log logger = LogFactory.getLog(SimpleRetryPolicy.class);
26  
27      protected RetryCounter retryCounter;
28  
29      private volatile int count = SimpleRetryPolicyTemplate.DEFAULT_RETRY_COUNT;
30      private volatile long frequency = SimpleRetryPolicyTemplate.DEFAULT_FREQUENCY;
31  
32      public SimpleRetryPolicy(long frequency, int retryCount)
33      {
34          this.frequency = frequency;
35          this.count = retryCount;
36          retryCounter = new RetryCounter();
37      }
38  
39      public PolicyStatus applyPolicy(Throwable cause)
40      {
41  
42          if (isExhausted() || !isApplicableTo(cause))
43          {
44              return PolicyStatus.policyExhausted(cause);
45          }
46          else
47          {
48              if (logger.isInfoEnabled())
49              {
50                  logger.info("Waiting for "
51                              + frequency
52                              + "ms before reconnecting. Failed attempt "
53                              + (retryCounter.current().get() + 1)
54                              + " of "
55                              + (count != SimpleRetryPolicyTemplate.RETRY_COUNT_FOREVER
56                                                                                       ? String.valueOf(count)
57                                                                                       : "unlimited"));
58              }
59  
60              try
61              {
62                  retryCounter.current().getAndIncrement();
63                  Thread.sleep(frequency);
64                  return PolicyStatus.policyOk();
65              }
66              catch (InterruptedException e)
67              {
68                  // If we get an interrupt exception, some one is telling us to stop
69                  return PolicyStatus.policyExhausted(e);
70              }
71          }
72      }
73  
74      /**
75       * Indicates if the policy is applicable for the cause that caused the policy invocation. Subclasses can override
76       * this method in order to filter the type of exceptions that does not deserve a retry.
77       * 
78       * @return true if the policy is applicable, false otherwise.
79       */
80      protected boolean isApplicableTo(Throwable cause)
81      {
82          return true;
83      }
84  
85      /**
86       * Determines if the policy is exhausted or not comparing the original configuration against the current state.
87       */
88      protected boolean isExhausted()
89      {
90          return count != SimpleRetryPolicyTemplate.RETRY_COUNT_FOREVER
91                 && retryCounter.current().get() >= count;
92      }
93  
94      protected static class RetryCounter extends ThreadLocal<AtomicInteger>
95      {
96          public int countRetry()
97          {
98              return get().incrementAndGet();
99          }
100 
101         public void reset()
102         {
103             get().set(0);
104         }
105 
106         public AtomicInteger current()
107         {
108             return get();
109         }
110 
111         @Override
112         protected AtomicInteger initialValue()
113         {
114             return new AtomicInteger(0);
115         }
116     }
117 }