5

这个特殊的问题已经被问了好几次了,但不是很让我满意。我对提出的解决方法并不真正感兴趣,而是对如何做我真正想做的事情感兴趣。

想要一个令人满意的解释,说明为什么如果不是这样是不可能的,并且由于我建议自己为此提交一个修复程序,我想了解为什么没有尝试过看起来如此简单的事情。

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

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

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

特别是我正在尝试调用Schematron Ant任务,该任务应根据以下文档进行设置:

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

但是,这对 saxon 有传递依赖,因此如果没有saxon.jaravailable on CLASSPATH,则构建失败:

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

ant 文档本身继续建议它应该是 taskdef 本身接受这些额外的条目CLASSPATH,但我已经尝试使用 schematron ant-task 进行此操作,但无济于事。

关键问题是是否应该由 schematron ant 任务来支持这一点,或者 ant build.xml 是否可以在其内部配置其全局类路径?

似乎这是人们经常想要做的事情,而且由于 ant 文档本身建议不要自己使用 CLASSPATH,我很惊讶 build.xml 本身没有替代方案!

4

1 回答 1

1

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

乍一看,ValidatorFactory 中的这段代码看起来很合理:

private TransformerFactory _factory = TransformerFactoryImpl.newInstance();

TransformerFactoryImplSaxon 的实现在哪里TransformerFactory),但实际上TransformerFactoryImpl并没有定义newInstance()自己的方法,所以这是从继承newInstance的,它将根据系统属性TransformerFactory的值查找适当的工厂。javax.xml.transform.TransformerFactoryAnt 任务确实设置了这个系统属性

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

会正常工作。

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

于 2014-04-17T12:13:28.897 回答