Class Cleanup<EX extends Exception>

  • Type Parameters:
    EX - The checked exception type for transparent pass-through or RuntimeException. This is the one that will be forwarded when explicitly called. We cannot ensure that all clean-up task provide the very same exception type or a subclass. So all checked exceptions thrown by clean-up tasks incompatible with this type will be wrapped in a UndeclaredThrowableException.

    public class Cleanup<EX extends Exception>
    extends Object
    Cleanup aims to complement the functionality of Cleaner and provide some answers to questions that Cleaner left open. As with Cleaner the main purpose is to release resources when the objects holding those resources aren't reachable anymore. This is only meant as a fail-safe mechanism; resources should always be properly released once they are no longer needed.
    • Cleanup allows to register multiple clean-up tasks and they can be added either at the start or the end of the queue. This enables subclasses to share the same Cleanup and decide whether their tasks need to be executed before or after those of the superclass(es). Every clean-up tasks is guaranteed to be executed even in case of exceptions. The first encountered exception is passed through, with all others being attached as suppressed.
    • Transparent pass-through of checked exceptions: Cleaner.Cleanable.clean() cannot pass through checked exceptions, like the typical IOException. They would need to be manually wrapped and maybe unwrapped again. Cleanup can handle this transparently for one checked exception type specified during creation. This allows to use the clean-up for an explicitly called clean-up, e. g. AutoCloseable.close() with normal exception handling.
    • Exceptions occurring post-mortem (i. e. during implicit clean-up) are logged as they cannot be passed through to a caller.
    Implementations of CleanupTask must fulfil certain requirements aimed at preventing accidental references to the monitored object. The implementation
    • must be final,
    • must NOT be a lambda,
    • must NOT be an anonymous class,
    • and must NOT have any non-static inner classes in its type hierarchy.
    • Method Detail

      • register

        public static Cleanup<RuntimeException> register​(Object object)
        Creates a Cleanup as post-mortem action for the designated object. This only registers the notification mechanism, actual clean-up tasks need to be registered yet. No exception will be expected by any clean-up task.
        Parameters:
        object - The object for which to register post-mortem clean-up.
        Returns:
        A new Cleanup registered for as post-mortem action for the designated object.
        See Also:
        builder()
      • register

        public static Cleanup<RuntimeException> register​(Object object,
                                                         String descriptor)
        Creates a Cleanup as post-mortem action for the designated object with the designated descriptor. This only registers the notification mechanism, actual clean-up tasks need to be registered yet. No exception will be expected by any clean-up task.
        Parameters:
        object - The object for which to register post-mortem clean-up.
        descriptor - A string that meaningfully describes this clean-up when used for logging etc. or null to use the class name of the designated object.
        Returns:
        A new Cleanup registered for as post-mortem action for the designated object.
        See Also:
        builder()
      • register

        public static <EX extends ExceptionCleanup<EX> register​(Object object,
                                                                  Class<EX> checkedExceptionType)
        Creates a Cleanup as post-mortem action for the designated object. This only registers the notification mechanism, actual clean-up tasks need to be registered yet. There will be transparent pass-through for the provided checked exception type in clean().
        Parameters:
        object - The object for which to register post-mortem clean-up.
        checkedExceptionType - The exception that is expected by the clean-up. This will be forwarded when manually triggering clean-up.
        Returns:
        A new Cleanup registered for as post-mortem action for the designated object.
        See Also:
        builder()
      • register

        public static <EX extends ExceptionCleanup<EX> register​(Object object,
                                                                  String descriptor,
                                                                  Class<EX> checkedExceptionType)
        Creates a Cleanup as post-mortem action for the designated object with the designated descriptor. This only registers the notification mechanism, actual clean-up tasks need to be registered yet. There will be transparent pass-through for the provided checked exception type in clean().
        Parameters:
        object - The object for which to register post-mortem clean-up.
        descriptor - A string that meaningfully describes this clean-up when used for logging etc. or null to use the class name of the designated object.
        checkedExceptionType - The exception that is expected by the clean-up. This will be forwarded when manually triggering clean-up.
        Returns:
        A new Cleanup registered for as post-mortem action for the designated object.
        See Also:
        builder()
      • builder

        public static Cleanup.Builder builder()
        Starts building a Cleanup.
        Returns:
        The Builder for building a Cleanup.
      • addTask

        public Cleanup<EX> addTask​(CleanupTask<? extends Exception> task)
        Adds the given clean-up task to the end of the list of registered clean-up tasks.

        If an exception thrown by the task is not a RuntimeException and is not compatible with this Cleanup's pass-through exception type, it will be wrapped in an UndeclaredThrowableException.

        Parameters:
        task - The clean-up task to be executed as post-mortem or when explicitly triggered. For proper/normal exception handling, let its exception be EX or a subclass thereof.
        Returns:
        This Cleanup.
      • addTaskAsFirst

        public Cleanup<EX> addTaskAsFirst​(CleanupTask<? extends Exception> task)
        Adds the given clean-up task to the first position of the list of registered clean-up tasks.

        If an exception thrown by the task is not a RuntimeException and is not compatible with this Cleanup's pass-through exception type, it will be wrapped in an UndeclaredThrowableException.

        Parameters:
        task - The clean-up task to be executed as post-mortem or when explicitly triggered. For proper/normal exception handling, let its exception be EX or a subclass thereof.
        Returns:
        This Cleanup.
      • addTask

        public Cleanup<EX> addTask​(Supplier<? extends AutoCloseable> autoCloseable)
        Adds an Cleanup.AutoCloseableCleanupTask for the designated AutoCloseable to the end of the list of registered clean-up tasks. Uses the class name(s) of the Supplier to generate a descriptor for the task.

        If an exception thrown by the AutoCloseable is not a RuntimeException and is not compatible with this Cleanup's pass-through exception type, it will be wrapped in an UndeclaredThrowableException.

        Parameters:
        autoCloseable - The Supplier to get the AutoCloseable to close when cleaning-up. For proper/normal exception handling, make sure EX is IOException (or Exception).
        Returns:
        This Cleanup.
      • addTask

        public Cleanup<EX> addTask​(AutoCloseable... autoCloseables)
        Adds an Cleanup.AutoCloseableCleanupTask for the designated AutoCloseables to the end of the list of registered clean-up tasks. Uses the class name(s) of the AutoCloseable(s) to generate a descriptor for the task(s).

        If an exception thrown by an AutoCloseable is not a RuntimeException and is not compatible with this Cleanup's pass-through exception type, it will be wrapped in an UndeclaredThrowableException.

        Parameters:
        autoCloseables - The AutoCloseables to be added as clean-up task. For proper/normal exception handling, make sure EX is IOException (or Exception).
        Returns:
        This Cleanup.
      • addTask

        public Cleanup<EX> addTask​(Collection<? extends AutoCloseable> autoCloseables)
        Adds an Cleanup.AutoCloseableCleanupTask for the designated AutoCloseables to the end of the list of registered clean-up tasks. Uses the class name(s) of the AutoCloseable(s) to generate a descriptor for the task(s).

        If an exception thrown by an AutoCloseable is not a RuntimeException and is not compatible with this Cleanup's pass-through exception type, it will be wrapped in an UndeclaredThrowableException.

        Parameters:
        autoCloseables - The AutoCloseables to be added as clean-up task. For proper/normal exception handling, make sure EX is IOException (or Exception).
        Returns:
        This Cleanup.
      • addTask

        public Cleanup<EX> addTask​(String descriptor,
                                   Supplier<? extends AutoCloseable> autoCloseable)
        Adds an Cleanup.AutoCloseableCleanupTask for the designated AutoCloseables to the end of the list of registered clean-up tasks.

        If an exception thrown by the AutoCloseable is not a RuntimeException and is not compatible with this Cleanup's pass-through exception type, it will be wrapped in an UndeclaredThrowableException.

        Parameters:
        descriptor - A string that meaningfully describes the clean-up task or null for the class name(s) of the AutoCloseable(s).
        autoCloseable - The Supplier to get the AutoCloseable to close when cleaning-up. For proper/normal exception handling, make sure EX is IOException (or Exception).
        Returns:
        This Cleanup.
      • addTask

        public Cleanup<EX> addTask​(String descriptor,
                                   AutoCloseable... autoCloseables)
        Adds an Cleanup.AutoCloseableCleanupTask for the designated AutoCloseables to the end of the list of registered clean-up tasks.

        If an exception thrown by an AutoCloseable is not a RuntimeException and is not compatible with this Cleanup's pass-through exception type, it will be wrapped in an UndeclaredThrowableException.

        Parameters:
        descriptor - A string that meaningfully describes the clean-up task or null for the class name(s) of the AutoCloseable(s).
        autoCloseables - The AutoCloseables to be added as clean-up task. For proper/normal exception handling, make sure EX is IOException (or Exception).
        Returns:
        This Cleanup.
      • addTask

        public Cleanup<EX> addTask​(String descriptor,
                                   Collection<? extends AutoCloseable> autoCloseables)
        Adds an Cleanup.AutoCloseableCleanupTask for the designated AutoCloseables to the end of the list of registered clean-up tasks.

        If an exception thrown by an AutoCloseable is not a RuntimeException and is not compatible with this Cleanup's pass-through exception type, it will be wrapped in an UndeclaredThrowableException.

        Parameters:
        descriptor - A string that meaningfully describes the clean-up task or null for the class name(s) of the AutoCloseable(s).
        autoCloseables - The AutoCloseables to be added as clean-up task. For proper/normal exception handling, make sure EX is IOException (or Exception).
        Returns:
        This Cleanup.
      • addTaskAsFirst

        public Cleanup<EX> addTaskAsFirst​(Supplier<AutoCloseable> autoCloseable)
        Adds an Cleanup.AutoCloseableCleanupTask for the designated AutoCloseable to the first position of the list of registered clean-up tasks. Uses the class name(s) of the Supplier to generate a descriptor for the task.

        If an exception thrown by the AutoCloseable is not a RuntimeException and is not compatible with this Cleanup's pass-through exception type, it will be wrapped in an UndeclaredThrowableException.

        Parameters:
        autoCloseable - The Supplier to get the AutoCloseable to close when cleaning-up. For proper/normal exception handling, make sure EX is IOException (or Exception).
        Returns:
        This Cleanup.
      • addTaskAsFirst

        public Cleanup<EX> addTaskAsFirst​(AutoCloseable... autoCloseables)
        Adds an Cleanup.AutoCloseableCleanupTask for the designated AutoCloseables to the first position of the list of registered clean-up tasks. Uses the class name(s) of the Supplier(s) to generate a descriptor for the task(s).

        If an exception thrown by the AutoCloseable is not a RuntimeException and is not compatible with this Cleanup's pass-through exception type, it will be wrapped in an UndeclaredThrowableException.

        Parameters:
        autoCloseables - The AutoCloseables to be added as clean-up task. For proper/normal exception handling, make sure EX is IOException (or Exception).
        Returns:
        This Cleanup.
      • addTaskAsFirst

        public Cleanup<EX> addTaskAsFirst​(Collection<? extends AutoCloseable> autoCloseables)
        Adds an Cleanup.AutoCloseableCleanupTask for the designated AutoCloseables to the first position of the list of registered clean-up tasks. Uses the class name(s) of the AutoCloseable(s) to generate a descriptor for the task(s).

        If an exception thrown by the AutoCloseable is not a RuntimeException and is not compatible with this Cleanup's pass-through exception type, it will be wrapped in an UndeclaredThrowableException.

        Parameters:
        autoCloseables - The AutoCloseables to be added as clean-up task. For proper/normal exception handling, make sure EX is IOException (or Exception).
        Returns:
        This Cleanup.
      • addTaskAsFirst

        public Cleanup<EX> addTaskAsFirst​(String descriptor,
                                          Supplier<AutoCloseable> autoCloseable)
        Adds an Cleanup.AutoCloseableCleanupTask for the designated AutoCloseables to the first position of the list of registered clean-up tasks.

        If an exception thrown by the AutoCloseable is not a RuntimeException and is not compatible with this Cleanup's pass-through exception type, it will be wrapped in an UndeclaredThrowableException.

        Parameters:
        descriptor - A string that meaningfully describes the clean-up task or null for the class name(s) of the AutoCloseable(s).
        autoCloseable - The Supplier to get the AutoCloseable to close when cleaning-up. For proper/normal exception handling, make sure EX is IOException (or Exception).
        Returns:
        This Cleanup.
      • addTaskAsFirst

        public Cleanup<EX> addTaskAsFirst​(String descriptor,
                                          AutoCloseable... autoCloseables)
        Adds an Cleanup.AutoCloseableCleanupTask for the designated AutoCloseables to the first position of the list of registered clean-up tasks.

        If an exception thrown by an AutoCloseable is not a RuntimeException and is not compatible with this Cleanup's pass-through exception type, it will be wrapped in an UndeclaredThrowableException.

        Parameters:
        descriptor - A string that meaningfully describes the clean-up task or null for the class name(s) of the AutoCloseable(s).
        autoCloseables - The AutoCloseables to be added as clean-up task. For proper/normal exception handling, make sure EX is IOException (or Exception).
        Returns:
        This Cleanup.
      • addTaskAsFirst

        public Cleanup<EX> addTaskAsFirst​(String descriptor,
                                          Collection<? extends AutoCloseable> autoCloseables)
        Adds an Cleanup.AutoCloseableCleanupTask for the designated AutoCloseables to the first position of the list of registered clean-up tasks.

        If an exception thrown by an AutoCloseable is not a RuntimeException and is not compatible with this Cleanup's pass-through exception type, it will be wrapped in an UndeclaredThrowableException.

        Parameters:
        descriptor - A string that meaningfully describes the clean-up task or null for the class name(s) of the AutoCloseable(s).
        autoCloseables - The AutoCloseables to be added as clean-up task. For proper/normal exception handling, make sure EX is IOException (or Exception).
        Returns:
        This Cleanup.
      • runTasks

        protected void runTasks()
        Executes all registered clean-up tasks. See Cleanup for details on the behaviour.
      • runTasks

        protected static void runTasks​(Collection<CleanupTask<? extends Exception>> tasks,
                                       boolean explicitlyCleaned,
                                       String objectDescriptor,
                                       Logger logger)
        Executes the designated tasks by calling CleanupTask.cleanup(boolean) and collecting the corresponding exceptions. See Cleanup for details on the behaviour.
        If one or more exceptions occur, the most critical one will be selected having all others as suppressed ones. In an explicit clean it will be thrown, otherwise it will be logged together with the corresponding description.
        Parameters:
        tasks - The tasks to be run.
        explicitlyCleaned - Whether the tasks are run due to an explicit call to clean(). In this case it is not called as post-mortem action of the monitored object.
        objectDescriptor - A string that meaningfully describes the monitored object for logging purpose.
        logger - The logger for messages and/or problems, e. g. unexpected exceptions.
      • clean

        public void clean()
                   throws EX extends Exception
        Triggers the clean-up and invokes all registered clean-up tasks. These tasks are invoked at most once regardless of the number of calls to clean(). You may call it for clean-up normally, that is, before post-mortem which will deregister it from post-mortem cleaning.

        This method is the replacement of Cleaner.Cleanable.clean() when using the vanilla Cleaner.

        Throws:
        EX - the exception(s) passed through from the clean-up tasks.
        EX extends Exception