Repository: ant-ivy
Updated Branches:
  refs/heads/master 692071797 -> 6607bdcb3


http://git-wip-us.apache.org/repos/asf/ant-ivy/blob/6607bdcb/src/java/org/apache/ivy/util/url/HttpClientHandler.java
----------------------------------------------------------------------
diff --git a/src/java/org/apache/ivy/util/url/HttpClientHandler.java 
b/src/java/org/apache/ivy/util/url/HttpClientHandler.java
index 2c25026..469ad0c 100644
--- a/src/java/org/apache/ivy/util/url/HttpClientHandler.java
+++ b/src/java/org/apache/ivy/util/url/HttpClientHandler.java
@@ -17,19 +17,6 @@
  */
 package org.apache.ivy.util.url;
 
-import java.io.File;
-import java.io.FileInputStream;
-import java.io.IOException;
-import java.io.InputStream;
-import java.io.OutputStream;
-import java.net.URL;
-import java.net.UnknownHostException;
-import java.text.ParseException;
-import java.text.SimpleDateFormat;
-import java.util.ArrayList;
-import java.util.List;
-import java.util.Locale;
-
 import org.apache.commons.httpclient.Credentials;
 import org.apache.commons.httpclient.Header;
 import org.apache.commons.httpclient.HttpClient;
@@ -48,11 +35,25 @@ import org.apache.commons.httpclient.methods.HeadMethod;
 import org.apache.commons.httpclient.methods.PutMethod;
 import org.apache.commons.httpclient.methods.RequestEntity;
 import org.apache.commons.httpclient.params.HttpMethodParams;
+import org.apache.ivy.core.settings.TimeoutConstraint;
 import org.apache.ivy.util.CopyProgressListener;
 import org.apache.ivy.util.FileUtil;
 import org.apache.ivy.util.HostUtil;
 import org.apache.ivy.util.Message;
 
+import java.io.File;
+import java.io.FileInputStream;
+import java.io.IOException;
+import java.io.InputStream;
+import java.io.OutputStream;
+import java.net.URL;
+import java.net.UnknownHostException;
+import java.text.ParseException;
+import java.text.SimpleDateFormat;
+import java.util.ArrayList;
+import java.util.List;
+import java.util.Locale;
+
 /**
  *
  */
@@ -93,8 +94,16 @@ public class HttpClientHandler extends AbstractURLHandler {
         }
     }
 
-    public InputStream openStream(URL url) throws IOException {
-        GetMethod get = doGet(url, 0);
+    @Override
+    public InputStream openStream(final URL url) throws IOException {
+        return this.openStream(url, null);
+    }
+
+    @Override
+    public InputStream openStream(final URL url, final TimeoutConstraint 
timeoutConstraint) throws IOException {
+        final int connectionTimeout = (timeoutConstraint == null || 
timeoutConstraint.getConnectionTimeout() < 0) ? 0 : 
timeoutConstraint.getConnectionTimeout();
+        final int readTimeout = (timeoutConstraint == null || 
timeoutConstraint.getReadTimeout() < 0) ? 0 : 
timeoutConstraint.getReadTimeout();
+        final GetMethod get = doGet(url, connectionTimeout, readTimeout);
         if (!checkStatusCode(url, get)) {
             get.releaseConnection();
             throw new IOException("The HTTP response code for " + url
@@ -103,11 +112,21 @@ public class HttpClientHandler extends AbstractURLHandler 
{
 
         Header encoding = get.getResponseHeader("Content-Encoding");
         return getDecodingInputStream(encoding == null ? null : 
encoding.getValue(),
-            get.getResponseBodyAsStream());
+                get.getResponseBodyAsStream());
     }
 
-    public void download(URL src, File dest, CopyProgressListener l) throws 
IOException {
-        GetMethod get = doGet(src, 0);
+    @Override
+    public void download(final URL src, final File dest, final 
CopyProgressListener l) throws IOException {
+        this.download(src, dest, l, null);
+    }
+
+    @Override
+    public void download(final URL src, final File dest, final 
CopyProgressListener listener,
+                         final TimeoutConstraint timeoutConstraint) throws 
IOException {
+
+        final int connectionTimeout = (timeoutConstraint == null || 
timeoutConstraint.getConnectionTimeout() < 0) ? 0 : 
timeoutConstraint.getConnectionTimeout();
+        final int readTimeout = (timeoutConstraint == null || 
timeoutConstraint.getReadTimeout() < 0) ? 0 : 
timeoutConstraint.getReadTimeout();
+        final GetMethod get = doGet(src, connectionTimeout, readTimeout);
         try {
             // We can only figure the content we got is want we want if the 
status is success.
             if (!checkStatusCode(src, get)) {
@@ -117,18 +136,28 @@ public class HttpClientHandler extends AbstractURLHandler 
{
 
             Header encoding = get.getResponseHeader("Content-Encoding");
             InputStream is = getDecodingInputStream(encoding == null ? null : 
encoding.getValue(),
-                get.getResponseBodyAsStream());
-            FileUtil.copy(is, dest, l);
+                    get.getResponseBodyAsStream());
+            FileUtil.copy(is, dest, listener);
             dest.setLastModified(getLastModified(get));
         } finally {
             get.releaseConnection();
         }
     }
 
-    public void upload(File src, URL dest, CopyProgressListener l) throws 
IOException {
-        HttpClient client = getClient();
+    @Override
+    public void upload(final File src, final URL dest, final 
CopyProgressListener l) throws IOException {
+        this.upload(src, dest, l, null);
+    }
 
-        PutMethod put = new PutMethod(normalizeToString(dest));
+    @Override
+    public void upload(final File src, final URL dest, final 
CopyProgressListener listener, final TimeoutConstraint timeoutConstraint) 
throws IOException {
+        final int connectionTimeout = (timeoutConstraint == null || 
timeoutConstraint.getConnectionTimeout() < 0) ? 0 : 
timeoutConstraint.getConnectionTimeout();
+        final HttpClient client = getClient();
+        // TODO: Use the newer way of settings the connection timeout via 
HttpConnectionManagerParams
+        // once we stop support for HttpClient 2.x version
+        client.setConnectionTimeout(connectionTimeout);
+
+        final PutMethod put = new PutMethod(normalizeToString(dest));
         put.setDoAuthentication(useAuthentication(dest) || 
useProxyAuthentication());
         put.getParams().setBooleanParameter("http.protocol.expect-continue", 
true);
         try {
@@ -138,20 +167,29 @@ public class HttpClientHandler extends AbstractURLHandler 
{
         } finally {
             put.releaseConnection();
         }
+
+    }
+
+    @Override
+    public URLInfo getURLInfo(final URL url) {
+        return this.getURLInfo(url, null);
     }
 
-    public URLInfo getURLInfo(URL url) {
-        return getURLInfo(url, 0);
+    @Override
+    public URLInfo getURLInfo(final URL url, final int timeout) {
+        return this.getURLInfo(url, createTimeoutConstraints(timeout));
     }
 
-    @SuppressWarnings("deprecation")
-    public URLInfo getURLInfo(URL url, int timeout) {
+    @Override
+    public URLInfo getURLInfo(final URL url, final TimeoutConstraint 
timeoutConstraint) {
+        final int connectionTimeout = (timeoutConstraint == null || 
timeoutConstraint.getConnectionTimeout() < 0) ? 0 : 
timeoutConstraint.getConnectionTimeout();
+        final int readTimeout = (timeoutConstraint == null || 
timeoutConstraint.getReadTimeout() < 0) ? 0 : 
timeoutConstraint.getReadTimeout();
         HttpMethodBase method = null;
         try {
             if (getRequestMethod() == URLHandler.REQUEST_METHOD_HEAD) {
-                method = doHead(url, timeout);
+                method = doHead(url, connectionTimeout, readTimeout);
             } else {
-                method = doGet(url, timeout);
+                method = doGet(url, connectionTimeout, readTimeout);
             }
             if (checkStatusCode(url, method)) {
                 return new URLInfo(true, getResponseContentLength(method), 
getLastModified(method),
@@ -246,10 +284,12 @@ public class HttpClientHandler extends AbstractURLHandler 
{
         return helper.getHttpClientMajorVersion();
     }
 
-    @SuppressWarnings("deprecation")
-    private GetMethod doGet(URL url, int timeout) throws IOException {
-        HttpClient client = getClient();
-        client.setTimeout(timeout);
+    private GetMethod doGet(final URL url, final int connectionTimeout, final 
int readTimeout) throws IOException {
+        final HttpClient client = getClient();
+        // TODO: Use the newer way of settings the connection and read timeout 
via HttpConnectionManagerParams
+        // once we stop support for HttpClient 2.x version
+        client.setConnectionTimeout(connectionTimeout);
+        client.setTimeout(readTimeout);
 
         GetMethod get = new GetMethod(normalizeToString(url));
         get.setDoAuthentication(useAuthentication(url) || 
useProxyAuthentication());
@@ -258,10 +298,12 @@ public class HttpClientHandler extends AbstractURLHandler 
{
         return get;
     }
 
-    @SuppressWarnings("deprecation")
-    private HeadMethod doHead(URL url, int timeout) throws IOException {
-        HttpClient client = getClient();
-        client.setTimeout(timeout);
+    private HeadMethod doHead(final URL url, final int connectionTimeout, 
final int readTimeout) throws IOException {
+        final HttpClient client = getClient();
+        // TODO: Use the newer way of settings the connection and read timeout 
via HttpConnectionManagerParams
+        // once we stop support for HttpClient 2.x version
+        client.setConnectionTimeout(connectionTimeout);
+        client.setTimeout(readTimeout);
 
         HeadMethod head = new HeadMethod(normalizeToString(url));
         head.setDoAuthentication(useAuthentication(url) || 
useProxyAuthentication());
@@ -290,18 +332,18 @@ public class HttpClientHandler extends AbstractURLHandler 
{
                 httpClient.getHostConfiguration().setProxy(proxyHost, 
proxyPort);
                 if (useProxyAuthentication()) {
                     httpClient.getState().setProxyCredentials(
-                        new AuthScope(proxyHost, proxyPort, 
AuthScope.ANY_REALM),
-                        createCredentials(proxyUserName, proxyPasswd));
+                            new AuthScope(proxyHost, proxyPort, 
AuthScope.ANY_REALM),
+                            createCredentials(proxyUserName, proxyPasswd));
                 }
             }
 
             // user-agent
             httpClient.getParams().setParameter(HttpMethodParams.USER_AGENT,
-                getUserAgent());
+                    getUserAgent());
 
             // authentication
             httpClient.getParams().setParameter(CredentialsProvider.PROVIDER,
-                new IvyCredentialsProvider());
+                    new IvyCredentialsProvider());
         }
 
         return httpClient;
@@ -376,7 +418,7 @@ public class HttpClientHandler extends AbstractURLHandler {
             String realm = scheme.getRealm();
 
             org.apache.ivy.util.Credentials c = 
CredentialsStore.INSTANCE.getCredentials(realm,
-                host);
+                    host);
             if (c != null) {
                 return createCredentials(c.getUserName(), c.getPasswd());
             }

http://git-wip-us.apache.org/repos/asf/ant-ivy/blob/6607bdcb/src/java/org/apache/ivy/util/url/URLHandler.java
----------------------------------------------------------------------
diff --git a/src/java/org/apache/ivy/util/url/URLHandler.java 
b/src/java/org/apache/ivy/util/url/URLHandler.java
index b429ef9..0b31c5e 100644
--- a/src/java/org/apache/ivy/util/url/URLHandler.java
+++ b/src/java/org/apache/ivy/util/url/URLHandler.java
@@ -17,13 +17,14 @@
  */
 package org.apache.ivy.util.url;
 
+import org.apache.ivy.core.settings.TimeoutConstraint;
+import org.apache.ivy.util.CopyProgressListener;
+
 import java.io.File;
 import java.io.IOException;
 import java.io.InputStream;
 import java.net.URL;
 
-import org.apache.ivy.util.CopyProgressListener;
-
 /**
  * This interface is responsible for handling some URL manipulation (stream 
opening, downloading,
  * check reachability, ...).
@@ -34,14 +35,14 @@ public interface URLHandler {
      * Using the slower REQUEST method for getting the basic URL infos. Use 
this when getting errors
      * behind a problematic/special proxy or firewall chain.
      */
-    public static final int REQUEST_METHOD_GET = 1;
+    int REQUEST_METHOD_GET = 1;
 
     /**
      * Using the faster HEAD method for getting the basic URL infos. Works for 
most common networks.
      */
-    public static final int REQUEST_METHOD_HEAD = 2;
+    int REQUEST_METHOD_HEAD = 2;
 
-    public static class URLInfo {
+    class URLInfo {
         private long contentLength;
 
         private long lastModified;
@@ -55,7 +56,7 @@ public interface URLHandler {
         }
 
         protected URLInfo(boolean available, long contentLength, long 
lastModified,
-                String bodyCharset) {
+                          String bodyCharset) {
             this.available = available;
             this.contentLength = contentLength;
             this.lastModified = lastModified;
@@ -79,86 +80,210 @@ public interface URLHandler {
         }
     }
 
-    public static final URLInfo UNAVAILABLE = new URLInfo(false, 0, 0);
+    URLInfo UNAVAILABLE = new URLInfo(false, 0, 0);
 
     /**
      * Please prefer getURLInfo when several infos are needed.
      *
      * @param url the url to check
      * @return true if the target is reachable
+     * @deprecated Use {@link #isReachable(URL, TimeoutConstraint)} instead
      */
-    public boolean isReachable(URL url);
+    @Deprecated
+    boolean isReachable(URL url);
 
     /**
      * Please prefer getURLInfo when several infos are needed.
      *
-     * @param url the url to check
+     * @param url     the url to check
      * @param timeout the timeout in milliseconds
      * @return true if the target is reachable
+     * @deprecated Use {@link #isReachable(URL, TimeoutConstraint)} instead
+     */
+    @Deprecated
+    boolean isReachable(URL url, int timeout);
+
+    /**
+     * Returns true if the passed <code>URL</code> is reachable. Else returns 
false. Uses the
+     * passed <code>timeoutConstraint</code> for determining the connectivity 
to the URL.
+     * <p>
+     * Please use {@link #getURLInfo(URL, TimeoutConstraint)} if more one 
information about the <code>url</code>
+     * is needed
+     *
+     * @param url                The URL to access
+     * @param timeoutConstraint The connectivity timeout constraints. Can be 
null, in which case the timeouts
+     *                           are implementation specific
+     * @return
+     * @since 2.5
      */
-    public boolean isReachable(URL url, int timeout);
+    boolean isReachable(URL url, TimeoutConstraint timeoutConstraint);
 
     /**
      * Please prefer getURLInfo when several infos are needed.
      *
      * @param url the url to check
      * @return the length of the target if the given url is reachable, 0 
otherwise. No error code in
-     *         case of http urls.
+     * case of http urls.
+     * @deprecated Use {@link #getContentLength(URL, TimeoutConstraint)} 
instead
      */
-    public long getContentLength(URL url);
+    @Deprecated
+    long getContentLength(URL url);
 
     /**
-     * @param url
-     *            the url to check
-     * @param timeout
-     *            the maximum time before considering an url is not reachable a
-     *            timeout of zero indicates no timeout
+     * @param url     the url to check
+     * @param timeout the maximum time before considering an url is not 
reachable a
+     *                timeout of zero indicates no timeout
      * @return the length of the target if the given url is reachable, 0 
otherwise. No error code in
-     *         case of http urls.
+     * case of http urls.
+     * @deprecated Use {@link #getContentLength(URL, TimeoutConstraint)} 
instead
      */
-    public long getContentLength(URL url, int timeout);
+    @Deprecated
+    long getContentLength(URL url, int timeout);
+
+    /**
+     * Returns the number of bytes of data that's available for the resource 
at the passed <code>url</code>.
+     * Returns 0 if the passed <code>url</code> isn't reachable
+     *
+     * @param url                The URL to access
+     * @param timeoutConstraint The connectivity timeout constraints. Can be 
null, in which case the timeouts
+     *                           are implementation specific
+     * @return
+     * @since 2.5
+     */
+    long getContentLength(URL url, TimeoutConstraint timeoutConstraint);
 
     /**
      * Please prefer getURLInfo when several infos are needed.
      *
-     * @param url
-     *            the url to check
+     * @param url the url to check
      * @return last modified timestamp of the given url
+     * @deprecated Use {@link #getLastModified(URL, TimeoutConstraint)} instead
      */
-    public long getLastModified(URL url);
+    @Deprecated
+    long getLastModified(URL url);
 
     /**
      * Please prefer getURLInfo when several infos are needed.
      *
-     * @param url the url to check
+     * @param url     the url to check
      * @param timeout the timeout in milliseconds
      * @return last modified timestamp of the given url
+     * @deprecated Use {@link #getLastModified(URL, TimeoutConstraint)} instead
      */
-    public long getLastModified(URL url, int timeout);
+    @Deprecated
+    long getLastModified(URL url, int timeout);
 
     /**
-     * @param url
-     *            The url from which information is retrieved.
+     * Returns the last modified timestamp of the resource accessible at the 
passed <code>url</code>.
+     * <p>
+     * Please use {@link #getURLInfo(URL, TimeoutConstraint)} if more one 
information about the <code>url</code>
+     * is needed
+     *
+     * @param url                The URL to access
+     * @param timeoutConstraint The connectivity timeout constraints. Can be 
null, in which case the timeouts
+     *                           are implementation specific
+     * @return
+     * @since 2.5
+     */
+    long getLastModified(URL url, TimeoutConstraint timeoutConstraint);
+
+    /**
+     * @param url The url from which information is retrieved.
      * @return The URLInfo extracted from the given url, or {@link 
#UNAVAILABLE} instance when the
-     *         url is not reachable.
+     * url is not reachable.
+     * @deprecated Use {@link #getURLInfo(URL, TimeoutConstraint)} instead
      */
-    public URLInfo getURLInfo(URL url);
+    @Deprecated
+    URLInfo getURLInfo(URL url);
 
     /**
-     * @param url
-     *            The url from which information is retrieved.
-     * @param timeout
-     *            The timeout in milliseconds.
+     * @param url     The url from which information is retrieved.
+     * @param timeout The timeout in milliseconds.
      * @return The URLInfo extracted from the given url, or {@link 
#UNAVAILABLE} when the url is not
-     *         reachable, never null.
+     * reachable, never null.
+     * @deprecated Use {@link #getURLInfo(URL, TimeoutConstraint)} instead
      */
-    public URLInfo getURLInfo(URL url, int timeout);
+    @Deprecated
+    URLInfo getURLInfo(URL url, int timeout);
 
-    public InputStream openStream(URL url) throws IOException;
+    /**
+     * Returns the {@link URLInfo} extracted from the given url, or {@link 
#UNAVAILABLE} when the url is not
+     * reachable. Never returns null.
+     *
+     * @param url                The URL for which the information is to be 
retrieved
+     * @param timeoutConstraint The connectivity timeout constraints. Can be 
null, in which case the timeouts
+     *                           are implementation specific
+     * @return
+     * @since 2.5
+     */
+    URLInfo getURLInfo(URL url, TimeoutConstraint timeoutConstraint);
+
+    /**
+     * @param url
+     * @return
+     * @throws IOException
+     * @deprecated Use {@link #openStream(URL, TimeoutConstraint)} instead
+     */
+    @Deprecated
+    InputStream openStream(URL url) throws IOException;
 
-    public void download(URL src, File dest, CopyProgressListener l) throws 
IOException;
+    /**
+     * Opens and returns an {@link InputStream} to the passed <code>url</code>.
+     *
+     * @param url                The URL to which an {@link InputStream} has 
to be opened
+     * @param timeoutConstraint The connectivity timeout constraints. Can be 
null, in which case the timeouts
+     *                           are implementation specific
+     * @return
+     * @throws IOException
+     * @since 2.5
+     */
+    InputStream openStream(URL url, TimeoutConstraint timeoutConstraint) 
throws IOException;
 
-    public void upload(File src, URL dest, CopyProgressListener l) throws 
IOException;
+    /**
+     * @param src
+     * @param dest
+     * @param l
+     * @throws IOException
+     * @deprecated Use {@link #download(URL, File, CopyProgressListener, 
TimeoutConstraint)} instead
+     */
+    @Deprecated
+    void download(URL src, File dest, CopyProgressListener l) throws 
IOException;
+
+    /**
+     * Downloads the resource available at <code>src</code> to the target 
<code>dest</code>
+     *
+     * @param src                The source URL to download the resource from
+     * @param dest               The destination {@link File} to download the 
resource to
+     * @param listener           The listener that will be notified of the 
download progress
+     * @param timeoutConstraint The connectivity timeout constraints. Can be 
null, in which case the timeouts
+     *                           are implementation specific
+     * @throws IOException
+     * @since 2.5
+     */
+    void download(URL src, File dest, CopyProgressListener listener, 
TimeoutConstraint timeoutConstraint) throws IOException;
+
+    /**
+     * @param src
+     * @param dest
+     * @param l
+     * @throws IOException
+     * @deprecated Use {@link #upload(File, URL, CopyProgressListener, 
TimeoutConstraint)} instead
+     */
+    @Deprecated
+    void upload(File src, URL dest, CopyProgressListener l) throws IOException;
+
+    /**
+     * Uploads the <code>src</code> {@link File} to the target 
<code>dest</code> {@link URL}
+     *
+     * @param src                The source {@link File} to upload
+     * @param dest               The target URL where the {@link File} has to 
be uploaded
+     * @param listener           The listener that will be notified of the 
upload progress
+     * @param timeoutConstraint The connectivity timeout constraints. Can be 
null, in which case the timeouts
+     *                           are implementation specific
+     * @throws IOException
+     * @since 2.5
+     */
+    void upload(File src, URL dest, CopyProgressListener listener, 
TimeoutConstraint timeoutConstraint) throws IOException;
 
-    public void setRequestMethod(int requestMethod);
+    void setRequestMethod(int requestMethod);
 }

http://git-wip-us.apache.org/repos/asf/ant-ivy/blob/6607bdcb/src/java/org/apache/ivy/util/url/URLHandlerDispatcher.java
----------------------------------------------------------------------
diff --git a/src/java/org/apache/ivy/util/url/URLHandlerDispatcher.java 
b/src/java/org/apache/ivy/util/url/URLHandlerDispatcher.java
index 2c89098..354d46e 100644
--- a/src/java/org/apache/ivy/util/url/URLHandlerDispatcher.java
+++ b/src/java/org/apache/ivy/util/url/URLHandlerDispatcher.java
@@ -17,6 +17,9 @@
  */
 package org.apache.ivy.util.url;
 
+import org.apache.ivy.core.settings.TimeoutConstraint;
+import org.apache.ivy.util.CopyProgressListener;
+
 import java.io.File;
 import java.io.IOException;
 import java.io.InputStream;
@@ -24,8 +27,6 @@ import java.net.URL;
 import java.util.HashMap;
 import java.util.Map;
 
-import org.apache.ivy.util.CopyProgressListener;
-
 /**
  * This class is used to dispatch downloading requests
  */
@@ -37,48 +38,94 @@ public class URLHandlerDispatcher implements URLHandler {
     public URLHandlerDispatcher() {
     }
 
-    public boolean isReachable(URL url) {
-        return getHandler(url.getProtocol()).isReachable(url);
+    @Override
+    public boolean isReachable(final URL url) {
+        return this.isReachable(url, null);
+    }
+
+    @Override
+    public boolean isReachable(final URL url, final int timeout) {
+        return this.isReachable(url, createTimeoutConstraints(timeout));
+    }
+
+    @Override
+    public boolean isReachable(final URL url, final TimeoutConstraint 
timeoutConstraint) {
+        return this.getHandler(url.getProtocol()).isReachable(url, 
timeoutConstraint);
+    }
+
+    @Override
+    public long getContentLength(final URL url) {
+        return this.getContentLength(url, null);
+    }
+
+    @Override
+    public long getContentLength(final URL url, final int timeout) {
+        return this.getContentLength(url, createTimeoutConstraints(timeout));
+    }
+
+    @Override
+    public long getContentLength(final URL url, final TimeoutConstraint 
timeoutConstraint) {
+        return this.getHandler(url.getProtocol()).getContentLength(url, 
timeoutConstraint);
     }
 
-    public boolean isReachable(URL url, int timeout) {
-        return getHandler(url.getProtocol()).isReachable(url, timeout);
+    @Override
+    public long getLastModified(final URL url) {
+        return this.getLastModified(url, null);
     }
 
-    public long getContentLength(URL url) {
-        return getHandler(url.getProtocol()).getContentLength(url);
+    @Override
+    public long getLastModified(final URL url, final int timeout) {
+        return this.getLastModified(url, createTimeoutConstraints(timeout));
     }
 
-    public long getContentLength(URL url, int timeout) {
-        return getHandler(url.getProtocol()).getContentLength(url, timeout);
+    @Override
+    public long getLastModified(final URL url, final TimeoutConstraint 
timeoutConstraint) {
+        return this.getHandler(url.getProtocol()).getLastModified(url, 
timeoutConstraint);
     }
 
-    public long getLastModified(URL url) {
-        return getHandler(url.getProtocol()).getLastModified(url);
+    @Override
+    public URLInfo getURLInfo(final URL url) {
+        return this.getURLInfo(url, null);
     }
 
-    public long getLastModified(URL url, int timeout) {
-        return getHandler(url.getProtocol()).getLastModified(url, timeout);
+    @Override
+    public URLInfo getURLInfo(final URL url, final int timeout) {
+        return this.getURLInfo(url, createTimeoutConstraints(timeout));
     }
 
-    public URLInfo getURLInfo(URL url) {
-        return getHandler(url.getProtocol()).getURLInfo(url);
+    @Override
+    public URLInfo getURLInfo(final URL url, final TimeoutConstraint 
timeoutConstraint) {
+        return this.getHandler(url.getProtocol()).getURLInfo(url, 
timeoutConstraint);
     }
 
-    public URLInfo getURLInfo(URL url, int timeout) {
-        return getHandler(url.getProtocol()).getURLInfo(url, timeout);
+    @Override
+    public InputStream openStream(final URL url) throws IOException {
+        return this.openStream(url, null);
     }
 
-    public InputStream openStream(URL url) throws IOException {
-        return getHandler(url.getProtocol()).openStream(url);
+    @Override
+    public InputStream openStream(final URL url, final TimeoutConstraint 
timeoutConstraint) throws IOException {
+        return this.getHandler(url.getProtocol()).openStream(url, 
timeoutConstraint);
     }
 
-    public void download(URL src, File dest, CopyProgressListener l) throws 
IOException {
-        getHandler(src.getProtocol()).download(src, dest, l);
+    @Override
+    public void download(final URL src, final File dest, final 
CopyProgressListener l) throws IOException {
+        this.download(src, dest, l);
     }
 
-    public void upload(File src, URL dest, CopyProgressListener l) throws 
IOException {
-        getHandler(dest.getProtocol()).upload(src, dest, l);
+    @Override
+    public void download(final URL src, final File dest, final 
CopyProgressListener listener, final TimeoutConstraint timeoutConstraint) 
throws IOException {
+        this.getHandler(src.getProtocol()).download(src, dest, listener, 
timeoutConstraint);
+    }
+
+    @Override
+    public void upload(final File src, final URL dest, final 
CopyProgressListener l) throws IOException {
+        this.upload(src, dest, l);
+    }
+
+    @Override
+    public void upload(final File src, final URL dest, final 
CopyProgressListener listener, final TimeoutConstraint timeoutConstraint) 
throws IOException {
+        this.getHandler(dest.getProtocol()).upload(src, dest, listener, 
timeoutConstraint);
     }
 
     public void setRequestMethod(int requestMethod) {
@@ -104,4 +151,19 @@ public class URLHandlerDispatcher implements URLHandler {
     public void setDefault(URLHandler default1) {
         defaultHandler = default1;
     }
+
+    private static TimeoutConstraint createTimeoutConstraints(final int 
connectionTimeout) {
+        return new TimeoutConstraint() {
+            @Override
+            public int getConnectionTimeout() {
+                return connectionTimeout;
+            }
+
+            @Override
+            public int getReadTimeout() {
+                return -1;
+            }
+
+        };
+    }
 }

http://git-wip-us.apache.org/repos/asf/ant-ivy/blob/6607bdcb/test/java/org/apache/ivy/LocalFileRepoOverHttp.java
----------------------------------------------------------------------
diff --git a/test/java/org/apache/ivy/LocalFileRepoOverHttp.java 
b/test/java/org/apache/ivy/LocalFileRepoOverHttp.java
new file mode 100644
index 0000000..c1fb17d
--- /dev/null
+++ b/test/java/org/apache/ivy/LocalFileRepoOverHttp.java
@@ -0,0 +1,91 @@
+/*
+ * 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.ivy;
+
+import com.sun.net.httpserver.HttpExchange;
+import com.sun.net.httpserver.HttpHandler;
+import org.apache.ivy.util.Message;
+
+import java.io.IOException;
+import java.io.OutputStream;
+import java.net.URI;
+import java.net.URISyntaxException;
+import java.nio.file.Files;
+import java.nio.file.Path;
+
+/**
+ * A {@link HttpHandler} that can be used in tests to serve local file system 
based resources over HTTP
+ * NOTE: This handler reads the complete file contents, all into memory while 
serving it and thus isn't suitable
+ * with very large files. Use this handler only in test cases where the files 
to serve are reasonably small in size
+ */
+final class LocalFileRepoOverHttp implements HttpHandler {
+
+    private final String webContextRoot;
+    private final Path localFileRepoRoot;
+
+    LocalFileRepoOverHttp(final String webContextRoot, final Path 
localFileRepoRoot) {
+        if (!Files.isDirectory(localFileRepoRoot)) {
+            throw new IllegalArgumentException(localFileRepoRoot + " is either 
missing or not a directory");
+        }
+        this.webContextRoot = webContextRoot;
+        this.localFileRepoRoot = localFileRepoRoot;
+    }
+
+    @Override
+    public void handle(final HttpExchange httpExchange) throws IOException {
+        final URI requestURI = httpExchange.getRequestURI();
+        Message.info("Handling " + httpExchange.getRequestMethod() + " request 
" + requestURI);
+        final URI artifactURI;
+        try {
+            artifactURI = new URI(webContextRoot).relativize(requestURI);
+        } catch (URISyntaxException e) {
+            throw new IOException(e);
+        }
+        final Path localFilePath = 
localFileRepoRoot.resolve(artifactURI.toString());
+        if (httpExchange.getRequestMethod().equals("HEAD")) {
+            final boolean available = this.isPresent(localFilePath);
+            if (!available) {
+                httpExchange.sendResponseHeaders(404, -1);
+            } else {
+                httpExchange.sendResponseHeaders(200, -1);
+            }
+            return;
+        }
+        if (!httpExchange.getRequestMethod().equals("GET")) {
+            throw new IOException("Cannot handle " + 
httpExchange.getRequestMethod() + " HTTP method");
+        }
+        final OutputStream responseStream = httpExchange.getResponseBody();
+        final int numBytes = this.serve(httpExchange, localFilePath, 
responseStream);
+        responseStream.close();
+    }
+
+    private boolean isPresent(final Path localFile) {
+        return Files.isRegularFile(localFile);
+    }
+
+    private int serve(final HttpExchange httpExchange, final Path localFile, 
final OutputStream os) throws IOException {
+        if (!Files.isRegularFile(localFile)) {
+            throw new IOException("No such file at path " + localFile);
+        }
+        Message.debug("Serving contents of " + localFile + " for request " + 
httpExchange.getRequestURI());
+        final byte[] data = Files.readAllBytes(localFile);
+        httpExchange.sendResponseHeaders(200, data.length);
+        os.write(data);
+        return data.length;
+    }
+}

http://git-wip-us.apache.org/repos/asf/ant-ivy/blob/6607bdcb/test/java/org/apache/ivy/TestHelper.java
----------------------------------------------------------------------
diff --git a/test/java/org/apache/ivy/TestHelper.java 
b/test/java/org/apache/ivy/TestHelper.java
index e20144b..a908fbd 100644
--- a/test/java/org/apache/ivy/TestHelper.java
+++ b/test/java/org/apache/ivy/TestHelper.java
@@ -17,19 +17,7 @@
  */
 package org.apache.ivy;
 
-import static org.junit.Assert.assertEquals;
-
-import java.io.File;
-import java.io.IOException;
-import java.lang.reflect.Field;
-import java.net.Authenticator;
-import java.util.ArrayList;
-import java.util.Collection;
-import java.util.Date;
-import java.util.LinkedHashSet;
-import java.util.regex.Matcher;
-import java.util.regex.Pattern;
-
+import com.sun.net.httpserver.HttpServer;
 import org.apache.ivy.core.cache.DefaultRepositoryCacheManager;
 import org.apache.ivy.core.event.EventManager;
 import org.apache.ivy.core.module.descriptor.Artifact;
@@ -51,6 +39,21 @@ import org.apache.tools.ant.DefaultLogger;
 import org.apache.tools.ant.Project;
 import org.apache.tools.ant.taskdefs.Delete;
 
+import java.io.File;
+import java.io.IOException;
+import java.lang.reflect.Field;
+import java.net.Authenticator;
+import java.net.InetSocketAddress;
+import java.nio.file.Path;
+import java.util.ArrayList;
+import java.util.Collection;
+import java.util.Date;
+import java.util.LinkedHashSet;
+import java.util.regex.Matcher;
+import java.util.regex.Pattern;
+
+import static org.junit.Assert.assertEquals;
+
 public class TestHelper {
 
     public static DefaultArtifact newArtifact(String organisation, String 
module, String revision,
@@ -371,4 +374,33 @@ public class TestHelper {
             return null;
         }
     }
+
+    /**
+     * Creates a HTTP server, backed by a local file system, which can be used 
as a repository to serve Ivy module descriptors
+     * and artifacts.
+     * NOTE: This is supposed to be used only in test cases and only a limited 
functionality is added in the handler(s) backing the
+     * server
+     *
+     * @param serverAddress           The address to which the server will be 
bound
+     * @param webAppContext           The context root of the application 
which will be handling the requests to the server
+     * @param localFilesystemRepoRoot The path to the root directory 
containing the module descriptors and artifacts
+     * @return
+     * @throws IOException
+     */
+    public static AutoCloseable createHttpServerBackedRepository(final 
InetSocketAddress serverAddress, final String webAppContext,
+                                                                 final Path 
localFilesystemRepoRoot) throws IOException {
+        final LocalFileRepoOverHttp handler = new 
LocalFileRepoOverHttp(webAppContext, localFilesystemRepoRoot);
+        final HttpServer server = HttpServer.create(serverAddress, -1);
+        // setup the handler
+        server.createContext(webAppContext, handler);
+        // start the server
+        server.start();
+        return new AutoCloseable() {
+            @Override
+            public void close() throws Exception {
+                final int delaySeconds = 0;
+                server.stop(delaySeconds);
+            }
+        };
+    }
 }

http://git-wip-us.apache.org/repos/asf/ant-ivy/blob/6607bdcb/test/java/org/apache/ivy/core/resolve/ResolveTest.java
----------------------------------------------------------------------
diff --git a/test/java/org/apache/ivy/core/resolve/ResolveTest.java 
b/test/java/org/apache/ivy/core/resolve/ResolveTest.java
index 43d3cf4..3de1346 100644
--- a/test/java/org/apache/ivy/core/resolve/ResolveTest.java
+++ b/test/java/org/apache/ivy/core/resolve/ResolveTest.java
@@ -840,7 +840,7 @@ public class ResolveTest {
         // put necessary stuff in cache, and it should now be ok
         File ivyfile = getIvyFileInCache(ModuleRevisionId.newInstance("org1", 
"mod1.2", "2.0"));
         File art = getArchiveFileInCache(ivy, "org1", "mod1.2", "2.0", 
"mod1.2", "jar", "jar");
-        FileUtil.copy(ResolveTest.class.getResource("ivy-mod1.2.xml"), 
ivyfile, null);
+        FileUtil.copy(ResolveTest.class.getResource("ivy-mod1.2.xml"), 
ivyfile, null, null);
         FileUtil.copy(new 
File("test/repositories/1/org1/mod1.2/jars/mod1.2-2.0.jar"), art, null);
 
         ResolveReport report = ivy.resolve(new File(

http://git-wip-us.apache.org/repos/asf/ant-ivy/blob/6607bdcb/test/java/org/apache/ivy/core/settings/XmlSettingsParserTest.java
----------------------------------------------------------------------
diff --git a/test/java/org/apache/ivy/core/settings/XmlSettingsParserTest.java 
b/test/java/org/apache/ivy/core/settings/XmlSettingsParserTest.java
index 2cf7a4f..6a271a4 100644
--- a/test/java/org/apache/ivy/core/settings/XmlSettingsParserTest.java
+++ b/test/java/org/apache/ivy/core/settings/XmlSettingsParserTest.java
@@ -17,16 +17,6 @@
  */
 package org.apache.ivy.core.settings;
 
-import static org.junit.Assert.assertEquals;
-import static org.junit.Assert.assertFalse;
-import static org.junit.Assert.assertNotNull;
-import static org.junit.Assert.assertTrue;
-
-import java.io.File;
-import java.io.IOException;
-import java.text.ParseException;
-import java.util.List;
-
 import org.apache.ivy.core.cache.DefaultRepositoryCacheManager;
 import org.apache.ivy.core.cache.ResolutionCacheManager;
 import org.apache.ivy.core.module.descriptor.Artifact;
@@ -47,6 +37,7 @@ import org.apache.ivy.plugins.resolver.DependencyResolver;
 import org.apache.ivy.plugins.resolver.FileSystemResolver;
 import org.apache.ivy.plugins.resolver.IBiblioResolver;
 import org.apache.ivy.plugins.resolver.MockResolver;
+import org.apache.ivy.plugins.resolver.URLResolver;
 import org.apache.ivy.plugins.resolver.packager.PackagerResolver;
 import org.apache.ivy.plugins.version.ChainVersionMatcher;
 import org.apache.ivy.plugins.version.MockVersionMatcher;
@@ -55,8 +46,19 @@ import org.junit.Rule;
 import org.junit.Test;
 import org.junit.rules.ExpectedException;
 
+import java.io.File;
+import java.io.IOException;
+import java.text.ParseException;
+import java.util.List;
+
+import static org.junit.Assert.assertEquals;
+import static org.junit.Assert.assertFalse;
+import static org.junit.Assert.assertNotNull;
+import static org.junit.Assert.assertNull;
+import static org.junit.Assert.assertTrue;
+
 /**
- * TODO write javadoc
+ * Test the parsing of Ivy settings file through the {@link XmlSettingsParser}
  */
 public class XmlSettingsParserTest {
     @Rule
@@ -77,7 +79,7 @@ public class XmlSettingsParserTest {
 
         assertEquals("[module]/ivys/ivy-[revision].xml", 
settings.getDefaultCacheIvyPattern());
         assertEquals("[module]/[type]s/[artifact]-[revision].[ext]",
-            settings.getDefaultCacheArtifactPattern());
+                settings.getDefaultCacheArtifactPattern());
 
         LatestStrategy latest = 
settings.getLatestStrategy("mylatest-revision");
         assertNotNull(latest);
@@ -95,7 +97,7 @@ public class XmlSettingsParserTest {
         assertNotNull(ivyPatterns);
         assertEquals(1, ivyPatterns.size());
         
assertLocationEquals("lib/[organisation]/[module]/ivys/ivy-[revision].xml",
-            ivyPatterns.get(0));
+                ivyPatterns.get(0));
 
         LatestStrategy strategy = fsres.getLatestStrategy();
         assertNotNull(strategy);
@@ -120,15 +122,15 @@ public class XmlSettingsParserTest {
         assertTrue(strategy instanceof LatestTimeStrategy);
 
         assertEquals("libraries",
-            settings.getResolver(ModuleRevisionId.newInstance("unknown", 
"lib", "1.0")).getName());
+                settings.getResolver(ModuleRevisionId.newInstance("unknown", 
"lib", "1.0")).getName());
         assertEquals("internal",
-            settings.getResolver(ModuleRevisionId.newInstance("apache", "ant", 
"1.0")).getName());
+                settings.getResolver(ModuleRevisionId.newInstance("apache", 
"ant", "1.0")).getName());
         assertEquals("int2",
-            settings.getResolver(ModuleRevisionId.newInstance("apache", "ivy", 
"2.0")).getName());
+                settings.getResolver(ModuleRevisionId.newInstance("apache", 
"ivy", "2.0")).getName());
         assertEquals("int1",
-            settings.getResolver(ModuleRevisionId.newInstance("apache", "ivy", 
"1.0")).getName());
+                settings.getResolver(ModuleRevisionId.newInstance("apache", 
"ivy", "1.0")).getName());
         assertEquals("int1",
-            settings.getResolver(ModuleRevisionId.newInstance("apache", 
"ivyde", "1.0")).getName());
+                settings.getResolver(ModuleRevisionId.newInstance("apache", 
"ivyde", "1.0")).getName());
     }
 
     @Test
@@ -217,7 +219,7 @@ public class XmlSettingsParserTest {
 
         assertEquals("[module]/ivys/ivy-[revision].xml", 
settings.getDefaultCacheIvyPattern());
         assertEquals("[module]/[type]s/[artifact]-[revision].[ext]",
-            settings.getDefaultCacheArtifactPattern());
+                settings.getDefaultCacheArtifactPattern());
         assertEquals(true, settings.isDefaultUseOrigin());
 
         DefaultRepositoryCacheManager c = (DefaultRepositoryCacheManager) 
settings
@@ -226,13 +228,13 @@ public class XmlSettingsParserTest {
         assertEquals("mycache", c.getName());
         assertEquals(1000, c.getDefaultTTL());
         assertEquals(200,
-            c.getTTL(ModuleRevisionId.newInstance("apache", "ivy", 
"latest.integration")));
+                c.getTTL(ModuleRevisionId.newInstance("apache", "ivy", 
"latest.integration")));
         assertEquals(10 * 60 * 1000 + 20 * 1000, // 10m 20s
-            c.getTTL(ModuleRevisionId.newInstance("org1", "A", "A")));
+                c.getTTL(ModuleRevisionId.newInstance("org1", "A", "A")));
         assertEquals(5 * 3600 * 1000, // 5h
-            c.getTTL(ModuleRevisionId.newInstance("org2", "A", "A")));
+                c.getTTL(ModuleRevisionId.newInstance("org2", "A", "A")));
         assertEquals(60 * 3600 * 1000, // 2d 12h = 60h
-            c.getTTL(ModuleRevisionId.newInstance("org3", "A", "A")));
+                c.getTTL(ModuleRevisionId.newInstance("org3", "A", "A")));
         assertEquals(new File("mycache").getCanonicalFile(), 
c.getBasedir().getCanonicalFile());
         assertEquals(false, c.isUseOrigin());
         assertEquals("no-lock", c.getLockStrategy().getName());
@@ -328,7 +330,7 @@ public class XmlSettingsParserTest {
         assertNotNull(ivyPatterns);
         assertEquals(1, ivyPatterns.size());
         
assertLocationEquals("sharedrep/[organisation]/[module]/ivys/ivy-[revision].xml",
-            ivyPatterns.get(0));
+                ivyPatterns.get(0));
 
         DependencyResolver external = settings.getResolver("external");
         assertNotNull(external);
@@ -344,7 +346,7 @@ public class XmlSettingsParserTest {
         assertNotNull(ivyPatterns);
         assertEquals(1, ivyPatterns.size());
         
assertLocationEquals("sharedrep/[organisation]/[module]/ivys/ivy-[revision].xml",
-            ivyPatterns.get(0));
+                ivyPatterns.get(0));
     }
 
     @Test
@@ -367,8 +369,8 @@ public class XmlSettingsParserTest {
         assertNotNull(ivyPatterns);
         assertEquals(1, ivyPatterns.size());
         assertLocationEquals(
-            
"path/to/myrep/[organisation]/[module]/[type]s/[artifact]-[revision].[ext]",
-            ivyPatterns.get(0));
+                
"path/to/myrep/[organisation]/[module]/[type]s/[artifact]-[revision].[ext]",
+                ivyPatterns.get(0));
 
         FileSystemResolver fsInt2 = (FileSystemResolver) subresolvers.get(1);
         assertEquals("default-fs2", fsInt2.getName());
@@ -377,8 +379,8 @@ public class XmlSettingsParserTest {
         assertNotNull(ivyPatterns);
         assertEquals(1, ivyPatterns.size());
         assertLocationEquals(
-            
"path/to/secondrep/[organisation]/[module]/[type]s/ivy-[revision].xml",
-            ivyPatterns.get(0));
+                
"path/to/secondrep/[organisation]/[module]/[type]s/ivy-[revision].xml",
+                ivyPatterns.get(0));
 
         DependencyResolver other = settings.getResolver("other");
         assertNotNull(other);
@@ -395,7 +397,7 @@ public class XmlSettingsParserTest {
         assertNotNull(ivyPatterns);
         assertEquals(1, ivyPatterns.size());
         
assertLocationEquals("path/to/secondrep/[module]/[type]s/ivy-[revision].xml",
-            ivyPatterns.get(0));
+                ivyPatterns.get(0));
     }
 
     @Test
@@ -476,8 +478,8 @@ public class XmlSettingsParserTest {
         assertNotNull(ivyPatterns);
         assertEquals(1, ivyPatterns.size());
         assertLocationEquals(
-            
"path/to/myrep/[organisation]/[module]/[type]s/[artifact]-[revision].[ext]",
-            ivyPatterns.get(0));
+                
"path/to/myrep/[organisation]/[module]/[type]s/[artifact]-[revision].[ext]",
+                ivyPatterns.get(0));
 
         DependencyResolver inc = settings.getResolver("includeworks");
         assertNotNull(inc);
@@ -494,8 +496,8 @@ public class XmlSettingsParserTest {
         assertNotNull(ivyPatterns);
         assertEquals(1, ivyPatterns.size());
         assertLocationEquals(
-            
"included/myrep/[organisation]/[module]/[type]s/[artifact]-[revision].[ext]",
-            ivyPatterns.get(0));
+                
"included/myrep/[organisation]/[module]/[type]s/[artifact]-[revision].[ext]",
+                ivyPatterns.get(0));
 
         // properties defined in included file should be available to 
including file (IVY-780)
         assertEquals("myvalue", settings.getVariable("ivy.test.prop"));
@@ -543,8 +545,8 @@ public class XmlSettingsParserTest {
         assertNotNull(ivyPatterns);
         assertEquals(1, ivyPatterns.size());
         assertLocationEquals(
-            
"path/to/myrep/[organisation]/[module]/[type]s/[artifact]-[revision].[ext]",
-            ivyPatterns.get(0));
+                
"path/to/myrep/[organisation]/[module]/[type]s/[artifact]-[revision].[ext]",
+                ivyPatterns.get(0));
 
         DependencyResolver inc = settings.getResolver("includeworks");
         assertNotNull(inc);
@@ -561,8 +563,8 @@ public class XmlSettingsParserTest {
         assertNotNull(ivyPatterns);
         assertEquals(1, ivyPatterns.size());
         assertLocationEquals(
-            
"included/myrep/[organisation]/[module]/[type]s/[artifact]-[revision].[ext]",
-            ivyPatterns.get(0));
+                
"included/myrep/[organisation]/[module]/[type]s/[artifact]-[revision].[ext]",
+                ivyPatterns.get(0));
 
         // properties defined in included file should be available to 
including file (IVY-780)
         assertEquals("myvalue", settings.getVariable("ivy.test.prop"));
@@ -584,7 +586,7 @@ public class XmlSettingsParserTest {
         XmlSettingsParser parser = new XmlSettingsParser(settings);
         
parser.parse(XmlSettingsParserTest.class.getResource("ivysettings-parser.xml"));
         
assertEquals(ModuleDescriptorParserRegistryTest.MyParser.class.getName(),
-            
ModuleDescriptorParserRegistry.getInstance().getParsers()[0].getClass().getName());
+                
ModuleDescriptorParserRegistry.getInstance().getParsers()[0].getClass().getName());
     }
 
     @Test
@@ -633,14 +635,14 @@ public class XmlSettingsParserTest {
         settings.setBaseDir(new File("test/base/dir"));
         assertEquals(new File("test/base/dir").getAbsolutePath(), 
settings.getVariable("basedir"));
         assertEquals(new File("test/base/dir").getAbsolutePath(),
-            settings.getVariable("ivy.basedir"));
+                settings.getVariable("ivy.basedir"));
 
         settings = new IvySettings();
         settings.setVariable("basedir", new 
File("other/base/dir").getAbsolutePath());
         settings.setBaseDir(new File("test/base/dir"));
         assertEquals(new File("other/base/dir").getAbsolutePath(), 
settings.getVariable("basedir"));
         assertEquals(new File("test/base/dir").getAbsolutePath(),
-            settings.getVariable("ivy.basedir"));
+                settings.getVariable("ivy.basedir"));
     }
 
     /**
@@ -668,9 +670,79 @@ public class XmlSettingsParserTest {
         assertEquals("Unexpected ttl for module " + module2 + " on cache 
manager", 60000, module2SpecificTTL);
     }
 
+    /**
+     * Tests that the <code>timeout-constraint</code> elements in a Ivy 
settings file are parsed correctly
+     *
+     * @throws Exception
+     */
+    @Test
+    public void testTimeoutConstraints() throws Exception {
+        final IvySettings settings = new IvySettings();
+        settings.setBaseDir(new File("test/base/dir"));
+        final XmlSettingsParser parser = new XmlSettingsParser(settings);
+        
parser.parse(XmlSettingsParserTest.class.getResource("ivysettings-timeout-constraints.xml"));
+
+        final TimeoutConstraint timeout1 = 
settings.getTimeoutConstraint("test-timeout-1");
+        assertNotNull("test-timeout-1 timeout constraint is missing", 
timeout1);
+        assertEquals("Unexpected connection timeout " + 
timeout1.getConnectionTimeout() + " on time constraint test-timeout-1", 100, 
timeout1.getConnectionTimeout());
+        assertEquals("Unexpected read timeout " + timeout1.getReadTimeout() + 
" on time constraint test-timeout-1", 500, timeout1.getReadTimeout());
+
+
+        final TimeoutConstraint timeout2 = 
settings.getTimeoutConstraint("test-timeout-2");
+        assertNotNull("test-timeout-2 timeout constraint is missing", 
timeout2);
+        assertEquals("Unexpected connection timeout " + 
timeout2.getConnectionTimeout() + " on time constraint test-timeout-2", -1, 
timeout2.getConnectionTimeout());
+        assertEquals("Unexpected read timeout " + timeout2.getReadTimeout() + 
" on time constraint test-timeout-2", 20, timeout2.getReadTimeout());
+
+
+        final TimeoutConstraint timeout3 = 
settings.getTimeoutConstraint("test-timeout-3");
+        assertNotNull("test-timeout-3 timeout constraint is missing", 
timeout3);
+        assertEquals("Unexpected connection timeout " + 
timeout3.getConnectionTimeout() + " on time constraint test-timeout-3", 400, 
timeout3.getConnectionTimeout());
+        assertEquals("Unexpected read timeout " + timeout3.getReadTimeout() + 
" on time constraint test-timeout-3", -1, timeout3.getReadTimeout());
+
+        final TimeoutConstraint timeout4 = 
settings.getTimeoutConstraint("test-timeout-4");
+        assertNotNull("test-timeout-4 timeout constraint is missing", 
timeout4);
+        assertEquals("Unexpected connection timeout " + 
timeout4.getConnectionTimeout() + " on time constraint test-timeout-4", -1, 
timeout4.getConnectionTimeout());
+        assertEquals("Unexpected read timeout " + timeout4.getReadTimeout() + 
" on time constraint test-timeout-4", -1, timeout4.getReadTimeout());
+
+    }
+
+    /**
+     * Tests that timeout constraints referenced by resolvers, in an ivy 
settings file, are processed correctly and the
+     * corresponding resolvers use the right timeout constraints
+     *
+     * @throws Exception
+     */
+    @Test
+    public void testResolverTimeoutConstraintRefs() throws Exception {
+        final IvySettings settings = new IvySettings();
+        settings.setBaseDir(new File("test/base/dir"));
+        final XmlSettingsParser parser = new XmlSettingsParser(settings);
+        
parser.parse(XmlSettingsParserTest.class.getResource("ivysettings-timeout-constraints.xml"));
+
+        final URLResolver resolver1 = (URLResolver) 
settings.getResolver("urlresolver-1");
+        assertNotNull("Missing resolver urlresolver-1", resolver1);
+        final TimeoutConstraint resolver1Timeouts = 
resolver1.getTimeoutConstraint();
+        assertNotNull("Timeout constraint missing on resolver " + 
resolver1.getName(), resolver1Timeouts);
+        assertEquals("Unexpected connection timeout " + 
resolver1Timeouts.getConnectionTimeout() + " on resolver " + 
resolver1.getName(), 400, resolver1Timeouts.getConnectionTimeout());
+        assertEquals("Unexpected read timeout " + 
resolver1Timeouts.getReadTimeout() + " on resolver " + resolver1.getName(), -1, 
resolver1Timeouts.getReadTimeout());
+
+        final IBiblioResolver resolver2 = (IBiblioResolver) 
settings.getResolver("ibiblio-resolver");
+        assertNotNull("Missing resolver ibiblio-resolver", resolver2);
+        final TimeoutConstraint resolver2Timeouts = 
resolver2.getTimeoutConstraint();
+        assertNotNull("Timeout constraint missing on resolver " + 
resolver2.getName(), resolver2Timeouts);
+        assertEquals("Unexpected connection timeout " + 
resolver2Timeouts.getConnectionTimeout() + " on resolver " + 
resolver2.getName(), 100, resolver2Timeouts.getConnectionTimeout());
+        assertEquals("Unexpected read timeout " + 
resolver2Timeouts.getReadTimeout() + " on resolver " + resolver2.getName(), 
500, resolver2Timeouts.getReadTimeout());
+
+        final FileSystemResolver resolver3 = (FileSystemResolver) 
settings.getResolver("fs");
+        assertNotNull("Missing resolver fs", resolver3);
+        final TimeoutConstraint resolver3Timeouts = 
resolver3.getTimeoutConstraint();
+        assertNull("No timeout was expected on resolver " + 
resolver3.getName(), resolver3Timeouts);
+
+    }
+
     public static class MyOutputter implements ReportOutputter {
         public void output(ResolveReport report, ResolutionCacheManager 
cacheMgr,
-                ResolveOptions options) {
+                           ResolveOptions options) {
         }
 
         public String getName() {
@@ -691,6 +763,6 @@ public class XmlSettingsParserTest {
 
     private void assertLocationEquals(String expected, Object pattern) throws 
IOException {
         assertEquals(new File(expected).getCanonicalFile(),
-            new File((String) pattern).getCanonicalFile());
+                new File((String) pattern).getCanonicalFile());
     }
 }

http://git-wip-us.apache.org/repos/asf/ant-ivy/blob/6607bdcb/test/java/org/apache/ivy/core/settings/ivysettings-timeout-constraints.xml
----------------------------------------------------------------------
diff --git 
a/test/java/org/apache/ivy/core/settings/ivysettings-timeout-constraints.xml 
b/test/java/org/apache/ivy/core/settings/ivysettings-timeout-constraints.xml
new file mode 100644
index 0000000..e7ba18a
--- /dev/null
+++ b/test/java/org/apache/ivy/core/settings/ivysettings-timeout-constraints.xml
@@ -0,0 +1,30 @@
+<!--
+  ~ 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.
+  -->
+<ivysettings>
+    <timeout-constraints>
+        <timeout-constraint name="test-timeout-1" connectionTimeout="100" 
readTimeout="500"/>
+        <timeout-constraint name="test-timeout-2" readTimeout="20"/>
+        <timeout-constraint name="test-timeout-3" connectionTimeout="400"/>
+        <timeout-constraint name="test-timeout-4"/>
+    </timeout-constraints>
+
+    <resolvers>
+        <url name="urlresolver-1" timeoutConstraint="test-timeout-3"/>
+        <ibiblio name="ibiblio-resolver" timeoutConstraint="test-timeout-1"/>
+        <filesystem name="fs"/>
+    </resolvers>
+</ivysettings>
\ No newline at end of file

http://git-wip-us.apache.org/repos/asf/ant-ivy/blob/6607bdcb/test/java/org/apache/ivy/osgi/updatesite/UpdateSiteLoaderTest.java
----------------------------------------------------------------------
diff --git a/test/java/org/apache/ivy/osgi/updatesite/UpdateSiteLoaderTest.java 
b/test/java/org/apache/ivy/osgi/updatesite/UpdateSiteLoaderTest.java
index c41c80a..f6ed927 100644
--- a/test/java/org/apache/ivy/osgi/updatesite/UpdateSiteLoaderTest.java
+++ b/test/java/org/apache/ivy/osgi/updatesite/UpdateSiteLoaderTest.java
@@ -53,7 +53,7 @@ public class UpdateSiteLoaderTest {
         cache.mkdirs();
         ivySettings.setDefaultCache(cache);
         CacheResourceOptions options = new CacheResourceOptions();
-        loader = new 
UpdateSiteLoader(ivySettings.getDefaultRepositoryCacheManager(), null, options);
+        loader = new 
UpdateSiteLoader(ivySettings.getDefaultRepositoryCacheManager(), null, options, 
null);
     }
 
     @After

http://git-wip-us.apache.org/repos/asf/ant-ivy/blob/6607bdcb/test/java/org/apache/ivy/plugins/parser/xml/XmlModuleDescriptorParserTest.java
----------------------------------------------------------------------
diff --git 
a/test/java/org/apache/ivy/plugins/parser/xml/XmlModuleDescriptorParserTest.java
 
b/test/java/org/apache/ivy/plugins/parser/xml/XmlModuleDescriptorParserTest.java
index 2291722..d000006 100644
--- 
a/test/java/org/apache/ivy/plugins/parser/xml/XmlModuleDescriptorParserTest.java
+++ 
b/test/java/org/apache/ivy/plugins/parser/xml/XmlModuleDescriptorParserTest.java
@@ -1396,7 +1396,7 @@ public class XmlModuleDescriptorParserTest extends 
AbstractModuleDescriptorParse
         assertTrue(resolveRoot.exists() || resolveRoot.mkdirs());
 
         FileUtil.copy(getClass().getResource("test-extends-parent.xml"), new 
File(resolveRoot,
-                "myorg/myparent/ivy.xml"), null);
+                "myorg/myparent/ivy.xml"), null, null);
 
         FileSystemResolver resolver = new FileSystemResolver();
         resolver.setSettings(settings);

http://git-wip-us.apache.org/repos/asf/ant-ivy/blob/6607bdcb/test/java/org/apache/ivy/plugins/resolver/URLResolverTest.java
----------------------------------------------------------------------
diff --git a/test/java/org/apache/ivy/plugins/resolver/URLResolverTest.java 
b/test/java/org/apache/ivy/plugins/resolver/URLResolverTest.java
index a7ad5ec..f894598 100644
--- a/test/java/org/apache/ivy/plugins/resolver/URLResolverTest.java
+++ b/test/java/org/apache/ivy/plugins/resolver/URLResolverTest.java
@@ -17,10 +17,6 @@
  */
 package org.apache.ivy.plugins.resolver;
 
-import java.io.File;
-import java.util.Date;
-import java.util.GregorianCalendar;
-
 import org.apache.ivy.TestHelper;
 import org.apache.ivy.core.cache.DefaultRepositoryCacheManager;
 import org.apache.ivy.core.event.EventManager;
@@ -28,6 +24,7 @@ import org.apache.ivy.core.module.descriptor.Artifact;
 import org.apache.ivy.core.module.descriptor.DefaultArtifact;
 import org.apache.ivy.core.module.descriptor.DefaultDependencyDescriptor;
 import org.apache.ivy.core.module.descriptor.DefaultIncludeRule;
+import org.apache.ivy.core.module.descriptor.DependencyDescriptor;
 import org.apache.ivy.core.module.id.ArtifactId;
 import org.apache.ivy.core.module.id.ModuleRevisionId;
 import org.apache.ivy.core.report.ArtifactDownloadReport;
@@ -39,15 +36,30 @@ import org.apache.ivy.core.resolve.ResolveEngine;
 import org.apache.ivy.core.resolve.ResolveOptions;
 import org.apache.ivy.core.resolve.ResolvedModuleRevision;
 import org.apache.ivy.core.settings.IvySettings;
+import org.apache.ivy.core.settings.NamedTimeoutConstraint;
+import org.apache.ivy.core.settings.TimeoutConstraint;
 import org.apache.ivy.core.sort.SortEngine;
 import org.apache.ivy.plugins.matcher.ExactPatternMatcher;
 import org.junit.After;
 import org.junit.Before;
 import org.junit.Test;
 
+import java.io.File;
+import java.net.InetSocketAddress;
+import java.nio.file.Files;
+import java.nio.file.Path;
+import java.util.Collections;
+import java.util.Date;
+import java.util.GregorianCalendar;
+import java.util.concurrent.Callable;
+import java.util.concurrent.ExecutorService;
+import java.util.concurrent.Executors;
+import java.util.concurrent.Future;
+
 import static org.junit.Assert.assertEquals;
 import static org.junit.Assert.assertNotNull;
 import static org.junit.Assert.assertNull;
+import static org.junit.Assert.assertTrue;
 
 /**
  * Tests URLResolver. Http tests are based upon ibiblio site.
@@ -367,4 +379,130 @@ public class URLResolverTest extends 
AbstractDependencyResolverTest {
         assertEquals(artifact, ar.getArtifact());
         assertEquals(DownloadStatus.NO, ar.getDownloadStatus());
     }
+
+    /**
+     * Tests that the timeout constraint set on the URL resolver is used 
correctly by the resolver
+     *
+     * @throws Exception
+     */
+    @Test
+    public void testTimeoutConstraint() throws Exception {
+        final NamedTimeoutConstraint highTimeout = new 
NamedTimeoutConstraint("test-high-timeout");
+        highTimeout.setConnectionTimeout(60000);
+        settings.addConfigured(highTimeout);
+        final NamedTimeoutConstraint extremelyLowTimeout = new 
NamedTimeoutConstraint("test-extremely-low-timeout");
+        extremelyLowTimeout.setConnectionTimeout(10);
+        extremelyLowTimeout.setReadTimeout(20);
+        settings.addConfigured(extremelyLowTimeout);
+
+        // setup a HTTP backed repo
+        // TODO: Right now the port is hard coded, but we need to find a 
"available" port to which can be bind to.
+        // Else this can lead to occasional bind failures
+        final InetSocketAddress fastServerBindAddr = new 
InetSocketAddress("localhost", 12345);
+        final String contextRoot = "/testTimeouts";
+        final Path repoRoot = new File("test/repositories/1").toPath();
+        assertTrue(repoRoot + " is not a directory", 
Files.isDirectory(repoRoot));
+        final DependencyDescriptor dependency = new 
DefaultDependencyDescriptor(ModuleRevisionId.newInstance("org1", "mod1.1", 
"2.0"), false);
+        try (final AutoCloseable httpServer = 
TestHelper.createHttpServerBackedRepository(fastServerBindAddr, contextRoot, 
repoRoot)) {
+            final String ivyPattern = "http://"; + 
fastServerBindAddr.getHostName() + ":" + fastServerBindAddr.getPort() +
+                    
"/testTimeouts/[organisation]/[module]/ivys/ivy-[revision].xml";
+            final String artifactPattern = "http://"; + 
fastServerBindAddr.getHostName() + ":" + fastServerBindAddr.getPort() +
+                    
"/testTimeouts/[organisation]/[module]/[type]s/[artifact]-[revision].[type]";
+            // first use a resolver with a high timeout to make sure it can 
actually fetch the resources
+            final URLResolver highTimeoutResolver = new URLResolver();
+            highTimeoutResolver.setName("high-timeout-resolver");
+            highTimeoutResolver.setAllownomd(false);
+            highTimeoutResolver.setTimeoutConstraint("test-high-timeout");
+            highTimeoutResolver.setSettings(settings);
+            
highTimeoutResolver.setIvyPatterns(Collections.singletonList(ivyPattern));
+            
highTimeoutResolver.setArtifactPatterns(Collections.singletonList(artifactPattern));
+            highTimeoutResolver.validate();
+
+            final TimeoutConstraint resolverTimeoutConstraint = 
highTimeoutResolver.getTimeoutConstraint();
+            assertNotNull("Timeout constraint is missing on resolver " + 
highTimeoutResolver.getName(), resolverTimeoutConstraint);
+            assertEquals("Unexpected connection timeout on resolver", 60000, 
resolverTimeoutConstraint.getConnectionTimeout());
+            assertEquals("Unexpected read timeout on resolver", -1, 
resolverTimeoutConstraint.getReadTimeout());
+
+            // do the fetch (expected to work fine)
+            final ResolvedModuleRevision resolvedModule = 
highTimeoutResolver.getDependency(dependency, data);
+            assertNotNull("Dependency wasn't resolved by resolver " + 
highTimeoutResolver.getName(), resolvedModule);
+            assertEquals("Unexpected dependency resolved by resolver " + 
highTimeoutResolver.getName(), dependency.getDependencyRevisionId(), 
resolvedModule.getId());
+        }
+
+        // now test this whole fetch using a resolver with a very low 
connection timeout and by starting the repo server
+        // with a delay so that the connection request can timeout
+
+        // clean the cache before testing to ensure the resource isn't fetched 
from cache
+        settings.getDefaultRepositoryCacheManager().clean();
+        settings.getResolutionCacheManager().clean();
+
+        final InetSocketAddress slowServerAddr = new 
InetSocketAddress("localhost", 23456);
+        final String ivyPattern = "http://"; + slowServerAddr.getHostName() + 
":" + slowServerAddr.getPort() +
+                
"/testTimeouts/[organisation]/[module]/ivys/ivy-[revision].xml";
+        final String artifactPattern = "http://"; + 
slowServerAddr.getHostName() + ":" + slowServerAddr.getPort() +
+                
"/testTimeouts/[organisation]/[module]/[type]s/[artifact]-[revision].[type]";
+        final URLResolver lowTimeoutResolver = new URLResolver();
+        lowTimeoutResolver.setAllownomd(false);
+        lowTimeoutResolver.setName("low-timeout-resolver");
+        lowTimeoutResolver.setTimeoutConstraint("test-extremely-low-timeout");
+        lowTimeoutResolver.setSettings(settings);
+        
lowTimeoutResolver.setIvyPatterns(Collections.singletonList(ivyPattern));
+        
lowTimeoutResolver.setArtifactPatterns(Collections.singletonList(artifactPattern));
+        lowTimeoutResolver.validate();
+
+        final TimeoutConstraint lowTimeoutConstraint = 
lowTimeoutResolver.getTimeoutConstraint();
+        assertNotNull("Timeout constraint is missing on resolver " + 
lowTimeoutResolver.getName(), lowTimeoutConstraint);
+        assertEquals("Unexpected connection timeout on resolver", 10, 
lowTimeoutConstraint.getConnectionTimeout());
+        assertEquals("Unexpected read timeout on resolver", 20, 
lowTimeoutConstraint.getReadTimeout());
+
+        final ExecutorService executor = Executors.newSingleThreadExecutor();
+        final long serverStartupDelayInMillis = 500;
+        final Future<AutoCloseable> httpServer = executor.submit(new 
ServerManager(slowServerAddr, contextRoot, repoRoot, 
serverStartupDelayInMillis));
+        try {
+            // do the fetch (resolution *isn't* expected to return resolved 
module)
+            final ResolvedModuleRevision resolvedModuleFromLowTimeouts = 
lowTimeoutResolver.getDependency(dependency, data);
+            assertNull("Dependency wasn't expected to be resolved by resolver 
" + lowTimeoutResolver.getName(), resolvedModuleFromLowTimeouts);
+        } finally {
+            try {
+                // stop the server
+                httpServer.get().close();
+            } catch (Exception e) {
+                // ignore
+                // TODO: Better log it too. But I don't see usage of loggers 
in test cases currently. So need to get to this later
+            }
+            try {
+                executor.shutdownNow();
+            } catch (Exception e) {
+                // ignore
+                // TODO: Better log it too. But I don't see usage of loggers 
in test cases currently. So need to get to this later
+            }
+        }
+    }
+
+    private final class ServerManager implements Callable<AutoCloseable> {
+
+        private final InetSocketAddress serverBindAddress;
+        private final long startupDelayInMillis;
+        private final String contextRoot;
+        private final Path localRepoRoot;
+
+        ServerManager(final InetSocketAddress serverBindAddress, final String 
contextRoot,
+                      final Path localRepoRoot, final long 
startupDelayInMillis) {
+            this.serverBindAddress = serverBindAddress;
+            this.contextRoot = contextRoot;
+            this.localRepoRoot = localRepoRoot;
+            this.startupDelayInMillis = startupDelayInMillis;
+        }
+
+        @Override
+        public AutoCloseable call() throws Exception {
+            if (startupDelayInMillis <= 0) {
+                return 
TestHelper.createHttpServerBackedRepository(serverBindAddress, contextRoot, 
localRepoRoot);
+            }
+            // wait for the specified amount of startup delay
+            Thread.sleep(startupDelayInMillis);
+            // start the server
+            return 
TestHelper.createHttpServerBackedRepository(serverBindAddress, contextRoot, 
localRepoRoot);
+        }
+    }
 }

http://git-wip-us.apache.org/repos/asf/ant-ivy/blob/6607bdcb/test/java/org/apache/ivy/util/url/AbstractURLHandlerTest.java
----------------------------------------------------------------------
diff --git a/test/java/org/apache/ivy/util/url/AbstractURLHandlerTest.java 
b/test/java/org/apache/ivy/util/url/AbstractURLHandlerTest.java
index a13467d..d30f1dd 100644
--- a/test/java/org/apache/ivy/util/url/AbstractURLHandlerTest.java
+++ b/test/java/org/apache/ivy/util/url/AbstractURLHandlerTest.java
@@ -22,6 +22,7 @@ import java.io.IOException;
 import java.io.InputStream;
 import java.net.URL;
 
+import org.apache.ivy.core.settings.TimeoutConstraint;
 import org.apache.ivy.util.CopyProgressListener;
 
 import org.junit.Test;
@@ -74,6 +75,11 @@ public class AbstractURLHandlerTest {
             throw new UnsupportedOperationException();
         }
 
+        @Override
+        public void download(final URL src, final File dest, final 
CopyProgressListener listener, final TimeoutConstraint timeoutConstraint) 
throws IOException {
+            throw new UnsupportedOperationException();
+        }
+
         public URLInfo getURLInfo(URL url) {
             throw new UnsupportedOperationException();
         }
@@ -82,13 +88,28 @@ public class AbstractURLHandlerTest {
             throw new UnsupportedOperationException();
         }
 
+        @Override
+        public URLInfo getURLInfo(final URL url, final TimeoutConstraint 
timeoutConstraint) {
+            throw new UnsupportedOperationException();
+        }
+
         public InputStream openStream(URL url) throws IOException {
             throw new UnsupportedOperationException();
         }
 
+        @Override
+        public InputStream openStream(final URL url, final TimeoutConstraint 
timeoutConstraint) throws IOException {
+            throw new UnsupportedOperationException();
+        }
+
         public void upload(File src, URL dest, CopyProgressListener l) throws 
IOException {
             throw new UnsupportedOperationException();
         }
 
+        @Override
+        public void upload(final File src, final URL dest, final 
CopyProgressListener listener, final TimeoutConstraint timeoutConstraint) 
throws IOException {
+            throw new UnsupportedOperationException();
+        }
+
     }
 }

http://git-wip-us.apache.org/repos/asf/ant-ivy/blob/6607bdcb/test/java/org/apache/ivy/util/url/BasicURLHandlerTest.java
----------------------------------------------------------------------
diff --git a/test/java/org/apache/ivy/util/url/BasicURLHandlerTest.java 
b/test/java/org/apache/ivy/util/url/BasicURLHandlerTest.java
index 65269fa..7355b08 100644
--- a/test/java/org/apache/ivy/util/url/BasicURLHandlerTest.java
+++ b/test/java/org/apache/ivy/util/url/BasicURLHandlerTest.java
@@ -62,7 +62,7 @@ public class BasicURLHandlerTest {
 
         // to test ftp we should know of an anonymous ftp site... !
         // assertTrue(handler.isReachable(new 
URL("ftp://ftp.mozilla.org/pub/dir.sizes";)));
-        assertFalse(handler.isReachable(new 
URL("ftp://ftp.mozilla.org/unknown.file";), connectionTimeoutInMillis));
+        assertFalse(handler.isReachable(new 
URL("ftp://ftp.mozilla.org/unknown.file";), 5000));
     }
 
     @Test

Reply via email to