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
