代码之家  ›  专栏  ›  技术社区  ›  Nik Reiman

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

  •  16
  • Nik Reiman  · 技术社区  · 17 年前

    我想在ant中使用FTP任务,我已经找到了合适的jar文件,并且一切正常。我将jar文件与构建中使用的其他文件放在“libs”目录中。唯一的问题是,用户必须运行“ant-libcommons-net-ftp-2.0.jar”进行构建;我真的希望可以在没有参数的情况下运行“ant”。

    ant optional tasks intallation page ,我发现有五种方法可以在ant中加载额外的库,但它们都不是我真正想要的。我不想强迫用户对其系统进行任何修改以运行此任务;应该可以从产品源文件夹中的“libs”目录加载它。因此,这意味着设置全局类路径也不可行(无论如何,这是个坏主意)。

    如文件中所述,最后一个选项是首选方法。。。从构建脚本本身分别加载jar文件。我以前在ant contrib任务和JUnit中做过这件事,我想在这里做这件事,但我不知道如何才能做到这一点。FTP任务不支持嵌套的classpath元素,而且我不知道通过taskdef加载此库所需的XML资源。如何从ant中加载库?

    编辑: 为了回答到目前为止在这里发布的答案和问题,我使用ant 1.7.1。制作ftp任务def肯定不起作用;这将引发以下错误:

    构建失败 /my/path/build.xml:13:taskdef class org.apache.tools.ant.taskdefs.optional.net.FTP找不到

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

    6 回复  |  直到 17 年前
        1
  •  12
  •   Dan Dyer    17 年前

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

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

    文档中的第五个选项在理论上很好。他们最终在1.7.0中解决了类加载问题。不幸的是,正如您所提到的,没有人重新安装FTP任务以获取类路径。您可以尝试提交增强请求,但这在短期内没有帮助。

    还有一个选择,并不比其他选择好多少。不必确保Commons Net类由加载FTP任务的类加载器加载,您可以确保FTP任务由加载Commons Net类的类加载器加载。为此,您必须从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任务来使用,而不是默认任务。

        2
  •  6
  •   juanolo    17 年前

    我有一个解决办法:

    http://enitsys.sourceforge.net/ant-classloadertask/ 并将其加载到以下位置:

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

    Naw可以使用ant用于其任务的相同类加载器加载类:

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

    或“loader=”项目“”

    然后你定义你的任务:

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

        3
  •  4
  •   Mat Schaffer    16 年前

    因此,我成功地为ant-salesforce.jar完成了这项工作,您在尝试执行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" />
    

    希望这能帮助一些人。

        4
  •  1
  •   Erik Lievaart    11 年前

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

    我想对丹·戴尔表示衷心的感谢。如果没有你对幕后发生的事情的详尽解释,我就不会找到这个解决方案。

        5
  •  0
  •   ShuggyCoUk    17 年前

    假设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>
    
        6
  •  0
  •   Instantsoup    17 年前

    你的用户都在他们的机器上安装了ant,但是你不能/不想让他们添加FTP jar?您是否可以将ant与您的项目捆绑在一起,使任务调用ant捆绑包,并放置JAR,使其按如下方式工作?

    <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>