diff --git a/build.xml b/build.xml index bbef59f5f..8747a9a12 100644 --- a/build.xml +++ b/build.xml @@ -31,6 +31,7 @@ + @@ -56,7 +57,7 @@ - + @@ -113,13 +114,13 @@ + refid="tests-classpath"/> - + @@ -157,7 +158,6 @@ - @@ -166,10 +166,10 @@ but not all of them --> - + - + @@ -312,7 +312,7 @@ - + @@ -392,110 +392,110 @@ + classname="org.apache.bsf.BSFManager" + classpathref="classpath"/> + classname="netrexx.lang.Rexx" + classpathref="classpath"/> + classname="javax.xml.transform.Transformer" + classpathref="classpath"/> + classpathref="classpath"/> + classname="com.kvisco.xsl.XSLProcessor" + classpathref="classpath"/> + classname="org.apache.xml.resolver.tools.CatalogResolver" + classpathref="classpath"/> + classname="org.apache.xalan.xslt.XSLTProcessorFactory" + classpathref="classpath"/> + classname="org.apache.xalan.transformer.TransformerImpl" + classpathref="classpath"/> + classname="weblogic.ejbc" + classpathref="classpath"/> + classname="weblogic.ejb.utils.DDCreator" + classpathref="classpath"/> + classname="weblogic.Server" + classpathref="classpath"/> + classname="junit.framework.TestCase" + classpathref="classpath"/> + classname="org.apache.commons.net.ftp.FTPClient" + classpathref="classpath"/> + classname="com.starbase.util.Platform" + classpathref="classpath"/> + classname="antlr.Tool" + classpathref="classpath"/> + classname="com.ibm.ivj.util.base.Workspace" + classpathref="classpath"/> + classname="org.apache.stylebook.Engine" + classpathref="classpath"/> + classname="org.apache.regexp.RE" + classpathref="classpath"/> + classname="org.apache.oro.text.regex.Perl5Matcher" + classpathref="classpath"/> + classname="javax.sound.sampled.Clip" + classpathref="classpath"/> + classname="javax.media.jai.JAI" + classpathref="classpath"/> + classname="com.reliablesystems.iContract.IContracted" + classpathref="classpath"/> + classname="jdepend.framework.JDepend" + classpathref="classpath"/> + classname="org.apache.log4j.Logger" + classpathref="classpath"/> + classname="org.apache.commons.logging.LogFactory" + classpathref="classpath"/> + classname="org.apache.xalan.xslt.EnvironmentCheck" + classpathref="classpath"/> + classname="org.apache.env.Which" + classpathref="classpath"/> + classname="org.apache.xerces.parsers.SAXParser" + classpathref="classpath"/> + classname="org.apache.bcel.Constants" + classpathref="classpath"/> + classname="sun.misc.UUEncoder" + classpathref="classpath"/> + classpathref="classpath"/> + classpathref="classpath"/> @@ -528,10 +528,10 @@ + substring="${build.tests}"/> + substring="${build.tests.resolved}"/> @@ -549,7 +549,7 @@ + classpathref="classpath"/> @@ -565,7 +565,7 @@ - + @@ -573,8 +573,8 @@ wsdl.found=${wsdl.found} - - + + @@ -589,17 +589,17 @@ dotnetapps.found=${dotnetapps.found} + classname="org.mozilla.javascript.Scriptable" + classpathref="classpath"/> + classname="bsh.StringUtil" + classpathref="classpath"/> + classname="org.apache.xerces.framework.XMLParser" + classpathref="classpath"/> + classname="com.jcraft.jsch.Session" + classpathref="classpath"/> @@ -646,19 +646,19 @@ =================================================================== --> + depends="prepare, check_for_optional_packages" + description="--> compiles the source code"> + destdir="${build.classes}" + debug="${debug}" + deprecation="${deprecation}" + target="${javac.target}" + source="${javac.source}" + optimize="${optimize}"> @@ -677,12 +677,12 @@ + unless="apache.regexp.present"/> + unless="commons.logging.present"/> @@ -690,7 +690,7 @@ + unless="ejb.DDCreator.present"/> @@ -699,7 +699,7 @@ - + @@ -715,7 +715,7 @@ + overwrite="true" encoding="UTF-8"> @@ -724,10 +724,10 @@ - - - - + + + + @@ -737,8 +737,8 @@ =================================================================== --> + depends="build" + description="--> creates the Apache Ant jars"> @@ -755,24 +755,24 @@
+ value="org.apache.tools.ant"/> + value="Apache Ant"/> + value="${manifest-version}"/> + value="Apache Software Foundation"/> + value="org.apache.tools.ant"/> + value="${manifest-version}"/> + value="Apache Software Foundation"/>
+ basedir="${build.classes}"> @@ -780,8 +780,8 @@ + basedir="${build.classes}" + manifest="${manifest}"> @@ -807,19 +807,19 @@
+ value="org.apache.tools.ant"/> + value="Apache Ant"/> + value="${manifest-version}"/> + value="Apache Software Foundation"/> + value="org.apache.tools.ant"/> + value="${manifest-version}"/> + value="Apache Software Foundation"/>
@@ -829,8 +829,8 @@
+ basedir="${build.classes}" + manifest="${manifest}"> @@ -838,13 +838,13 @@ + value="ant.jar xml-apis.jar xercesImpl.jar xalan.jar"/> + basedir="${build.classes}" + manifest="${manifest.tmp}"> @@ -922,11 +922,11 @@ + basedir="${build.classes}" + manifest="${manifest.tmp}"> - + @@ -935,15 +935,15 @@ + depends="compile-tests" + description="--> creates the Apache Ant Test Utilties jar"> We cannot build the test jar unless JUnit is present, as JUnit is needed to compile the test classes. + basedir="${build.tests}"> @@ -954,8 +954,8 @@ =================================================================== --> + depends="jars" + description="--> creates a minimum distribution to run Apache Ant"> @@ -986,25 +986,25 @@ + failonerror="${chmod.fail}"/> + failonerror="${chmod.fail}" maxparallel="${chmod.maxparallel}"/> - - - - - - + + + + + + - + @@ -1055,34 +1055,34 @@
+ failonerror="${chmod.fail}"/> + failonerror="${chmod.fail}" maxparallel="${chmod.maxparallel}"/> - - - - - - + + + + + + - - - - - - - - - - - - - - + + + + + + + + + + + + + + @@ -1109,7 +1109,7 @@ =================================================================== --> + description="--> creates a source distribution"> @@ -1167,16 +1167,16 @@ + failonerror="${chmod.fail}"/> - - - - - - - + + + + + + + @@ -1187,7 +1187,7 @@ =================================================================== --> + description="--> creates the zip and tar distributions"> @@ -1212,7 +1212,7 @@ + destfile="${dist.base}/bin/${dist.name}-bin.tar"> @@ -1228,9 +1228,9 @@ + src="${dist.base}/bin/${dist.name}-bin.tar"/> + src="${dist.base}/bin/${dist.name}-bin.tar"/> @@ -1256,7 +1256,7 @@ + destfile="${dist.base}/src/${dist.name}-src.tar"> @@ -1268,9 +1268,9 @@ + src="${dist.base}/src/${dist.name}-src.tar"/> + src="${dist.base}/src/${dist.name}-src.tar"/> @@ -1283,7 +1283,7 @@ + description="--> creates the full Apache Ant distribution"> @@ -1293,7 +1293,7 @@ =================================================================== --> + description="--> cleans up build and dist directories"> @@ -1308,8 +1308,8 @@ =================================================================== --> + 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); + } +}