我想在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文件,我究竟如何找到我应该使用的类名?它没有记录在任何地方,我在罐子里找不到任何类似于那条道路的东西。
答案 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)
<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>