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