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 }