View Javadoc

1   package com.atlassian.plugin.util;
2   
3   import static java.lang.Thread.sleep;
4   
5   import java.util.concurrent.TimeUnit;
6   
7   import org.slf4j.Logger;
8   import org.slf4j.LoggerFactory;
9   
10  import com.atlassian.util.concurrent.Timeout;
11  
12  /**
13   * Utility methods for synchronising on asynchronous processes
14   */
15  public class WaitUntil
16  {
17      private static final Logger log = LoggerFactory.getLogger(WaitUntil.class);
18  
19      /**
20       * Default {@link #STARTUP_WAIT}
21       */
22      private static final int DEFAULT_STARTUP_WAIT = 60;
23  
24      /**
25       * Number of seconds to wait before a plugin starts up. Configurable through
26       * system property "com.atlassian.plugin.startup.wait". Defaults to
27       * {@link #DEFAULT_STARTUP_WAIT}
28       */
29      private static final int STARTUP_WAIT = Integer.getInteger("com.atlassian.plugin.startup.wait", DEFAULT_STARTUP_WAIT);
30  
31      private WaitUntil()
32      {}
33  
34      /**
35       * Invokes the wait condition, trying every second for 10 seconds
36       * 
37       * @param waitCondition The condition that determines when to stop waiting
38       * @return True if the condition returned true
39       */
40      public static boolean invoke(final WaitCondition waitCondition)
41      {
42          return invoke(waitCondition, STARTUP_WAIT);
43      }
44  
45      /**
46       * Invokes the wait condition, trying every second for the configured
47       * seconds
48       * 
49       * @param waitCondition The condition that determines when to stop waiting
50       * @param tries The number of tries to attempt
51       * @return True if the condition returned true
52       */
53      public static boolean invoke(final WaitCondition waitCondition, final int tries)
54      {
55          final int secondMillis = 1000;
56          return invoke(waitCondition, tries * secondMillis, TimeUnit.MILLISECONDS, secondMillis);
57      }
58  
59      /**
60       * Invokes the wait condition, trying every second for the configured
61       * seconds
62       * 
63       * @param waitCondition The condition that determines when to stop waiting
64       * @param time the amount of time to wait
65       * @param unit the time unit time is specified in
66       * @param retryInterval how often to re-check the condition (specified in
67       *            the supplied TimeUnit)
68       * @return True if the condition returned true
69       */
70      public static boolean invoke(final WaitCondition waitCondition, final int time, final TimeUnit unit, final int retryInterval)
71      {
72          final Timeout timeout = Timeout.getMillisTimeout(time, unit);
73          boolean successful = false;
74          while (!timeout.isExpired())
75          {
76              if (waitCondition.isFinished())
77              {
78                  successful = true;
79                  break;
80              }
81  
82              if (log.isInfoEnabled())
83              {
84                  log.info(waitCondition.getWaitMessage() + ", " + TimeUnit.SECONDS.convert(timeout.getTime(), timeout.getUnit()) + " seconds remaining");
85              }
86              try
87              {
88                  sleep(unit.toMillis(retryInterval));
89              }
90              catch (final InterruptedException e)
91              {
92                  break;
93              }
94          }
95          return successful;
96      }
97  
98      /**
99       * The condition to determine when to stop waiting
100      */
101     public interface WaitCondition
102     {
103         /**
104          * If the condition has been finished
105          * 
106          * @return True if finished and should stop waiting
107          */
108         boolean isFinished();
109 
110         /**
111          * Gets the wait message to log for each try
112          * 
113          * @return The string to print describing why the code is waiting
114          */
115         String getWaitMessage();
116     }
117 }