    001    /*
    002     * Copyright (C) 2007 The Guava Authors
    003     *
    004     * Licensed under the Apache License, Version 2.0 (the "License");
    005     * you may not use this file except in compliance with the License.
    006     * You may obtain a copy of the License at
    007     *
    008     * http://www.apache.org/licenses/LICENSE-2.0
    009     *
    010     * Unless required by applicable law or agreed to in writing, software
    011     * distributed under the License is distributed on an "AS IS" BASIS,
    012     * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
    013     * See the License for the specific language governing permissions and
    014     * limitations under the License.
    015     */
    016
    017    package com.google.common.io;
    018
    019    import com.google.common.annotations.Beta;
    020
    021    import java.io.Closeable;
    022    import java.io.IOException;
    023    import java.util.logging.Level;
    024    import java.util.logging.Logger;
    025
    026    import javax.annotation.Nullable;
    027
    028    /**
    029     * Utility methods for working with {@link Closeable} objects.
    030     *
    031     * @author Michael Lancaster
    032     * @since 1.0
    033     */
    034    @Beta
    035    public final class Closeables {
    036      private static final Logger logger
    037          = Logger.getLogger(Closeables.class.getName());
    038
    039      private Closeables() {}
    040
    041      /**
    042       * Closes a {@link Closeable}, with control over whether an
    043       * {@code IOException} may be thrown. This is primarily useful in a
    044       * finally block, where a thrown exception needs to be logged but not
    045       * propagated (otherwise the original exception will be lost).
    046       *
    047       * <p>If {@code swallowIOException} is true then we never throw
    048       * {@code IOException} but merely log it.
    049       *
    050       * <p>Example:
    051       *
    052       * <p><pre>public void useStreamNicely() throws IOException {
    053       * SomeStream stream = new SomeStream("foo");
    054       * boolean threw = true;
    055       * try {
    056       *   // Some code which does something with the Stream. May throw a
    057       *   // Throwable.
    058       *   threw = false; // No throwable thrown.
    059       * } finally {
    060       *   // Close the stream.
    061       *   // If an exception occurs, only rethrow it if (threw==false).
    062       *   Closeables.close(stream, threw);
    063       * }
    064       * </pre>
    065       *
    066       * @param closeable the {@code Closeable} object to be closed, or null,
    067       *     in which case this method does nothing
    068       * @param swallowIOException if true, don't propagate IO exceptions
    069       *     thrown by the {@code close} methods
    070       * @throws IOException if {@code swallowIOException} is false and
    071       *     {@code close} throws an {@code IOException}.
    072       */
    073      public static void close(@Nullable Closeable closeable,
    074          boolean swallowIOException) throws IOException {
    075        if (closeable == null) {
    076          return;
    077        }
    078        try {
    079          closeable.close();
    080        } catch (IOException e) {
    081          if (swallowIOException) {
    082            logger.log(Level.WARNING,
    083                "IOException thrown while closing Closeable.", e);
    084          } else {
    085            throw e;
    086          }
    087        }
    088      }
    089
    090      /**
    091       * Equivalent to calling {@code close(closeable, true)}, but with no
    092       * IOException in the signature.
    093       * @param closeable the {@code Closeable} object to be closed, or null, in
    094       *      which case this method does nothing
    095       */
    096      public static void closeQuietly(@Nullable Closeable closeable) {
    097        try {
    098          close(closeable, true);
    099        } catch (IOException e) {
    100          logger.log(Level.SEVERE, "IOException should not have been thrown.", e);
    101        }
    102      }
    103    }