在build.xml中设置ANT CLASSPATH

时间:2014-04-17 11:42:50

标签: java ant schematron

这个问题已被问过几次,但并不令我满意。我对提出的解决方法并不感兴趣,但是如何做我真正想做的事情。

想要一个令人满意的解释,为什么这是不可能的,如果不是,并且因为我建议自己提交一个解决方案,我想了解为什么看似如此简单的东西没有尝试。

目前,为了确保ant可以使用一组jar,必须采用以下方法之一:

  • 添加到CLASSPATH环境变量 - 文档
  • 中的“不推荐”
  • 添加到$ANT_HOME/lib~/.ant/lib - 需要在构建环境中进行配置
  • -lib调用
  • 上设置ant参数

最后一个选项是我已经确定的首选选项,但它仍然需要调用构建的人进行一些干预(我已经在我的开发存储库中的ant包装器脚本中捕获了)。

特别是我试图调用Schematron Ant任务,该任务应根据the documentation设置,如下所示:

<taskdef name="schematron" 
 classname="com.schematron.ant.SchematronTask"
 classpath="lib/ant-schematron.jar"/>

然而,这对撒克逊人具有传递依赖性,因此如果saxon.jar上没有CLASSPATH,则构建失败:

java.lang.NoClassDefFoundError: net/sf/saxon/TransformerFactoryImpl

ant documentation itself继续建议它应该是taskdef本身带来这些额外的CLASSPATH条目,但我已尝试使用schematron ant-task无效。

关键问题是它是否应该是支持这种情况的schematron ant任务,或者ant build.xml是否可以在其内部配置其全局类路径?

似乎这是人们想要经常做的事情,并且由于ant文档本身建议使用CLASSPATH本身我很惊讶build.xml本身没有其他选择!

1 个答案:

答案 0 :(得分:1)

这似乎是Schematron任务中的一个错误。 Ant任务加载Saxon XSLT处理器的方式要求Saxon在系统类路径上,即使任务本身位于子类加载器上也是如此。

乍一看this code in ValidatorFactory看起来很合理:

private TransformerFactory _factory = TransformerFactoryImpl.newInstance();

(其中TransformerFactoryImpl是撒克逊人对TransformerFactory)的实现,但实际上TransformerFactoryImpl并没有定义自己的newInstance()方法,所以这是来自newInstance的继承TransformerFactory,它将根据javax.xml.transform.TransformerFactory系统属性的值查找适当的工厂。 Ant任务does set this system property

System.setProperty("javax.xml.transform.TransformerFactory",
      "net.sf.saxon.TransformerFactoryImpl");

TransformerFactory.newInstance()将在系统类加载器上查找此类,而不一定在加载schematron任务的类加载器上查找。

修复方法是将ValidatorFactory第120行更改为

private TransformerFactory _factory = new TransformerFactoryImpl();

将绕过所有动态查找并直接实例化正确的类。有了这个修复程序

<taskdef name="schematron" 
 classname="com.schematron.ant.SchematronTask"
 classpath="lib/ant-schematron.jar:lib/saxon9he.jar"/>

会正常工作。

我建议您向开发人员报告错误,但该项目看起来并不活跃,因此您可能只需构建自己的本地分支......