Подтвердить что ты не робот

Как узнать, какая реализация JAXP используется и откуда она загружена?

Я хотел бы предоставить диагностическую информацию о том, какая реализация JAXP используется, и из какого файла JAR она была загружена.

Один из способов добиться этого - создать, например, DocumentBuilderFactory, а затем проверить свойства этого класса:

private static String GetJaxpImplementation() {
    DocumentBuilderFactory documentBuilderFactory = DocumentBuilderFactory.newInstance();
    Class<? extends DocumentBuilderFactory> c = documentBuilderFactory.getClass();
    Package p = c.getPackage();
    CodeSource source = c.getProtectionDomain().getCodeSource();
    return MessageFormat.format(
            "Using JAXP implementation ''{0}'' ({1}) version {2} ({3}){4}",
            p.getName(),
            p.getImplementationVendor(),
            p.getSpecificationVersion(),
            p.getImplementationVersion(),
            source == null ? "." : " loaded from: " + source.getLocation());
}

Есть ли лучший способ достичь этого, возможно, без создания DocumentBuilderFactory?

4b9b3361

Ответ 1

Трудно предсказать, какая конкретная реализация JAXP factory будет загружена без фактического создания экземпляра, потому что процесс выбора реализации.

Из Официальный вопрос JAXP (Вопрос 14):

Когда приложение хочет создать новый JAXP DocumentBuilderFactoryНапример, он вызывает статический метод DocumentBuilderFactory.newInstance(). Это вызывает поиск имени конкретный подкласс DocumentBuilderFactory, используя в следующем порядке:

  • Значение системного свойства, такого как javax.xml.parsers.DocumentBuilderFactory, если оно существует и доступно.
  • Содержимое файла $JAVA_HOME/jre/lib/jaxp.properties, если оно существует.
  • Механизм обнаружения Jar Service Provider, указанный в спецификации Jar File. Файл jar может иметь ресурс (т.е. Встроенный файл), например META-INF/services/javax.xml.parsers.DocumentBuilderFactory, содержащий имя конкретного класса для создания экземпляра.
  • Реализация резервной платформы по умолчанию.

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

Следующий код выводит информацию о четырех основных фабриках JAXP:

private static void OutputJaxpImplementationInfo() {
    System.out.println(getJaxpImplementationInfo("DocumentBuilderFactory", DocumentBuilderFactory.newInstance().getClass()));
    System.out.println(getJaxpImplementationInfo("XPathFactory", XPathFactory.newInstance().getClass()));
    System.out.println(getJaxpImplementationInfo("TransformerFactory", TransformerFactory.newInstance().getClass()));
    System.out.println(getJaxpImplementationInfo("SAXParserFactory", SAXParserFactory.newInstance().getClass()));
}

private static String getJaxpImplementationInfo(String componentName, Class componentClass) {
    CodeSource source = componentClass.getProtectionDomain().getCodeSource();
    return MessageFormat.format(
            "{0} implementation: {1} loaded from: {2}",
            componentName,
            componentClass.getName(),
            source == null ? "Java Runtime" : source.getLocation());
}

Следующий примерный вывод иллюстрирует смешивание и соответствие трех различных реализаций JAXP (встроенных Xerces и внешних JAR для Xerces 2.8 и Xalan), работающих вместе:

DocumentBuilderFactory implementation: org.apache.xerces.jaxp.DocumentBuilderFactoryImpl loaded from: file:/C:/Projects/Scratch/lib/xerces-2.8.0.jar
XPathFactory implementation: com.sun.org.apache.xpath.internal.jaxp.XPathFactoryImpl loaded from: Java Runtime
TransformerFactory implementation: org.apache.xalan.processor.TransformerFactoryImpl loaded from: file:/C:/Projects/Scratch/lib/xalan.jar
SAXParserFactory implementation: org.apache.xerces.jaxp.SAXParserFactoryImpl loaded from: file:/C:/Projects/Scratch/lib/xerces-2.8.0.jar

Ответ 3

это легко, вы просто установите

System.setProperty("jaxp.debug", "1");

трек скажет вам whick impl и использовать jaxp для whick.

Ответ 4

Это зависит, но обычно нет.

DocumentBuilderFactory.newInstance() либо вернет реализацию DocumentBuilderFactory, которая настроена в системном свойстве "javax.xml.parsers.DocumentBuilderFactory" или JRE по умолчанию factory, если системное свойство не установлено. По умолчанию factory, скорее всего, жестко закодирован в реализации метода newInstance, а не доступен для других.

Если системное свойство установлено, вы можете по крайней мере использовать метод getResource в соответствующем загрузчике классов, чтобы получить URL-адрес, из которого загрузчик классов загрузил соответствующий файл класса. Если это из файла jar, вы должны иметь возможность извлечь имя файла (или URL-адрес источника) из jar: URL. Подробная информация о пакете также должна быть доступна, если вы manaully читаете файлы метаданных из пути к классам.

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

Ответ 5

Существует другое место, которое выполняется до реализации "резервной платформы по умолчанию", и это каталог java.endorsed.dirs, как описано в механизм переопределения стандартов Java

Механизм переопределения одобренных стандартов предоставляет средства, позволяющие более поздним версиям классов и интерфейсов, которые реализуют одобренные стандарты или автономные технологии, могут быть включены в платформу Java.