1 /* 2 * Copyright (C) 2008 The Guava Authors 3 * 4 * Licensed under the Apache License, Version 2.0 (the "License"); 5 * you may not use this file except in compliance with the License. 6 * You may obtain a copy of the License at 7 * 8 * http://www.apache.org/licenses/LICENSE-2.0 9 * 10 * Unless required by applicable law or agreed to in writing, software 11 * distributed under the License is distributed on an "AS IS" BASIS, 12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 * See the License for the specific language governing permissions and 14 * limitations under the License. 15 */ 16 17 package com.google.common.util.concurrent; 18 19 import com.google.common.annotations.Beta; 20 21 import java.util.concurrent.CancellationException; 22 import java.util.concurrent.ExecutionException; 23 import java.util.concurrent.TimeUnit; 24 import java.util.concurrent.TimeoutException; 25 26 /** 27 * A delegating wrapper around a {@link ListenableFuture} that adds support for 28 * the {@link #checkedGet()} and {@link #checkedGet(long, TimeUnit)} methods. 29 * 30 * @author Sven Mawson 31 * @since 1.0 32 */ 33 @Beta 34 public abstract class AbstractCheckedFuture<V, X extends Exception> 35 extends ForwardingListenableFuture.SimpleForwardingListenableFuture<V> 36 implements CheckedFuture<V, X> { 37 /** 38 * Constructs an {@code AbstractCheckedFuture} that wraps a delegate. 39 */ AbstractCheckedFuture(ListenableFuture<V> delegate)40 protected AbstractCheckedFuture(ListenableFuture<V> delegate) { 41 super(delegate); 42 } 43 44 /** 45 * Translates from an {@link InterruptedException}, 46 * {@link CancellationException} or {@link ExecutionException} thrown by 47 * {@code get} to an exception of type {@code X} to be thrown by 48 * {@code checkedGet}. Subclasses must implement this method. 49 * 50 * <p>If {@code e} is an {@code InterruptedException}, the calling 51 * {@code checkedGet} method has already restored the interrupt after catching 52 * the exception. If an implementation of {@link #mapException(Exception)} 53 * wishes to swallow the interrupt, it can do so by calling 54 * {@link Thread#interrupted()}. 55 * 56 * <p>Subclasses may choose to throw, rather than return, a subclass of 57 * {@code RuntimeException} to allow creating a CheckedFuture that throws 58 * both checked and unchecked exceptions. 59 */ mapException(Exception e)60 protected abstract X mapException(Exception e); 61 62 /** 63 * {@inheritDoc} 64 * 65 * <p>This implementation calls {@link #get()} and maps that method's standard 66 * exceptions to instances of type {@code X} using {@link #mapException}. 67 * 68 * <p>In addition, if {@code get} throws an {@link InterruptedException}, this 69 * implementation will set the current thread's interrupt status before 70 * calling {@code mapException}. 71 * 72 * @throws X if {@link #get()} throws an {@link InterruptedException}, 73 * {@link CancellationException}, or {@link ExecutionException} 74 */ 75 @Override checkedGet()76 public V checkedGet() throws X { 77 try { 78 return get(); 79 } catch (InterruptedException e) { 80 Thread.currentThread().interrupt(); 81 throw mapException(e); 82 } catch (CancellationException e) { 83 throw mapException(e); 84 } catch (ExecutionException e) { 85 throw mapException(e); 86 } 87 } 88 89 /** 90 * {@inheritDoc} 91 * 92 * <p>This implementation calls {@link #get(long, TimeUnit)} and maps that 93 * method's standard exceptions (excluding {@link TimeoutException}, which is 94 * propagated) to instances of type {@code X} using {@link #mapException}. 95 * 96 * <p>In addition, if {@code get} throws an {@link InterruptedException}, this 97 * implementation will set the current thread's interrupt status before 98 * calling {@code mapException}. 99 * 100 * @throws X if {@link #get()} throws an {@link InterruptedException}, 101 * {@link CancellationException}, or {@link ExecutionException} 102 * @throws TimeoutException {@inheritDoc} 103 */ 104 @Override checkedGet(long timeout, TimeUnit unit)105 public V checkedGet(long timeout, TimeUnit unit) throws TimeoutException, X { 106 try { 107 return get(timeout, unit); 108 } catch (InterruptedException e) { 109 Thread.currentThread().interrupt(); 110 throw mapException(e); 111 } catch (CancellationException e) { 112 throw mapException(e); 113 } catch (ExecutionException e) { 114 throw mapException(e); 115 } 116 } 117 } 118