Revision created by MOE tool push_codebase.
[gae.git] / java / src / main / com / google / appengine / api / search / FutureHelper.java
blobe2cbeaa5b4d034ca3bcc0d5547e98b5b3f82b062
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;
9 /**
10 * Utilities for working with {@link Future Futures} in the synchronous
11 * search api.
14 final class FutureHelper {
16 /**
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 {
31 try {
32 return getInternal(future);
33 } catch (ExecutionException e) {
34 return (T) processExecutionException(e);
38 /**
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
54 * type is caught
56 @SuppressWarnings("unchecked")
57 static <T, E extends Exception> T quietGet(Future<T> future, Class<E> exceptionClass)
58 throws E, SearchBaseException {
59 try {
60 return getInternal(future);
61 } catch (ExecutionException e) {
62 if (e.getCause().getClass().equals(exceptionClass)) {
63 @SuppressWarnings("unchecked")
64 E exception = (E) e.getCause();
65 throw exception;
67 return (T) processExecutionException(e);
71 private static <T> T getInternal(Future<T> future) throws ExecutionException {
72 try {
73 return future.get();
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();
84 } else {
85 throw new UndeclaredThrowableException(e.getCause());
89 /**
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) {
98 this.result = result;
101 @Override
102 public boolean cancel(boolean mayInterruptIfRunning) {
103 return false;
106 @Override
107 public boolean isCancelled() {
108 return false;
111 @Override
112 public boolean isDone() {
113 return true;
116 @SuppressWarnings("unused")
117 @Override
118 public T get() throws InterruptedException, ExecutionException {
119 return result;
122 @Override
123 public T get(long timeout, TimeUnit unit) {
124 return result;