    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    import com.google.common.annotations.VisibleForTesting;
    021
    022    import java.io.Closeable;
    023    import java.io.IOException;
    024    import java.util.logging.Level;
    025    import java.util.logging.Logger;
    026
    027    import javax.annotation.Nullable;
    028
    029    /**
    030     * Utility methods for working with {@link Closeable} objects.
    031     *
    032     * @author Michael Lancaster
    033     * @since 1.0
    034     */
    035    @Beta
    036    public final class Closeables {
    037      @VisibleForTesting static final Logger logger
    038          = Logger.getLogger(Closeables.class.getName());
    039
    040      private Closeables() {}
    041
    042      /**
    043       * Closes a {@link Closeable}, with control over whether an
    044       * {@code IOException} may be thrown. This is primarily useful in a
    045       * finally block, where a thrown exception needs to be logged but not
    046       * propagated (otherwise the original exception will be lost).
    047       *
    048       * <p>If {@code swallowIOException} is true then we never throw
    049       * {@code IOException} but merely log it.
    050       *
    051       * <p>Example:
    052       *
    053       * <p><pre>public void useStreamNicely() throws IOException {
    054       * SomeStream stream = new SomeStream("foo");
    055       * boolean threw = true;
    056       * try {
    057       *   // Some code which does something with the Stream. May throw a
    058       *   // Throwable.
    059       *   threw = false; // No throwable thrown.
    060       * } finally {
    061       *   // Close the stream.
    062       *   // If an exception occurs, only rethrow it if (threw==false).
    063       *   Closeables.close(stream, threw);
    064       * }
    065       * </pre>
    066       *
    067       * @param closeable the {@code Closeable} object to be closed, or null,
    068       *     in which case this method does nothing
    069       * @param swallowIOException if true, don't propagate IO exceptions
    070       *     thrown by the {@code close} methods
    071       * @throws IOException if {@code swallowIOException} is false and
    072       *     {@code close} throws an {@code IOException}.
    073       */
    074      public static void close(@Nullable Closeable closeable,
    075          boolean swallowIOException) throws IOException {
    076        if (closeable == null) {
    077          return;
    078        }
    079        try {
    080          closeable.close();
    081        } catch (IOException e) {
    082          if (swallowIOException) {
    083            logger.log(Level.WARNING,
    084                "IOException thrown while closing Closeable.", e);
    085          } else {
    086            throw e;
    087          }
    088        }
    089      }
    090
    091      /**
    092       * Equivalent to calling {@code close(closeable, true)}, but with no
    093       * IOException in the signature.
    094       * @param closeable the {@code Closeable} object to be closed, or null, in
    095       *      which case this method does nothing
    096       */
    097      public static void closeQuietly(@Nullable Closeable closeable) {
    098        try {
    099          close(closeable, true);
    100        } catch (IOException e) {
    101          logger.log(Level.SEVERE, "IOException should not have been thrown.", e);
    102        }
    103      }
    104    }