Синтаксическая ошибка в файле конфигурации провайдера javax.xml.xpath.XPathFactory Saxon-HE 9.3

Я использую Java SE 6 в Mac OS X и Saxon-HE 9.3.0.5. ServiceLoader не может найти саксонскую реализацию javax.xml.xpath.XPathFactory.

mac:test2 ludo$ java -version
java version "1.6.0_26"
Java(TM) SE Runtime Environment (build 1.6.0_26-b03-383-11A511)
Java HotSpot(TM) 64-Bit Server VM (build 20.1-b02-383, mixed mode)

В javadoc метода newInstance метода javax.xml.xpath.XPathFactory в пункте 3 процедуры поиска указывается локализация реализации, которая:

У загрузчика классов запрашиваются файлы конфигурации поставщика услуг, соответствующие javax.xml.xpath.XPathFactory в каталоге ресурсов META-INF/services. См. Спецификацию файла JAR для формата файла и правил синтаксического анализа.

Раздел поставщика услуг Спецификация файла JAR гласит, что:

Файл должен содержать разделенный новой строкой список уникальных имен конкретных классов провайдеров.

Но если я извлеку файл saxon9he.jar и загляну в каталог META-INF, я увижу:

mac:Java ludo$ mkdir test
mac:Java ludo$ cd test
mac:test ludo$ jar fx ../saxon9he.jar 
mac:test ludo$ cat META-INF/services/javax.xml.xpath.XPathFactory 
net.sf.saxon.xpath.XPathFactoryImpl
http\://java.sun.com/jaxp/xpath/dom:    net.sf.saxon.xpath.XPathFactoryImpl
http\://saxon.sf.net/jaxp/xpath/om:     net.sf.saxon.xpath.XPathFactoryImpl

Первая строка верна, но я не понимаю, почему есть две дополнительные строки, и похоже, что эти строки создают проблемы для ServiceLoader. Я увидел проблему с тестовым примером, который я написал, чтобы понять механизм, используемый для поиска провайдера. Мы видим, что saxon9he.jar находится в CLASSPATH.

mac:services ludo$ java ServicesTest
CLASSPATH = ..., /Users/ludo/Library/Java/saxon9he.jar, ...
Service XPathFactory: java.util.ServiceLoader[javax.xml.xpath.XPathFactory]
ServiceConfigurationError: javax.xml.xpath.XPathFactory: jar:file:/Users/ludo/Library/Java/saxon9he.jar!/META-INF/services/javax.xml.xpath.XPathFactory:2: Illegal configuration-file syntax

Линия интереса:

jar:file:/Users/ludo/Library/Java/saxon9he.jar!/META-INF/services/javax.xml.xpath.XPathFactory:2: Illegal configuration-file syntax

Это ошибка Saxon или расширенный синтаксис, не поддерживаемый моей системой? Что я могу сделать, чтобы решить проблему?

Обратите внимание, что если я явно выбираю класс для реализации, я могу получить фабрику. Но я хочу использовать механизм Services. Работает следующий код:

XPathFactory xpf = XPathFactory.newInstance(
  XPathFactory.DEFAULT_OBJECT_MODEL_URI,
  "net.sf.saxon.xpath.XPathFactoryImpl",
  ClassLoader.getSystemClassLoader());

Ниже я добавил всю тестовую программу Java.

import java.net.URL;
import java.net.URLClassLoader;
import java.util.Iterator;
import java.util.ServiceConfigurationError;
import java.util.ServiceLoader;
import javax.xml.xpath.XPathFactory;

public class ServicesTest {
    public static String getClasspathString() {
        StringBuilder classpath = new StringBuilder();
        ClassLoader classLoader = ClassLoader.getSystemClassLoader();
        URL[] urls = ((URLClassLoader) classLoader).getURLs();
        for (int i = 0; i < urls.length - 1; i++) {
            classpath.append(urls[i].getFile()).append(", ");
        }
        if (urls.length > 0) {
            classpath.append(urls[urls.length - 1].getFile());
        }

        return classpath.toString();
    }

    public static void availableProviders(ServiceLoader sl) {
        Iterator it = sl.iterator();
        int index = 0;
        for (;;) {
            try {
                if (!it.hasNext()) {
                    break;
                }
                index++;
                Object o = it.next();
                System.out.printf("%03d Concrete class name: %s\n", index, o.getClass().getName());
            } catch (ServiceConfigurationError e) {
                System.err.printf("ServiceConfigurationError: %s\n", e.getMessage());
            }
        }
    }

    public static void main(String[] args) {
        System.out.printf("CLASSPATH = %s\n", getClasspathString());
        System.out.println();

        ServiceLoader<XPathFactory> slXPathFactory = ServiceLoader.load(XPathFactory.class);
        System.out.printf("Service XPathFactory: %s\n", slXPathFactory.toString());
        availableProviders(slXPathFactory);
    }
}

person Ludovic Kuty    schedule 27.10.2011    source источник
comment
Вы можете извлечь файл прямо в командную строку за один шаг с помощью «unzip -p /path/to/lib/jarfile.jar META-INF/services/javax.xml.xpath.XPathFactory».   -  person andrew lorien    schedule 05.10.2017


Ответы (2)


Майкл Кей ответил на вопрос на форуме SourceForge. Он сказал, что:

Формат файла был выбран, чтобы обойти ошибку JDK5.

А еще что:

На самом деле, я бы все равно не рекомендовал использовать механизм поиска JAXP. Он очень медленный и предоставляет механизм XPath, который не обязательно будет работать с вашим приложением. У вас нет возможности узнать, получите ли вы обратно реализацию XPath 1.0 или 2.0, а API настолько слабо определен, что очень мало шансов, что ваше приложение будет работать с конкретным провайдером, если вы сначала не протестировали его с этим провайдером. Так что даже без этой ошибки я бы ее избегал.

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

XPathFactory xpf = XPathFactory.newInstance(
  XPathFactory.DEFAULT_OBJECT_MODEL_URI,
  "net.sf.saxon.xpath.XPathFactoryImpl",
  ClassLoader.getSystemClassLoader());
person Ludovic Kuty    schedule 28.10.2011
comment
В Saxon 9.5 и выше эта проблема решена. Если кто-то считает, что ему нужно заставить это работать со старой версией и не имеет доступа к коду, вызывающему newInstance - вы решаете проблему, удаляя каталог services из вышеупомянутого файла JAR. Это следует за примечанием в ветке сообщения об ошибке. - person stav; 03.10.2014
comment
А в Saxon 9.6 разрешение JAXP для XPath было удалено — см. saxonica.plan.io/issues. /1944#примечание-5 - person Philip Helger; 26.11.2014

Я знаю, что это старая ветка, но этот мой пост Может пролить свет на этот вопрос. Он находит XPathFactory, используя параметр -D, который я никогда не видел документально.

person Erik Ostermueller    schedule 29.05.2017
comment
Спасибо за продолжение в любом случае. - person Ludovic Kuty; 29.05.2017