    001/*
    002 * Licensed to the Apache Software Foundation (ASF) under one or more
    003 * contributor license agreements.  See the NOTICE file distributed with
    004 * this work for additional information regarding copyright ownership.
    005 * The ASF licenses this file to You under the Apache License, Version 2.0
    006 * (the "License"); you may not use this file except in compliance with
    007 * the License.  You may obtain a copy of the License at
    008 *
    009 *      http://www.apache.org/licenses/LICENSE-2.0
    010 *
    011 * Unless required by applicable law or agreed to in writing, software
    012 * distributed under the License is distributed on an "AS IS" BASIS,
    013 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
    014 * See the License for the specific language governing permissions and
    015 * limitations under the License.
    016 */
    017package org.apache.commons.lang3;
    018
    019import java.io.IOException;
    020import java.io.UncheckedIOException;
    021import java.lang.reflect.UndeclaredThrowableException;
    022import java.util.Arrays;
    023import java.util.Collection;
    024import java.util.Objects;
    025import java.util.concurrent.Callable;
    026import java.util.function.BiConsumer;
    027import java.util.function.BiFunction;
    028import java.util.function.BiPredicate;
    029import java.util.function.Consumer;
    030import java.util.function.Function;
    031import java.util.function.Predicate;
    032import java.util.function.Supplier;
    033import java.util.stream.Stream;
    034
    035import org.apache.commons.lang3.Streams.FailableStream;
    036import org.apache.commons.lang3.exception.ExceptionUtils;
    037import org.apache.commons.lang3.function.Failable;
    038import org.apache.commons.lang3.function.FailableBooleanSupplier;
    039
    040/**
    041 * This class provides utility functions, and classes for working with the {@code java.util.function} package, or more
    042 * generally, with Java 8 lambdas. More specifically, it attempts to address the fact that lambdas are supposed not to
    043 * throw Exceptions, at least not checked Exceptions, AKA instances of {@link Exception}. This enforces the use of
    044 * constructs like:
    045 *
    046 * <pre>
    047 * {@code
    048 *     Consumer<java.lang.reflect.Method> consumer = m -> {
    049 *         try {
    050 *             m.invoke(o, args);
    051 *         } catch (Throwable t) {
    052 *             throw Functions.rethrow(t);
    053 *         }
    054 *     };
    055 * }</pre>
    056 *
    057 * <p>
    058 * By replacing a {@link java.util.function.Consumer Consumer&lt;O&gt;} with a {@link FailableConsumer
    059 * FailableConsumer&lt;O,? extends Throwable&gt;}, this can be written like follows:
    060 * </p>
    061 *
    062 * <pre>
    063 * {@code
    064 *   Functions.accept((m) -> m.invoke(o,args));
    065 * }</pre>
    066 *
    067 * <p>
    068 * Obviously, the second version is much more concise and the spirit of Lambda expressions is met better than the second
    069 * version.
    070 * </p>
    071 * @since 3.9
    072 * @deprecated Use {@link org.apache.commons.lang3.function.Failable}.
    073 */
    074@Deprecated
    075public class Functions {
    076
    077    /**
    078     * A functional interface like {@link BiConsumer} that declares a {@link Throwable}.
    079     *
    080     * <p>TODO for 4.0: Move to org.apache.commons.lang3.function.</p>
    081     *
    082     * @param <O1> Consumed type 1.
    083     * @param <O2> Consumed type 2.
    084     * @param <T> Thrown exception.
    085     * @deprecated Use {@link org.apache.commons.lang3.function.FailableBiConsumer}.
    086     */
    087    @Deprecated
    088    @FunctionalInterface
    089    public interface FailableBiConsumer<O1, O2, T extends Throwable> {
    090
    091        /**
    092         * Accepts the consumer.
    093         *
    094         * @param object1 the first parameter for the consumable to accept
    095         * @param object2 the second parameter for the consumable to accept
    096         * @throws T Thrown when the consumer fails.
    097         */
    098        void accept(O1 object1, O2 object2) throws T;
    099    }
    100
    101    /**
    102     * A functional interface like {@link BiFunction} that declares a {@link Throwable}.
    103     *
    104     * <p>TODO for 4.0: Move to org.apache.commons.lang3.function.</p>
    105     *
    106     * @param <O1> Input type 1.
    107     * @param <O2> Input type 2.
    108     * @param <R> Return type.
    109     * @param <T> Thrown exception.
    110     * @deprecated Use {@link org.apache.commons.lang3.function.FailableBiFunction}.
    111     */
    112    @Deprecated
    113    @FunctionalInterface
    114    public interface FailableBiFunction<O1, O2, R, T extends Throwable> {
    115
    116        /**
    117         * Applies this function.
    118         *
    119         * @param input1 the first input for the function
    120         * @param input2 the second input for the function
    121         * @return the result of the function
    122         * @throws T Thrown when the function fails.
    123         */
    124        R apply(O1 input1, O2 input2) throws T;
    125    }
    126
    127    /**
    128     * A functional interface like {@link BiPredicate} that declares a {@link Throwable}.
    129     *
    130     * <p>TODO for 4.0: Move to org.apache.commons.lang3.function.</p>
    131     *
    132     * @param <O1> Predicate type 1.
    133     * @param <O2> Predicate type 2.
    134     * @param <T> Thrown exception.
    135     * @deprecated Use {@link org.apache.commons.lang3.function.FailableBiPredicate}.
    136     */
    137    @Deprecated
    138    @FunctionalInterface
    139    public interface FailableBiPredicate<O1, O2, T extends Throwable> {
    140
    141        /**
    142         * Tests the predicate.
    143         *
    144         * @param object1 the first object to test the predicate on
    145         * @param object2 the second object to test the predicate on
    146         * @return the predicate's evaluation
    147         * @throws T if the predicate fails
    148         */
    149        boolean test(O1 object1, O2 object2) throws T;
    150    }
    151
    152    /**
    153     * A functional interface like {@link java.util.concurrent.Callable} that declares a {@link Throwable}.
    154     *
    155     * <p>TODO for 4.0: Move to org.apache.commons.lang3.function.</p>
    156     *
    157     * @param <R> Return type.
    158     * @param <T> Thrown exception.
    159     * @deprecated Use {@link org.apache.commons.lang3.function.FailableCallable}.
    160     */
    161    @Deprecated
    162    @FunctionalInterface
    163    public interface FailableCallable<R, T extends Throwable> {
    164
    165        /**
    166         * Calls the callable.
    167         *
    168         * @return The value returned from the callable
    169         * @throws T if the callable fails
    170         */
    171        R call() throws T;
    172    }
    173
    174    /**
    175     * A functional interface like {@link Consumer} that declares a {@link Throwable}.
    176     *
    177     * <p>TODO for 4.0: Move to org.apache.commons.lang3.function.</p>
    178     *
    179     * @param <O> Consumed type 1.
    180     * @param <T> Thrown exception.
    181     * @deprecated Use {@link org.apache.commons.lang3.function.FailableConsumer}.
    182     */
    183    @Deprecated
    184    @FunctionalInterface
    185    public interface FailableConsumer<O, T extends Throwable> {
    186
    187        /**
    188         * Accepts the consumer.
    189         *
    190         * @param object the parameter for the consumable to accept
    191         * @throws T Thrown when the consumer fails.
    192         */
    193        void accept(O object) throws T;
    194    }
    195
    196    /**
    197     * A functional interface like {@link Function} that declares a {@link Throwable}.
    198     *
    199     * <p>TODO for 4.0: Move to org.apache.commons.lang3.function.</p>
    200     *
    201     * @param <I> Input type 1.
    202     * @param <R> Return type.
    203     * @param <T> Thrown exception.
    204     * @deprecated Use {@link org.apache.commons.lang3.function.FailableFunction}.
    205     */
    206    @Deprecated
    207    @FunctionalInterface
    208    public interface FailableFunction<I, R, T extends Throwable> {
    209
    210        /**
    211         * Applies this function.
    212         *
    213         * @param input the input for the function
    214         * @return the result of the function
    215         * @throws T Thrown when the function fails.
    216         */
    217        R apply(I input) throws T;
    218    }
    219
    220    /**
    221     * A functional interface like {@link Predicate} that declares a {@link Throwable}.
    222     *
    223     * <p>TODO for 4.0: Move to org.apache.commons.lang3.function.</p>
    224     *
    225     * @param <I> Predicate type 1.
    226     * @param <T> Thrown exception.
    227     * @deprecated Use {@link org.apache.commons.lang3.function.FailablePredicate}.
    228     */
    229    @Deprecated
    230    @FunctionalInterface
    231    public interface FailablePredicate<I, T extends Throwable> {
    232
    233        /**
    234         * Tests the predicate.
    235         *
    236         * @param object the object to test the predicate on
    237         * @return the predicate's evaluation
    238         * @throws T if the predicate fails
    239         */
    240        boolean test(I object) throws T;
    241    }
    242
    243    /**
    244     * A functional interface like {@link Runnable} that declares a {@link Throwable}.
    245     *
    246     * <p>TODO for 4.0: Move to org.apache.commons.lang3.function.</p>
    247     *
    248     * @param <T> Thrown exception.
    249     * @deprecated Use {@link org.apache.commons.lang3.function.FailableRunnable}.
    250     */
    251    @Deprecated
    252    @FunctionalInterface
    253    public interface FailableRunnable<T extends Throwable> {
    254
    255        /**
    256         * Runs the function.
    257         *
    258         * @throws T Thrown when the function fails.
    259         */
    260        void run() throws T;
    261    }
    262
    263    /**
    264     * A functional interface like {@link Supplier} that declares a {@link Throwable}.
    265     *
    266     * <p>TODO for 4.0: Move to org.apache.commons.lang3.function.</p>
    267     *
    268     * @param <R> Return type.
    269     * @param <T> Thrown exception.
    270     * @deprecated Use {@link org.apache.commons.lang3.function.FailableSupplier}.
    271     */
    272    @Deprecated
    273    @FunctionalInterface
    274    public interface FailableSupplier<R, T extends Throwable> {
    275
    276        /**
    277         * Supplies an object
    278         *
    279         * @return a result
    280         * @throws T if the supplier fails
    281         */
    282        R get() throws T;
    283    }
    284
    285    /**
    286     * Consumes a consumer and rethrows any exception as a {@link RuntimeException}.
    287     *
    288     * @param consumer the consumer to consume
    289     * @param object1 the first object to consume by {@code consumer}
    290     * @param object2 the second object to consume by {@code consumer}
    291     * @param <O1> the type of the first argument the consumer accepts
    292     * @param <O2> the type of the second argument the consumer accepts
    293     * @param <T> the type of checked exception the consumer may throw
    294     */
    295    public static <O1, O2, T extends Throwable> void accept(final FailableBiConsumer<O1, O2, T> consumer,
    296        final O1 object1, final O2 object2) {
    297        run(() -> consumer.accept(object1, object2));
    298    }
    299
    300    /**
    301     * Consumes a consumer and rethrows any exception as a {@link RuntimeException}.
    302     *
    303     * @param consumer the consumer to consume
    304     * @param object the object to consume by {@code consumer}
    305     * @param <O> the type the consumer accepts
    306     * @param <T> the type of checked exception the consumer may throw
    307     */
    308    public static <O, T extends Throwable> void accept(final FailableConsumer<O, T> consumer, final O object) {
    309        run(() -> consumer.accept(object));
    310    }
    311
    312    /**
    313     * Applies a function and rethrows any exception as a {@link RuntimeException}.
    314     *
    315     * @param function the function to apply
    316     * @param input1 the first input to apply {@code function} on
    317     * @param input2 the second input to apply {@code function} on
    318     * @param <O1> the type of the first argument the function accepts
    319     * @param <O2> the type of the second argument the function accepts
    320     * @param <O> the return type of the function
    321     * @param <T> the type of checked exception the function may throw
    322     * @return the value returned from the function
    323     */
    324    public static <O1, O2, O, T extends Throwable> O apply(final FailableBiFunction<O1, O2, O, T> function,
    325        final O1 input1, final O2 input2) {
    326        return get(() -> function.apply(input1, input2));
    327    }
    328
    329    /**
    330     * Applies a function and rethrows any exception as a {@link RuntimeException}.
    331     *
    332     * @param function the function to apply
    333     * @param input the input to apply {@code function} on
    334     * @param <I> the type of the argument the function accepts
    335     * @param <O> the return type of the function
    336     * @param <T> the type of checked exception the function may throw
    337     * @return the value returned from the function
    338     */
    339    public static <I, O, T extends Throwable> O apply(final FailableFunction<I, O, T> function, final I input) {
    340        return get(() -> function.apply(input));
    341    }
    342
    343    /**
    344     * Converts the given {@link FailableBiConsumer} into a standard {@link BiConsumer}.
    345     *
    346     * @param <O1> the type of the first argument of the consumers
    347     * @param <O2> the type of the second argument of the consumers
    348     * @param consumer a failable {@link BiConsumer}
    349     * @return a standard {@link BiConsumer}
    350     * @since 3.10
    351     */
    352    public static <O1, O2> BiConsumer<O1, O2> asBiConsumer(final FailableBiConsumer<O1, O2, ?> consumer) {
    353        return (input1, input2) -> accept(consumer, input1, input2);
    354    }
    355
    356    /**
    357     * Converts the given {@link FailableBiFunction} into a standard {@link BiFunction}.
    358     *
    359     * @param <O1> the type of the first argument of the input of the functions
    360     * @param <O2> the type of the second argument of the input of the functions
    361     * @param <O> the type of the output of the functions
    362     * @param function a {@link FailableBiFunction}
    363     * @return a standard {@link BiFunction}
    364     * @since 3.10
    365     */
    366    public static <O1, O2, O> BiFunction<O1, O2, O> asBiFunction(final FailableBiFunction<O1, O2, O, ?> function) {
    367        return (input1, input2) -> apply(function, input1, input2);
    368    }
    369
    370    /**
    371     * Converts the given {@link FailableBiPredicate} into a standard {@link BiPredicate}.
    372     *
    373     * @param <O1> the type of the first argument used by the predicates
    374     * @param <O2> the type of the second argument used by the predicates
    375     * @param predicate a {@link FailableBiPredicate}
    376     * @return a standard {@link BiPredicate}
    377     * @since 3.10
    378     */
    379    public static <O1, O2> BiPredicate<O1, O2> asBiPredicate(final FailableBiPredicate<O1, O2, ?> predicate) {
    380        return (input1, input2) -> test(predicate, input1, input2);
    381    }
    382
    383    /**
    384     * Converts the given {@link FailableCallable} into a standard {@link Callable}.
    385     *
    386     * @param <O> the type used by the callables
    387     * @param callable a {@link FailableCallable}
    388     * @return a standard {@link Callable}
    389     * @since 3.10
    390     */
    391    public static <O> Callable<O> asCallable(final FailableCallable<O, ?> callable) {
    392        return () -> call(callable);
    393    }
    394
    395    /**
    396     * Converts the given {@link FailableConsumer} into a standard {@link Consumer}.
    397     *
    398     * @param <I> the type used by the consumers
    399     * @param consumer a {@link FailableConsumer}
    400     * @return a standard {@link Consumer}
    401     * @since 3.10
    402     */
    403    public static <I> Consumer<I> asConsumer(final FailableConsumer<I, ?> consumer) {
    404        return input -> accept(consumer, input);
    405    }
    406
    407    /**
    408     * Converts the given {@link FailableFunction} into a standard {@link Function}.
    409     *
    410     * @param <I> the type of the input of the functions
    411     * @param <O> the type of the output of the functions
    412     * @param function a {code FailableFunction}
    413     * @return a standard {@link Function}
    414     * @since 3.10
    415     */
    416    public static <I, O> Function<I, O> asFunction(final FailableFunction<I, O, ?> function) {
    417        return input -> apply(function, input);
    418    }
    419
    420    /**
    421     * Converts the given {@link FailablePredicate} into a standard {@link Predicate}.
    422     *
    423     * @param <I> the type used by the predicates
    424     * @param predicate a {@link FailablePredicate}
    425     * @return a standard {@link Predicate}
    426     * @since 3.10
    427     */
    428    public static <I> Predicate<I> asPredicate(final FailablePredicate<I, ?> predicate) {
    429        return input -> test(predicate, input);
    430    }
    431
    432    /**
    433     * Converts the given {@link FailableRunnable} into a standard {@link Runnable}.
    434     *
    435     * @param runnable a {@link FailableRunnable}
    436     * @return a standard {@link Runnable}
    437     * @since 3.10
    438     */
    439    public static Runnable asRunnable(final FailableRunnable<?> runnable) {
    440        return () -> run(runnable);
    441    }
    442
    443    /**
    444     * Converts the given {@link FailableSupplier} into a standard {@link Supplier}.
    445     *
    446     * @param <O> the type supplied by the suppliers
    447     * @param supplier a {@link FailableSupplier}
    448     * @return a standard {@link Supplier}
    449     * @since 3.10
    450     */
    451    public static <O> Supplier<O> asSupplier(final FailableSupplier<O, ?> supplier) {
    452        return () -> get(supplier);
    453    }
    454
    455    /**
    456     * Calls a callable and rethrows any exception as a {@link RuntimeException}.
    457     *
    458     * @param callable the callable to call
    459     * @param <O> the return type of the callable
    460     * @param <T> the type of checked exception the callable may throw
    461     * @return the value returned from the callable
    462     */
    463    public static <O, T extends Throwable> O call(final FailableCallable<O, T> callable) {
    464        return get(callable::call);
    465    }
    466
    467    /**
    468     * Invokes a supplier, and returns the result.
    469     *
    470     * @param supplier The supplier to invoke.
    471     * @param <O> The suppliers output type.
    472     * @param <T> The type of checked exception, which the supplier can throw.
    473     * @return The object, which has been created by the supplier
    474     * @since 3.10
    475     */
    476    public static <O, T extends Throwable> O get(final FailableSupplier<O, T> supplier) {
    477        try {
    478            return supplier.get();
    479        } catch (final Throwable t) {
    480            throw rethrow(t);
    481        }
    482    }
    483
    484    /**
    485     * Invokes a boolean supplier, and returns the result.
    486     *
    487     * @param supplier The boolean supplier to invoke.
    488     * @param <T> The type of checked exception, which the supplier can throw.
    489     * @return The boolean, which has been created by the supplier
    490     */
    491    private static <T extends Throwable> boolean getAsBoolean(final FailableBooleanSupplier<T> supplier) {
    492        try {
    493            return supplier.getAsBoolean();
    494        } catch (final Throwable t) {
    495            throw rethrow(t);
    496        }
    497    }
    498
    499    /**
    500     * Rethrows a {@link Throwable} as an unchecked exception. If the argument is already unchecked, namely a
    501     * {@link RuntimeException} or {@link Error} then the argument will be rethrown without modification. If the
    502     * exception is {@link IOException} then it will be wrapped into a {@link UncheckedIOException}. In every other
    503     * cases the exception will be wrapped into a {@code
    504     * UndeclaredThrowableException}
    505     *
    506     * <p>
    507     * Note that there is a declared return type for this method, even though it never returns. The reason for that is
    508     * to support the usual pattern:
    509     * </p>
    510     *
    511     * <pre>
    512     * throw rethrow(myUncheckedException);</pre>
    513     *
    514     * <p>
    515     * instead of just calling the method. This pattern may help the Java compiler to recognize that at that point an
    516     * exception will be thrown and the code flow analysis will not demand otherwise mandatory commands that could
    517     * follow the method call, like a {@code return} statement from a value returning method.
    518     * </p>
    519     *
    520     * @param throwable The throwable to rethrow possibly wrapped into an unchecked exception
    521     * @return Never returns anything, this method never terminates normally.
    522     */
    523    public static RuntimeException rethrow(final Throwable throwable) {
    524        Objects.requireNonNull(throwable, "throwable");
    525        ExceptionUtils.throwUnchecked(throwable);
    526        if (throwable instanceof IOException) {
    527            throw new UncheckedIOException((IOException) throwable);
    528        }
    529        throw new UndeclaredThrowableException(throwable);
    530    }
    531
    532    /**
    533     * Runs a runnable and rethrows any exception as a {@link RuntimeException}.
    534     *
    535     * @param runnable The runnable to run
    536     * @param <T> the type of checked exception the runnable may throw
    537     */
    538    public static <T extends Throwable> void run(final FailableRunnable<T> runnable) {
    539        try {
    540            runnable.run();
    541        } catch (final Throwable t) {
    542            throw rethrow(t);
    543        }
    544    }
    545
    546    /**
    547     * Converts the given collection into a {@link FailableStream}. The {@link FailableStream} consists of the
    548     * collections elements. Shortcut for
    549     *
    550     * <pre>
    551     * Functions.stream(collection.stream());</pre>
    552     *
    553     * @param collection The collection, which is being converted into a {@link FailableStream}.
    554     * @param <O> The collections element type. (In turn, the result streams element type.)
    555     * @return The created {@link FailableStream}.
    556     * @since 3.10
    557     */
    558    public static <O> FailableStream<O> stream(final Collection<O> collection) {
    559        return new FailableStream<>(collection.stream());
    560    }
    561
    562    /**
    563     * Converts the given stream into a {@link FailableStream}. The {@link FailableStream} consists of the same
    564     * elements, than the input stream. However, failable lambdas, like {@link FailablePredicate},
    565     * {@link FailableFunction}, and {@link FailableConsumer} may be applied, rather than {@link Predicate},
    566     * {@link Function}, {@link Consumer}, etc.
    567     *
    568     * @param stream The stream, which is being converted into a {@link FailableStream}.
    569     * @param <O> The streams element type.
    570     * @return The created {@link FailableStream}.
    571     * @since 3.10
    572     */
    573    public static <O> FailableStream<O> stream(final Stream<O> stream) {
    574        return new FailableStream<>(stream);
    575    }
    576
    577    /**
    578     * Tests a predicate and rethrows any exception as a {@link RuntimeException}.
    579     *
    580     * @param predicate the predicate to test
    581     * @param object1 the first input to test by {@code predicate}
    582     * @param object2 the second input to test by {@code predicate}
    583     * @param <O1> the type of the first argument the predicate tests
    584     * @param <O2> the type of the second argument the predicate tests
    585     * @param <T> the type of checked exception the predicate may throw
    586     * @return the boolean value returned by the predicate
    587     */
    588    public static <O1, O2, T extends Throwable> boolean test(final FailableBiPredicate<O1, O2, T> predicate,
    589        final O1 object1, final O2 object2) {
    590        return getAsBoolean(() -> predicate.test(object1, object2));
    591    }
    592
    593    /**
    594     * Tests a predicate and rethrows any exception as a {@link RuntimeException}.
    595     *
    596     * @param predicate the predicate to test
    597     * @param object the input to test by {@code predicate}
    598     * @param <O> the type of argument the predicate tests
    599     * @param <T> the type of checked exception the predicate may throw
    600     * @return the boolean value returned by the predicate
    601     */
    602    public static <O, T extends Throwable> boolean test(final FailablePredicate<O, T> predicate, final O object) {
    603        return getAsBoolean(() -> predicate.test(object));
    604    }
    605
    606    /**
    607     * A simple try-with-resources implementation, that can be used, if your objects do not implement the
    608     * {@link AutoCloseable} interface. The method executes the {@code action}. The method guarantees, that <em>all</em>
    609     * the {@code resources} are being executed, in the given order, afterwards, and regardless of success, or failure.
    610     * If either the original action, or any of the resource action fails, then the <em>first</em> failure (AKA
    611     * {@link Throwable}) is rethrown. Example use:
    612     *
    613     * <pre>
    614     * {@code
    615     *     final FileInputStream fis = new FileInputStream("my.file");
    616     *     Functions.tryWithResources(useInputStream(fis), null, () -> fis.close());
    617     * }</pre>
    618     *
    619     * @param action The action to execute. This object <em>will</em> always be invoked.
    620     * @param errorHandler An optional error handler, which will be invoked finally, if any error occurred. The error
    621     *        handler will receive the first error, AKA {@link Throwable}.
    622     * @param resources The resource actions to execute. <em>All</em> resource actions will be invoked, in the given
    623     *        order. A resource action is an instance of {@link FailableRunnable}, which will be executed.
    624     * @see #tryWithResources(FailableRunnable, FailableRunnable...)
    625     */
    626    @SafeVarargs
    627    public static void tryWithResources(final FailableRunnable<? extends Throwable> action,
    628        final FailableConsumer<Throwable, ? extends Throwable> errorHandler,
    629        final FailableRunnable<? extends Throwable>... resources) {
    630        final org.apache.commons.lang3.function.FailableRunnable<?>[] fr = new org.apache.commons.lang3.function.FailableRunnable[resources.length];
    631        Arrays.setAll(fr, i -> () -> resources[i].run());
    632        Failable.tryWithResources(action::run, errorHandler != null ? errorHandler::accept : null, fr);
    633    }
    634
    635    /**
    636     * A simple try-with-resources implementation, that can be used, if your objects do not implement the
    637     * {@link AutoCloseable} interface. The method executes the {@code action}. The method guarantees, that <em>all</em>
    638     * the {@code resources} are being executed, in the given order, afterwards, and regardless of success, or failure.
    639     * If either the original action, or any of the resource action fails, then the <em>first</em> failure (AKA
    640     * {@link Throwable}) is rethrown. Example use:
    641     *
    642     * <pre>
    643     * {@code
    644     *     final FileInputStream fis = new FileInputStream("my.file");
    645     *     Functions.tryWithResources(useInputStream(fis), () -> fis.close());
    646     * }</pre>
    647     *
    648     * @param action The action to execute. This object <em>will</em> always be invoked.
    649     * @param resources The resource actions to execute. <em>All</em> resource actions will be invoked, in the given
    650     *        order. A resource action is an instance of {@link FailableRunnable}, which will be executed.
    651     * @see #tryWithResources(FailableRunnable, FailableConsumer, FailableRunnable...)
    652     */
    653    @SafeVarargs
    654    public static void tryWithResources(final FailableRunnable<? extends Throwable> action,
    655        final FailableRunnable<? extends Throwable>... resources) {
    656        tryWithResources(action, null, resources);
    657    }
    658}