diff --git a/src/main/java/com/machinezoo/noexception/Exceptions.java b/src/main/java/com/machinezoo/noexception/Exceptions.java index 345a445..67937df 100644 --- a/src/main/java/com/machinezoo/noexception/Exceptions.java +++ b/src/main/java/com/machinezoo/noexception/Exceptions.java @@ -13,217 +13,190 @@ * Typical usage: {@code Exceptions.silence().get(() -> my_throwing_lambda).orElse(fallback)} *
* Usage with checked exceptions: {@code Exceptions.silence().run(Exceptions.sneak().runnable(() -> my_throwing_lambda))} - * + * * @see NoException tutorial */ public final class Exceptions { - private static final Logger logger = LoggerFactory.getLogger(Exceptions.class); - private static final PropagatingHandler propagate = new PropagatingHandler(); - @Deprecated - private static final LoggingHandler log = new LoggingHandler(logger, () -> "Caught exception."); - private static final SilencingHandler silence = new SilencingHandler(); - private static final SneakingHandler sneak = new SneakingHandler(); - private static final WrappingHandler wrap = new WrappingHandler(); - private Exceptions() { - } - /** - * Returns {@code ExceptionHandler} that propagates (lets through) all exceptions. - * This exception handler is equivalent to having no exception handler at all. - * It is useful when switching among several exception handlers at runtime. - * - * @return propagating exception handler - */ - public static ExceptionHandler propagate() { - return propagate; - } - /** - * Returns {@code ExceptionHandler} that lets all exceptions through. - * This is an old deprecated alias for {@link #propagate()}. - * - * @return pass-through exception handler - * @deprecated Use {@link #propagate()} instead. - */ - @Deprecated - public static ExceptionHandler ignore() { - return propagate(); - } - /** - * Returns {@code ExceptionHandler} that lets all exceptions through. - * This is an old deprecated alias for {@link #propagate()}. - * - * @return pass-through exception handler - * @deprecated Use {@link #propagate()} instead. - */ - @Deprecated - public static ExceptionHandler pass() { - return propagate(); - } - /** - * Returns {@code ExceptionHandler} that writes all exceptions to common logger. - * Logs are written to SLF4J logger named after this class. - * This handler is convenient and a suitable default choice, - * but the single shared logger can make logs harder to filter. - * Use {@link #log(Logger)} to specify custom logger where filtering is important. - *
- * Typical usage: {@code Exceptions.log().run(() -> my_throwing_lambda)} - *
- * No exceptions are allowed through, not even {@code Error}s. - * If {@link InterruptedException} is caught, {@link Thread#interrupt()} is called. - * - * @return logging exception handler - * @see #log(Logger) - * @deprecated Use SLF4J extension instead. - */ - @Deprecated - public static ExceptionHandler log() { - return log; - } - /** - * Creates {@code ExceptionHandler} that writes all exceptions to the specified {@code logger}. - * Most application code can use the more convenient {@link #log()} method. - * Use {@link #log(Logger, String)} overload to specify unique message where necessary. - *
- * Typical usage: {@code Exceptions.log(logger).run(() -> my_throwing_lambda)} - *
- * No exceptions are allowed through, not even {@code Error}s. - * If {@link InterruptedException} is caught, {@link Thread#interrupt()} is called. - * - * @param logger - * where all exceptions are logged - * @return exception handler with custom logger - * @throws NullPointerException - * if {@code logger} is {@code null} - * @see #log() - * @see #log(Logger, String) - * @deprecated Use SLF4J extension instead. - */ - @Deprecated - public static ExceptionHandler log(Logger logger) { - return new LoggingHandler(logger, () -> "Caught exception."); - } - /** - * Creates {@code ExceptionHandler} that writes all exceptions to the specified {@code logger} with the specified {@code message}. - * If you just need to specify custom logger, use {@link #log(Logger)}. - * This overload allows for differentiating or explanatory message. - * If the message is expensive to construct, use {@link #log(Logger, Supplier)} method. - *
- * Typical usage: {@code Exceptions.log(logger, "Failed to do X.").run(() -> my_throwing_lambda)} - *
- * No exceptions are allowed through, not even {@code Error}s. - * If {@link InterruptedException} is caught, {@link Thread#interrupt()} is called. - * - * @param logger - * where all exceptions are logged - * @param message - * introduces every exception in the log - * @return exception handler with custom logger and message - * @throws NullPointerException - * if {@code logger} or {@code message} is {@code null} - * @see #log(Logger) - * @see #log(Logger, Supplier) - * @deprecated Use SLF4J extension instead. - */ - @Deprecated - public static ExceptionHandler log(Logger logger, String message) { - Objects.requireNonNull(message); - return new LoggingHandler(logger, () -> message); - } - /** - * Creates {@code ExceptionHandler} that writes all exceptions to the specified {@code logger} with lazily evaluated {@code message}. - * If the message does not need lazy evaluation, use the {@link #log(Logger, String)} method. - * This overload constructs expensive messages lazily only when exception is caught. - * If {@code message} throws, the exception is logged and fallback message is used to log the original exception. - *
- * Typical usage: {@code Exceptions.log(logger, () -> "Exception in " + this).run(() -> my_throwing_lambda)} - *
- * No exceptions are allowed through, not even {@code Error}s.
- * If {@link InterruptedException} is caught, {@link Thread#interrupt()} is called.
- *
- * @param logger
- * where all exceptions are logged
- * @param message
- * a {@link Supplier} that is lazily evaluated to generate log message
- * @return exception handler with custom logger and lazily evaluated message
- * @throws NullPointerException
- * if {@code logger} or {@code message} is {@code null}
- * @see #log(Logger, String)
- * @deprecated Use SLF4J extension instead.
- */
- @Deprecated
- public static ExceptionHandler log(Logger logger, Supplier
- * Typical usage: {@code Exceptions.silence().run(() -> my_throwing_lambda)}
- *
- * No exceptions are allowed through, not even {@code Error}s.
- * If {@link InterruptedException} is caught, {@link Thread#interrupt()} is called.
- *
- * @return exception handler that ignores all exceptions
- */
- public static ExceptionHandler silence() {
- return silence;
- }
- /**
- * Returns {@code CheckedExceptionHandler} that lets through checked exceptions without declaring them.
- * All exceptions are allowed through unmodified, including checked ones, even though no checked exceptions are declared.
- *
- * Typical usage: {@code Exceptions.sneak().run(() -> my_throwing_lambda)}
- *
- * This is the recommended {@code CheckedExceptionHandler}, because it does not obfuscate the original exception in any way.
- * Use {@link #wrap()} if using sneaky exceptions is not possible or not desirable.
- *
- * Sneaky throw is implemented using a neat trick with type erasure
- * that persuades java compiler to tolerate throwing undeclared checked exception from specially crafted generic method.
- * The trick is safe. It is legal java code and JVMs do not mind it. It is just considered dirty by some developers.
- *
- * @return exception handler that lets checked exceptions through
- * @see #wrap()
- */
- public static CheckedExceptionHandler sneak() {
- return sneak;
- }
- /**
- * Returns {@code CheckedExceptionHandler} that wraps all checked exceptions.
- * Unchecked exceptions are passed through unmodified.
- * Checked exceptions are wrapped in {@link UndeclaredThrowableException}.
- * Use {@link #sneak()} to avoid wrapping.
- * Use {@link #wrap(Function)} to specify a custom wrapper.
- *
- * Typical usage: {@code Exceptions.wrap().run(() -> my_throwing_lambda)}
- *
- * If {@link InterruptedException} is caught, {@link Thread#interrupt()} is called.
- *
- * @return exception handler that wraps checked exceptions
- * @see #sneak()
- * @see #wrap(Function)
- */
- public static CheckedExceptionHandler wrap() {
- return wrap;
- }
- /**
- * Creates {@code CheckedExceptionHandler} that applies custom wrapper to checked exceptions.
- * Unchecked exceptions are passed through unmodified.
- * Checked exceptions are passed to {@code wrapper} and the resulting unchecked exception is thrown.
- * Use {@link #sneak()} to avoid wrapping and {@link #wrap()} to use standard wrapper.
- *
- * Typical usage: {@code Exceptions.wrap(MyWrapperException::new).run(() -> my_throwing_lambda)}
- *
- * If {@link InterruptedException} is caught, {@link Thread#interrupt()} is called before invoking the {@code wrapper}.
- *
- * @param wrapper
- * method converting checked exception into an unchecked one, often just exception constructor reference
- * @return exception handler with custom exception transform
- * @throws NullPointerException
- * if {@code wrapper} is {@code null}
- * @see #sneak()
- * @see #wrap()
- */
- public static CheckedExceptionHandler wrap(Function
+ * Typical usage: {@code Exceptions.log().run(() -> my_throwing_lambda)}
+ *
+ * No exceptions are allowed through, not even {@code Error}s.
+ * If {@link InterruptedException} is caught, {@link Thread#interrupt()} is called.
+ *
+ * @return logging exception handler
+ * @see #log(Logger)
+ * @deprecated Use SLF4J extension instead.
+ */
+ @Deprecated public static ExceptionHandler log() { return log; }
+ /**
+ * Creates {@code ExceptionHandler} that writes all exceptions to the specified {@code logger}.
+ * Most application code can use the more convenient {@link #log()} method.
+ * Use {@link #log(Logger, String)} overload to specify unique message where necessary.
+ *
+ * Typical usage: {@code Exceptions.log(logger).run(() -> my_throwing_lambda)}
+ *
+ * No exceptions are allowed through, not even {@code Error}s.
+ * If {@link InterruptedException} is caught, {@link Thread#interrupt()} is called.
+ *
+ * @param logger
+ * where all exceptions are logged
+ * @return exception handler with custom logger
+ * @throws NullPointerException
+ * if {@code logger} is {@code null}
+ * @see #log()
+ * @see #log(Logger, String)
+ * @deprecated Use SLF4J extension instead.
+ */
+ @Deprecated public static ExceptionHandler log(Logger logger) { return new LoggingHandler(logger, () -> "Caught exception."); }
+ /**
+ * Creates {@code ExceptionHandler} that writes all exceptions to the specified {@code logger} with the specified {@code message}.
+ * If you just need to specify custom logger, use {@link #log(Logger)}.
+ * This overload allows for differentiating or explanatory message.
+ * If the message is expensive to construct, use {@link #log(Logger, Supplier)} method.
+ *
+ * Typical usage: {@code Exceptions.log(logger, "Failed to do X.").run(() -> my_throwing_lambda)}
+ *
+ * No exceptions are allowed through, not even {@code Error}s.
+ * If {@link InterruptedException} is caught, {@link Thread#interrupt()} is called.
+ *
+ * @param logger
+ * where all exceptions are logged
+ * @param message
+ * introduces every exception in the log
+ * @return exception handler with custom logger and message
+ * @throws NullPointerException
+ * if {@code logger} or {@code message} is {@code null}
+ * @see #log(Logger)
+ * @see #log(Logger, Supplier)
+ * @deprecated Use SLF4J extension instead.
+ */
+ @Deprecated public static ExceptionHandler log(Logger logger, String message) {
+ Objects.requireNonNull(message);
+ return new LoggingHandler(logger, () -> message);
+ }
+ /**
+ * Creates {@code ExceptionHandler} that writes all exceptions to the specified {@code logger} with lazily evaluated {@code message}.
+ * If the message does not need lazy evaluation, use the {@link #log(Logger, String)} method.
+ * This overload constructs expensive messages lazily only when exception is caught.
+ * If {@code message} throws, the exception is logged and fallback message is used to log the original exception.
+ *
+ * Typical usage: {@code Exceptions.log(logger, () -> "Exception in " + this).run(() -> my_throwing_lambda)}
+ *
+ * No exceptions are allowed through, not even {@code Error}s.
+ * If {@link InterruptedException} is caught, {@link Thread#interrupt()} is called.
+ *
+ * @param logger
+ * where all exceptions are logged
+ * @param message
+ * a {@link Supplier} that is lazily evaluated to generate log message
+ * @return exception handler with custom logger and lazily evaluated message
+ * @throws NullPointerException
+ * if {@code logger} or {@code message} is {@code null}
+ * @see #log(Logger, String)
+ * @deprecated Use SLF4J extension instead.
+ */
+ @Deprecated public static ExceptionHandler log(Logger logger, Supplier
+ * Typical usage: {@code Exceptions.silence().run(() -> my_throwing_lambda)}
+ *
+ * No exceptions are allowed through, not even {@code Error}s.
+ * If {@link InterruptedException} is caught, {@link Thread#interrupt()} is called.
+ *
+ * @return exception handler that ignores all exceptions
+ */
+ public static ExceptionHandler silence() { return silence; }
+ /**
+ * Returns {@code CheckedExceptionHandler} that lets through checked exceptions without declaring them.
+ * All exceptions are allowed through unmodified, including checked ones, even though no checked exceptions are declared.
+ *
+ * Typical usage: {@code Exceptions.sneak().run(() -> my_throwing_lambda)}
+ *
+ * This is the recommended {@code CheckedExceptionHandler}, because it does not obfuscate the original exception in any way.
+ * Use {@link #wrap()} if using sneaky exceptions is not possible or not desirable.
+ *
+ * Sneaky throw is implemented using a neat trick with type erasure
+ * that persuades java compiler to tolerate throwing undeclared checked exception from specially crafted generic method.
+ * The trick is safe. It is legal java code and JVMs do not mind it. It is just considered dirty by some developers.
+ *
+ * @return exception handler that lets checked exceptions through
+ * @see #wrap()
+ */
+ public static CheckedExceptionHandler sneak() { return sneak; }
+ /**
+ * Returns {@code CheckedExceptionHandler} that wraps all checked exceptions.
+ * Unchecked exceptions are passed through unmodified.
+ * Checked exceptions are wrapped in {@link UndeclaredThrowableException}.
+ * Use {@link #sneak()} to avoid wrapping.
+ * Use {@link #wrap(Function)} to specify a custom wrapper.
+ *
+ * Typical usage: {@code Exceptions.wrap().run(() -> my_throwing_lambda)}
+ *
+ * If {@link InterruptedException} is caught, {@link Thread#interrupt()} is called.
+ *
+ * @return exception handler that wraps checked exceptions
+ * @see #sneak()
+ * @see #wrap(Function)
+ */
+ public static CheckedExceptionHandler wrap() { return wrap; }
+ /**
+ * Creates {@code CheckedExceptionHandler} that applies custom wrapper to checked exceptions.
+ * Unchecked exceptions are passed through unmodified.
+ * Checked exceptions are passed to {@code wrapper} and the resulting unchecked exception is thrown.
+ * Use {@link #sneak()} to avoid wrapping and {@link #wrap()} to use standard wrapper.
+ *
+ * Typical usage: {@code Exceptions.wrap(MyWrapperException::new).run(() -> my_throwing_lambda)}
+ *
+ * If {@link InterruptedException} is caught, {@link Thread#interrupt()} is called before invoking the {@code wrapper}.
+ *
+ * @param wrapper
+ * method converting checked exception into an unchecked one, often just exception constructor reference
+ * @return exception handler with custom exception transform
+ * @throws NullPointerException
+ * if {@code wrapper} is {@code null}
+ * @see #sneak()
+ * @see #wrap()
+ */
+ public static CheckedExceptionHandler wrap(Function