001/*
002 * Licensed to the Apache Software Foundation (ASF) under one or more
003 * contributor license agreements.  See the NOTICE file distributed with
004 * this work for additional information regarding copyright ownership.
005 * The ASF licenses this file to You under the Apache License, Version 2.0
006 * (the "License"); you may not use this file except in compliance with
007 * the License.  You may obtain a copy of the License at
008 *
009 *      https://www.apache.org/licenses/LICENSE-2.0
010 *
011 * Unless required by applicable law or agreed to in writing, software
012 * distributed under the License is distributed on an "AS IS" BASIS,
013 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
014 * See the License for the specific language governing permissions and
015 * limitations under the License.
016 */
017
018package org.apache.commons.lang3;
019
020import java.io.Closeable;
021import java.util.function.Consumer;
022
023import org.apache.commons.lang3.function.Consumers;
024import org.apache.commons.lang3.function.FailableConsumer;
025
026/**
027 * Static operations on {@link AutoCloseable}.
028 * <p>
029 * For {@link Closeable}-specific methods, see Apache Commons IO's
030 * <a href="https://commons.apache.org/proper/commons-io/apidocs/org/apache/commons/io/IOUtils.html">IOUtils</a>.
031 * </p>
032 *
033 * @since 3.21.0
034 */
035public class AutoCloseables {
036
037    /**
038     * Closes the given {@link AutoCloseable} as a null-safe operation.
039     *
040     * @param closeable The resource to close, may be null.
041     * @throws Exception Thrown if an error occurs.
042     */
043    public static void close(final AutoCloseable closeable) throws Exception {
044        if (closeable != null) {
045            closeable.close();
046        }
047    }
048
049    /**
050     * Closes the given {@link AutoCloseable} as a null-safe operation.
051     *
052     * @param closeable The resource to close, may be null.
053     * @param consumer  Consume the Exception thrown by {@link AutoCloseable#close()}.
054     * @throws Exception Thrown if the consumer throws an exception.
055     */
056    public static void close(final AutoCloseable closeable, final FailableConsumer<Exception, Exception> consumer) throws Exception {
057        if (closeable != null) {
058            try {
059                closeable.close();
060            } catch (final Exception e) {
061                FailableConsumer.accept(consumer, e);
062            }
063        }
064    }
065
066    /**
067     * Closes an {@link AutoCloseable}, never throwing an {@link Exception}.
068     * <p>
069     * Equivalent to {@link AutoCloseable#close()}, except any exceptions will be ignored.
070     * </p>
071     *
072     * @param closeable The objects to close, may be null or already closed.
073     * @see Throwable#addSuppressed(Throwable)
074     */
075    public static void closeQuietly(final AutoCloseable closeable) {
076        closeQuietly(closeable, (Consumer<Exception>) null);
077    }
078
079    /**
080     * Closes the given {@link AutoCloseable} as a null-safe operation while consuming Exception by the given {@code consumer}.
081     *
082     * @param closeable The resource to close, may be null.
083     * @param consumer  Consumes the Exception thrown by {@link AutoCloseable#close()}.
084     */
085    public static void closeQuietly(final AutoCloseable closeable, final Consumer<Exception> consumer) {
086        if (closeable != null) {
087            try {
088                closeable.close();
089            } catch (final Exception e) {
090                Consumers.accept(consumer, e);
091            }
092        }
093    }
094
095    /**
096     * Closes an iterable of {@link AutoCloseable}, never throwing an {@link Exception}.
097     * <p>
098     * Equivalent calling {@link AutoCloseable#close()} on each element, except any exceptions will be ignored.
099     * </p>
100     *
101     * @param closeables The objects to close, may be null or already closed.
102     * @see #closeQuietly(AutoCloseable)
103     */
104    public static void closeQuietly(final Iterable<AutoCloseable> closeables) {
105        if (closeables != null) {
106            closeables.forEach(AutoCloseables::closeQuietly);
107        }
108    }
109
110    /**
111     * Closes a {@link Closeable} unconditionally and adds any exception thrown by the {@code close()} to the given Throwable.
112     * <p>
113     * For example:
114     * </p>
115     *
116     * <pre>
117     * AutoCloseable autoCloseable = ...;
118     * try {
119     *     // process autoCloseable.
120     * } catch (Exception e) {
121     *     // Handle exception.
122     *     throw AutoCloseables.closeQuietlySuppress(autoCloseable, e);
123     * }
124     * </pre>
125     * <p>
126     * Also consider using a try-with-resources statement where appropriate.
127     * </p>
128     *
129     * @param <T>       The Throwable type.
130     * @param closeable The object to close, may be null or already closed.
131     * @param throwable Add the exception throw by the closeable to the given Throwable.
132     * @return The given Throwable.
133     * @see Throwable#addSuppressed(Throwable)
134     */
135    public static <T extends Throwable> T closeQuietlySuppress(final Closeable closeable, final T throwable) {
136        closeQuietly(closeable, throwable::addSuppressed);
137        return throwable;
138    }
139
140    /**
141     * No instances needed.
142     */
143    private AutoCloseables() {
144        // empty
145    }
146}