Author: mgrigorov
Date: Fri Dec 16 14:17:28 2011
New Revision: 1215140
URL: http://svn.apache.org/viewvc?rev=1215140&view=rev
Log:
WICKET-4293
UrlResourceStream closes incorrect InputStream causing stacktraces on undeploy
on GlassFish
Modified:
wicket/trunk/wicket-core/src/main/java/org/apache/wicket/util/resource/UrlResourceStream.java
wicket/trunk/wicket-core/src/test/java/org/apache/wicket/util/resource/UrlResourceStreamTest.java
wicket/trunk/wicket-util/src/main/java/org/apache/wicket/util/io/Connections.java
Modified:
wicket/trunk/wicket-core/src/main/java/org/apache/wicket/util/resource/UrlResourceStream.java
URL:
http://svn.apache.org/viewvc/wicket/trunk/wicket-core/src/main/java/org/apache/wicket/util/resource/UrlResourceStream.java?rev=1215140&r1=1215139&r2=1215140&view=diff
==============================================================================
---
wicket/trunk/wicket-core/src/main/java/org/apache/wicket/util/resource/UrlResourceStream.java
(original)
+++
wicket/trunk/wicket-core/src/main/java/org/apache/wicket/util/resource/UrlResourceStream.java
Fri Dec 16 14:17:28 2011
@@ -20,6 +20,8 @@ import java.io.IOException;
import java.io.InputStream;
import java.net.URL;
import java.net.URLConnection;
+import java.util.ArrayList;
+import java.util.List;
import org.apache.wicket.Application;
import org.apache.wicket.util.io.Connections;
@@ -67,8 +69,15 @@ public class UrlResourceStream extends A
{
private URLConnection connection;
- /** The stream read from this connection */
- private InputStream inputStream;
+ /**
+ * The streams read from this connection.
+ * Some URLConnection implementations return the same instance
of InputStream
+ * every time URLConnection#getInputStream() is called. Other
return a new instance
+ * of InputStream.
+ * Here we keep a list of all returned ones and close them in
UrlResourceStream#close().
+ * Even it is the same instance several times we will try to
close it quietly several times.
+ */
+ private List<InputStream> inputStreams;
/** Length of stream. */
private long contentLength;
@@ -126,7 +135,7 @@ public class UrlResourceStream extends A
{
throw new IllegalArgumentException("Invalid URL
parameter " + url, ex);
}
- }
+ }
return streamData;
}
@@ -144,9 +153,11 @@ public class UrlResourceStream extends A
if (data != null)
{
Connections.closeQuietly(data.connection);
- if (data.inputStream != null)
+ if (data.inputStreams != null)
{
- IOUtils.closeQuietly(data.inputStream);
+ for (InputStream is : data.inputStreams) {
+ IOUtils.closeQuietly(is);
+ }
}
streamData = null;
}
@@ -162,8 +173,12 @@ public class UrlResourceStream extends A
try
{
StreamData data = getData(true);
- data.inputStream = data.connection.getInputStream();
- return data.inputStream;
+ InputStream is = data.connection.getInputStream();
+ if (data.inputStreams == null) {
+ data.inputStreams = new
ArrayList<InputStream>();
+ }
+ data.inputStreams.add(is);
+ return is;
}
catch (IOException e)
{
Modified:
wicket/trunk/wicket-core/src/test/java/org/apache/wicket/util/resource/UrlResourceStreamTest.java
URL:
http://svn.apache.org/viewvc/wicket/trunk/wicket-core/src/test/java/org/apache/wicket/util/resource/UrlResourceStreamTest.java?rev=1215140&r1=1215139&r2=1215140&view=diff
==============================================================================
---
wicket/trunk/wicket-core/src/test/java/org/apache/wicket/util/resource/UrlResourceStreamTest.java
(original)
+++
wicket/trunk/wicket-core/src/test/java/org/apache/wicket/util/resource/UrlResourceStreamTest.java
Fri Dec 16 14:17:28 2011
@@ -17,6 +17,7 @@
package org.apache.wicket.util.resource;
import java.io.IOException;
+import java.io.InputStream;
import java.net.URL;
import java.net.URLConnection;
import java.net.URLStreamHandler;
@@ -27,19 +28,16 @@ import org.junit.Assert;
import org.junit.Test;
/**
- *
* @author Kent Tong
*/
-public class UrlResourceStreamTest extends Assert
-{
+public class UrlResourceStreamTest extends Assert {
/**
* lastModified() shouldn't change the content length if the file isn't
really changed.
- *
+ *
* @throws IOException
*/
@Test
- public void lastModifiedForResourceInJar() throws IOException
- {
+ public void lastModifiedForResourceInJar() throws IOException {
String anyClassInJarFile = "/java/lang/String.class";
URL url = getClass().getResource(anyClassInJarFile);
UrlResourceStream stream = new UrlResourceStream(url);
@@ -50,64 +48,98 @@ public class UrlResourceStreamTest exten
}
/**
+ * Verifies that a connection is opened just once but each
#getInputStream() opens a new one
+ * and all input streams are closed with UrlResourceStream#close()
+ *
* https://issues.apache.org/jira/browse/WICKET-3176
- *
+ * https://issues.apache.org/jira/browse/WICKET-4293
+ *
* @throws IOException
* @throws ResourceStreamNotFoundException
*/
@Test
- public void loadJustOnce() throws IOException,
ResourceStreamNotFoundException
- {
+ public void loadJustOnce() throws IOException,
ResourceStreamNotFoundException {
String anyClassInJarFile = "/java/lang/String.class";
URL realURL = getClass().getResource(anyClassInJarFile);
- final AtomicInteger counter = new AtomicInteger(0);
- URL url = new URL(null, "test://anything", new
CountingURLStreamHandler(realURL, counter));
+ final AtomicInteger connectCounter = new AtomicInteger(0);
+ final AtomicInteger streamCounter = new AtomicInteger(0);
+ URL url = new URL(null, "test://anything", new
CountingURLStreamHandler(realURL,
+ connectCounter, streamCounter));
UrlResourceStream countingStream = new UrlResourceStream(url);
+
// assert the call is not made yet
- assertEquals(0, counter.get());
- countingStream.length();
+ assertEquals(0, connectCounter.get());
+ assertEquals(0, streamCounter.get());
+
// assert the connection is loaded lazily
- assertEquals(1, counter.get());
+ countingStream.length();
+ assertEquals(1, connectCounter.get());
+ assertEquals(0, streamCounter.get());
// assert the following calls do not make new connections
countingStream.getInputStream();
- assertEquals(1, counter.get());
+ assertEquals(1, connectCounter.get());
+ assertEquals(1, streamCounter.get());
countingStream.getContentType();
- assertEquals(1, counter.get());
+ assertEquals(1, connectCounter.get());
+ assertEquals(1, streamCounter.get());
countingStream.getInputStream();
- assertEquals(1, counter.get());
+ assertEquals(1, connectCounter.get());
+ assertEquals(2, streamCounter.get());
countingStream.close();
- assertEquals(1, counter.get());
- // assert the connection is re-opened (again lazily) second time
+ assertEquals(1, connectCounter.get());
+ assertEquals(2, streamCounter.get());
+
+ // assert the connection is re-opened (again lazily) second
time,
+ // but stream is not re-opened yet
countingStream.length();
- assertEquals(2, counter.get());
+
+ assertEquals(2, connectCounter.get());
+ assertEquals(2, streamCounter.get());
+
+ // assert stream is re-opened on next getInputStream call
+ countingStream.getInputStream();
+ assertEquals(2, connectCounter.get());
+ assertEquals(3, streamCounter.get());
}
/**
* {@link URLStreamHandler} that counts the calls to {@link
URL#openConnection()}
*/
- private static final class CountingURLStreamHandler extends
URLStreamHandler
- {
- private final AtomicInteger counter;
+ private static final class CountingURLStreamHandler extends
URLStreamHandler {
+ private final AtomicInteger connectCounter, streamCounter;
private final URL realURL;
- public CountingURLStreamHandler(URL realURL, AtomicInteger
counter)
- {
- this.counter = counter;
+ public CountingURLStreamHandler(URL realURL, AtomicInteger
connectCounter,
+
AtomicInteger streamCounter) {
+ this.connectCounter = connectCounter;
+ this.streamCounter = streamCounter;
this.realURL = realURL;
}
@Override
- protected URLConnection openConnection(URL u) throws IOException
- {
- counter.getAndIncrement();
- return realURL.openConnection();
- }
+ protected URLConnection openConnection(URL u) throws
IOException {
+ connectCounter.getAndIncrement();
+ final URLConnection realConn = realURL.openConnection();
+ return new URLConnection(u) {
+
+ @Override
+ public void connect() throws IOException {
+ realConn.connect();
+ }
+
+ @Override
+ public InputStream getInputStream() throws
IOException {
+ streamCounter.incrementAndGet();
+ return realConn.getInputStream();
+ }
+ };
+ }
}
}
Modified:
wicket/trunk/wicket-util/src/main/java/org/apache/wicket/util/io/Connections.java
URL:
http://svn.apache.org/viewvc/wicket/trunk/wicket-util/src/main/java/org/apache/wicket/util/io/Connections.java?rev=1215140&r1=1215139&r2=1215140&view=diff
==============================================================================
---
wicket/trunk/wicket-util/src/main/java/org/apache/wicket/util/io/Connections.java
(original)
+++
wicket/trunk/wicket-util/src/main/java/org/apache/wicket/util/io/Connections.java
Fri Dec 16 14:17:28 2011
@@ -128,9 +128,5 @@ public class Connections
{
((HttpURLConnection)connection).disconnect();
}
- else
- {
- connection.getInputStream().close();
- }
}
}