package com.googlecode.totallylazy; import com.googlecode.totallylazy.functions.Block; import com.googlecode.totallylazy.functions.Function1; import com.googlecode.totallylazy.functions.Function2; import com.googlecode.totallylazy.reflection.Methods; import java.io.Closeable; import java.io.IOException; import java.lang.reflect.Method; import static com.googlecode.totallylazy.Callers.call; import static com.googlecode.totallylazy.Sequences.sequence; public class Closeables { public static <T extends Closeable, R> Function1<T, R> closeAfter(final Function1<? super T, R> callable) { return t -> using(t, callable); } public static <T> T safeClose(final T t) { try { close(t); return null; } catch (Exception e) { return null; } } public static <T> void safeClose(final T t1, final T t2) { reflectiveSafeClose(sequence(t1, t2)); } public static <T> void safeClose(final T t1, final T t2, final T t3) { reflectiveSafeClose(sequence(t1, t2, t3)); } public static <T> void safeClose(final T t1, final T t2, final T t3, final T t4) { reflectiveSafeClose(sequence(t1, t2, t3, t4)); } public static <T> void safeClose(final T t1, final T t2, final T t3, final T t4, final T t5) { reflectiveSafeClose(sequence(t1, t2, t3, t4, t5)); } @SafeVarargs public static <T> void safeClose(final T... t) { reflectiveSafeClose(sequence(t)); } public static <T> void reflectiveSafeClose(final Iterable<? extends T> t) { sequence(t).each(reflectiveSafeClose()); } public static <T extends Closeable> T safeClose(final T t) { try { close(t); return null; } catch (Exception e) { return null; } } public static <T extends Closeable> void safeClose(final T t1, final T t2) { safeClose(sequence(t1, t2)); } public static <T extends Closeable> void safeClose(final T t1, final T t2, final T t3) { safeClose(sequence(t1, t2, t3)); } public static <T extends Closeable> void safeClose(final T t1, final T t2, final T t3, final T t4) { safeClose(sequence(t1, t2, t3, t4)); } public static <T extends Closeable> void safeClose(final T t1, final T t2, final T t3, final T t4, final T t5) { safeClose(sequence(t1, t2, t3, t4, t5)); } @SafeVarargs public static <T extends Closeable> void safeClose(final T... t) { safeClose(sequence(t)); } public static <T extends Closeable> void safeClose(final Iterable<? extends T> t) { sequence(t).each(safeClose()); } public static <T> T close(final T t) { if (t == null) { return t; } final Option<Method> close = Methods.method(t, "close"); if (close.isEmpty()) { return t; } Methods.invoke(close.get(), t); return t; } public static <T extends Closeable> T close(final T t) { if (t == null) { return t; } try { t.close(); } catch (IOException e) { throw LazyException.lazyException(e); } return t; } public static <T extends Closeable, R> R using(T t, Function1<? super T, ? extends R> callable) { try { return call(callable, t); } finally { call(close(), t); } } public static <A extends Closeable, B extends Closeable, R> R using(A a, B b, Function2<? super A, ? super B, ? extends R> callable) { try { return call(callable, a, b); } finally { try { call(close(), a); } finally { call(close(), b); } } } public static <T, R> R using(T instanceWithCloseMethod, Function1<? super T, ? extends R> callable) { try { return call(callable, instanceWithCloseMethod); } finally { call(reflectiveClose(), instanceWithCloseMethod); } } public static <T> Block<T> reflectiveClose() { return Closeables::close; } public static Block<Closeable> close() { return Closeables::close; } public static Block<Closeable> safeClose() { return Closeables::safeClose; } public static <T> Block<T> reflectiveSafeClose() { return Closeables::safeClose; } }