mirror of https://github.com/apache/ant-ivy
IMPROVE: better url querying management (IVY-138) (thanks to Bernard Niset)
git-svn-id: https://svn.apache.org/repos/asf/incubator/ivy/trunk@484106 13f79535-47bb-0310-9956-ffa450edef68
This commit is contained in:
parent
469a603599
commit
af59bab18e
|
|
@ -8,6 +8,8 @@
|
|||
- NEW: it is now possible to reference existing resolver in resolver containers (IVY-35)
|
||||
- NEW: overwrite attribute in the publish task now let force overwrite of read only files (IVY-83)
|
||||
- NEW: add a conflict manager ("strict") making build fail when a diamond conflict is found (thanks to Christer Jonsson) (IVY-118)
|
||||
|
||||
- IMPROVE: better url querying management (IVY-138) (thanks to Bernard Niset)
|
||||
- IMPROVE: do not add resolver info in ivy files in cache so that they can be safely used as usual ivy files in a repository (IVY-137)
|
||||
- IMPROVE: review default conf mapping management (IVY-134)
|
||||
- IMPROVE: add possibility for a chain to behave like a dual chain (IVY-131)
|
||||
|
|
@ -24,6 +26,7 @@
|
|||
- IMPROVE: string identifying a module is now clearly different from a path
|
||||
- IMPROVE: better error message when publish fails due to readonly destination (IVY-83)
|
||||
- IMPROVE: some javadoc improvements (IVY-136 IVY-129) (thanks to Stephen Nesbitt)
|
||||
|
||||
- FIX: no variable replacement during the deliver step (IVY-133)
|
||||
- FIX: conflict badly solved in some complex cases (IVY-130)
|
||||
- FIX: mapping on conf * now only takes public configurations (IVY-126)
|
||||
|
|
|
|||
|
|
@ -6,14 +6,11 @@
|
|||
*/
|
||||
package fr.jayasoft.ivy.repository.url;
|
||||
|
||||
import java.io.IOException;
|
||||
import java.net.HttpURLConnection;
|
||||
import java.net.URL;
|
||||
import java.net.URLConnection;
|
||||
|
||||
import fr.jayasoft.ivy.repository.Resource;
|
||||
import fr.jayasoft.ivy.url.URLHandlerRegistry;
|
||||
import fr.jayasoft.ivy.util.Message;
|
||||
import fr.jayasoft.ivy.url.URLHandler.URLInfo;
|
||||
|
||||
public class URLResource implements Resource {
|
||||
private URL _url;
|
||||
|
|
@ -38,24 +35,10 @@ public class URLResource implements Resource {
|
|||
}
|
||||
|
||||
private void init() {
|
||||
URLConnection con = null;
|
||||
try {
|
||||
_lastModified = 0;
|
||||
_contentLength = 0;
|
||||
_exists = URLHandlerRegistry.getDefault().isReachable(_url);
|
||||
if (_exists) {
|
||||
con = _url.openConnection();
|
||||
_lastModified = con.getLastModified();
|
||||
_contentLength = con.getContentLength();
|
||||
}
|
||||
} catch (IOException e) {
|
||||
Message.verbose("impossible to open connection to "+_url+":"+e.getMessage());
|
||||
_exists = false;
|
||||
} finally {
|
||||
if (con instanceof HttpURLConnection) {
|
||||
((HttpURLConnection)con).disconnect();
|
||||
}
|
||||
}
|
||||
URLInfo info = URLHandlerRegistry.getDefault().getURLInfo(_url);
|
||||
_contentLength = info.getContentLength();
|
||||
_lastModified = info.getLastModified();
|
||||
_exists = info.isReachable();
|
||||
_init = true;
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -0,0 +1,31 @@
|
|||
/*
|
||||
* This file is subject to the licence found in LICENCE.TXT in the root directory of the project.
|
||||
* Copyright Jayasoft 2005 - All rights reserved
|
||||
*
|
||||
* #SNAPSHOT#
|
||||
*/
|
||||
package fr.jayasoft.ivy.url;
|
||||
|
||||
import java.net.URL;
|
||||
|
||||
public abstract class AbstractURLHandler implements URLHandler {
|
||||
public boolean isReachable(URL url) {
|
||||
return getURLInfo(url).isReachable();
|
||||
}
|
||||
public boolean isReachable(URL url, int timeout) {
|
||||
return getURLInfo(url, timeout).isReachable();
|
||||
}
|
||||
public long getContentLength(URL url) {
|
||||
return getURLInfo(url).getContentLength();
|
||||
}
|
||||
public long getContentLength(URL url, int timeout) {
|
||||
return getURLInfo(url, timeout).getContentLength();
|
||||
}
|
||||
|
||||
public long getLastModified(URL url) {
|
||||
return getURLInfo(url).getLastModified();
|
||||
}
|
||||
public long getLastModified(URL url, int timeout) {
|
||||
return getURLInfo(url, timeout).getLastModified();
|
||||
}
|
||||
}
|
||||
|
|
@ -25,18 +25,22 @@ import fr.jayasoft.ivy.util.Message;
|
|||
* @author Xavier Hanin
|
||||
*
|
||||
*/
|
||||
public class BasicURLHandler implements URLHandler {
|
||||
public boolean isReachable(URL url) {
|
||||
return isReachable(url, 0);
|
||||
public class BasicURLHandler extends AbstractURLHandler {
|
||||
public URLInfo getURLInfo(URL url) {
|
||||
return getURLInfo(url, 0);
|
||||
}
|
||||
public boolean isReachable(URL url, int timeout) {
|
||||
public URLInfo getURLInfo(URL url, int timeout) {
|
||||
URLConnection con = null;
|
||||
try {
|
||||
con = url.openConnection();
|
||||
if (con instanceof HttpURLConnection) {
|
||||
int status = ((HttpURLConnection)con).getResponseCode();
|
||||
if (status == HttpStatus.SC_OK) {
|
||||
return true;
|
||||
return new URLInfo(
|
||||
true,
|
||||
((HttpURLConnection)con).getContentLength(),
|
||||
con.getLastModified()
|
||||
);
|
||||
}
|
||||
if (status == HttpStatus.SC_PROXY_AUTHENTICATION_REQUIRED) {
|
||||
Message.warn("Your proxy requires authentication.");
|
||||
|
|
@ -48,7 +52,15 @@ public class BasicURLHandler implements URLHandler {
|
|||
Message.debug("HTTP response status: "+status+" url="+url);
|
||||
} else {
|
||||
int contentLength = con.getContentLength();
|
||||
return contentLength > 0;
|
||||
if (contentLength <= 0) {
|
||||
return UNAVAILABLE;
|
||||
} else {
|
||||
return new URLInfo(
|
||||
true,
|
||||
contentLength,
|
||||
con.getLastModified()
|
||||
);
|
||||
}
|
||||
}
|
||||
} catch (UnknownHostException e) {
|
||||
Message.warn("Host " + e.getMessage() +" not found. url="+url);
|
||||
|
|
@ -60,7 +72,7 @@ public class BasicURLHandler implements URLHandler {
|
|||
((HttpURLConnection)con).disconnect();
|
||||
}
|
||||
}
|
||||
return false;
|
||||
return UNAVAILABLE;
|
||||
}
|
||||
|
||||
public InputStream openStream(URL url) throws IOException {
|
||||
|
|
|
|||
|
|
@ -5,15 +5,20 @@
|
|||
*/
|
||||
package fr.jayasoft.ivy.url;
|
||||
|
||||
import java.io.ByteArrayInputStream;
|
||||
import java.io.File;
|
||||
import java.io.IOException;
|
||||
import java.io.InputStream;
|
||||
import java.lang.reflect.Method;
|
||||
import java.net.URL;
|
||||
import java.net.UnknownHostException;
|
||||
import java.text.ParseException;
|
||||
import java.text.SimpleDateFormat;
|
||||
import java.util.Locale;
|
||||
|
||||
import org.apache.commons.httpclient.Header;
|
||||
import org.apache.commons.httpclient.HttpClient;
|
||||
import org.apache.commons.httpclient.HttpException;
|
||||
import org.apache.commons.httpclient.HttpMethodBase;
|
||||
import org.apache.commons.httpclient.HttpStatus;
|
||||
import org.apache.commons.httpclient.UsernamePasswordCredentials;
|
||||
import org.apache.commons.httpclient.methods.GetMethod;
|
||||
|
|
@ -27,7 +32,8 @@ import fr.jayasoft.ivy.util.Message;
|
|||
* @author Xavier Hanin
|
||||
*
|
||||
*/
|
||||
public class HttpClientHandler implements URLHandler {
|
||||
public class HttpClientHandler extends AbstractURLHandler {
|
||||
private static final SimpleDateFormat LAST_MODIFIED_FORMAT = new SimpleDateFormat("EEE, d MMM yyyy HH:mm:ss z", Locale.US);
|
||||
private String _realm = null;
|
||||
private String _host = null;
|
||||
private String _userName = null;
|
||||
|
|
@ -41,6 +47,9 @@ public class HttpClientHandler implements URLHandler {
|
|||
private String _proxyUserName = null;
|
||||
private String _proxyPasswd = null;
|
||||
|
||||
private HttpClient _client;
|
||||
private HttpClientHelper _httpClientHelper;
|
||||
|
||||
public HttpClientHandler() {
|
||||
configureProxy();
|
||||
}
|
||||
|
|
@ -85,10 +94,8 @@ public class HttpClientHandler implements URLHandler {
|
|||
|
||||
public InputStream openStream(URL url) throws IOException {
|
||||
GetMethod get = doGet(url);
|
||||
byte[] response = get.getResponseBody();
|
||||
get.releaseConnection();
|
||||
|
||||
return new ByteArrayInputStream(response);
|
||||
final InputStream is = get.getResponseBodyAsStream();
|
||||
return new GETInputStream(get);
|
||||
}
|
||||
|
||||
public void download(URL src, File dest, CopyProgressListener l) throws IOException {
|
||||
|
|
@ -97,17 +104,18 @@ public class HttpClientHandler implements URLHandler {
|
|||
get.releaseConnection();
|
||||
}
|
||||
|
||||
public boolean isReachable(URL url) {
|
||||
return isReachable(url, 0);
|
||||
public URLInfo getURLInfo(URL url) {
|
||||
return getURLInfo(url, 0);
|
||||
}
|
||||
|
||||
public boolean isReachable(URL url, int timeout) {
|
||||
|
||||
public URLInfo getURLInfo(URL url, int timeout) {
|
||||
HeadMethod head = null;
|
||||
try {
|
||||
HeadMethod head = doHead(url, timeout);
|
||||
head = doHead(url, timeout);
|
||||
int status = head.getStatusCode();
|
||||
head.releaseConnection();
|
||||
if (status == HttpStatus.SC_OK) {
|
||||
return true;
|
||||
return new URLInfo(true, getResponseContentLength(head), getLastModified(head));
|
||||
}
|
||||
if (status == HttpStatus.SC_PROXY_AUTHENTICATION_REQUIRED) {
|
||||
Message.error("Your proxy requires authentication.");
|
||||
|
|
@ -124,9 +132,56 @@ public class HttpClientHandler implements URLHandler {
|
|||
Message.info("You probably access the destination server through a proxy server that is not well configured.");
|
||||
}catch (IOException e) {
|
||||
Message.error("HttpClientHandler: "+e.getMessage()+" url="+url);
|
||||
} finally{
|
||||
if(head != null) {
|
||||
head.releaseConnection();
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}
|
||||
return UNAVAILABLE;
|
||||
}
|
||||
|
||||
private long getLastModified(HeadMethod head) {
|
||||
Header header = head.getResponseHeader("last-modified");
|
||||
if (header != null) {
|
||||
String lastModified = header.getValue();
|
||||
try {
|
||||
return LAST_MODIFIED_FORMAT.parse(lastModified).getTime();
|
||||
} catch (ParseException e) {
|
||||
}
|
||||
return System.currentTimeMillis();
|
||||
} else {
|
||||
return System.currentTimeMillis();
|
||||
}
|
||||
}
|
||||
|
||||
private long getResponseContentLength(HeadMethod head) {
|
||||
return getHttpClientHelper().getResponseContentLength(head);
|
||||
}
|
||||
|
||||
private HttpClientHelper getHttpClientHelper() {
|
||||
if (_httpClientHelper == null) {
|
||||
// use commons httpclient 3.0 if available
|
||||
try {
|
||||
Method method = HttpMethodBase.class.getMethod("getResponseContentLength", new Class[0]);
|
||||
if (method.isAccessible()) {
|
||||
_httpClientHelper = new HttpClientHelper3x();
|
||||
Message.verbose("using commons httpclient 3.x helper");
|
||||
} else {
|
||||
_httpClientHelper = new HttpClientHelper2x();
|
||||
Message.verbose("using commons httpclient 2.x helper");
|
||||
}
|
||||
} catch (SecurityException e) {
|
||||
Message.verbose("unable to get access to getResponseContentLength of commons-httpclient HeadMethod. Please use commons-httpclient 3.0 or use ivy with sufficient security permissions.");
|
||||
Message.verbose("exception: "+e.getMessage());
|
||||
_httpClientHelper = new HttpClientHelper2x();
|
||||
Message.verbose("using commons httpclient 2.x helper");
|
||||
} catch (NoSuchMethodException e) {
|
||||
_httpClientHelper = new HttpClientHelper2x();
|
||||
Message.verbose("using commons httpclient 2.x helper");
|
||||
}
|
||||
}
|
||||
return _httpClientHelper;
|
||||
}
|
||||
|
||||
private GetMethod doGet(URL url) throws IOException, HttpException {
|
||||
HttpClient client = getClient();
|
||||
|
|
@ -148,22 +203,24 @@ public class HttpClientHandler implements URLHandler {
|
|||
}
|
||||
|
||||
private HttpClient getClient() {
|
||||
HttpClient client = new HttpClient();
|
||||
if (useProxy()) {
|
||||
client.getHostConfiguration().setProxy(_proxyHost, _proxyPort);
|
||||
if (useProxyAuthentication()) {
|
||||
client.getState().setProxyCredentials(_proxyRealm, _proxyHost,
|
||||
new UsernamePasswordCredentials(_proxyUserName, _proxyPasswd));
|
||||
}
|
||||
if(_client == null){
|
||||
_client = new HttpClient();
|
||||
if (useProxy()) {
|
||||
_client.getHostConfiguration().setProxy(_proxyHost, _proxyPort);
|
||||
if (useProxyAuthentication()) {
|
||||
_client.getState().setProxyCredentials(_proxyRealm, _proxyHost,
|
||||
new UsernamePasswordCredentials(_proxyUserName, _proxyPasswd));
|
||||
}
|
||||
}
|
||||
if (useAuthentication()) {
|
||||
_client.getState().setCredentials(
|
||||
_realm,
|
||||
_host,
|
||||
new UsernamePasswordCredentials(_userName, _passwd)
|
||||
);
|
||||
}
|
||||
}
|
||||
if (useAuthentication()) {
|
||||
client.getState().setCredentials(
|
||||
_realm,
|
||||
_host,
|
||||
new UsernamePasswordCredentials(_userName, _passwd)
|
||||
);
|
||||
}
|
||||
return client;
|
||||
return _client;
|
||||
}
|
||||
|
||||
private boolean useProxy() {
|
||||
|
|
@ -175,4 +232,90 @@ public class HttpClientHandler implements URLHandler {
|
|||
private boolean useProxyAuthentication() {
|
||||
return (_proxyUserName != null && _proxyUserName.trim().length() > 0);
|
||||
}
|
||||
|
||||
private static final class GETInputStream extends InputStream {
|
||||
private InputStream _is;
|
||||
private GetMethod _get;
|
||||
|
||||
private GETInputStream(GetMethod get) throws IOException {
|
||||
_get = get;
|
||||
_is = get.getResponseBodyAsStream();
|
||||
}
|
||||
|
||||
public int available() throws IOException {
|
||||
return _is.available();
|
||||
}
|
||||
|
||||
public void close() throws IOException {
|
||||
_is.close();
|
||||
_get.releaseConnection();
|
||||
}
|
||||
|
||||
public boolean equals(Object obj) {
|
||||
return _is.equals(obj);
|
||||
}
|
||||
|
||||
public int hashCode() {
|
||||
return _is.hashCode();
|
||||
}
|
||||
|
||||
public void mark(int readlimit) {
|
||||
_is.mark(readlimit);
|
||||
}
|
||||
|
||||
public boolean markSupported() {
|
||||
return _is.markSupported();
|
||||
}
|
||||
|
||||
public int read() throws IOException {
|
||||
return _is.read();
|
||||
}
|
||||
|
||||
public int read(byte[] b, int off, int len) throws IOException {
|
||||
return _is.read(b, off, len);
|
||||
}
|
||||
|
||||
public int read(byte[] b) throws IOException {
|
||||
return _is.read(b);
|
||||
}
|
||||
|
||||
public void reset() throws IOException {
|
||||
_is.reset();
|
||||
}
|
||||
|
||||
public long skip(long n) throws IOException {
|
||||
return _is.skip(n);
|
||||
}
|
||||
|
||||
public String toString() {
|
||||
return _is.toString();
|
||||
}
|
||||
}
|
||||
private static final class HttpClientHelper3x implements HttpClientHelper {
|
||||
private HttpClientHelper3x() {
|
||||
}
|
||||
|
||||
public long getResponseContentLength(HeadMethod head) {
|
||||
return head.getResponseContentLength();
|
||||
}
|
||||
}
|
||||
private static final class HttpClientHelper2x implements HttpClientHelper {
|
||||
private HttpClientHelper2x() {
|
||||
}
|
||||
|
||||
public long getResponseContentLength(HeadMethod head) {
|
||||
Header header = head.getResponseHeader("Content-Length");
|
||||
if (header != null) {
|
||||
try {
|
||||
return Integer.parseInt(header.getValue());
|
||||
} catch (NumberFormatException e) {
|
||||
Message.verbose("Invalid content-length value: " + e.getMessage());
|
||||
}
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
public interface HttpClientHelper {
|
||||
long getResponseContentLength(HeadMethod head);
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -20,22 +20,84 @@ import fr.jayasoft.ivy.util.CopyProgressListener;
|
|||
*
|
||||
*/
|
||||
public interface URLHandler {
|
||||
public static class URLInfo {
|
||||
private long _contentLength;
|
||||
private long _lastModified;
|
||||
private boolean _available;
|
||||
|
||||
protected URLInfo(boolean available, long contentLength, long lastModified) {
|
||||
_available = available;
|
||||
_contentLength = contentLength;
|
||||
_lastModified = lastModified;
|
||||
}
|
||||
public boolean isReachable() {
|
||||
return _available;
|
||||
}
|
||||
public long getContentLength() {
|
||||
return _contentLength;
|
||||
}
|
||||
public long getLastModified() {
|
||||
return _lastModified;
|
||||
}
|
||||
}
|
||||
public static final URLInfo UNAVAILABLE = new URLInfo(false, 0,0);
|
||||
|
||||
/**
|
||||
* Returns true if the given url is reachable, and without
|
||||
* error code in case of http urls.
|
||||
* Please prefer getURLInfo when several infos are needed.
|
||||
* @param url the url to check
|
||||
* @return true if the given url is reachable
|
||||
* @return true if the target is reachable
|
||||
*/
|
||||
public boolean isReachable(URL url);
|
||||
/**
|
||||
* Returns true if the given url is reachable, and without
|
||||
* Please prefer getURLInfo when several infos are needed.
|
||||
* @param url the url to check
|
||||
* @return true if the target is reachable
|
||||
*/
|
||||
public boolean isReachable(URL url, int timeout);
|
||||
/**
|
||||
* Returns the length of the target if the given url is reachable, and without
|
||||
* error code in case of http urls.
|
||||
* Please prefer getURLInfo when several infos are needed.
|
||||
* @param url the url to check
|
||||
* @return the length of the target if available, 0 if not reachable
|
||||
*/
|
||||
public long getContentLength(URL url);
|
||||
/**
|
||||
* Returns the length of the target if the given url is reachable, and without
|
||||
* error code in case of http urls.
|
||||
* @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 true if the given url is reachable
|
||||
* @return the length of the target if available, 0 if not reachable
|
||||
*/
|
||||
public boolean isReachable(URL url, int timeout);
|
||||
public long getContentLength(URL url, int timeout);
|
||||
|
||||
/**
|
||||
* Please prefer getURLInfo when several infos are needed.
|
||||
* @param url the url to check
|
||||
* @return last modified timestamp of the given url
|
||||
*/
|
||||
public long getLastModified(URL url);
|
||||
/**
|
||||
* Please prefer getURLInfo when several infos are needed.
|
||||
* @param url the url to check
|
||||
* @return last modified timestamp of the given url
|
||||
*/
|
||||
public long getLastModified(URL url, int timeout);
|
||||
|
||||
/**
|
||||
* never returns null, return UNAVAILABLE when url is not reachable
|
||||
* @param url
|
||||
* @return
|
||||
*/
|
||||
public URLInfo getURLInfo(URL url);
|
||||
/**
|
||||
* never returns null, return UNAVAILABLE when url is not reachable
|
||||
* @param url
|
||||
* @return
|
||||
*/
|
||||
public URLInfo getURLInfo(URL url, int timeout);
|
||||
|
||||
public InputStream openStream(URL url) throws IOException;
|
||||
public void download(URL src, File dest, CopyProgressListener l) throws IOException;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -35,6 +35,30 @@ public class URLHandlerDispatcher implements URLHandler {
|
|||
return getHandler(url.getProtocol()).isReachable(url, timeout);
|
||||
}
|
||||
|
||||
public long getContentLength(URL url) {
|
||||
return getHandler(url.getProtocol()).getContentLength(url);
|
||||
}
|
||||
|
||||
public long getContentLength(URL url, int timeout) {
|
||||
return getHandler(url.getProtocol()).getContentLength(url, timeout);
|
||||
}
|
||||
|
||||
|
||||
public long getLastModified(URL url) {
|
||||
return getHandler(url.getProtocol()).getLastModified(url);
|
||||
}
|
||||
|
||||
public long getLastModified(URL url, int timeout) {
|
||||
return getHandler(url.getProtocol()).getLastModified(url, timeout);
|
||||
}
|
||||
|
||||
public URLInfo getURLInfo(URL url) {
|
||||
return getHandler(url.getProtocol()).getURLInfo(url);
|
||||
}
|
||||
|
||||
public URLInfo getURLInfo(URL url, int timeout) {
|
||||
return getHandler(url.getProtocol()).getURLInfo(url, timeout);
|
||||
}
|
||||
public InputStream openStream(URL url) throws IOException {
|
||||
return getHandler(url.getProtocol()).openStream(url);
|
||||
}
|
||||
|
|
|
|||
Loading…
Reference in New Issue