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();
-               }
        }
 }


Reply via email to