All Downloads are FREE. Search and download functionalities are using the official Maven repository.

net.yetamine.lang.closeables.AutoCloseableAdapter Maven / Gradle / Ivy

There is a newer version: 1.3.0
Show newest version
package net.yetamine.lang.closeables;

import java.util.Objects;
import java.util.Optional;
import java.util.concurrent.atomic.AtomicReference;
import java.util.function.Consumer;
import java.util.function.Function;

/**
 * An {@link AutoCloseable} adapter for resources that don't implement that
 * interface.
 *
 * 

* The implementation is thread-safe, guarantees that the given closing handler * is invoked only on the first invocation of {@link #close()}, while * {@link #resource()} provides only the resource which is not closed yet. * * @param * the type of the adapted resource * @param * the type of the exception that the {@link #close()} method may * throw for this resource */ public final class AutoCloseableAdapter implements AutoCloseableResource { /** Adapted object. */ private final AtomicReference resource; /** Closing handler providing exceptions. */ private final Function close; /** * Creates a new instance. * * @param object * the object to adapt. It must not be {@code null}. * @param closingHandler * the handler to clean up and return the exception to throw ( * {@code null} if none should be thrown). It must not be * {@code null}. */ private AutoCloseableAdapter(T object, Function closingHandler) { resource = new AtomicReference<>(Objects.requireNonNull(object)); close = closingHandler; assert (close != null); } /** * Creates a new instance. * * @param * the type of the adapted resource * @param * the type of the exception * @param object * the object to adapt. It must not be {@code null}. * @param closingHandler * the handler to clean up and return the exception to throw ( * {@code null} if none should be thrown). It must not be * {@code null}. * * @return an adapter for the object */ public static AutoCloseableAdapter using(T object, Function closingHandler) { Objects.requireNonNull(closingHandler); return new AutoCloseableAdapter<>(object, closingHandler); } /** * Creates a new instance. * * @param * the type of the adapted resource * @param * the type of the exception * @param object * the object to adapt. It must not be {@code null}. * @param closingHandler * the handler to clean up; because it can't return any * exception, it may signal a problem only by throwing an * unchecked exception. It must not be {@code null}. * * @return an adapter for the object */ public static AutoCloseableAdapter using(T object, Consumer closingHandler) { Objects.requireNonNull(closingHandler); // Using explicit definition, Eclipse is unhappy otherwise final Function closingFunction = o -> { closingHandler.accept(o); return null; }; return new AutoCloseableAdapter<>(object, closingFunction); } /** * Provides the adapted object. * * @throws IllegalStateException * if closed already * * @see net.yetamine.lang.closeables.AutoCloseableResource#resource() */ public T resource() { final T result = resource.get(); if (result != null) { return result; } throw new IllegalStateException(); } /** * @see net.yetamine.lang.closeables.AutoCloseableResource#close() */ public void close() throws X { final T value = resource.getAndSet(null); if (value == null) { return; } final X toThrow = close.apply(value); if (toThrow != null) { throw toThrow; } } /** * Provides the adapted object if not closed yet. * * @return an {@link Optional} containing the adapted object, or an empty * container if the resource has been closed */ public Optional available() { return Optional.ofNullable(resource.get()); } /** * Indicates whether the resource is closed; note that the state may change * by closing the resource from another thread any time. * * @return {@code true} if the resource is closed */ public boolean isClosed() { return (resource.get() == null); } }





© 2015 - 2025 Weber Informatics LLC | Privacy Policy