【问题标题】:How to load an optional task into ant without -lib or global installation?如何在没有 -lib 或全局安装的情况下将可选任务加载到 ant 中?
【发布时间】:2010-10-03 02:54:19
【问题描述】:

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

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

最后一个选项,如文档中所述,是首选方法...从构建脚本本身单独加载 jarfile。我过去曾使用 ant-contrib 任务和 JUnit 完成此操作,并且想在这里执行此操作,但我不知道如何完成此操作。 FTP 任务不支持嵌套的类路径元素,而且我不知道通过 taskdef 加载该库所需的 XML 资源。如何从 ant 中加载库?

编辑:为了回答到目前为止已在此处发布的答案和问题,我使用的是 ant 1.7.1。制作一个 ftp taskdef 肯定是行不通的;引发以下错误:

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

也许这是因为类名错误。如果我只有一个 jarfile,我该如何找到我应该使用的类名?它没有在任何地方记录,我在 jar 本身中找不到任何类似于该路径的东西。

【问题讨论】:

  • 我认为 ftp 所依赖的另一个任务可以完成,但我不太确定 - 我必须尝试一下。
  • 对我来说也一样。对于外部任务,我通常在 taskdef 中包含一个类路径,但是对于一些内部可选任务(ssh、scp、scriptdef),我没有找到比让用户将 JAR 复制到 /home/.ant/lib 更好的解决方案: -S
  • 你用的是什么版本的 Ant ?
  • 我意识到你已经有一段时间没有发布这个了 :-) 但我想知道你是否会在项目中使用三叶草。
  • 不,我不是。为什么要问?

标签: ant ftp


【解决方案1】:

您的用户都在他们的机器上安装了 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>

【讨论】:

  • 是的,但“我不想强迫用户对其系统进行任何修改以运行此任务”是一项要求。
  • 啊,我读错了问题。这些罐子在他项目的库中!
【解决方案2】:

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

【讨论】:

    【解决方案3】:

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

    我同意它们都不是理想的(CLASSPATH 环境变量是最差的)。解决此问题的一种方法是为您的项目提供一个 shell 脚本,该脚本调用 Ant 并传递适当的 -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 任务而不是默认任务。

    【讨论】:

    • 感谢您在这里的详细解释。这确实有效,但同样需要修改默认安装,这不太理想。我想与其让我们的用户从他们的 ant lib 目录中删除 ant-commons-net,不如让他们添加 commons-net-2.0-ftp。
    【解决方案4】:

    我有一个解决方案:

    您可以从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="project"”

    然后你定义你的任务:

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

    然后去:-)

    【讨论】:

    • 完美运行!唯一的一点是您需要将您的 ant 更新到 1.8.1 才能工作。
    【解决方案5】:

    所以我成功地为您在尝试进行销售人员工作时获得的 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" />
    

    希望对一些人有所帮助。

    【讨论】:

      【解决方案6】:

      啊,伙计,这太恶心了。我从日食运行蚂蚁。我不想在 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。如果没有您对幕后发生的事情的广泛解释,我不会找到这个解决方案。

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 1970-01-01
        • 2015-03-30
        • 2013-10-21
        • 1970-01-01
        • 2015-10-13
        • 2016-12-13
        • 2018-08-19
        相关资源
        最近更新 更多