如何在没有-lib或全局安装的情况下将可选任务加载到ant中?

时间:2009-01-23 11:08:28

标签: ant ftp

我想在ant中使用FTP任务,我找到了相应的jar文件并且一切正常。我已将jar文件放在“libs”目录中,并与构建中使用的其他文件一起放置。唯一的问题是用户必须运行“ant -lib commons-net-ftp-2.0.jar”才能进行构建;我真的更喜欢可以只运行没有参数的“ant”。

阅读ant optional tasks intallation page,我发现有五种方法可以在ant中加载额外的库,而且它们都不是我正在寻找的。我不想强迫用户对他们的系统进行任何修改来运行这个任务;应该可以从我们产品的源文件夹中的“libs”目录加载它。这意味着设置全局CLASSPATH也是不对的(反正这是一个坏主意)。

如文档中所述,最后一个选项是首选方法...从构建脚本本身单独加载jar文件。我在过去使用ant-contrib任务和JUnit做了这个,并且想在这里做,但我不知道如何实现这一点。 FTP任务不支持嵌套的classpath元素,我不知道通过taskdef加载这个库需要的XML资源。如何从ant?中加载库?

编辑:针对目前已发布的答案和问题,我正在使用ant 1.7.1。制作ftp taskdef肯定不起作用;抛出以下错误:

建立失败 /my/path/build.xml:13:无法找到taskdef类org.apache.tools.ant.taskdefs.optional.net.FTP

也许这是因为类名错了。如果我只有一个jar文件,我究竟如何找到我应该使用的类名?它没有记录在任何地方,我在罐子里找不到任何类似于那条道路的东西。

6 个答案:

答案 0 :(得分:12)

您遇到的问题是由于使用了不同的类加载器。 Commons Net类必须由加载FTP任务的同一个类加载器加载。因为在启动时Ant加载了FTP任务,所以需要将Commons Net添加到Ant的类路径中,以便它由相同的类加载器加载。这就是为什么文档为您提供了4种不同的方法。

我同意它们都不是理想的(CLASSPATH环境变量是最差的)。解决此问题的一种方法是为您的项目提供一个shell脚本,该脚本调用Ant并传递apporpriate -lib参数。然后,您可以让人们使用它,而不是直接调用Ant。事实上,你可以狡猾地将它命名为'ant',以便它在路径上运行而不是现有的'ant'(这只适用于当前目录在路径上,在其他目录之前)。

文档中的第五个选项理论上很棒。他们最终修复了1.7.0中的类加载问题。不幸的是,正如你所提到的,没有人改装FTP任务来采用类路径。您可以尝试提交增强请求,但这在短期内无济于事。

还有另外一种选择,这种选择并不比其他选择更好。而不是确保加载FTP任务的类加载器加载Commons Net类,您可以确保加载Commons Net类的类加载器加载FTP任务。为此,您必须从Ant安装的“lib”目录中删除ant-commons-lib.jar文件。这意味着启动时不会加载FTP任务。这实际上是为什么可选任务被分解为如此多的单独JAR - 以便可以单独删除它们。将此JAR文件与Commons Net JAR文件放在一起,以便可以同时加载它。然后你可以做这样的事情(我试过这个并且它有效):

<taskdef name="ftp"
         classname="org.apache.tools.ant.taskdefs.optional.net.FTP">
  <classpath>
    <pathelement location="${basedir}/lib/ant-commons-net.jar"/>
    <pathelement location="${basedir}/lib/commons-net-2.0.jar"/>
  </classpath>
</taskdef>
<ftp server="yourserver.com"
     userid="anonymous"
     password="blah">
  <fileset dir="somedirectory"/>
</ftp>

但这可能是比使用-lib开关(带或不带包装脚本)更糟糕的选择。我能想到的唯一另一件事就是尝试找到第三方FTP任务而不是默认任务。

答案 1 :(得分:6)

我有一个解决方案:

你可以从http://enitsys.sourceforge.net/ant-classloadertask/下载一个新的“classloader”任务并加载它:

    <taskdef resource="net/jtools/classloadertask/antlib.xml"
            classpath="XXX/ant-classloadertask.jar"/>

Naw可以执行诸如使用与其用于任务的相同类加载器加载类的操作:

    <classloader loader="system" classpath="XXX/commons-net-2.0.jar"/>

或“loader =”project“”

然后你定义你的任务:

    <taskdef name="ftp" classname="org.apache.tools.ant.taskdefs.optional.net.FTP"/>    

然后去: - )

答案 2 :(得分:4)

所以我成功地为你在尝试做salesforce工作时获得的ant-salesforce.jar做了这​​个(有趣......)

检查jar中是否有一个xml文件,如下所示:

<antlib>
  <typedef name="compileAndTest" classname="com.salesforce.ant.CompileAndTest"/>
  ....
</antlib>

然后在ant中给它一个taskdev,从给定的jar内部读取该文件,如下所示:

<taskdef resource="com/salesforce/antlib.xml" classpath="lib/ant-salesforce.jar" />

希望有所帮助。

答案 3 :(得分:1)

啊,伙计,这真是太讨厌了。我从日食中运行蚂蚁。我不想在eclipse中为新工作区重新配置ant,所以这就是我决定要做的事情,以解耦运行任务和配置ant。我将ftp任务解压缩到一个单独的构建文件。接下来,我在命令行中添加了一个本机调用,以启动一个全新的ant进程,其中包含路径上所需的库:

<target name="deploy-ftp">
    <exec command="ant">
        <arg line="-buildfile ftp.xml deploy-ftp -lib lib/ant"/>
    </exec>
</target>

现在可以在没有任何特殊参数的情况下运行主构建文件,并且不需要对ant安装进行任何修改。但这很糟糕,因为ftp任务在一个完全干净的环境中运行。主构建文件中的所有属性和路径均不可用。幸运的是,无论如何我将所有这些都放在一个单独的属性文件中,所以我只需要一次导入。

我要非常感谢Dan Dyer。如果没有对幕后发生的事情进行广泛的解释,我就不会找到这个解决方案。

答案 4 :(得分:0)

您的用户都在他们的计算机上安装了ant,但您不能/不想让他们添加FTP jar?你可以将ant与你的项目捆绑制作任务,调用你的蚂蚁包,放入罐子,这样就可以按照以下方式工作吗?

<taskdef name="ftp" classname="org.apache.tools.ant.taskdefs.optional.net.FTP">
  <classpath>
    <pathelement location="\lib\commons-net-1.4.0.jar"/>
  </classpath>
</taskdef>
<target name="testFtp">
  <ftp server="blah" userid="foo" password="bar">
    <fileset file="test.file" />
  </ftp>
</target>

答案 5 :(得分:0)

假设libs直接位于项目的基本目录

下,这是否可行
<taskdef name="ftp" classname="org.apache.tools.ant.taskdefs.optional.net.FTP">
  <classpath>
    <pathelement location="${basedir}\libs\commons-net-1.4.0.jar"/>
  </classpath>
</taskdef>