• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2  * Copyright (C) 2007 The Guava Authors
3  *
4  * Licensed under the Apache License, Version 2.0 (the "License");
5  * you may not use this file except in compliance with the License.
6  * You may obtain a copy of the License at
7  *
8  * http://www.apache.org/licenses/LICENSE-2.0
9  *
10  * Unless required by applicable law or agreed to in writing, software
11  * distributed under the License is distributed on an "AS IS" BASIS,
12  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13  * See the License for the specific language governing permissions and
14  * limitations under the License.
15  */
16 
17 package com.google.common.io;
18 
19 import com.google.common.collect.Sets;
20 
21 import java.io.IOException;
22 import java.util.Set;
23 
24 /**
25  * The purpose of the CheckCloseSupplier is to report when all closeable objects
26  * supplied by the delegate supplier are closed. To do this, the factory method
27  * returns a decorated version of the {@code delegate} supplied in the
28  * constructor. The decoration mechanism is left up to the subclass via the
29  * abstract {@link #wrap} method.
30  *
31  * <p>The decorated object returned from {@link #wrap} should ideally override
32  * its {@code close} method to not only call {@code super.close()} but to also
33  * call {@code callback.delegateClosed()}.
34  *
35  * @author Chris Nokleberg
36  */
37 abstract class CheckCloseSupplier<T> {
38   private final Set<Callback> open = Sets.newHashSet();
39 
40   abstract static class Input<T> extends CheckCloseSupplier<T>
41       implements InputSupplier<T> {
42     private final InputSupplier<? extends T> delegate;
43 
Input(InputSupplier<? extends T> delegate)44     public Input(InputSupplier<? extends T> delegate) {
45       this.delegate = delegate;
46     }
47 
getInput()48     @Override public T getInput() throws IOException {
49       return wrap(delegate.getInput(), newCallback());
50     }
51   }
52 
53   abstract static class Output<T> extends CheckCloseSupplier<T>
54       implements OutputSupplier<T> {
55     private final OutputSupplier<? extends T> delegate;
56 
Output(OutputSupplier<? extends T> delegate)57     public Output(OutputSupplier<? extends T> delegate) {
58       this.delegate = delegate;
59     }
60 
getOutput()61     @Override public T getOutput() throws IOException {
62       return wrap(delegate.getOutput(), newCallback());
63     }
64   }
65 
66   public final class Callback {
delegateClosed()67     public void delegateClosed() {
68       open.remove(this);
69     }
70   }
71 
newCallback()72   protected Callback newCallback() {
73     Callback callback = new Callback();
74     open.add(callback);
75     return callback;
76   }
77 
78   /**
79    * Subclasses should wrap the given object and call
80    * {@link Callback#delegateClosed} when the close method of the delegate is
81    * called, to inform the supplier that the underlying
82    * {@code Closeable} is not longer open.
83    *
84    * @param object the object to wrap.
85    * @param callback the object that the wrapper should call to signal that the
86    */
wrap(T object, Callback callback)87   protected abstract T wrap(T object, Callback callback);
88 
89   /** Returns true if all the closeables have been closed closed */
areClosed()90   public boolean areClosed() {
91     return open.isEmpty();
92   }
93 }
94