如何从OSGi包中使用Java扩展执行XSLT转换

如何从OSGi包中使用Java扩展执行XSLT转换,osgi,classloader,xslt,Osgi,Classloader,Xslt,我们正在将现有代码转换为OSGi环境。在我们的一个(尚未成为)OSGi捆绑包中,我们有执行XSLT转换的代码。XSLT的一部分包括一个java扩展函数,用于创建唯一的数值。Java类也驻留在包中。这是样式表的一个片段: <xsl:template match="m:property"> <xsl:variable name="uniqueDataStreamName" select="concat(../@id,'/',@name)" /> <xsl:v

我们正在将现有代码转换为OSGi环境。在我们的一个(尚未成为)OSGi捆绑包中,我们有执行XSLT转换的代码。XSLT的一部分包括一个java扩展函数,用于创建唯一的数值。Java类也驻留在包中。这是样式表的一个片段:

<xsl:template match="m:property">
   <xsl:variable name="uniqueDataStreamName" select="concat(../@id,'/',@name)" />
   <xsl:variable name="uniqueDataStreamId"
       select="java:com.xyz.TransformationUtils.makeDataStreamIdFromUniqueName($uniqueDataStreamName)" />
   <data id="{number($uniqueDataStreamId)}">
   <tag>
      <xsl:value-of select="$uniqueDataStreamName" />
   </tag>
   <current_value>
     <xsl:value-of select="@value" />
  </current_value>
</data>
在非OSGi环境中运行时,它可以工作。在OSGi框架中运行时,它会失败,因为找不到类TransformationUtils,所以无法编译样式表。我有点理解——加载jaxp transformer实现的类加载器在我们的包中看不到扩展类。然而,我很难找到解决办法。我尝试过使用OSGi:fied-Xalan和Xerces捆绑包,但都没有用


我的问题是:如何解决这个问题?可以吗?

答案取决于XSLT处理器如何查找扩展类。您可能需要阅读源代码和/或通过调试器运行源代码才能找到答案

例如,如果XSLT处理器使用线程上下文类加载器(TCCL),那么这通常会失败,因为OSGi中未定义TCCL。您可以通过显式设置调用XSLT处理器期间的TCCL来解决此问题,例如:

ClassLoader orig = Thread.currentThread().getContextClassLoader();
Thread.currentThread().setContextClassLoader(MyClass.class.getClassLoader());
try {
    // invoke XSLT processor
} finally {
    Thread.currentThread.setContextClassLoader(orig);
}
其中
MyClass
是捆绑包中的一个类,具有扩展类的可见性


在最坏的情况下,处理器可能会使用自己的类加载器查找扩展,也就是说,只需调用
Class.forName()
。在这里,最好的办法就是痛斥库的开发人员如此愚蠢。完成后,可以使用片段将扩展类附加到处理器包。。。这是一个令人讨厌的黑客行为,但比其他一些可能令人讨厌的黑客行为要好。

当然,这是有效的!刚意识到我做过几次是因为其他原因。呃,至少我不必去打别人——除了我自己!谢谢需要注意的一点是,获取和设置TCCL是一项特权操作,因此,如果在启用Java 2安全性时需要此操作,则需要设置permissions.perm文件以允许它,并且可能需要一些策略性地调用doPriv。
ClassLoader orig = Thread.currentThread().getContextClassLoader();
Thread.currentThread().setContextClassLoader(MyClass.class.getClassLoader());
try {
    // invoke XSLT processor
} finally {
    Thread.currentThread.setContextClassLoader(orig);
}