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