All tests run against localhost. This *should* work everywhere, but no doubt someone with a confused /etc/hosts or no IPv4 stack will have different opinions. git-svn-id: https://svn.apache.org/repos/asf/ant/core/trunk@277887 13f79535-47bb-0310-9956-ffa450edef68master
| @@ -537,7 +537,11 @@ Check for Xerces-specific definition of the location of the no namespace schema. | |||
| <p>Uses Java1.5+ networking APIs to probe for a (remote) system being | |||
| reachable. Exactly what probe mechanisms are used is an implementation | |||
| feature of the JVM. They may include ICMP "ping" packets | |||
| feature of the JVM. They may include ICMP "ping" packets, UDP or TCP connections | |||
| to port 7 "echo service" or other means. On Java1.4 and earlier, being able | |||
| to resolve the hostname is considered success. This means that if DNS is not | |||
| working or a URL/hostname is bad, the test will fail, but otherwise succeed | |||
| even if the remote host is actually absent. | |||
| </p> | |||
| <p> | |||
| @@ -0,0 +1,104 @@ | |||
| <project name="isreachable"> | |||
| <!-- | |||
| * Copyright 2005 The Apache Software Foundation | |||
| * | |||
| * Licensed 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. | |||
| * | |||
| --> | |||
| <macrodef name="assertHostReachable"> | |||
| <attribute name="host"/> | |||
| <sequential> | |||
| <fail message="not reachable: @{host}"> | |||
| <condition> | |||
| <not> | |||
| <isreachable host="@{host}"/> | |||
| </not> | |||
| </condition> | |||
| </fail> | |||
| </sequential> | |||
| </macrodef> | |||
| <macrodef name="assertHostNotReachable"> | |||
| <attribute name="host"/> | |||
| <sequential> | |||
| <fail message="unexpectedly reachable: @{host}"> | |||
| <condition> | |||
| <isreachable host="@{host}"/> | |||
| </condition> | |||
| </fail> | |||
| </sequential> | |||
| </macrodef> | |||
| <macrodef name="assertUrlReachable"> | |||
| <attribute name="url"/> | |||
| <sequential> | |||
| <fail message="not reachable: @{url}"> | |||
| <condition> | |||
| <not> | |||
| <isreachable url="@{url}"/> | |||
| </not> | |||
| </condition> | |||
| </fail> | |||
| </sequential> | |||
| </macrodef> | |||
| <target name="testLocalhost"> | |||
| <assertHostReachable host="localhost"/> | |||
| </target> | |||
| <!-- bugs in XPSP2 mean this is the only IPv4 loopback addr allowed --> | |||
| <target name="testIpv4localhost"> | |||
| <assertHostReachable host="127.0.0.1"/> | |||
| </target> | |||
| <target name="testBoth"> | |||
| <condition property="both"> | |||
| <isreachable host="localhost" url="http://localhost"/> | |||
| </condition> | |||
| <fail>Expected failure before here</fail> | |||
| </target> | |||
| <target name="testLocalhostURL"> | |||
| <assertUrlReachable url="http://localhost"/> | |||
| </target> | |||
| <target name="testIpv4localhostURL"> | |||
| <assertUrlReachable url="http://127.0.0.1/"/> | |||
| </target> | |||
| <target name="testFTPURL"> | |||
| <assertUrlReachable url="ftp://localhost"/> | |||
| </target> | |||
| <target name="testFile"> | |||
| <assertUrlReachable url="file://build.xml"/> | |||
| </target> | |||
| <target name="testBadURL"> | |||
| <assertUrlReachable url="uuid:3349-4404-0ac0ddee"/> | |||
| </target> | |||
| <target name="testBadTimeout"> | |||
| <condition property="testBadTimeout"> | |||
| <isreachable host="localhost" timeout="-1"/> | |||
| </condition> | |||
| </target> | |||
| <target name="testNoTargets"> | |||
| <condition property="none"> | |||
| <isreachable/> | |||
| </condition> | |||
| </target> | |||
| </project> | |||
| @@ -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 IsPingable extends ProjectComponent implements Condition { | |||
| public class IsReachable 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; | |||
| } | |||
| } | |||
| @@ -37,7 +37,7 @@ assertions=org.apache.tools.ant.types.Assertions | |||
| concatfilter=org.apache.tools.ant.filters.ConcatFilter | |||
| issigned=org.apache.tools.ant.taskdefs.condition.IsSigned | |||
| isfileselected=org.apache.tools.ant.taskdefs.condition.IsFileSelected | |||
| isreachable=org.apache.tools.ant.taskdefs.optional.condition.IsPingable | |||
| isreachable=org.apache.tools.ant.taskdefs.condition.IsReachable | |||
| mavenrepository=org.apache.tools.ant.taskdefs.repository.MavenRepository | |||
| scriptselector=org.apache.tools.ant.types.optional.ScriptSelector | |||
| scriptcondition=org.apache.tools.ant.types.optional.ScriptCondition | |||
| @@ -0,0 +1,81 @@ | |||
| /* | |||
| * Copyright 2005 The Apache Software Foundation | |||
| * | |||
| * Licensed 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.tools.ant.taskdefs.condition; | |||
| import org.apache.tools.ant.BuildFileTest; | |||
| /** | |||
| * test for reachable things | |||
| */ | |||
| public class IsReachableTest extends BuildFileTest { | |||
| public IsReachableTest(String name) { | |||
| super(name); | |||
| } | |||
| public void setUp() { | |||
| configureProject( | |||
| "src/etc/testcases/taskdefs/conditions/isreachable.xml"); | |||
| } | |||
| public void testLocalhost() throws Exception { | |||
| executeTarget("testLocalhost"); | |||
| } | |||
| public void testLocalhostURL() throws Exception { | |||
| executeTarget("testLocalhostURL"); | |||
| } | |||
| public void testIpv4localhost() throws Exception { | |||
| executeTarget("testIpv4localhost"); | |||
| } | |||
| public void testFTPURL() throws Exception { | |||
| executeTarget("testFTPURL"); | |||
| } | |||
| public void testBoth() throws Exception { | |||
| expectBuildExceptionContaining("testBoth", | |||
| "error on two targets", | |||
| IsReachable.ERROR_BOTH_TARGETS); | |||
| } | |||
| public void testNoTargets() throws Exception { | |||
| expectBuildExceptionContaining("testNoTargets", | |||
| "no params", | |||
| IsReachable.ERROR_NO_HOSTNAME); | |||
| } | |||
| public void testBadTimeout() throws Exception { | |||
| expectBuildExceptionContaining("testBadTimeout", | |||
| "error on -ve timeout", | |||
| IsReachable.ERROR_BAD_TIMEOUT); | |||
| } | |||
| public void NotestFile() throws Exception { | |||
| expectBuildExceptionContaining("testFile", | |||
| "error on file URL", | |||
| IsReachable.ERROR_NO_HOST_IN_URL); | |||
| } | |||
| public void testBadURL() throws Exception { | |||
| expectBuildExceptionContaining("testBadURL", | |||
| "error in URL", | |||
| IsReachable.ERROR_BAD_URL); | |||
| } | |||
| } | |||