Coverage Summary for Class: AbstractCatchingFuture (com.google.common.util.concurrent)
| Class | Method, % | Line, % |
|---|---|---|
| AbstractCatchingFuture | 0% (0/6) | 0% (0/60) |
| AbstractCatchingFuture$AsyncCatchingFuture | 0% (0/3) | 0% (0/5) |
| AbstractCatchingFuture$CatchingFuture | 0% (0/3) | 0% (0/3) |
| Total | 0% (0/12) | 0% (0/68) |
1 /* 2 * Copyright (C) 2006 The Guava Authors 3 * 4 * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except 5 * in compliance with the License. You may obtain a copy of the License at 6 * 7 * http://www.apache.org/licenses/LICENSE-2.0 8 * 9 * Unless required by applicable law or agreed to in writing, software distributed under the License 10 * is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express 11 * or implied. See the License for the specific language governing permissions and limitations under 12 * the License. 13 */ 14 15 package com.google.common.util.concurrent; 16 17 import static com.google.common.base.Preconditions.checkNotNull; 18 import static com.google.common.util.concurrent.Futures.getDone; 19 import static com.google.common.util.concurrent.MoreExecutors.rejectionPropagatingExecutor; 20 import static com.google.common.util.concurrent.NullnessCasts.uncheckedCastNullableTToT; 21 import static com.google.common.util.concurrent.Platform.isInstanceOfThrowableClass; 22 23 import com.google.common.annotations.GwtCompatible; 24 import com.google.common.base.Function; 25 import com.google.common.util.concurrent.internal.InternalFutureFailureAccess; 26 import com.google.common.util.concurrent.internal.InternalFutures; 27 import com.google.errorprone.annotations.ForOverride; 28 import java.util.concurrent.ExecutionException; 29 import java.util.concurrent.Executor; 30 import javax.annotation.CheckForNull; 31 import org.checkerframework.checker.nullness.qual.Nullable; 32 33 /** Implementations of {@code Futures.catching*}. */ 34 @GwtCompatible 35 @ElementTypesAreNonnullByDefault 36 abstract class AbstractCatchingFuture< 37 V extends @Nullable Object, X extends Throwable, F, T extends @Nullable Object> 38 extends FluentFuture.TrustedFuture<V> implements Runnable { 39 static <V extends @Nullable Object, X extends Throwable> ListenableFuture<V> create( 40 ListenableFuture<? extends V> input, 41 Class<X> exceptionType, 42 Function<? super X, ? extends V> fallback, 43 Executor executor) { 44 CatchingFuture<V, X> future = new CatchingFuture<>(input, exceptionType, fallback); 45 input.addListener(future, rejectionPropagatingExecutor(executor, future)); 46 return future; 47 } 48 49 static <X extends Throwable, V extends @Nullable Object> ListenableFuture<V> create( 50 ListenableFuture<? extends V> input, 51 Class<X> exceptionType, 52 AsyncFunction<? super X, ? extends V> fallback, 53 Executor executor) { 54 AsyncCatchingFuture<V, X> future = new AsyncCatchingFuture<>(input, exceptionType, fallback); 55 input.addListener(future, rejectionPropagatingExecutor(executor, future)); 56 return future; 57 } 58 59 /* 60 * In certain circumstances, this field might theoretically not be visible to an afterDone() call 61 * triggered by cancel(). For details, see the comments on the fields of TimeoutFuture. 62 */ 63 @CheckForNull ListenableFuture<? extends V> inputFuture; 64 @CheckForNull Class<X> exceptionType; 65 @CheckForNull F fallback; 66 67 AbstractCatchingFuture( 68 ListenableFuture<? extends V> inputFuture, Class<X> exceptionType, F fallback) { 69 this.inputFuture = checkNotNull(inputFuture); 70 this.exceptionType = checkNotNull(exceptionType); 71 this.fallback = checkNotNull(fallback); 72 } 73 74 @Override 75 public final void run() { 76 ListenableFuture<? extends V> localInputFuture = inputFuture; 77 Class<X> localExceptionType = exceptionType; 78 F localFallback = fallback; 79 if (localInputFuture == null | localExceptionType == null | localFallback == null 80 // This check, unlike all the others, is a volatile read 81 || isCancelled()) { 82 return; 83 } 84 inputFuture = null; 85 86 // For an explanation of the cases here, see the comments on AbstractTransformFuture.run. 87 V sourceResult = null; 88 Throwable throwable = null; 89 try { 90 if (localInputFuture instanceof InternalFutureFailureAccess) { 91 throwable = 92 InternalFutures.tryInternalFastPathGetFailure( 93 (InternalFutureFailureAccess) localInputFuture); 94 } 95 if (throwable == null) { 96 sourceResult = getDone(localInputFuture); 97 } 98 } catch (ExecutionException e) { 99 throwable = e.getCause(); 100 if (throwable == null) { 101 throwable = 102 new NullPointerException( 103 "Future type " 104 + localInputFuture.getClass() 105 + " threw " 106 + e.getClass() 107 + " without a cause"); 108 } 109 } catch (Throwable e) { // this includes cancellation exception 110 throwable = e; 111 } 112 113 if (throwable == null) { 114 /* 115 * The cast is safe: There was no exception, so the assignment from getDone must have 116 * succeeded. 117 */ 118 set(uncheckedCastNullableTToT(sourceResult)); 119 return; 120 } 121 122 if (!isInstanceOfThrowableClass(throwable, localExceptionType)) { 123 setFuture(localInputFuture); 124 // TODO(cpovirk): Test that fallback is not run in this case. 125 return; 126 } 127 128 @SuppressWarnings("unchecked") // verified safe by isInstanceOfThrowableClass 129 X castThrowable = (X) throwable; 130 T fallbackResult; 131 try { 132 fallbackResult = doFallback(localFallback, castThrowable); 133 } catch (Throwable t) { 134 setException(t); 135 return; 136 } finally { 137 exceptionType = null; 138 fallback = null; 139 } 140 141 setResult(fallbackResult); 142 } 143 144 @Override 145 @CheckForNull 146 protected String pendingToString() { 147 ListenableFuture<? extends V> localInputFuture = inputFuture; 148 Class<X> localExceptionType = exceptionType; 149 F localFallback = fallback; 150 String superString = super.pendingToString(); 151 String resultString = ""; 152 if (localInputFuture != null) { 153 resultString = "inputFuture=[" + localInputFuture + "], "; 154 } 155 if (localExceptionType != null && localFallback != null) { 156 return resultString 157 + "exceptionType=[" 158 + localExceptionType 159 + "], fallback=[" 160 + localFallback 161 + "]"; 162 } else if (superString != null) { 163 return resultString + superString; 164 } 165 return null; 166 } 167 168 /** Template method for subtypes to actually run the fallback. */ 169 @ForOverride 170 @ParametricNullness 171 abstract T doFallback(F fallback, X throwable) throws Exception; 172 173 /** Template method for subtypes to actually set the result. */ 174 @ForOverride 175 abstract void setResult(@ParametricNullness T result); 176 177 @Override 178 protected final void afterDone() { 179 maybePropagateCancellationTo(inputFuture); 180 this.inputFuture = null; 181 this.exceptionType = null; 182 this.fallback = null; 183 } 184 185 /** 186 * An {@link AbstractCatchingFuture} that delegates to an {@link AsyncFunction} and {@link 187 * #setFuture(ListenableFuture)}. 188 */ 189 private static final class AsyncCatchingFuture<V extends @Nullable Object, X extends Throwable> 190 extends AbstractCatchingFuture< 191 V, X, AsyncFunction<? super X, ? extends V>, ListenableFuture<? extends V>> { 192 AsyncCatchingFuture( 193 ListenableFuture<? extends V> input, 194 Class<X> exceptionType, 195 AsyncFunction<? super X, ? extends V> fallback) { 196 super(input, exceptionType, fallback); 197 } 198 199 @Override 200 ListenableFuture<? extends V> doFallback( 201 AsyncFunction<? super X, ? extends V> fallback, X cause) throws Exception { 202 ListenableFuture<? extends V> replacement = fallback.apply(cause); 203 checkNotNull( 204 replacement, 205 "AsyncFunction.apply returned null instead of a Future. " 206 + "Did you mean to return immediateFuture(null)? %s", 207 fallback); 208 return replacement; 209 } 210 211 @Override 212 void setResult(ListenableFuture<? extends V> result) { 213 setFuture(result); 214 } 215 } 216 217 /** 218 * An {@link AbstractCatchingFuture} that delegates to a {@link Function} and {@link 219 * #set(Object)}. 220 */ 221 private static final class CatchingFuture<V extends @Nullable Object, X extends Throwable> 222 extends AbstractCatchingFuture<V, X, Function<? super X, ? extends V>, V> { 223 CatchingFuture( 224 ListenableFuture<? extends V> input, 225 Class<X> exceptionType, 226 Function<? super X, ? extends V> fallback) { 227 super(input, exceptionType, fallback); 228 } 229 230 @Override 231 @ParametricNullness 232 V doFallback(Function<? super X, ? extends V> fallback, X cause) throws Exception { 233 return fallback.apply(cause); 234 } 235 236 @Override 237 void setResult(@ParametricNullness V result) { 238 set(result); 239 } 240 } 241 }