1 /*
2 * Licensed to the Apache Software Foundation (ASF) under one or more
3 * contributor license agreements. See the NOTICE file distributed with
4 * this work for additional information regarding copyright ownership.
5 * The ASF licenses this file to You under the Apache License, Version 2.0
6 * (the "License"); you may not use this file except in compliance with
7 * the License. You may obtain a copy of the License at
8 *
9 * https://www.apache.org/licenses/LICENSE-2.0
10 *
11 * Unless required by applicable law or agreed to in writing, software
12 * distributed under the License is distributed on an "AS IS" BASIS,
13 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14 * See the License for the specific language governing permissions and
15 * limitations under the License.
16 */
17
18 package org.apache.commons.lang3.function;
19
20 import java.io.IOException;
21 import java.io.UncheckedIOException;
22 import java.lang.reflect.UndeclaredThrowableException;
23 import java.util.Collection;
24 import java.util.Objects;
25 import java.util.Optional;
26 import java.util.concurrent.Callable;
27 import java.util.function.BiConsumer;
28 import java.util.function.BiFunction;
29 import java.util.function.BiPredicate;
30 import java.util.function.Consumer;
31 import java.util.function.Function;
32 import java.util.function.Predicate;
33 import java.util.function.Supplier;
34 import java.util.stream.Stream;
35
36 import org.apache.commons.lang3.exception.ExceptionUtils;
37 import org.apache.commons.lang3.stream.Streams;
38 import org.apache.commons.lang3.stream.Streams.FailableStream;
39
40 /**
41 * This class provides utility functions, and classes for working with the {@code java.util.function} package, or more
42 * generally, with Java 8 lambdas. More specifically, it attempts to address the fact that lambdas are supposed not to
43 * throw Exceptions, at least not checked Exceptions, like instances of {@link Exception}. This enforces the use of
44 * constructs like:
45 *
46 * <pre>{@code
47 * Consumer<java.lang.reflect.Method> consumer = m -> {
48 * try {
49 * m.invoke(o, args);
50 * } catch (Throwable t) {
51 * throw Failable.rethrow(t);
52 * }
53 * };
54 * }
55 * </pre>
56 *
57 * <p>
58 * By replacing a {@link java.util.function.Consumer Consumer<O>} with a {@link FailableConsumer
59 * FailableConsumer<O,? extends Throwable>}, this can be written like follows:
60 * </p>
61 *
62 * <pre>{@code
63 * Functions.accept(m -> m.invoke(o, args));
64 * }</pre>
65 *
66 * <p>
67 * Obviously, the second version is much more concise and the spirit of Lambda expressions is met better than the second
68 * version.
69 * </p>
70 *
71 * @since 3.11
72 */
73 public class Failable {
74
75 /**
76 * Consumes a consumer and rethrows any exception as a {@link RuntimeException}.
77 *
78 * @param consumer the consumer to accept, may be null for a noop.
79 * @param object1 the first object to consume by {@code consumer}
80 * @param object2 the second object to consume by {@code consumer}
81 * @param <T> the type of the first argument the consumer accepts
82 * @param <U> the type of the second argument the consumer accepts
83 * @param <E> the type of checked exception the consumer may throw
84 */
85 public static <T, U, E extends Throwable> void accept(final FailableBiConsumer<T, U, E> consumer, final T object1,
86 final U object2) {
87 run(consumer, () -> consumer.accept(object1, object2));
88 }
89
90 /**
91 * Consumes a consumer and rethrows any exception as a {@link RuntimeException}.
92 *
93 * @param consumer the consumer to accept, may be null for a noop.
94 * @param object the object to consume by {@code consumer}
95 * @param <T> the type the consumer accepts
96 * @param <E> the type of checked exception the consumer may throw
97 */
98 public static <T, E extends Throwable> void accept(final FailableConsumer<T, E> consumer, final T object) {
99 run(consumer, () -> consumer.accept(object));
100 }
101
102 /**
103 * Consumes a consumer and rethrows any exception as a {@link RuntimeException}.
104 *
105 * @param consumer the consumer to accept, may be null for a noop.
106 * @param value the value to consume by {@code consumer}
107 * @param <E> the type of checked exception the consumer may throw
108 */
109 public static <E extends Throwable> void accept(final FailableDoubleConsumer<E> consumer, final double value) {
110 run(consumer, () -> consumer.accept(value));
111 }
112 /**
113 * Consumes a consumer and rethrows any exception as a {@link RuntimeException}.
114 *
115 * @param consumer the consumer to accept, may be null for a noop.
116 * @param value the value to consume by {@code consumer}
117 * @param <E> the type of checked exception the consumer may throw
118 */
119 public static <E extends Throwable> void accept(final FailableIntConsumer<E> consumer, final int value) {
120 run(consumer, () -> consumer.accept(value));
121 }
122
123 /**
124 * Consumes a consumer and rethrows any exception as a {@link RuntimeException}.
125 *
126 * @param consumer the consumer to accept, may be null for a noop.
127 * @param value the value to consume by {@code consumer}
128 * @param <E> the type of checked exception the consumer may throw
129 */
130 public static <E extends Throwable> void accept(final FailableLongConsumer<E> consumer, final long value) {
131 run(consumer, () -> consumer.accept(value));
132 }
133
134 /**
135 * Applies a function and rethrows any exception as a {@link RuntimeException}.
136 *
137 * @param function the function to apply
138 * @param input1 the first input to apply {@code function} on
139 * @param input2 the second input to apply {@code function} on
140 * @param <T> the type of the first argument the function accepts
141 * @param <U> the type of the second argument the function accepts
142 * @param <R> the return type of the function
143 * @param <E> the type of checked exception the function may throw
144 * @return the value returned from the function
145 */
146 public static <T, U, R, E extends Throwable> R apply(final FailableBiFunction<T, U, R, E> function, final T input1,
147 final U input2) {
148 return get(() -> function.apply(input1, input2));
149 }
150
151 /**
152 * Applies a function and rethrows any exception as a {@link RuntimeException}.
153 *
154 * @param function the function to apply
155 * @param input the input to apply {@code function} on
156 * @param <T> the type of the argument the function accepts
157 * @param <R> the return type of the function
158 * @param <E> the type of checked exception the function may throw
159 * @return the value returned from the function
160 */
161 public static <T, R, E extends Throwable> R apply(final FailableFunction<T, R, E> function, final T input) {
162 return get(() -> function.apply(input));
163 }
164
165 /**
166 * Applies a function and rethrows any exception as a {@link RuntimeException}.
167 *
168 * @param function the function to apply
169 * @param left the first input to apply {@code function} on
170 * @param right the second input to apply {@code function} on
171 * @param <E> the type of checked exception the function may throw
172 * @return the value returned from the function
173 */
174 public static <E extends Throwable> double applyAsDouble(final FailableDoubleBinaryOperator<E> function,
175 final double left, final double right) {
176 return getAsDouble(() -> function.applyAsDouble(left, right));
177 }
178
179 /**
180 * Applies a value to a function if the value isn't {@code null}, otherwise the method returns {@code null}. If the value isn't {@code null} then return the
181 * result of the applying function.
182 *
183 * <pre>{@code
184 * Failable.applyNonNull("a", String::toUpperCase) = "A"
185 * Failable.applyNonNull(null, String::toUpperCase) = null
186 * Failable.applyNonNull("a", s -> null) = null
187 * }</pre>
188 * <p>
189 * Useful when working with expressions that may return {@code null} as it allows a single-line expression without using temporary local variables or
190 * evaluating expressions twice. Provides an alternative to using {@link Optional} that is shorter and has less allocation.
191 * </p>
192 *
193 * @param <T> The type of the input of this method and the function.
194 * @param <R> The type of the result of the function and this method.
195 * @param <E> The type of thrown exception or error.
196 * @param value The value to apply the function to, may be {@code null}.
197 * @param mapper The function to apply, must not be {@code null}.
198 * @return The result of the function (which may be {@code null}) or {@code null} if the input value is {@code null}.
199 * @throws E Thrown by the given function.
200 * @see #applyNonNull(Object, FailableFunction, FailableFunction)
201 * @see #applyNonNull(Object, FailableFunction, FailableFunction, FailableFunction)
202 * @since 3.19.0
203 */
204 public static <T, R, E extends Throwable> R applyNonNull(final T value, final FailableFunction<? super T, ? extends R, E> mapper) throws E {
205 return value != null ? Objects.requireNonNull(mapper, "mapper").apply(value) : null;
206 }
207
208 /**
209 * Applies values to a chain of functions, where a {@code null} can short-circuit each step. A function is only applied if the previous value is not
210 * {@code null}, otherwise this method returns {@code null}.
211 *
212 * <pre>{@code
213 * Failable.applyNonNull(" a ", String::toUpperCase, String::trim) = "A"
214 * Failable.applyNonNull(null, String::toUpperCase, String::trim) = null
215 * Failable.applyNonNull(" a ", s -> null, String::trim) = null
216 * Failable.applyNonNull(" a ", String::toUpperCase, s -> null) = null
217 * }</pre>
218 * <p>
219 * Useful when working with expressions that may return {@code null} as it allows a single-line expression without using temporary local variables or
220 * evaluating expressions twice. Provides an alternative to using {@link Optional} that is shorter and has less allocation.
221 * </p>
222 *
223 * @param <T> The type of the input of this method and the first function.
224 * @param <U> The type of the result of the first function and the input to the second function.
225 * @param <R> The type of the result of the second function and this method.
226 * @param <E1> The type of thrown exception or error by the first function.
227 * @param <E2> The type of thrown exception or error by the second function.
228 * @param value1 The value to apply the functions to, may be {@code null}.
229 * @param mapper1 The first function to apply, must not be {@code null}.
230 * @param mapper2 The second function to apply, must not be {@code null}.
231 * @return The result of the final function (which may be {@code null}) or {@code null} if the input value or any intermediate value is {@code null}.
232 * @throws E1 Thrown by the first function.
233 * @throws E2 Thrown by the second function.
234 * @see #applyNonNull(Object, FailableFunction)
235 * @see #applyNonNull(Object, FailableFunction, FailableFunction, FailableFunction)
236 * @since 3.19.0
237 */
238 public static <T, U, R, E1 extends Throwable, E2 extends Throwable> R applyNonNull(final T value1,
239 final FailableFunction<? super T, ? extends U, E1> mapper1, final FailableFunction<? super U, ? extends R, E2> mapper2) throws E1, E2 {
240 return applyNonNull(applyNonNull(value1, mapper1), mapper2);
241 }
242
243 /**
244 * Applies values to a chain of functions, where a {@code null} can short-circuit each step. A function is only applied if the previous value is not
245 * {@code null}, otherwise this method returns {@code null}.
246 *
247 * <pre>{@code
248 * Failable.applyNonNull(" abc ", String::toUpperCase, String::trim, StringUtils::reverse) = "CBA"
249 * Failable.applyNonNull(null, String::toUpperCase, String::trim, StringUtils::reverse) = null
250 * Failable.applyNonNull(" abc ", s -> null, String::trim, StringUtils::reverse) = null
251 * Failable.applyNonNull(" abc ", String::toUpperCase, s -> null, StringUtils::reverse) = null
252 * Failable.applyNonNull(" abc ", String::toUpperCase, String::trim, s -> null) = null
253 * }</pre>
254 * <p>
255 * Useful when working with expressions that may return {@code null} as it allows a single-line expression without using temporary local variables or
256 * evaluating expressions twice. Provides an alternative to using {@link Optional} that is shorter and has less allocation.
257 * </p>
258 *
259 * @param <T> The type of the input of this method and the first function.
260 * @param <U> The type of the result of the first function and the input to the second function.
261 * @param <V> The type of the result of the second function and the input to the third function.
262 * @param <R> The type of the result of the third function and this method.
263 * @param <E1> The type of thrown exception or error by the first function.
264 * @param <E2> The type of thrown exception or error by the second function.
265 * @param <E3> The type of thrown exception or error by the second function.
266 * @param value1 The value to apply the first function, may be {@code null}.
267 * @param mapper1 The first function to apply, must not be {@code null}.
268 * @param mapper2 The second function to apply, must not be {@code null}.
269 * @param mapper3 The third function to apply, must not be {@code null}.
270 * @return The result of the final function (which may be {@code null}) or {@code null} if the input value or any intermediate value is {@code null}.
271 * @throws E1 Thrown by the first function.
272 * @throws E2 Thrown by the second function.
273 * @throws E3 Thrown by the third function.
274 * @see #applyNonNull(Object, FailableFunction)
275 * @see #applyNonNull(Object, FailableFunction, FailableFunction)
276 * @since 3.19.0
277 */
278 public static <T, U, V, R, E1 extends Throwable, E2 extends Throwable, E3 extends Throwable> R applyNonNull(final T value1,
279 final FailableFunction<? super T, ? extends U, E1> mapper1, final FailableFunction<? super U, ? extends V, E2> mapper2,
280 final FailableFunction<? super V, ? extends R, E3> mapper3) throws E1, E2, E3 {
281 return applyNonNull(applyNonNull(applyNonNull(value1, mapper1), mapper2), mapper3);
282 }
283
284 /**
285 * Converts the given {@link FailableBiConsumer} into a standard {@link BiConsumer}.
286 *
287 * @param <T> the type of the first argument of the consumers
288 * @param <U> the type of the second argument of the consumers
289 * @param consumer a failable {@link BiConsumer}
290 * @return a standard {@link BiConsumer}
291 */
292 public static <T, U> BiConsumer<T, U> asBiConsumer(final FailableBiConsumer<T, U, ?> consumer) {
293 return (input1, input2) -> accept(consumer, input1, input2);
294 }
295
296 /**
297 * Converts the given {@link FailableBiFunction} into a standard {@link BiFunction}.
298 *
299 * @param <T> the type of the first argument of the input of the functions
300 * @param <U> the type of the second argument of the input of the functions
301 * @param <R> the type of the output of the functions
302 * @param function a {@link FailableBiFunction}
303 * @return a standard {@link BiFunction}
304 */
305 public static <T, U, R> BiFunction<T, U, R> asBiFunction(final FailableBiFunction<T, U, R, ?> function) {
306 return (input1, input2) -> apply(function, input1, input2);
307 }
308
309 /**
310 * Converts the given {@link FailableBiPredicate} into a standard {@link BiPredicate}.
311 *
312 * @param <T> the type of the first argument used by the predicates
313 * @param <U> the type of the second argument used by the predicates
314 * @param predicate a {@link FailableBiPredicate}
315 * @return a standard {@link BiPredicate}
316 */
317 public static <T, U> BiPredicate<T, U> asBiPredicate(final FailableBiPredicate<T, U, ?> predicate) {
318 return (input1, input2) -> test(predicate, input1, input2);
319 }
320
321 /**
322 * Converts the given {@link FailableCallable} into a standard {@link Callable}.
323 *
324 * @param <V> the type used by the callables
325 * @param callable a {@link FailableCallable}
326 * @return a standard {@link Callable}
327 */
328 public static <V> Callable<V> asCallable(final FailableCallable<V, ?> callable) {
329 return () -> call(callable);
330 }
331
332 /**
333 * Converts the given {@link FailableConsumer} into a standard {@link Consumer}.
334 *
335 * @param <T> the type used by the consumers
336 * @param consumer a {@link FailableConsumer}
337 * @return a standard {@link Consumer}
338 */
339 public static <T> Consumer<T> asConsumer(final FailableConsumer<T, ?> consumer) {
340 return input -> accept(consumer, input);
341 }
342
343 /**
344 * Converts the given {@link FailableFunction} into a standard {@link Function}.
345 *
346 * @param <T> the type of the input of the functions
347 * @param <R> the type of the output of the functions
348 * @param function a {code FailableFunction}
349 * @return a standard {@link Function}
350 */
351 public static <T, R> Function<T, R> asFunction(final FailableFunction<T, R, ?> function) {
352 return input -> apply(function, input);
353 }
354
355 /**
356 * Converts the given {@link FailablePredicate} into a standard {@link Predicate}.
357 *
358 * @param <T> the type used by the predicates
359 * @param predicate a {@link FailablePredicate}
360 * @return a standard {@link Predicate}
361 */
362 public static <T> Predicate<T> asPredicate(final FailablePredicate<T, ?> predicate) {
363 return input -> test(predicate, input);
364 }
365
366 /**
367 * Converts the given {@link FailableRunnable} into a standard {@link Runnable}.
368 *
369 * @param runnable a {@link FailableRunnable}
370 * @return a standard {@link Runnable}
371 */
372 public static Runnable asRunnable(final FailableRunnable<?> runnable) {
373 return () -> run(runnable);
374 }
375
376 /**
377 * Converts the given {@link FailableSupplier} into a standard {@link Supplier}.
378 *
379 * @param <T> the type supplied by the suppliers
380 * @param supplier a {@link FailableSupplier}
381 * @return a standard {@link Supplier}
382 */
383 public static <T> Supplier<T> asSupplier(final FailableSupplier<T, ?> supplier) {
384 return () -> get(supplier);
385 }
386
387 /**
388 * Calls a callable and rethrows any exception as a {@link RuntimeException}.
389 *
390 * @param callable the callable to call
391 * @param <V> the return type of the callable
392 * @param <E> the type of checked exception the callable may throw
393 * @return the value returned from the callable
394 */
395 public static <V, E extends Throwable> V call(final FailableCallable<V, E> callable) {
396 return get(callable::call);
397 }
398
399 /**
400 * Invokes a supplier, and returns the result.
401 *
402 * @param supplier The supplier to invoke.
403 * @param <T> The suppliers output type.
404 * @param <E> The type of checked exception, which the supplier can throw.
405 * @return The object, which has been created by the supplier
406 */
407 public static <T, E extends Throwable> T get(final FailableSupplier<T, E> supplier) {
408 try {
409 return supplier.get();
410 } catch (final Throwable t) {
411 throw rethrow(t);
412 }
413 }
414
415 /**
416 * Invokes a boolean supplier, and returns the result.
417 *
418 * @param supplier The boolean supplier to invoke.
419 * @param <E> The type of checked exception, which the supplier can throw.
420 * @return The boolean, which has been created by the supplier
421 */
422 public static <E extends Throwable> boolean getAsBoolean(final FailableBooleanSupplier<E> supplier) {
423 try {
424 return supplier.getAsBoolean();
425 } catch (final Throwable t) {
426 throw rethrow(t);
427 }
428 }
429
430 /**
431 * Invokes a double supplier, and returns the result.
432 *
433 * @param supplier The double supplier to invoke.
434 * @param <E> The type of checked exception, which the supplier can throw.
435 * @return The double, which has been created by the supplier
436 */
437 public static <E extends Throwable> double getAsDouble(final FailableDoubleSupplier<E> supplier) {
438 try {
439 return supplier.getAsDouble();
440 } catch (final Throwable t) {
441 throw rethrow(t);
442 }
443 }
444
445 /**
446 * Invokes an int supplier, and returns the result.
447 *
448 * @param supplier The int supplier to invoke.
449 * @param <E> The type of checked exception, which the supplier can throw.
450 * @return The int, which has been created by the supplier
451 */
452 public static <E extends Throwable> int getAsInt(final FailableIntSupplier<E> supplier) {
453 try {
454 return supplier.getAsInt();
455 } catch (final Throwable t) {
456 throw rethrow(t);
457 }
458 }
459
460 /**
461 * Invokes a long supplier, and returns the result.
462 *
463 * @param supplier The long supplier to invoke.
464 * @param <E> The type of checked exception, which the supplier can throw.
465 * @return The long, which has been created by the supplier
466 */
467 public static <E extends Throwable> long getAsLong(final FailableLongSupplier<E> supplier) {
468 try {
469 return supplier.getAsLong();
470 } catch (final Throwable t) {
471 throw rethrow(t);
472 }
473 }
474
475 /**
476 * Invokes a short supplier, and returns the result.
477 *
478 * @param supplier The short supplier to invoke.
479 * @param <E> The type of checked exception, which the supplier can throw.
480 * @return The short, which has been created by the supplier
481 */
482 public static <E extends Throwable> short getAsShort(final FailableShortSupplier<E> supplier) {
483 try {
484 return supplier.getAsShort();
485 } catch (final Throwable t) {
486 throw rethrow(t);
487 }
488 }
489
490 /**
491 * Rethrows a {@link Throwable} as an unchecked exception. If the argument is already unchecked, namely a
492 * {@link RuntimeException} or {@link Error} then the argument will be rethrown without modification. If the
493 * exception is {@link IOException} then it will be wrapped into a {@link UncheckedIOException}. In every other
494 * cases the exception will be wrapped into a {@code
495 * UndeclaredThrowableException}
496 *
497 * <p>
498 * Note that there is a declared return type for this method, even though it never returns. The reason for that is
499 * to support the usual pattern:
500 * </p>
501 *
502 * <pre>
503 * throw rethrow(myUncheckedException);
504 * </pre>
505 *
506 * <p>
507 * instead of just calling the method. This pattern may help the Java compiler to recognize that at that point an
508 * exception will be thrown and the code flow analysis will not demand otherwise mandatory commands that could
509 * follow the method call, like a {@code return} statement from a value returning method.
510 * </p>
511 *
512 * @param throwable The throwable to rethrow possibly wrapped into an unchecked exception
513 * @return Never returns anything, this method never terminates normally.
514 */
515 public static RuntimeException rethrow(final Throwable throwable) {
516 Objects.requireNonNull(throwable, "throwable");
517 ExceptionUtils.throwUnchecked(throwable);
518 if (throwable instanceof IOException) {
519 throw new UncheckedIOException((IOException) throwable);
520 }
521 throw new UndeclaredThrowableException(throwable);
522 }
523
524 /**
525 * Runs a runnable and rethrows any exception as a {@link RuntimeException}.
526 *
527 * @param runnable The runnable to run, may be null for a noop.
528 * @param <E> the type of checked exception the runnable may throw.
529 */
530 public static <E extends Throwable> void run(final FailableRunnable<E> runnable) {
531 if (runnable != null) {
532 try {
533 runnable.run();
534 } catch (final Throwable t) {
535 throw rethrow(t);
536 }
537 }
538 }
539
540 private static <E extends Throwable> void run(final Object test, final FailableRunnable<E> runnable) {
541 if (runnable != null && test != null) {
542 try {
543 runnable.run();
544 } catch (final Throwable t) {
545 throw rethrow(t);
546 }
547 }
548 }
549
550 /**
551 * Converts the given collection into a {@link FailableStream}. The {@link FailableStream} consists of the
552 * collections elements. Shortcut for
553 *
554 * <pre>
555 * Functions.stream(collection.stream());
556 * </pre>
557 *
558 * @param collection The collection, which is being converted into a {@link FailableStream}.
559 * @param <E> The collections element type. (In turn, the result streams element type.)
560 * @return The created {@link FailableStream}.
561 */
562 public static <E> FailableStream<E> stream(final Collection<E> collection) {
563 return new FailableStream<>(collection.stream());
564 }
565
566 /**
567 * Converts the given stream into a {@link FailableStream}. The {@link FailableStream} consists of the same
568 * elements, than the input stream. However, failable lambdas, like {@link FailablePredicate},
569 * {@link FailableFunction}, and {@link FailableConsumer} may be applied, rather than {@link Predicate},
570 * {@link Function}, {@link Consumer}, etc.
571 *
572 * @param stream The stream, which is being converted into a {@link FailableStream}.
573 * @param <T> The streams element type.
574 * @return The created {@link FailableStream}.
575 */
576 public static <T> FailableStream<T> stream(final Stream<T> stream) {
577 return new FailableStream<>(stream);
578 }
579
580 /**
581 * Tests a predicate and rethrows any exception as a {@link RuntimeException}.
582 *
583 * @param predicate the predicate to test
584 * @param object1 the first input to test by {@code predicate}
585 * @param object2 the second input to test by {@code predicate}
586 * @param <T> the type of the first argument the predicate tests
587 * @param <U> the type of the second argument the predicate tests
588 * @param <E> the type of checked exception the predicate may throw
589 * @return the boolean value returned by the predicate
590 */
591 public static <T, U, E extends Throwable> boolean test(final FailableBiPredicate<T, U, E> predicate,
592 final T object1, final U object2) {
593 return getAsBoolean(() -> predicate.test(object1, object2));
594 }
595
596 /**
597 * Tests a predicate and rethrows any exception as a {@link RuntimeException}.
598 *
599 * @param predicate the predicate to test
600 * @param object the input to test by {@code predicate}
601 * @param <T> the type of argument the predicate tests
602 * @param <E> the type of checked exception the predicate may throw
603 * @return the boolean value returned by the predicate
604 */
605 public static <T, E extends Throwable> boolean test(final FailablePredicate<T, E> predicate, final T object) {
606 return getAsBoolean(() -> predicate.test(object));
607 }
608
609 /**
610 * A simple try-with-resources implementation, that can be used, if your objects do not implement the
611 * {@link AutoCloseable} interface. The method executes the {@code action}. The method guarantees, that <em>all</em>
612 * the {@code resources} are being executed, in the given order, afterwards, and regardless of success, or failure.
613 * If either the original action, or any of the resource action fails, then the <em>first</em> failure (AKA
614 * {@link Throwable}) is rethrown. Example use:
615 *
616 * <pre>{@code
617 * final FileInputStream fis = new FileInputStream("my.file");
618 * Functions.tryWithResources(useInputStream(fis), null, () -> fis.close());
619 * }</pre>
620 *
621 * @param action The action to execute. This object <em>will</em> always be invoked.
622 * @param errorHandler An optional error handler, which will be invoked finally, if any error occurred. The error
623 * handler will receive the first error, AKA {@link Throwable}.
624 * @param resources The resource actions to execute. <em>All</em> resource actions will be invoked, in the given
625 * order. A resource action is an instance of {@link FailableRunnable}, which will be executed.
626 * @see #tryWithResources(FailableRunnable, FailableRunnable...)
627 */
628 @SafeVarargs
629 public static void tryWithResources(final FailableRunnable<? extends Throwable> action,
630 final FailableConsumer<Throwable, ? extends Throwable> errorHandler,
631 final FailableRunnable<? extends Throwable>... resources) {
632 final FailableConsumer<Throwable, ? extends Throwable> actualErrorHandler;
633 if (errorHandler == null) {
634 actualErrorHandler = Failable::rethrow;
635 } else {
636 actualErrorHandler = errorHandler;
637 }
638 Streams.of(resources).forEach(r -> Objects.requireNonNull(r, "runnable"));
639 Throwable th = null;
640 try {
641 action.run();
642 } catch (final Throwable t) {
643 th = t;
644 }
645 if (resources != null) {
646 for (final FailableRunnable<?> runnable : resources) {
647 try {
648 runnable.run();
649 } catch (final Throwable t) {
650 if (th == null) {
651 th = t;
652 }
653 }
654 }
655 }
656 if (th != null) {
657 try {
658 actualErrorHandler.accept(th);
659 } catch (final Throwable t) {
660 throw rethrow(t);
661 }
662 }
663 }
664
665 /**
666 * A simple try-with-resources implementation, that can be used, if your objects do not implement the
667 * {@link AutoCloseable} interface. The method executes the {@code action}. The method guarantees, that <em>all</em>
668 * the {@code resources} are being executed, in the given order, afterwards, and regardless of success, or failure.
669 * If either the original action, or any of the resource action fails, then the <em>first</em> failure (AKA
670 * {@link Throwable}) is rethrown. Example use:
671 *
672 * <pre>{@code
673 * final FileInputStream fis = new FileInputStream("my.file");
674 * Functions.tryWithResources(useInputStream(fis), () -> fis.close());
675 * }</pre>
676 *
677 * @param action The action to execute. This object <em>will</em> always be invoked.
678 * @param resources The resource actions to execute. <em>All</em> resource actions will be invoked, in the given
679 * order. A resource action is an instance of {@link FailableRunnable}, which will be executed.
680 * @see #tryWithResources(FailableRunnable, FailableConsumer, FailableRunnable...)
681 */
682 @SafeVarargs
683 public static void tryWithResources(final FailableRunnable<? extends Throwable> action, final FailableRunnable<? extends Throwable>... resources) {
684 tryWithResources(action, null, resources);
685 }
686
687 private Failable() {
688 // empty
689 }
690
691 }