/** * Copyright (C) 2014 - present by OpenGamma Inc. and the OpenGamma group of companies * * Please see distribution for license. */ package com.opengamma.strata.collect; import java.io.File; import java.io.IOException; import java.io.UncheckedIOException; import java.lang.reflect.InvocationTargetException; import java.util.function.BiConsumer; import java.util.function.BiFunction; import java.util.function.BiPredicate; import java.util.function.BinaryOperator; import java.util.function.Consumer; import java.util.function.Function; import java.util.function.Predicate; import java.util.function.Supplier; import java.util.function.UnaryOperator; import com.google.common.base.Throwables; import com.opengamma.strata.collect.function.CheckedBiConsumer; import com.opengamma.strata.collect.function.CheckedBiFunction; import com.opengamma.strata.collect.function.CheckedBiPredicate; import com.opengamma.strata.collect.function.CheckedBinaryOperator; import com.opengamma.strata.collect.function.CheckedConsumer; import com.opengamma.strata.collect.function.CheckedFunction; import com.opengamma.strata.collect.function.CheckedPredicate; import com.opengamma.strata.collect.function.CheckedRunnable; import com.opengamma.strata.collect.function.CheckedSupplier; import com.opengamma.strata.collect.function.CheckedUnaryOperator; /** * Static utility methods that convert checked exceptions to unchecked. * <p> * Two {@code wrap()} methods are provided that can wrap an arbitrary piece of logic * and convert checked exceptions to unchecked. * <p> * A number of other methods are provided that allow a lambda block to be decorated * to avoid handling checked exceptions. * For example, the method {@link File#getCanonicalFile()} throws an {@link IOException} * which can be handled as follows: * <pre> * stream.map(Unchecked.function(file -> file.getCanonicalFile()) * </pre> * <p> * Each method accepts a functional interface that is defined to throw {@link Throwable}. * Catching {@code Throwable} means that any method can be wrapped. * Any {@code InvocationTargetException} is extracted and processed recursively. * Any {@link IOException} is converted to an {@link UncheckedIOException}. * Any {@link ReflectiveOperationException} is converted to an {@link UncheckedReflectiveOperationException}. * Any {@link Error} or {@link RuntimeException} is re-thrown without alteration. * Any other exception is wrapped in a {@link RuntimeException}. */ public final class Unchecked { /** * Restricted constructor. */ private Unchecked() { } //------------------------------------------------------------------------- /** * Wraps a block of code, converting checked exceptions to unchecked. * <pre> * Unchecked.wrap(() -> { * // any code that throws a checked exception * } * </pre> * <p> * If a checked exception is thrown it is converted to an {@link UncheckedIOException} * or {@link RuntimeException} as appropriate. * * @param block the code block to wrap * @throws UncheckedIOException if an IO exception occurs * @throws RuntimeException if an exception occurs */ public static void wrap(CheckedRunnable block) { try { block.run(); } catch (Throwable ex) { throw propagate(ex); } } /** * Wraps a block of code, converting checked exceptions to unchecked. * <pre> * Unchecked.wrap(() -> { * // any code that throws a checked exception * } * </pre> * <p> * If a checked exception is thrown it is converted to an {@link UncheckedIOException} * or {@link RuntimeException} as appropriate. * * @param <T> the type of the result * @param block the code block to wrap * @return the wrapper for unchecked exceptions * @throws UncheckedIOException if an IO exception occurs * @throws RuntimeException if an exception occurs */ public static <T> T wrap(CheckedSupplier<T> block) { try { return block.get(); } catch (Throwable ex) { throw propagate(ex); } } //------------------------------------------------------------------------- /** * Converts checked exceptions to unchecked based on the {@code Runnable} interface. * <p> * This wraps the specified runnable returning an instance that handles checked exceptions. * If a checked exception is thrown it is converted to an {@link UncheckedIOException} * or {@link RuntimeException} as appropriate. * * @param runnable the runnable to be decorated * @return the runnable instance that handles checked exceptions */ public static Runnable runnable(CheckedRunnable runnable) { return () -> { try { runnable.run(); } catch (Throwable ex) { throw propagate(ex); } }; } //------------------------------------------------------------------------- /** * Converts checked exceptions to unchecked based on the {@code Function} interface. * <p> * This wraps the specified function returning an instance that handles checked exceptions. * If a checked exception is thrown it is converted to an {@link UncheckedIOException} * or {@link RuntimeException} as appropriate. * * @param <T> the input type of the function * @param <R> the return type of the function * @param function the function to be decorated * @return the function instance that handles checked exceptions */ public static <T, R> Function<T, R> function(CheckedFunction<T, R> function) { return (t) -> { try { return function.apply(t); } catch (Throwable ex) { throw propagate(ex); } }; } /** * Converts checked exceptions to unchecked based on the {@code BiFunction} interface. * <p> * This wraps the specified function returning an instance that handles checked exceptions. * If a checked exception is thrown it is converted to an {@link UncheckedIOException} * or {@link RuntimeException} as appropriate. * * @param <T> the first input type of the function * @param <U> the second input type of the function * @param <R> the return type of the function * @param function the function to be decorated * @return the function instance that handles checked exceptions */ public static <T, U, R> BiFunction<T, U, R> biFunction(CheckedBiFunction<T, U, R> function) { return (t, u) -> { try { return function.apply(t, u); } catch (Throwable ex) { throw propagate(ex); } }; } //------------------------------------------------------------------------- /** * Converts checked exceptions to unchecked based on the {@code UnaryOperator} interface. * <p> * This wraps the specified operator returning an instance that handles checked exceptions. * If a checked exception is thrown it is converted to an {@link UncheckedIOException} * or {@link RuntimeException} as appropriate. * * @param <T> the type of the operator * @param function the function to be decorated * @return the function instance that handles checked exceptions */ public static <T> UnaryOperator<T> unaryOperator(CheckedUnaryOperator<T> function) { return (t) -> { try { return function.apply(t); } catch (Throwable ex) { throw propagate(ex); } }; } /** * Converts checked exceptions to unchecked based on the {@code BinaryOperator} interface. * <p> * This wraps the specified operator returning an instance that handles checked exceptions. * If a checked exception is thrown it is converted to an {@link UncheckedIOException} * or {@link RuntimeException} as appropriate. * * @param <T> the type of the operator * @param function the function to be decorated * @return the function instance that handles checked exceptions */ public static <T> BinaryOperator<T> binaryOperator(CheckedBinaryOperator<T> function) { return (t, u) -> { try { return function.apply(t, u); } catch (Throwable ex) { throw propagate(ex); } }; } //------------------------------------------------------------------------- /** * Converts checked exceptions to unchecked based on the {@code Predicate} interface. * <p> * This wraps the specified predicate returning an instance that handles checked exceptions. * If a checked exception is thrown it is converted to an {@link UncheckedIOException} * or {@link RuntimeException} as appropriate. * * @param <T> the type of the predicate * @param predicate the predicate to be decorated * @return the predicate instance that handles checked exceptions */ public static <T> Predicate<T> predicate(CheckedPredicate<T> predicate) { return (t) -> { try { return predicate.test(t); } catch (Throwable ex) { throw propagate(ex); } }; } /** * Converts checked exceptions to unchecked based on the {@code BiPredicate} interface. * <p> * This wraps the specified predicate returning an instance that handles checked exceptions. * If a checked exception is thrown it is converted to an {@link UncheckedIOException} * or {@link RuntimeException} as appropriate. * * @param <T> the first type of the predicate * @param <U> the second type of the predicate * @param predicate the predicate to be decorated * @return the predicate instance that handles checked exceptions */ public static <T, U> BiPredicate<T, U> biPredicate(CheckedBiPredicate<T, U> predicate) { return (t, u) -> { try { return predicate.test(t, u); } catch (Throwable ex) { throw propagate(ex); } }; } //------------------------------------------------------------------------- /** * Converts checked exceptions to unchecked based on the {@code Consumer} interface. * <p> * This wraps the specified consumer returning an instance that handles checked exceptions. * If a checked exception is thrown it is converted to an {@link UncheckedIOException} * or {@link RuntimeException} as appropriate. * * @param <T> the type of the consumer * @param consumer the consumer to be decorated * @return the consumer instance that handles checked exceptions */ public static <T> Consumer<T> consumer(CheckedConsumer<T> consumer) { return (t) -> { try { consumer.accept(t); } catch (Throwable ex) { throw propagate(ex); } }; } /** * Converts checked exceptions to unchecked based on the {@code BiConsumer} interface. * <p> * This wraps the specified consumer returning an instance that handles checked exceptions. * If a checked exception is thrown it is converted to an {@link UncheckedIOException} * or {@link RuntimeException} as appropriate. * * @param <T> the first type of the consumer * @param <U> the second type of the consumer * @param consumer the consumer to be decorated * @return the consumer instance that handles checked exceptions */ public static <T, U> BiConsumer<T, U> biConsumer(CheckedBiConsumer<T, U> consumer) { return (t, u) -> { try { consumer.accept(t, u); } catch (Throwable ex) { throw propagate(ex); } }; } //------------------------------------------------------------------------- /** * Converts checked exceptions to unchecked based on the {@code Supplier} interface. * <p> * This wraps the specified supplier returning an instance that handles checked exceptions. * If a checked exception is thrown it is converted to an {@link UncheckedIOException} * or {@link RuntimeException} as appropriate. * * @param <R> the result type of the supplier * @param supplier the supplier to be decorated * @return the supplier instance that handles checked exceptions */ public static <R> Supplier<R> supplier(CheckedSupplier<R> supplier) { return () -> { try { return supplier.get(); } catch (Throwable ex) { throw propagate(ex); } }; } /** * Propagates {@code throwable} as-is if possible, or by wrapping in a {@code RuntimeException} if not. * <ul> * <li>If {@code throwable} is an {@code InvocationTargetException} the cause is extracted and processed recursively.</li> * <li>If {@code throwable} is an {@code Error} or {@code RuntimeException} it is propagated as-is.</li> * <li>If {@code throwable} is an {@code IOException} it is wrapped in {@code UncheckedIOException} and thrown.</li> * <li>If {@code throwable} is an {@code ReflectiveOperationException} it is wrapped in * {@code UncheckedReflectiveOperationException} and thrown.</li> * <li>Otherwise {@code throwable} is wrapped in a {@code RuntimeException} and thrown.</li> * </ul> * This method always throws an exception. The return type is a convenience to satisfy the type system * when the enclosing method returns a value. For example: * <pre> * T foo() { * try { * return methodWithCheckedException(); * } catch (Exception e) { * throw Unchecked.propagate(e); * } * } * </pre> * * @param throwable the {@code Throwable} to propagate * @return nothing; this method always throws an exception */ public static RuntimeException propagate(Throwable throwable) { if (throwable instanceof InvocationTargetException) { throw propagate(((InvocationTargetException) throwable).getCause()); } else if (throwable instanceof IOException) { throw new UncheckedIOException((IOException) throwable); } else if (throwable instanceof ReflectiveOperationException) { throw new UncheckedReflectiveOperationException((ReflectiveOperationException) throwable); } else { Throwables.throwIfUnchecked(throwable); throw new RuntimeException(throwable); } } }