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 017 package com.google.common.util.concurrent; 018 019 import com.google.common.annotations.Beta; 020 021 import java.util.concurrent.CancellationException; 022 import java.util.concurrent.ExecutionException; 023 import java.util.concurrent.Executor; 024 import java.util.concurrent.TimeUnit; 025 import java.util.concurrent.TimeoutException; 026 027 /** 028 * A delegating wrapper around a {@link ListenableFuture} that adds support for 029 * the {@link #checkedGet()} and {@link #checkedGet(long, TimeUnit)} methods. 030 * 031 * @author Sven Mawson 032 * @since 1 033 */ 034 @Beta 035 public abstract class AbstractCheckedFuture<V, X extends Exception> 036 implements CheckedFuture<V, X> { 037 038 /** The delegate, used to pass along all our methods. */ 039 protected final ListenableFuture<V> delegate; 040 041 /** 042 * Constructs an {@code AbstractCheckedFuture} that wraps a delegate. 043 */ 044 protected AbstractCheckedFuture(ListenableFuture<V> delegate) { 045 this.delegate = delegate; 046 } 047 048 /** 049 * Translates from an {@link InterruptedException}, 050 * {@link CancellationException} or {@link ExecutionException} thrown by 051 * {@code get} to an exception of type {@code X} to be thrown by 052 * {@code checkedGet}. Subclasses must implement this method. 053 * 054 * <p>If {@code e} is an {@code InterruptedException}, the calling 055 * {@code checkedGet} method has already restored the interrupt after catching 056 * the exception. If an implementation of {@link #mapException(Exception)} 057 * wishes to swallow the interrupt, it can do so by calling 058 * {@link Thread#interrupted()}. 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 118 // Delegate methods for methods defined in the ListenableFuture interface. 119 120 @Override 121 public boolean cancel(boolean mayInterruptIfRunning) { 122 return delegate.cancel(mayInterruptIfRunning); 123 } 124 125 @Override 126 public boolean isCancelled() { 127 return delegate.isCancelled(); 128 } 129 130 @Override 131 public boolean isDone() { 132 return delegate.isDone(); 133 } 134 135 @Override 136 public V get() throws InterruptedException, ExecutionException { 137 return delegate.get(); 138 } 139 140 @Override 141 public V get(long timeout, TimeUnit unit) throws InterruptedException, 142 ExecutionException, TimeoutException { 143 return delegate.get(timeout, unit); 144 } 145 146 @Override 147 public void addListener(Runnable listener, Executor exec) { 148 delegate.addListener(listener, exec); 149 } 150 }