1 // Copyright 2010 Google Inc. All Rights Reserved.
2 package com
.google
.appengine
.api
.search
;
4 import java
.lang
.reflect
.UndeclaredThrowableException
;
5 import java
.util
.concurrent
.ExecutionException
;
6 import java
.util
.concurrent
.Future
;
7 import java
.util
.concurrent
.TimeUnit
;
10 * Utilities for working with {@link Future Futures} in the synchronous
14 final class FutureHelper
{
17 * Return the result of the provided {@link Future}, converting all
18 * checked exceptions to unchecked exceptions so the caller doesn't have to
19 * handle them. If an {@link ExecutionException ExecutionException} is
20 * thrown the cause is wrapped in a {@link RuntimeException}. If an {@link
21 * InterruptedException} is thrown it is wrapped in a {@link
22 * SearchServiceException}.
24 * @param future the Future whose result we want to return
25 * @param <T> the type of the provided Future
26 * @return the result of the provided Future
27 * @throws SearchBaseException if some failure occurred in the search service
29 @SuppressWarnings("unchecked")
30 static <T
> T
quietGet(Future
<T
> future
) throws SearchBaseException
{
32 return getInternal(future
);
33 } catch (ExecutionException e
) {
34 return (T
) processExecutionException(e
);
39 * Return the result of the provided {@link Future}, converting all
40 * checked exceptions except those of the provided type to unchecked
41 * exceptions so the caller doesn't have to handle them. If an {@link
42 * ExecutionException ExecutionException} is thrown and the type of the cause
43 * does not equal {@code exceptionClass} the cause is wrapped in a {@link
44 * RuntimeException}. If the type of the cause does equal {@code
45 * exceptionClass} the cause itself is thrown. If an {@link
46 * InterruptedException} is thrown it is wrapped in a {@link
47 * SearchServiceException}.
49 * @param future the Future whose result we want to return
50 * @param <T> the type of the provided Future
51 * @param exceptionClass Exceptions of this type will be re-thrown
52 * @return the result of the provided Future
53 * @throws E if an ExecutionException with a cause of the appropriate
56 @SuppressWarnings("unchecked")
57 static <T
, E
extends Exception
> T
quietGet(Future
<T
> future
, Class
<E
> exceptionClass
)
58 throws E
, SearchBaseException
{
60 return getInternal(future
);
61 } catch (ExecutionException e
) {
62 if (e
.getCause().getClass().equals(exceptionClass
)) {
63 @SuppressWarnings("unchecked")
64 E exception
= (E
) e
.getCause();
67 return (T
) processExecutionException(e
);
71 private static <T
> T
getInternal(Future
<T
> future
) throws ExecutionException
{
74 } catch (InterruptedException e
) {
75 throw new SearchServiceException("Unexpected failure", e
);
79 private static <T
> T
processExecutionException(ExecutionException e
) {
80 if (e
.getCause() instanceof RuntimeException
) {
81 throw (RuntimeException
) e
.getCause();
82 } else if (e
.getCause() instanceof Error
) {
83 throw (Error
) e
.getCause();
85 throw new UndeclaredThrowableException(e
.getCause());
90 * Wraps an already-resolved result in a {@link Future}.
92 * @param <T> the type of the Future
94 static class FakeFuture
<T
> implements Future
<T
> {
95 private final T result
;
97 FakeFuture(T result
) {
102 public boolean cancel(boolean mayInterruptIfRunning
) {
107 public boolean isCancelled() {
112 public boolean isDone() {
116 @SuppressWarnings("unused")
118 public T
get() throws InterruptedException
, ExecutionException
{
123 public T
get(long timeout
, TimeUnit unit
) {