diff --git a/aksw-commons-utils-parent/aksw-commons-utils/src/main/java/org/aksw/commons/util/exception/FinallyRunAll.java b/aksw-commons-utils-parent/aksw-commons-utils/src/main/java/org/aksw/commons/util/exception/FinallyRunAll.java index 6b9aaa31..2ff2a14a 100644 --- a/aksw-commons-utils-parent/aksw-commons-utils/src/main/java/org/aksw/commons/util/exception/FinallyRunAll.java +++ b/aksw-commons-utils-parent/aksw-commons-utils/src/main/java/org/aksw/commons/util/exception/FinallyRunAll.java @@ -1,11 +1,11 @@ package org.aksw.commons.util.exception; +import java.io.Serializable; import java.util.ArrayList; import java.util.Arrays; import java.util.Collection; import java.util.List; import java.util.concurrent.Callable; -import java.util.function.Consumer; import java.util.stream.Collectors; import org.aksw.commons.util.function.ThrowingRunnable; @@ -39,6 +39,13 @@ public class FinallyRunAll implements Runnable { + // TODO Consolidate with the identical interface from the lambda module + @FunctionalInterface + public interface ThrowingConsumer extends Serializable { + void accept(T t) throws Exception; + } + + // XXX Could change to an Iterator or Stream of actions. protected List actions; public static FinallyRunAll create() { @@ -87,47 +94,47 @@ protected void runAction(int index) { public static void run(ThrowingRunnable ... actions) { new FinallyRunAll(Arrays.asList(actions)).run(); } - - public static void runAll(Collection actions, Consumer runner, ThrowingRunnable finallyAction) { - ThrowingRunnable[] runnables = actions.stream().map(action -> { - ThrowingRunnable r = () -> { - runner.accept(action); - }; - return r; - }).collect(Collectors.toList()).toArray(new ThrowingRunnable[0]); - - try { - run(runnables); - } finally { - if (finallyAction != null) { - try { - finallyAction.run(); - } catch (Exception e) { - throw new RuntimeException(e); - } - } - } - - // Alternative approach using a loop - if (false) { - List exceptions = null; - for (T action : actions) { - try { - runner.accept(action); - } catch (Exception e) { - if (exceptions == null) { - exceptions = new ArrayList<>(); - } - exceptions.add(e); - } - } - - if (exceptions != null) { - RuntimeException e = new RuntimeException(); - exceptions.forEach(e::addSuppressed); - throw e; - } - } - } + + public static void runAll(Collection actions, ThrowingConsumer runner, ThrowingRunnable finallyAction) { + ThrowingRunnable[] runnables = actions.stream().map(action -> { + ThrowingRunnable r = () -> { + runner.accept(action); + }; + return r; + }).collect(Collectors.toList()).toArray(new ThrowingRunnable[0]); + + try { + run(runnables); + } finally { + if (finallyAction != null) { + try { + finallyAction.run(); + } catch (Exception e) { + throw new RuntimeException(e); + } + } + } + + // Alternative approach using a loop + if (false) { + List exceptions = null; + for (T action : actions) { + try { + runner.accept(action); + } catch (Exception e) { + if (exceptions == null) { + exceptions = new ArrayList<>(); + } + exceptions.add(e); + } + } + + if (exceptions != null) { + RuntimeException e = new RuntimeException(); + exceptions.forEach(e::addSuppressed); + throw e; + } + } + } } diff --git a/aksw-commons-utils-parent/aksw-commons-utils/src/main/java/org/aksw/commons/util/lifecycle/ResourceMgr.java b/aksw-commons-utils-parent/aksw-commons-utils/src/main/java/org/aksw/commons/util/lifecycle/ResourceMgr.java new file mode 100644 index 00000000..c4be4899 --- /dev/null +++ b/aksw-commons-utils-parent/aksw-commons-utils/src/main/java/org/aksw/commons/util/lifecycle/ResourceMgr.java @@ -0,0 +1,45 @@ +package org.aksw.commons.util.lifecycle; + +import java.util.Collections; +import java.util.IdentityHashMap; +import java.util.Map; + +import org.aksw.commons.util.exception.FinallyRunAll; +import org.aksw.commons.util.exception.FinallyRunAll.ThrowingConsumer; +import org.aksw.commons.util.function.ThrowingRunnable; + +/** + * A class where resources can be added. + * Upon closing the resource manager, all registered resources will be freed. + * + * @implNote + * This implementation closes resources sequentially. + */ +public class ResourceMgr + implements AutoCloseable +{ + private final Map resourceToCloser = + Collections.synchronizedMap(new IdentityHashMap<>()); + + public ResourceMgr() { + super(); + } + + public T register(T closable) { + return register(closable, AutoCloseable::close); + } + + public T register(T obj, ThrowingConsumer closer) { + return register(obj, () -> closer.accept(obj)); + } + + public T register(T obj, ThrowingRunnable closeAction) { + resourceToCloser.put(obj, closeAction); + return obj; + } + + @Override + public void close() { + FinallyRunAll.runAll(resourceToCloser.entrySet(), e -> e.getValue().run(), null); + } +}