19
19
import java .io .ByteArrayOutputStream ;
20
20
import java .io .FileNotFoundException ;
21
21
import java .io .FilePermission ;
22
+ import java .io .FilterInputStream ;
22
23
import java .io .IOException ;
23
24
import java .io .InputStream ;
24
25
import java .io .UnsupportedEncodingException ;
@@ -80,14 +81,18 @@ protected URLConnection openConnection(URL u) throws IOException {
80
81
81
82
private final JarEntryName jarEntryName ;
82
83
84
+ private final CloseAction closeAction ;
85
+
83
86
private JarEntry jarEntry ;
84
87
85
- private JarURLConnection (URL url , JarFile jarFile , JarEntryName jarEntryName ) throws IOException {
88
+ private JarURLConnection (URL url , JarFile jarFile , JarEntryName jarEntryName , CloseAction closeAction )
89
+ throws IOException {
86
90
// What we pass to super is ultimately ignored
87
91
super (EMPTY_JAR_URL );
88
92
this .url = url ;
89
93
this .jarFile = jarFile ;
90
94
this .jarEntryName = jarEntryName ;
95
+ this .closeAction = closeAction ;
91
96
}
92
97
93
98
@ Override
@@ -168,7 +173,17 @@ public InputStream getInputStream() throws IOException {
168
173
if (inputStream == null ) {
169
174
throwFileNotFound (this .jarEntryName , this .jarFile );
170
175
}
171
- return inputStream ;
176
+ return new FilterInputStream (inputStream ) {
177
+
178
+ @ Override
179
+ public void close () throws IOException {
180
+ super .close ();
181
+ if (JarURLConnection .this .closeAction != null ) {
182
+ JarURLConnection .this .closeAction .perform ();
183
+ }
184
+ }
185
+
186
+ };
172
187
}
173
188
174
189
private void throwFileNotFound (Object entry , JarFile jarFile ) throws FileNotFoundException {
@@ -249,24 +264,30 @@ static JarURLConnection get(URL url, JarFile jarFile) throws IOException {
249
264
int index = indexOfRootSpec (spec , jarFile .getPathFromRoot ());
250
265
if (index == -1 ) {
251
266
return (Boolean .TRUE .equals (useFastExceptions .get ()) ? NOT_FOUND_CONNECTION
252
- : new JarURLConnection (url , null , EMPTY_JAR_ENTRY_NAME ));
267
+ : new JarURLConnection (url , null , EMPTY_JAR_ENTRY_NAME , null ));
253
268
}
254
269
int separator ;
270
+ JarFile connectionJarFile = jarFile ;
255
271
while ((separator = spec .indexOf (SEPARATOR , index )) > 0 ) {
256
272
JarEntryName entryName = JarEntryName .get (spec .subSequence (index , separator ));
257
273
JarEntry jarEntry = jarFile .getJarEntry (entryName .toCharSequence ());
258
274
if (jarEntry == null ) {
259
- return JarURLConnection .notFound (jarFile , entryName );
275
+ return JarURLConnection .notFound (connectionJarFile , entryName ,
276
+ (connectionJarFile != jarFile ) ? connectionJarFile ::close : null );
260
277
}
261
- jarFile = jarFile .getNestedJarFile (jarEntry );
278
+ connectionJarFile = connectionJarFile .getNestedJarFile (jarEntry );
262
279
index = separator + SEPARATOR .length ();
263
280
}
264
281
JarEntryName jarEntryName = JarEntryName .get (spec , index );
265
282
if (Boolean .TRUE .equals (useFastExceptions .get ()) && !jarEntryName .isEmpty ()
266
- && !jarFile .containsEntry (jarEntryName .toString ())) {
283
+ && !connectionJarFile .containsEntry (jarEntryName .toString ())) {
284
+ if (connectionJarFile != jarFile ) {
285
+ connectionJarFile .close ();
286
+ }
267
287
return NOT_FOUND_CONNECTION ;
268
288
}
269
- return new JarURLConnection (url , jarFile , jarEntryName );
289
+ return new JarURLConnection (url , connectionJarFile , jarEntryName ,
290
+ (connectionJarFile != jarFile ) ? connectionJarFile ::close : null );
270
291
}
271
292
272
293
private static int indexOfRootSpec (StringSequence file , String pathFromRoot ) {
@@ -279,18 +300,22 @@ private static int indexOfRootSpec(StringSequence file, String pathFromRoot) {
279
300
280
301
private static JarURLConnection notFound () {
281
302
try {
282
- return notFound (null , null );
303
+ return notFound (null , null , null );
283
304
}
284
305
catch (IOException ex ) {
285
306
throw new IllegalStateException (ex );
286
307
}
287
308
}
288
309
289
- private static JarURLConnection notFound (JarFile jarFile , JarEntryName jarEntryName ) throws IOException {
310
+ private static JarURLConnection notFound (JarFile jarFile , JarEntryName jarEntryName , CloseAction closeAction )
311
+ throws IOException {
290
312
if (Boolean .TRUE .equals (useFastExceptions .get ())) {
313
+ if (closeAction != null ) {
314
+ closeAction .perform ();
315
+ }
291
316
return NOT_FOUND_CONNECTION ;
292
317
}
293
- return new JarURLConnection (null , jarFile , jarEntryName );
318
+ return new JarURLConnection (null , jarFile , jarEntryName , closeAction );
294
319
}
295
320
296
321
/**
@@ -393,4 +418,15 @@ public static JarEntryName get(StringSequence spec, int beginIndex) {
393
418
394
419
}
395
420
421
+ /**
422
+ * An action to be taken when the connection is being "closed" and its underlying
423
+ * resources are no longer needed.
424
+ */
425
+ @ FunctionalInterface
426
+ private interface CloseAction {
427
+
428
+ void perform () throws IOException ;
429
+
430
+ }
431
+
396
432
}
0 commit comments