如何在OSGi Bundle中使用Java扩展执行XSLT转换

for*_*two 3 xslt osgi classloader

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

<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>
Run Code Online (Sandbox Code Playgroud)

作为参考,这是如何设置和调用转换:

protected Templates createTemplates(Source xsltSource) {
    try {
        TransformerFactory tf = TransformerFactory.newInstance();
        Templates templates = tf.newTemplates(xsltSource);
        return templates;
    } catch (TransformerException e) {
        throw new RuntimeException(e);
    }
}


protected byte[] transform(byte[] input) throws TransformerException {
    ByteArrayOutputStream out = new ByteArrayOutputStream(2048);
    templates.newTransformer().transform(
            new StreamSource(new ByteArrayInputStream(input)),
            new StreamResult(out));
    return out.toByteArray();
}
Run Code Online (Sandbox Code Playgroud)

在非OSGi environemnt中运行时,它可以工作.在OSGi框架中运行时,它会失败,因为无法编译样式表,因为找不到类TransformationUtils.我有点明白 - 加载jaxp转换器实现的类加载器在我们的bundle中没有看到扩展类.但是,我很难找到解决方案.我尝试过使用OSGi:使用Xalan和Xerces捆绑无济于事.

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

Nei*_*ett 5

答案取决于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);
}
Run Code Online (Sandbox Code Playgroud)

哪个MyClass是您的包中的类,并且具有扩展类的可见性.

在最坏的情况下,处理器可能会使用自己的类加载器查找扩展,即通过简单的调用Class.forName().在这里做的最好的事情是打败图书馆的开发人员是如此愚蠢.在你完成之后,你可以使用一个片段将扩展类附加到处理器包......这是一个讨厌的黑客,但比其他一些可能讨厌的黑客更好.