/* * Copyright (C) 2012 The Guava Authors * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package com.google.common.io; import static com.google.common.base.Preconditions.checkNotNull; import java.io.Closeable; import java.io.IOException; import java.lang.reflect.Method; import java.util.ArrayDeque; import java.util.Deque; import java.util.logging.Level; import javax.annotation.Nullable; import com.google.common.annotations.Beta; import com.google.common.annotations.VisibleForTesting; import com.google.common.base.Throwables; /** * A {@link Closeable} that collects {@code Closeable} resources and closes them * all when it is {@linkplain #close closed}. This is intended to approximately * emulate the behavior of Java 7's * try-with-resources statement in JDK6-compatible code. Running on Java 7, * code using this should be approximately equivalent in behavior to the same * code written with try-with-resources. Running on Java 6, exceptions that * cannot be thrown must be logged rather than being added to the thrown * exception as a suppressed exception. * *
* This class is intended to be used in the following pattern: * *
* { * @code * Closer closer = Closer.create(); * try { * InputStream in = closer.register(openInputStream()); * OutputStream out = closer.register(openOutputStream()); * // do stuff * } catch (Throwable e) { * // ensure that any checked exception types other than IOException that could * // be thrown are * // provided here, e.g. throw closer.rethrow(e, CheckedException.class); * throw closer.rethrow(e); * } finally { * closer.close(); * } * } ** *
* Note that this try-catch-finally block is not equivalent to a * try-catch-finally block using try-with-resources. To get the equivalent of * that, you must wrap the above code in another try block in order to * catch any exception that may be thrown (including from the call to * {@code close()}). * *
* This pattern ensures the following: * *
* An exception that is suppressed is not thrown. The method of suppression used * depends on the version of Java the code is running on: * *
* This method always throws, and as such should be called as * {@code throw closer.rethrow(e);} to ensure the compiler knows that it will * throw. * * @return this method does not return; it always throws * @throws IOException when the given throwable is an IOException */ public RuntimeException rethrow(Throwable e) throws IOException { checkNotNull(e); thrown = e; Throwables.propagateIfPossible(e, IOException.class); throw new RuntimeException(e); } /** * Stores the given throwable and rethrows it. It will be rethrown as is if it * is an {@code IOException}, {@code RuntimeException}, {@code Error} or a * checked exception of the given type. Otherwise, it will be rethrown wrapped * in a {@code RuntimeException}. Note: Be sure to declare all of the * checked exception types your try block can throw when calling an overload of * this method so as to avoid losing the original exception type. * *
* This method always throws, and as such should be called as
* {@code throw closer.rethrow(e, ...);} to ensure the compiler knows that it
* will throw.
*
* @return this method does not return; it always throws
* @throws IOException when the given throwable is an IOException
* @throws X when the given throwable is of the declared type X
*/
public
* This method always throws, and as such should be called as
* {@code throw closer.rethrow(e, ...);} to ensure the compiler knows that it
* will throw.
*
* @return this method does not return; it always throws
* @throws IOException when the given throwable is an IOException
* @throws X1 when the given throwable is of the declared type X1
* @throws X2 when the given throwable is of the declared type X2
*/
public