1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18 package org.newsclub.net.unix;
19
20 import java.io.Closeable;
21 import java.io.IOException;
22 import java.lang.ref.WeakReference;
23 import java.util.ArrayList;
24 import java.util.Iterator;
25 import java.util.List;
26
27
28
29
30
31
32 public final class Closeables implements Closeable {
33 private boolean closed = false;
34 private List<WeakReference<Closeable>> list;
35
36
37
38
39 public Closeables() {
40 }
41
42
43
44
45
46
47
48 public Closeables(Closeable... closeable) {
49 this.list = new ArrayList<>();
50 for (Closeable cl : closeable) {
51 this.list.add(new HardReference<>(cl));
52 }
53 }
54
55 @Override
56 public void close() throws IOException {
57 close(null);
58 }
59
60
61
62
63
64
65 public synchronized boolean isClosed() {
66 return closed;
67 }
68
69
70
71
72
73
74
75
76 public void close(IOException superException) throws IOException {
77 IOException exc = superException;
78
79 List<WeakReference<Closeable>> l;
80 synchronized (this) {
81 closed = true;
82
83 l = this.list;
84 if (l == null) {
85 return;
86 }
87
88 l = new ArrayList<>(l);
89 this.list = null;
90 }
91
92 for (WeakReference<Closeable> ref : l) {
93 @SuppressWarnings("resource")
94 Closeable cl = ref.get();
95 if (cl == null) {
96 continue;
97 }
98 try {
99 cl.close();
100 } catch (IOException e) {
101 if (exc == null) {
102 exc = e;
103 } else {
104 exc.addSuppressed(e);
105 }
106 }
107 }
108
109 if (exc != null) {
110 throw exc;
111 }
112 }
113
114 private static final class HardReference<V> extends WeakReference<V> {
115 private final V strongRef;
116
117 @SuppressWarnings("null")
118 HardReference(final V referent) {
119 super(null);
120 this.strongRef = referent;
121 }
122
123 @Override
124 public V get() {
125 return strongRef;
126 }
127 }
128
129
130
131
132
133
134
135
136 public synchronized boolean add(WeakReference<Closeable> closeable) {
137 if (closed) {
138 return false;
139 }
140 Closeable cl = closeable.get();
141 if (cl == null) {
142
143 return false;
144 }
145 if (list == null) {
146 list = new ArrayList<>();
147 } else {
148 for (WeakReference<Closeable> ref : list) {
149 if (cl.equals(ref.get())) {
150 return false;
151 }
152 }
153 }
154 list.add(closeable);
155
156 return true;
157 }
158
159
160
161
162
163
164
165
166 public synchronized boolean add(Closeable closeable) {
167 return add(new HardReference<>(closeable));
168 }
169
170
171
172
173
174
175
176
177 public synchronized boolean remove(Closeable closeable) {
178 if (list == null || closeable == null || closed) {
179 return false;
180 }
181 for (Iterator<WeakReference<Closeable>> it = list.iterator(); it.hasNext();) {
182 if (closeable.equals(it.next().get())) {
183 it.remove();
184 return true;
185 }
186 }
187 return false;
188 }
189 }