Как выполнить XSLT-преобразование с расширением Java из OSGi Bundle - PullRequest
3 голосов
/ 11 сентября 2011

Мы находимся в процессе преобразования существующего кода в среду 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>

Для справки, вот как настроено и называется преобразование:

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();
}

При запуске вне OSGi environemnt, это работает.При запуске в среде OSGi происходит сбой, поскольку таблица стилей не может быть скомпилирована, поскольку класс TransformationUtils не может быть найден.Я вроде понимаю, что загрузчик классов, загружающий реализацию преобразователя jaxp, не видит класс расширения в нашем комплекте.Тем не менее, я нахожусь в тупике в поиске решения.Я пытался использовать OSGi: запускал пакеты Xalan и Xerces безрезультатно.

Мой вопрос: как это можно решить?Может ли это?

1 Ответ

5 голосов
/ 12 сентября 2011

Ответ зависит от того, как процессор XSLT ищет класс расширения. Вам может понадобиться прочитать исходный код и / или запустить его через отладчик, чтобы выяснить это.

Например, если процессор XSLT использует загрузчик классов потока (TCCL), это обычно приводит к сбою, поскольку TCCL не определен в OSGi. Вы можете обойти это, явно установив TCCL на время вызова процессору XSLT, например ::1003*

ClassLoader orig = Thread.currentThread().getContextClassLoader();
Thread.currentThread().setContextClassLoader(MyClass.class.getClassLoader());
try {
    // invoke XSLT processor
} finally {
    Thread.currentThread.setContextClassLoader(orig);
}

, где MyClass - это класс из вашего пакета и имеет видимость класса расширения.

В худшем случае процессор может искать расширение, используя собственный загрузчик классов, то есть с простым вызовом Class.forName(). Лучшее, что можно сделать здесь, - побить разработчика библиотеки за то, что он так глуп. После того, как вы это сделаете, вы можете использовать фрагмент, чтобы присоединить класс расширения к комплекту процессоров ... это неприятный хак, но лучше, чем некоторые другие возможные неприятные хаки.

...