Я использую 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);
}
}