1/*******************************************************************************
2 * Copyright (c) 2011 Google, Inc.
3 * All rights reserved. This program and the accompanying materials
4 * are made available under the terms of the Eclipse Public License v1.0
5 * which accompanies this distribution, and is available at
6 * http://www.eclipse.org/legal/epl-v10.html
7 *
8 * Contributors:
9 *    Google, Inc. - initial API and implementation
10 *******************************************************************************/
11package org.eclipse.wb.internal.core.utils.execution;
12
13import org.eclipse.swt.widgets.Display;
14import org.eclipse.wb.internal.core.DesignerPlugin;
15import org.eclipse.wb.internal.core.utils.reflect.ReflectionUtils;
16
17import java.beans.Beans;
18
19/**
20 * Utilities for executing actions, such as {@link RunnableEx}.
21 *
22 * @author scheglov_ke
23 * @coverage core.util
24 */
25public class ExecutionUtils {
26  ////////////////////////////////////////////////////////////////////////////
27  //
28  // Constructor
29  //
30  ////////////////////////////////////////////////////////////////////////////
31  private ExecutionUtils() {
32  }
33
34  ////////////////////////////////////////////////////////////////////////////
35  //
36  // Sleep
37  //
38  ////////////////////////////////////////////////////////////////////////////
39  /**
40   * Sleeps given number of milliseconds, ignoring exceptions.
41   */
42  public static void sleep(final int millis) {
43    runIgnore(new RunnableEx() {
44      @Override
45    public void run() throws Exception {
46        Thread.sleep(millis);
47      }
48    });
49  }
50
51  /**
52   * Waits given number of milliseconds and runs events loop every 1 millisecond. At least one
53   * events loop will be executed. If current thread is not UI thread, then this method works just
54   * as {@link #sleep(int)}.
55   */
56  public static void waitEventLoop(int millis) {
57    Display display = Display.getCurrent();
58    if (display != null) {
59      long nanos = millis * 1000000L;
60      long start = System.nanoTime();
61      do {
62        sleep(0);
63        while (display.readAndDispatch()) {
64          // do nothing
65        }
66      } while (System.nanoTime() - start < nanos);
67    } else {
68      sleep(millis);
69    }
70  }
71
72  ////////////////////////////////////////////////////////////////////////////
73  //
74  // void
75  //
76  ////////////////////////////////////////////////////////////////////////////
77  /**
78   * Runs given {@link RunnableEx} and ignores exceptions.
79   *
80   * @return <code>true</code> if execution was finished without exception.
81   */
82  public static boolean runIgnore(RunnableEx runnable) {
83    try {
84      runnable.run();
85      return true;
86    } catch (Throwable e) {
87      return false;
88    }
89  }
90
91  /**
92   * Runs given {@link RunnableEx} and logs exceptions using {@link DesignerPlugin#log(Throwable)}.
93   *
94   * @return <code>true</code> if execution was finished without exception.
95   */
96  public static boolean runLog(RunnableEx runnable) {
97    try {
98      runnable.run();
99      return true;
100    } catch (Throwable e) {
101      DesignerPlugin.log(e);
102      return false;
103    }
104  }
105
106  /**
107   * Runs given {@link RunnableEx} and re-throws exceptions using {@link RuntimeException}.
108   */
109  public static void runRethrow(RunnableEx runnable) {
110    try {
111      runnable.run();
112    } catch (Throwable e) {
113      throw ReflectionUtils.propagate(e);
114    }
115  }
116
117  /**
118   * Runs given {@link RunnableEx} and re-throws exceptions using {@link RuntimeException}.
119   */
120  public static void runRethrow(RunnableEx runnable, String format, Object... args) {
121    try {
122      runnable.run();
123    } catch (Throwable e) {
124      String message = String.format(format, args);
125      throw new RuntimeException(message, e);
126    }
127  }
128
129  /**
130   * Ensures that {@link Beans#isDesignTime()} returns <code>true</code> and runs given
131   * {@link RunnableEx}.
132   */
133  public static void runDesignTime(RunnableEx runnable) throws Exception {
134    boolean old_designTime = Beans.isDesignTime();
135    try {
136      Beans.setDesignTime(true);
137      runnable.run();
138    } finally {
139      Beans.setDesignTime(old_designTime);
140    }
141  }
142
143  /**
144   * Ensures that {@link Beans#isDesignTime()} returns <code>true</code> and runs given
145   * {@link RunnableEx}.
146   */
147  public static <T> T runDesignTime(RunnableObjectEx<T> runnable) throws Exception {
148    boolean old_designTime = Beans.isDesignTime();
149    try {
150      Beans.setDesignTime(true);
151      return runnable.runObject();
152    } finally {
153      Beans.setDesignTime(old_designTime);
154    }
155  }
156
157  ////////////////////////////////////////////////////////////////////////////
158  //
159  // UI
160  //
161  ////////////////////////////////////////////////////////////////////////////
162  /**
163   * Runs given {@link RunnableEx} inside of UI thread, using {@link Display#syncExec(Runnable)}.
164   *
165   * @return <code>true</code> if {@link RunnableEx} was executed without any {@link Exception}.
166   */
167  public static boolean runLogUI(final RunnableEx runnable) {
168    final boolean[] success = new boolean[1];
169    Display.getDefault().syncExec(new Runnable() {
170      @Override
171    public void run() {
172        success[0] = ExecutionUtils.runLog(runnable);
173      }
174    });
175    return success[0];
176  }
177
178  /**
179   * Runs given {@link RunnableEx} inside of UI thread, using {@link Display#syncExec(Runnable)}.
180   */
181  public static void runRethrowUI(final RunnableEx runnable) {
182    Display.getDefault().syncExec(new Runnable() {
183      @Override
184    public void run() {
185        ExecutionUtils.runRethrow(runnable);
186      }
187    });
188  }
189
190  /**
191   * Runs given {@link RunnableEx} within UI thread using {@link Display#asyncExec(Runnable)}. Logs
192   * a {@link Throwable} which may occur.
193   */
194  public static void runAsync(final RunnableEx runnable) {
195    Display.getDefault().asyncExec(new Runnable() {
196      @Override
197    public void run() {
198        ExecutionUtils.runLog(runnable);
199      }
200    });
201  }
202
203  /**
204   * Runs given {@link RunnableEx} inside of UI thread, using {@link Display#syncExec(Runnable)}.
205   */
206  @SuppressWarnings("unchecked")
207  public static <T> T runObjectUI(final RunnableObjectEx<T> runnable) {
208    final Object[] result = new Object[1];
209    runRethrowUI(new RunnableEx() {
210      @Override
211    public void run() throws Exception {
212        result[0] = runObject(runnable);
213      }
214    });
215    return (T) result[0];
216  }
217
218  /**
219   * Runs given {@link RunnableEx} as {@link #runLog(RunnableEx)}, but using
220   * {@link Display#asyncExec(Runnable)}.
221   */
222  public static void runLogLater(final RunnableEx runnable) {
223    Display.getDefault().asyncExec(new Runnable() {
224      @Override
225    public void run() {
226        ExecutionUtils.runLog(runnable);
227      }
228    });
229  }
230
231  ////////////////////////////////////////////////////////////////////////////
232  //
233  // Object
234  //
235  ////////////////////////////////////////////////////////////////////////////
236  /**
237   * Runs given {@link RunnableEx} and re-throws exceptions using {@link RuntimeException}.
238   *
239   * @return the {@link Object} returned by {@link RunnableEx#run()}.
240   */
241  public static <T> T runObject(RunnableObjectEx<T> runnable) {
242    try {
243      return runnable.runObject();
244    } catch (Throwable e) {
245      throw ReflectionUtils.propagate(e);
246    }
247  }
248
249  /**
250   * Runs given {@link RunnableEx} and re-throws exceptions using {@link RuntimeException}.
251   *
252   * @return the {@link Object} returned by {@link RunnableEx#run()}.
253   */
254  public static <T> T runObject(RunnableObjectEx<T> runnable, String format, Object... args) {
255    try {
256      return runnable.runObject();
257    } catch (Throwable e) {
258      String message = String.format(format, args);
259      throw new Error(message, e);
260    }
261  }
262
263  /**
264   * Runs given {@link RunnableEx} and ignores exceptions.
265   *
266   * @return the {@link Object} returned by {@link RunnableEx#run()} or <code>defaultValue</code> if
267   *         exception happened.
268   */
269  public static <T> T runObjectIgnore(RunnableObjectEx<T> runnable, T defaultValue) {
270    try {
271      return runnable.runObject();
272    } catch (Throwable e) {
273      return defaultValue;
274    }
275  }
276
277  /**
278   * Runs given {@link RunnableEx} and logs exceptions using {@link DesignerPlugin#log(Throwable)}.
279   *
280   * @return the {@link Object} returned by {@link RunnableEx#run()} or <code>defaultValue</code> if
281   *         exception was logged.
282   */
283  public static <T> T runObjectLog(RunnableObjectEx<T> runnable, T defaultValue) {
284    try {
285      return runnable.runObject();
286    } catch (Throwable e) {
287      DesignerPlugin.log(e);
288      return defaultValue;
289    }
290  }
291
292}
293