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 }