Можно ли избежать использования xalan TransformerFactory? - PullRequest
0 голосов
/ 24 апреля 2018

У меня есть следующий код:

final TransformerFactory factory = TransformerFactory.newInstance();

factory.setAttribute(XMLConstants.ACCESS_EXTERNAL_DTD, "");

Вторая строка отлично работает в современных JDK (я пробовал 1.8) со значением по умолчанию TransformerFactory.Но когда я добавляю xalan (версия 2.7.2, самая последняя) в classpath, я получаю следующее во второй строке:

Exception in thread "main" java.lang.IllegalArgumentException: Not supported: http://javax.xml.XMLConstants/property/accessExternalDTD
    at org.apache.xalan.processor.TransformerFactoryImpl.setAttribute(TransformerFactoryImpl.java:571)
    at Main.main(Main.java:11)

Я думаю, это потому, что xalan TransformerFactory не делаетподдержать этот атрибут.Реализация Xalan обрабатывается механизмом ServiceLoader: он указан в services/javax.xml.transform.TransfomerFactory в xalan jar.

Можно переопределить реализацию TransformerFactory, используя системное свойство javax.xml.transform.TransformerFactory или файл $JRE/lib/jaxp.propertiesили передайте имя класса прямо в коде.Но чтобы сделать это, я должен предоставить конкретное имя класса.На данный момент это com.sun.org.apache.xalan.internal.xsltc.trax.TransformerFactoryImpl, но немного страшно жестко закодировать его в системном свойстве, так как при обновлении JDK они могут легко изменить имя класса, и мы просто получим ошибку времени выполнения.

есть ли способ дать TransformerFactory.newInstance() команду просто игнорировать эту реализацию, предоставляемую xalan?Или скажите «просто используйте системное значение по умолчанию».

PS Я не могу просто удалить xalan из пути к классам, потому что от него зависит куча других библиотек, которые мы используем.

1 Ответ

0 голосов
/ 07 мая 2018

Единственное, чего я могу достичь здесь, - это жестко закодировать фабрику JDK по умолчанию и использовать обычный процесс обнаружения в качестве запасного варианта:

TransformerFactory factory;
try {
    factory = TransformerFactory.newInstance("com.sun.org.apache.xalan.internal.xsltc.trax.TransformerFactoryImpl", SecureXmlFactories.class.getClassLoader());
} catch (Exception | TransformerFactoryConfigurationError e) {
    LOGGER.error("Cannot load default TransformerFactory, let's try the usual way", e);
    factory = TransformerFactory.newInstance();
}

и затем настройте его под try/catch

// this works everywhere, but it does not disable accessing
// external DTDs... still enabling it just in case
try {
    factory.setFeature(XMLConstants.FEATURE_SECURE_PROCESSING, true);
} catch (TransformerConfigurationException e) {
    LOGGER.error("Cannot enable secure processing", e);
}

// this does not work in Xalan 2.7.2
try {
    factory.setAttribute(XMLConstants.ACCESS_EXTERNAL_DTD, "");
} catch (Exception e) {
    LOGGER.error("Cannot disable external DTD access", e);
}
// this does not work in Xalan 2.7.2
try {
    factory.setAttribute(XMLConstants.ACCESS_EXTERNAL_STYLESHEET, "");
} catch (Exception e) {
    LOGGER.error("Cannot disable external stylesheet access", e);
}

И отслеживание журналов, чтобы увидеть, если / когда имя класса фабрики JDK по умолчанию изменится.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...