Author: ivaynberg
Date: Thu Oct 22 06:43:37 2009
New Revision: 828326
URL: http://svn.apache.org/viewvc?rev=828326&view=rev
Log:
WICKET-2534: File Handle Leak in URLResourceStream
Issue: WICKET-2534
Added:
wicket/trunk/wicket/src/main/java/org/apache/wicket/util/io/Connections.java
(with props)
Modified:
wicket/trunk/wicket/src/main/java/org/apache/wicket/util/io/Streams.java
wicket/trunk/wicket/src/main/java/org/apache/wicket/util/resource/UrlResourceStream.java
Added:
wicket/trunk/wicket/src/main/java/org/apache/wicket/util/io/Connections.java
URL:
http://svn.apache.org/viewvc/wicket/trunk/wicket/src/main/java/org/apache/wicket/util/io/Connections.java?rev=828326&view=auto
==============================================================================
---
wicket/trunk/wicket/src/main/java/org/apache/wicket/util/io/Connections.java
(added)
+++
wicket/trunk/wicket/src/main/java/org/apache/wicket/util/io/Connections.java
Thu Oct 22 06:43:37 2009
@@ -0,0 +1,159 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.apache.wicket.util.io;
+
+import java.io.File;
+import java.io.IOException;
+import java.net.HttpURLConnection;
+import java.net.JarURLConnection;
+import java.net.URI;
+import java.net.URL;
+import java.net.URLConnection;
+
+/**
+ * {...@link URLConnection} related utilities
+ *
+ * @author igor.vaynberg
+ */
+public class Connections
+{
+ private Connections()
+ {
+
+ }
+
+ /**
+ * Gets last modified date of the given {...@link URL}
+ *
+ * @param url
+ * @return last modified timestamp
+ * @throws IOException
+ */
+ public static long getLastModified(URL url) throws IOException
+ {
+
+ URLConnection connection = url.openConnection();
+
+ try
+ {
+ if (connection instanceof JarURLConnection)
+ {
+ JarURLConnection jarUrlConnection =
(JarURLConnection)connection;
+ URL jarFileUrl =
jarUrlConnection.getJarFileURL();
+ URLConnection jarFileConnection =
jarFileUrl.openConnection();
+ try
+ {
+ return
jarFileConnection.getLastModified();
+ }
+ finally
+ {
+ close(jarFileConnection);
+ }
+ }
+ else
+ {
+ return connection.getLastModified();
+ }
+
+ }
+ finally
+ {
+ close(connection);
+ }
+ }
+
+ /**
+ * Tries to find a file on the harddisk that the url points to
+ *
+ * @param url
+ * @return file file pointing to the connection
+ * @throws Exception
+ * if file could not be located
+ */
+ public static File findFile(final URL url) throws Exception
+ {
+ File file = null;
+ URL fileUrl = url;
+ URLConnection connection = null;
+
+ try
+ {
+ connection = url.openConnection();
+
+ // if this is a connection to a file inside a jar we
point the file to the jar
+ // itself
+ if (connection instanceof JarURLConnection)
+ {
+ fileUrl =
((JarURLConnection)connection).getJarFileURL();
+ }
+
+ file = new File(new URI(fileUrl.toExternalForm()));
+
+ if (file != null && !file.exists())
+ {
+ file = null;
+ }
+
+ return file;
+ }
+ finally
+ {
+ close(connection);
+ }
+ }
+
+ /**
+ * Closes a connection, ignoring any exceptions if they occur
+ *
+ * @param connection
+ */
+ public static void closeQuietly(URLConnection connection)
+ {
+ try
+ {
+ close(connection);
+ }
+ catch (Exception e)
+ {
+ // ignore
+ }
+ }
+
+ /**
+ * Closes a connection
+ *
+ * @param connection
+ * @throws IOException
+ */
+ public static void close(URLConnection connection) throws IOException
+ {
+ if (connection == null)
+ {
+ return;
+ }
+
+ if (connection instanceof HttpURLConnection)
+ {
+ ((HttpURLConnection)connection).disconnect();
+ }
+ else
+ {
+ connection.getInputStream().close();
+ }
+ }
+
+}
Propchange:
wicket/trunk/wicket/src/main/java/org/apache/wicket/util/io/Connections.java
------------------------------------------------------------------------------
svn:mime-type = text/plain
Modified:
wicket/trunk/wicket/src/main/java/org/apache/wicket/util/io/Streams.java
URL:
http://svn.apache.org/viewvc/wicket/trunk/wicket/src/main/java/org/apache/wicket/util/io/Streams.java?rev=828326&r1=828325&r2=828326&view=diff
==============================================================================
--- wicket/trunk/wicket/src/main/java/org/apache/wicket/util/io/Streams.java
(original)
+++ wicket/trunk/wicket/src/main/java/org/apache/wicket/util/io/Streams.java
Thu Oct 22 06:43:37 2009
@@ -17,6 +17,7 @@
package org.apache.wicket.util.io;
import java.io.BufferedReader;
+import java.io.Closeable;
import java.io.IOException;
import java.io.InputStream;
import java.io.InputStreamReader;
@@ -44,6 +45,7 @@
* Utilities methods for working with input and output streams.
*
* @author Jonathan Locke
+ * @author Igor Vaynberg
*/
public final class Streams
{
@@ -53,6 +55,22 @@
+ "<!ELEMENT comment (#PCDATA) >" + "<!ELEMENT entry (#PCDATA)
>" + "<!ATTLIST entry "
+ " key CDATA #REQUIRED>";
+ /**
+ * Closes a closeable. Guards against null closables.
+ *
+ * @param closeable
+ * closeable to close
+ * @throws IOException
+ * when close fails
+ */
+ public static void close(Closeable closeable) throws IOException
+ {
+ if (closeable != null)
+ {
+ closeable.close();
+ }
+ }
+
/**
* Writes the input stream to the output stream. Input is done without
a Reader object, meaning
Modified:
wicket/trunk/wicket/src/main/java/org/apache/wicket/util/resource/UrlResourceStream.java
URL:
http://svn.apache.org/viewvc/wicket/trunk/wicket/src/main/java/org/apache/wicket/util/resource/UrlResourceStream.java?rev=828326&r1=828325&r2=828326&view=diff
==============================================================================
---
wicket/trunk/wicket/src/main/java/org/apache/wicket/util/resource/UrlResourceStream.java
(original)
+++
wicket/trunk/wicket/src/main/java/org/apache/wicket/util/resource/UrlResourceStream.java
Thu Oct 22 06:43:37 2009
@@ -19,14 +19,12 @@
import java.io.File;
import java.io.IOException;
import java.io.InputStream;
-import java.net.HttpURLConnection;
-import java.net.JarURLConnection;
-import java.net.URI;
import java.net.URL;
import java.net.URLConnection;
import org.apache.wicket.Application;
import org.apache.wicket.protocol.http.WebApplication;
+import org.apache.wicket.util.io.Connections;
import org.apache.wicket.util.time.Time;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
@@ -38,6 +36,7 @@
* @see org.apache.wicket.util.resource.IResourceStream
* @see org.apache.wicket.util.watch.IModifiable
* @author Jonathan Locke
+ * @author Igor Vaynberg
*/
public class UrlResourceStream extends AbstractResourceStream
implements
@@ -74,61 +73,36 @@
*/
public UrlResourceStream(final URL url)
{
- // Save URL
+ // save the url
this.url = url;
+
+ // retrieve the content type and length
URLConnection connection = null;
try
{
connection = url.openConnection();
contentLength = connection.getContentLength();
contentType = connection.getContentType();
- lastModified = connection.getLastModified();
- try
- {
- file = new File(new URI(url.toExternalForm()));
- }
- catch (Exception ex)
- {
- log.debug("cannot convert url: " + url + " to
file (" + ex.getMessage() +
- "), falling back to the inputstream for
polling");
- }
- if (file != null && !file.exists())
- {
- file = null;
- }
}
catch (IOException ex)
{
- // It should be impossible to get here or the original
URL
- // couldn't have been constructed. But we re-throw with
details
- // anyway.
- final IllegalArgumentException illegalArgumentException
= new IllegalArgumentException(
- "Invalid URL parameter " + url);
- illegalArgumentException.initCause(ex);
- throw illegalArgumentException;
+ throw new IllegalArgumentException("Invalid URL
parameter " + url, ex);
}
finally
{
- // if applicable, disconnect
- if (connection != null)
- {
- if (connection instanceof HttpURLConnection)
- {
-
((HttpURLConnection)connection).disconnect();
- }
- else
- {
- try
- {
-
connection.getInputStream().close();
- }
- catch (Exception ex)
- {
- // ignore
- }
- }
- }
+ Connections.closeQuietly(connection);
+ }
+
+ try
+ {
+ file = Connections.findFile(url);
}
+ catch (Exception e)
+ {
+ log.debug("cannot convert url: " + url + " to file (" +
e.getMessage() +
+ "), falling back to the inputstream for
polling");
+ }
+
}
/**
@@ -221,13 +195,15 @@
{
if (file != null)
{
- // In case the file has been removed by now
+ // in case the file has been removed by now
if (file.exists() == false)
{
return null;
}
long lastModified = file.lastModified();
+
+ // if last modified changed update content length and
last modified date
if (lastModified != this.lastModified)
{
this.lastModified = lastModified;
@@ -236,38 +212,18 @@
}
else
{
- URLConnection urlConnection = null;
- boolean close = false;
try
{
- urlConnection = url.openConnection();
- long lastModified = this.lastModified;
- if (urlConnection instanceof JarURLConnection)
- {
- JarURLConnection jarUrlConnection =
(JarURLConnection)urlConnection;
- URL jarFileUrl =
jarUrlConnection.getJarFileURL();
- URLConnection jarFileConnection =
jarFileUrl.openConnection();
- try
- {
- lastModified =
jarFileConnection.getLastModified();
- }
- finally
- {
-
jarFileConnection.getInputStream().close();
- }
- }
- else
- {
- close = true;
- lastModified =
urlConnection.getLastModified();
- }
+ long lastModified =
Connections.getLastModified(url);
- // update the last modified time.
+ // if last modified changed update content
length and last modified date
if (lastModified != this.lastModified)
{
this.lastModified = lastModified;
- close = true;
- contentLength =
urlConnection.getContentLength();
+
+ URLConnection connection =
url.openConnection();
+ contentLength =
connection.getContentLength();
+ Connections.close(connection);
}
}
catch (IOException e)
@@ -284,31 +240,10 @@
log.warn("getLastModified for " + url +
" failed: " + e.getMessage());
}
- // Allow modification watcher to detect the
problem
+ // allow modification watcher to detect the
problem
return null;
}
- finally
- {
- // if applicable, disconnect
- if (urlConnection != null)
- {
- if (urlConnection instanceof
HttpURLConnection)
- {
-
((HttpURLConnection)urlConnection).disconnect();
- }
- else if (close)
- {
- try
- {
-
urlConnection.getInputStream().close();
- }
- catch (Exception ex)
- {
- // ignore
- }
- }
- }
- }
+
}
return Time.milliseconds(lastModified);
}