+ depends="clean"
+ description="--> cleans up everything">
@@ -1340,28 +1340,28 @@
-->
-
+ targetfile="${build.javadocs}/packages.html">
+
-
+ targetfile="${build.tests.javadocs}/packages.html">
+
+ unless="javadoc.notrequired"
+ description="--> creates the API documentation">
+ destdir="${build.javadocs}"
+ author="true"
+ version="true"
+ locale="en"
+ windowtitle="${Name} API"
+ doctitle="${Name}">
@@ -1383,16 +1383,16 @@
+ unless="tests.javadoc.notrequired"
+ description="--> creates the API documentation for test utilities">
+ destdir="${build.tests.javadocs}"
+ author="true"
+ version="true"
+ locale="en"
+ windowtitle="${Name} Test Utilities"
+ doctitle="${Name}">
@@ -1411,11 +1411,11 @@
+ destdir="${build.tests}"
+ debug="${debug}"
+ target="${javac.target}"
+ source="${javac.source}"
+ deprecation="${deprecation}">
@@ -1423,16 +1423,16 @@
-
-
-
+
+
+
+ depends="xml-check">
@@ -1446,27 +1446,27 @@
-
+ if="xalan.envcheck" unless="which.present">
+
-
+ if="which.present">
+
-
+
-
+
- offline=${offline}
+ offline=${offline}
+ filtertrace="${junit.filtertrace}"
+ fork="${junit.fork}" forkmode="${junit.forkmode}"
+ failureproperty="tests.failed">
+
@@ -1500,7 +1500,7 @@
+ value="${tests-classpath.value}"/>
@@ -1540,102 +1540,102 @@
+ unless="some.regexp.support"/>
+ unless="some.regexp.support"/>
+ unless="some.regexp.support"/>
+ unless="some.regexp.support"/>
+ unless="bsf.present"/>
+ unless="rhino.present"/>
+ unless="bsf.present"/>
+ unless="rhino.present"/>
+ unless="bsf.present"/>
+ unless="beanshell.present"/>
+ unless="bsf.present"/>
+ unless="rhino.present"/>
+ if="tests.are.on.system.classpath"/>
+ if="tests.are.on.system.classpath"/>
+ if="tests.are.on.system.classpath"/>
+ unless="trax.impl.present"/>
+ unless="trax.impl.present"/>
+ unless="trax.impl.present"/>
+ unless="run.junitreport"/>
+ unless="trax.impl.present"/>
+ unless="bsf.present"/>
+ unless="xerces1.present"/>
+ unless="xerces1.present"/>
+ unless="apache.resolver.present"/>
+ unless="jasper.present"/>
+ unless="dotnetapps.found"/>
+ unless="dotnetapps.found"/>
+ unless="tests.and.ant.share.classloader"/>
+ unless="tests.and.ant.share.classloader"/>
+ unless="tests.and.ant.share.classloader"/>
+ unless="tests.and.ant.share.classloader"/>
+ unless="tests.and.ant.share.classloader"/>
+ unless="tests.and.ant.share.classloader"/>
+ unless="tests.and.ant.share.classloader"/>
+ unless="tests.and.ant.share.classloader"/>
+ unless="tests.and.ant.share.classloader"/>
+ unless="have.cvs"/>
@@ -1646,7 +1646,7 @@
+ if="tests.and.ant.share.classloader"/>
@@ -1661,16 +1661,16 @@
-
+ haltonfailure="${test.haltonfailure}"
+ fork="${junit.fork}"
+ filtertrace="${junit.filtertrace}">
+
-
+
+ value="${tests-classpath.value}"/>
@@ -1680,11 +1680,11 @@
+ depends="compile-tests"
+ if="jdk1.3+">
+ classname="org.apache.tools.ant.taskdefs.TestProcess"
+ fork="true"/>
+ description="--> creates a minimum distribution in ./dist"
+ depends="dist-lite"/>
diff --git a/docs/manual/CoreTasks/conditions.html b/docs/manual/CoreTasks/conditions.html
index ce5e3b480..8738298e1 100644
--- a/docs/manual/CoreTasks/conditions.html
+++ b/docs/manual/CoreTasks/conditions.html
@@ -537,7 +537,11 @@ Check for Xerces-specific definition of the location of the no namespace schema.
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.
diff --git a/src/etc/testcases/taskdefs/conditions/isreachable.xml b/src/etc/testcases/taskdefs/conditions/isreachable.xml
new file mode 100644
index 000000000..45151592a
--- /dev/null
+++ b/src/etc/testcases/taskdefs/conditions/isreachable.xml
@@ -0,0 +1,104 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ Expected failure before here
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/src/main/org/apache/tools/ant/taskdefs/optional/condition/IsPingable.java b/src/main/org/apache/tools/ant/taskdefs/condition/IsReachable.java
similarity index 56%
rename from src/main/org/apache/tools/ant/taskdefs/optional/condition/IsPingable.java
rename to src/main/org/apache/tools/ant/taskdefs/condition/IsReachable.java
index ae6ee00a3..737eb6b19 100644
--- a/src/main/org/apache/tools/ant/taskdefs/optional/condition/IsPingable.java
+++ b/src/main/org/apache/tools/ant/taskdefs/condition/IsReachable.java
@@ -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.
*
* 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.
*
- * 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.
*
* 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.
*
- * 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;
}
}
diff --git a/src/main/org/apache/tools/ant/types/defaults.properties b/src/main/org/apache/tools/ant/types/defaults.properties
index 97021fb2f..0838aecbb 100644
--- a/src/main/org/apache/tools/ant/types/defaults.properties
+++ b/src/main/org/apache/tools/ant/types/defaults.properties
@@ -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
diff --git a/src/testcases/org/apache/tools/ant/taskdefs/condition/IsReachableTest.java b/src/testcases/org/apache/tools/ant/taskdefs/condition/IsReachableTest.java
new file mode 100644
index 000000000..a8095d199
--- /dev/null
+++ b/src/testcases/org/apache/tools/ant/taskdefs/condition/IsReachableTest.java
@@ -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);
+ }
+}