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 * https://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 */ 017 018package org.apache.commons.lang3.function; 019 020import java.io.IOException; 021import java.io.UncheckedIOException; 022import java.lang.reflect.UndeclaredThrowableException; 023import java.util.Collection; 024import java.util.Objects; 025import java.util.Optional; 026import java.util.concurrent.Callable; 027import java.util.function.BiConsumer; 028import java.util.function.BiFunction; 029import java.util.function.BiPredicate; 030import java.util.function.Consumer; 031import java.util.function.Function; 032import java.util.function.Predicate; 033import java.util.function.Supplier; 034import java.util.stream.Stream; 035 036import org.apache.commons.lang3.exception.ExceptionUtils; 037import org.apache.commons.lang3.stream.Streams; 038import org.apache.commons.lang3.stream.Streams.FailableStream; 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, like instances of {@link Exception}. This enforces the use of 044 * constructs like: 045 * 046 * <pre>{@code 047 * Consumer<java.lang.reflect.Method> consumer = m -> { 048 * try { 049 * m.invoke(o, args); 050 * } catch (Throwable t) { 051 * throw Failable.rethrow(t); 052 * } 053 * }; 054 * } 055 * </pre> 056 * 057 * <p> 058 * By replacing a {@link java.util.function.Consumer Consumer<O>} with a {@link FailableConsumer 059 * FailableConsumer<O,? extends Throwable>}, this can be written like follows: 060 * </p> 061 * 062 * <pre> 063 * Functions.accept((m) -> m.invoke(o, args)); 064 * </pre> 065 * 066 * <p> 067 * Obviously, the second version is much more concise and the spirit of Lambda expressions is met better than the second 068 * version. 069 * </p> 070 * 071 * @since 3.11 072 */ 073public class Failable { 074 075 /** 076 * Consumes a consumer and rethrows any exception as a {@link RuntimeException}. 077 * 078 * @param consumer the consumer to accept, may be null for a noop. 079 * @param object1 the first object to consume by {@code consumer} 080 * @param object2 the second object to consume by {@code consumer} 081 * @param <T> the type of the first argument the consumer accepts 082 * @param <U> the type of the second argument the consumer accepts 083 * @param <E> the type of checked exception the consumer may throw 084 */ 085 public static <T, U, E extends Throwable> void accept(final FailableBiConsumer<T, U, E> consumer, final T object1, 086 final U object2) { 087 run(consumer, () -> consumer.accept(object1, object2)); 088 } 089 090 /** 091 * Consumes a consumer and rethrows any exception as a {@link RuntimeException}. 092 * 093 * @param consumer the consumer to accept, may be null for a noop. 094 * @param object the object to consume by {@code consumer} 095 * @param <T> the type the consumer accepts 096 * @param <E> the type of checked exception the consumer may throw 097 */ 098 public static <T, E extends Throwable> void accept(final FailableConsumer<T, E> consumer, final T object) { 099 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}