001/* 002 * Copyright (C) 2008 The Guava Authors 003 * 004 * Licensed under the Apache License, Version 2.0 (the "License"); 005 * you may not use this file except in compliance with the License. 006 * You may obtain a copy of the License at 007 * 008 * http://www.apache.org/licenses/LICENSE-2.0 009 * 010 * Unless required by applicable law or agreed to in writing, software 011 * distributed under the License is distributed on an "AS IS" BASIS, 012 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 013 * See the License for the specific language governing permissions and 014 * limitations under the License. 015 */ 016 017package com.google.common.util.concurrent; 018 019import com.google.common.annotations.Beta; 020 021import java.util.concurrent.CancellationException; 022import java.util.concurrent.ExecutionException; 023import java.util.concurrent.TimeUnit; 024import java.util.concurrent.TimeoutException; 025 026/** 027 * A delegating wrapper around a {@link ListenableFuture} that adds support for 028 * the {@link #checkedGet()} and {@link #checkedGet(long, TimeUnit)} methods. 029 * 030 * @author Sven Mawson 031 * @since 1.0 032 */ 033@Beta 034public abstract class AbstractCheckedFuture<V, X extends Exception> 035 extends ForwardingListenableFuture.SimpleForwardingListenableFuture<V> 036 implements CheckedFuture<V, X> { 037 /** 038 * Constructs an {@code AbstractCheckedFuture} that wraps a delegate. 039 */ 040 protected AbstractCheckedFuture(ListenableFuture<V> delegate) { 041 super(delegate); 042 } 043 044 /** 045 * Translates from an {@link InterruptedException}, 046 * {@link CancellationException} or {@link ExecutionException} thrown by 047 * {@code get} to an exception of type {@code X} to be thrown by 048 * {@code checkedGet}. Subclasses must implement this method. 049 * 050 * <p>If {@code e} is an {@code InterruptedException}, the calling 051 * {@code checkedGet} method has already restored the interrupt after catching 052 * the exception. If an implementation of {@link #mapException(Exception)} 053 * wishes to swallow the interrupt, it can do so by calling 054 * {@link Thread#interrupted()}. 055 * 056 * <p>Subclasses may choose to throw, rather than return, a subclass of 057 * {@code RuntimeException} to allow creating a CheckedFuture that throws 058 * both checked and unchecked exceptions. 059 */ 060 protected abstract X mapException(Exception e); 061 062 /** 063 * {@inheritDoc} 064 * 065 * <p>This implementation calls {@link #get()} and maps that method's standard 066 * exceptions to instances of type {@code X} using {@link #mapException}. 067 * 068 * <p>In addition, if {@code get} throws an {@link InterruptedException}, this 069 * implementation will set the current thread's interrupt status before 070 * calling {@code mapException}. 071 * 072 * @throws X if {@link #get()} throws an {@link InterruptedException}, 073 * {@link CancellationException}, or {@link ExecutionException} 074 */ 075 @Override 076 public V checkedGet() throws X { 077 try { 078 return get(); 079 } catch (InterruptedException e) { 080 Thread.currentThread().interrupt(); 081 throw mapException(e); 082 } catch (CancellationException e) { 083 throw mapException(e); 084 } catch (ExecutionException e) { 085 throw mapException(e); 086 } 087 } 088 089 /** 090 * {@inheritDoc} 091 * 092 * <p>This implementation calls {@link #get(long, TimeUnit)} and maps that 093 * method's standard exceptions (excluding {@link TimeoutException}, which is 094 * propagated) to instances of type {@code X} using {@link #mapException}. 095 * 096 * <p>In addition, if {@code get} throws an {@link InterruptedException}, this 097 * implementation will set the current thread's interrupt status before 098 * calling {@code mapException}. 099 * 100 * @throws X if {@link #get()} throws an {@link InterruptedException}, 101 * {@link CancellationException}, or {@link ExecutionException} 102 * @throws TimeoutException {@inheritDoc} 103 */ 104 @Override 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}