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    }