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>{@code 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 /** 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}