2011-10-27 9 views
11

Sto usando Java SE 6 su Mac OS X e Saxon-HE 9.3.0.5. ServiceLoader non è in grado di trovare l'implementazione Saxon di javax.xml.xpath.XPathFactory.Errore di sintassi in javax.xml.xpath.XPathFactory file di configurazione del provider di Saxon-HE 9.3

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 del metodo newInstance di javax.xml.xpath.XPathFactory stati al punto 3 della procedura di ricerca per localizzare un'implementazione che:

Il caricatore di classe è chiesto per i file di provider di configurazione del provider di servizi corrispondenti javax. xml.xpath.XPathFactory nella directory delle risorse META-INF/services. Vedere la specifica del file JAR per il formato del file e le regole di analisi.

La Service Provider section della specifica JAR File afferma che:

Il file dovrebbe contenere un elenco separato da fine riga di nomi concreti unici provider di classe.

Ma se ho estratto il file saxon9he.jar e guardo nella directory META-INF, vedo:

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 

La prima linea è corretta, ma non riesco a vedere il motivo per cui ci sono due extra linee e sembra che quelle linee stiano causando problemi a ServiceLoader. Ho visto il problema con un esempio di prova che ho scritto per capire il meccanismo usato per trovare un fornitore. Possiamo vedere che saxon9he.jar si trova nel 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 

La linea di interesse:

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

Si tratta di un bug di Saxon o di una sintassi estesa non supportato dal mio sistema? Cosa potrei fare per risolvere il problema?

Nota che se scelgo esplicitamente la classe per l'implementazione, posso ottenere una fabbrica. Ma voglio usare il meccanismo dei servizi. Il seguente codice funziona:

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

Ho aggiunto l'intero programma di test Java di seguito.

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); 
    } 
} 
+0

È possibile estrarre il file direttamente sulla riga di comando in un passaggio con "decomprimi -p /path/to/lib/jarfile.jar META-INF/services/javax.xml.xpath.XPathFactory" –

risposta

11

Michael Kay answered the question su un forum SourceForge. Ha risposto:

Il formato del file è stato scelto per aggirare un errore JDK5.

E anche che:

In realtà, non mi consiglia di utilizzare il meccanismo di ricerca JAXP comunque. È molto lento e fornisce un motore XPath che non funzionerà necessariamente con la tua applicazione. Non hai modo di sapere se hai ottenuto un'implementazione XPath 1.0 o 2.0 e l'API è definita in modo così debole che ci sono poche possibilità che la tua applicazione funzioni con un particolare provider, a meno che tu non l'abbia prima testata con quel fornitore. Quindi, anche senza questo bug, vorrei evitare di farlo.

Penso che risponda alla domanda anche se non fornisce una soluzione esplicita per il problema. Così abbiamo potuto scegliere l'applicazione da parte di scrittura:

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

in Saxon 9.5 e versioni successive questo problema è stato risolto. Se qualcuno si ritrova a richiedere che questo funzioni con la vecchia versione e non abbia accesso al codice che chiama 'newInstance', risolvi il problema eliminando la directory' services' dal suddetto file JAR. Questo sta seguendo una [nota] (https://saxonica.plan.io/issues/1944#note-3) sul thread del bug. – Stav

+0

E in Saxon 9.6 la risoluzione JAXP per XPath è stata abbandonata - vedere https://saxonica.plan.io/issues/1944#note-5 –

1

So che questo è un thread vecchio, ma this post of mine potrebbe far luce sulla questione. Trova XPathFactory usando un parametro -D che non ho mai visto documentato.

+0

Grazie per il follow-up comunque. – lkuty