@@ -15,42 +15,43 @@
*
*/
package org.apache.tools.ant.taskdefs.optional. condition;
package org.apache.tools.ant.taskdefs.condition;
import org.apache.tools.ant.ProjectComponent;
import org.apache.tools.ant.BuildException;
import org.apache.tools.ant.Project;
import org.apache.tools.ant.taskdefs.condition.Condition ;
import org.apache.tools.ant.ProjectComponent ;
import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;
import java.net.InetAddress;
import java.net.UnknownHostException;
import java.net.URL;
import java.net.MalformedURLException;
import java.io.IOException;
import java.net.URL;
import java.net.UnknownHostException;
/**
* Test for a host being reachable using ICMP "ping" packets.
* Test for a host being reachable using ICMP "ping" packets & echo operations .
* Ping packets are very reliable for assessing reachability in a LAN or WAN,
* but they do not get through any well-configured firewall.
* but they do not get through any well-configured firewall. Echo (port 7) may.
* <p/>
* This condition turns unknown host exceptions into false conditions. This is
* because on a laptop, DNS is one of the first services when the network goes; you
* are implicitly offline.
* because on a laptop, DNS is one of the first services when the network goes;
* you are implicitly offline.
* <p/>
* If a URL is supplied instead of a host, the hostname is extracted
* and used in the test - all other parts of the URL are discarded.
* If a URL is supplied instead of a host, the hostname is extracted and used in
* the test - all other parts of the URL are discarded.
* <p/>
* The test may not work through firewalls, that is, something may be reachable
* using a protocol such as HTTP, while the lower level ICMP packets get dropped
* on the floor. Similarly, a host may detected as reachable with ICMP, but
* not reachable on other ports (i.e. port 80), because of firewalls.
* on the floor. Similarly, a host may detected as reachable with ICMP, but not
* reachable on other ports (i.e. port 80), because of firewalls.
* <p/>
* Requires Java1.5+ to work
* Requires Java1.5+ to work properly. On Java1.4 and earlier, if a hostname is
* resolveable, the destination is assumed to be reachable.
*
* @ant.condition name="isreachable"
* @since Ant1.7
*/
public class IsPing able extends ProjectComponent implements Condition {
public class IsReach able extends ProjectComponent implements Condition {
private String host;
private String url;
@@ -71,12 +72,15 @@ public class IsPingable extends ProjectComponent implements Condition {
/**
* Unknown host message is seen.
*/
public static final String ERROR _UNKNOWN_HOST = "Unknown host:";
public static final String WARN _UNKNOWN_HOST = "Unknown host:";
/**
* Network error message is seen.
*/
public static final String ERROR_ON_NETWORK = "network error to ";
public static final String ERROR_BOTH_TARGETS = "Both url and host have been specified";
public static final String MSG_NO_REACHABLE_TEST = "cannot do a proper reachability test on this Java version";
public static final String ERROR_BAD_URL = "Bad URL ";
public static final String ERROR_NO_HOST_IN_URL = "No hostname in URL ";
/**
* The host to ping.
@@ -109,16 +113,20 @@ public class IsPingable extends ProjectComponent implements Condition {
* emptyness test
*
* @param string param to check
*
* @return true if it is empty
*/
private boolean empty(String string) {
return string == null || string.length() == 0;
}
private static Class[] parameterTypes = {Integer.class};
/**
* Is this condition true?
*
* @return true if the condition is true.
*
* @throws org.apache.tools.ant.BuildException
* if an error occurs
*/
@@ -138,25 +146,54 @@ public class IsPingable extends ProjectComponent implements Condition {
//get the host of a url
URL realURL = new URL(url);
target = realURL.getHost();
if (empty(target)) {
throw new BuildException(ERROR_NO_HOST_IN_URL + url);
}
} catch (MalformedURLException e) {
throw new BuildException("Bad URL " + url, e);
throw new BuildException(ERROR_BAD_URL + url, e);
}
}
log("Probing host " + target, Project.MSG_VERBOSE);
InetAddress address;
try {
log("Probing host " + target, Project.MSG_VERBOSE);
InetAddress address = InetAddress.getByName(target);
log("Host address =" + address.getHostAddress(),
Project.MSG_VERBOSE);
final boolean reachable = address.isReachable(timeout * 1000);
log("host is " + (reachable ? "" : "not") + " reachable",
Project.MSG_VERBOSE);
return reachable;
} catch (UnknownHostException e) {
log(ERROR_UNKNOWN_HOST + target);
return false;
} catch (IOException e) {
log(ERROR_ON_NETWORK + target + ": " + e.toString());
log(WARN_UNKNOWN_HOST + target);
address = InetAddress.getByName(target);
} catch (UnknownHostException e1) {
return false;
}
log("Host address =" + address.getHostAddress(),
Project.MSG_VERBOSE);
boolean reachable;
//Java1.5: reachable = address.isReachable(timeout * 1000);
Method reachableMethod = null;
try {
reachableMethod = InetAddress.class.getMethod("reachable",
parameterTypes);
Object[] params = new Object[1];
params[0] = new Integer(timeout * 1000);
try {
reachable = ((Boolean) reachableMethod.invoke(address, params))
.booleanValue();
} catch (IllegalAccessException e) {
//utterly implausible, but catered for anyway
throw new BuildException("When calling " + reachableMethod);
} catch (InvocationTargetException e) {
//assume this is an IOexception about un readability
Throwable nested = e.getTargetException();
log(ERROR_ON_NETWORK + target + ": " + nested.toString());
//any kind of fault: not reachable.
reachable = false;
}
} catch (NoSuchMethodException e) {
//java1.4 or earlier
log(MSG_NO_REACHABLE_TEST);
reachable = true;
}
log("host is " + (reachable ? "" : "not") + " reachable",
Project.MSG_VERBOSE);
return reachable;
}
}