interfaz grafica ejemplos componentes clase java version diagnostics jaxp

java - grafica - jframe



¿Cómo puedo saber qué implementación de JAXP está en uso y de dónde se cargó? (5)

Me gustaría proporcionar información de diagnóstico sobre qué implementación de JAXP está en uso y desde qué archivo JAR se cargó

Una forma de lograr esto es crear, por ejemplo, un DocumentBuilderFactory y luego inspeccionar las propiedades de esa clase:

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()); }

¿Hay una mejor manera de lograr esto, tal vez sin tener que crear una DocumentBuilderFactory ?


Depende, pero en general no.

DocumentBuilderFactory.newInstance() devolverá la implementación de DocumentBuilderFactory que está configurada en la propiedad del sistema "javax.xml.parsers.DocumentBuilderFactory" o la fábrica predeterminada de JRE si la propiedad del sistema no está establecida. Lo más probable es que la fábrica predeterminada esté codificada en hardware en la implementación del método newInstance y no esté accesible de otra manera.

Si se establece la propiedad del sistema, al menos podría usar el método getResource en el cargador de clases correspondiente para obtener la URL, desde la cual el cargador de clases cargaría el archivo de clases correspondiente. Si proviene de un archivo jar, debería poder extraer el nombre del archivo (o URL de origen) del jar: URL. La información detallada del paquete también debería estar disponible si lee manualmente los metadatos de la ruta de clase.

Si la propiedad del sistema no está establecida, estoy bastante seguro de que no tiene forma de obtener la información que busca sin crear una nueva fábrica como ya lo está haciendo.


Es bastante difícil predecir qué implementación concreta de JAXP Factory se cargará sin crear realmente una instancia debido al proceso para seleccionar una implementación.

De las preguntas frecuentes oficiales de JAXP (pregunta 14):

Cuando una aplicación desea crear una nueva instancia de JAXP DocumentBuilderFactory , llama al método básico DocumentBuilderFactory.newInstance() . Esto provoca una búsqueda del nombre de una subclase concreta de DocumentBuilderFactory usando el siguiente orden:

  1. El valor de una propiedad del sistema como javax.xml.parsers.DocumentBuilderFactory si existe y es accesible.
  2. El contenido del archivo $JAVA_HOME/jre/lib/jaxp.properties si existe.
  3. El mecanismo de descubrimiento del proveedor de servicios Jar especificado en la especificación del archivo Jar. Un archivo jar puede tener un recurso (es decir, un archivo incrustado) como META-INF/services/javax.xml.parsers.DocumentBuilderFactory contiene el nombre de la clase concreta para crear una instancia.
  4. La implementación predeterminada de la plataforma alternativa.

Además de esta complejidad, cada fábrica JAXP individual puede tener una implementación independiente especificada. Es común usar una implementación de analizador y otra implementación de XSLT, pero la granularidad del mecanismo de selección anterior le permite mezclar y combinar en un grado aún mayor.

El siguiente código dará información sobre las cuatro fábricas principales de 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()); }

La siguiente salida de muestra ilustra una combinación de tres implementaciones JAXP diferentes (Xerces incorporados y JAR externos para Xerces 2.8 y Xalan) trabajando juntos:

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


Es fácil, solo tienes que configurar

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

La pista te dirá qué puedes usar y cómo usar jaxp.


Hay otra ubicación que se busca antes de la "implementación predeterminada de la plataforma alternativa" y es el directorio java.endorsed.dirs tal como se documenta en el Mecanismo de anulación de estándares endosados ​​de Java

El Mecanismo de anulación de estándares avalados proporciona un medio por el cual las versiones posteriores de clases e interfaces que implementan estándares respaldados o tecnologías independientes pueden incorporarse en la plataforma Java.