English 中文(简体)
How do I find out which JAXP implementation is in use and where it was loaded from?
原标题:

I would like to provide diagnostic information about what JAXP implementation is in use, and which JAR file it was loaded from.

One way to achieve this is to create in instance of, for example, a DocumentBuilderFactory, and then inspect the properties of that class:

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

Is there a better way to achieve this, perhaps without having to create a DocumentBuilderFactory?

最佳回答

It is quite difficult to predict what concrete JAXP factory implementation will be loaded without actually creating an instance because the process for selecting an implementation.

From the Official JAXP FAQ (Question 14):

When an application wants to create a new JAXP DocumentBuilderFactory instance, it calls the staic method DocumentBuilderFactory.newInstance(). This causes a search for the name of a concrete subclass of DocumentBuilderFactory using the following order:

  1. The value of a system property like javax.xml.parsers.DocumentBuilderFactory if it exists and is accessible.
  2. The contents of the file $JAVA_HOME/jre/lib/jaxp.properties if it exists.
  3. The Jar Service Provider discovery mechanism specified in the Jar File Specification. A jar file can have a resource (i.e. an embedded file) such as META-INF/services/javax.xml.parsers.DocumentBuilderFactory containing the name of the concrete class to instantiate.
  4. The fallback platform default implementation.

Adding to this complexity, each individual JAXP factory can have an independent implementation specified. It is common to use one parser implementation and another XSLT implementation, but the granularity of the selection mechanism above allows you to mix and match to an even greater degree.

The following code will output information about the four main JAXP factories:

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

The following sample output illustrates a mix-and-match of three different JAXP implementations (Built-in Xerces and external JARs for Xerces 2.8 and Xalan) working together:

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
问题回答

Just add

-Djaxp.debug=1

to JAVA_OPTS and you will see such information.

For more detail: https://docs.oracle.com/javase/7/docs/api/javax/xml/parsers/DocumentBuilderFactory.html

it is easy, you just set

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

the track will tell you whick impl,and whick way jaxp use.

There is another location that is searched before the "fallback platform default implementation" and that is the java.endorsed.dirs directory as documented in the Java Endorsed Standards Override Mechanism

The Endorsed Standards Override Mechanism provides a means whereby later versions of classes and interfaces that implement Endorsed Standards or Standalone Technologies may be incorporated into the Java Platform.

It depends, but generally no.

DocumentBuilderFactory.newInstance() will either return the implementation of DocumentBuilderFactory which is configured in the system property "javax.xml.parsers.DocumentBuilderFactory" or the JRE s default factory if the system property is not set. The default factory is most likely hard coded in the implementation of the newInstance method and not otherwise accessible.

If the system property is set, you could at least use the getResource method on the relevant class loader to get the URL, from which the class loader would load the corresponding class file. If it is from a jar file, you should be able to extract the file name (or source URL) from the jar: URL. Detailed package information should also be available if you manaully read the meta data files from the classpath.

If the system property is not set, I m pretty sure that you have no way to get the information you are looking for without actually creating a new factory as you re already doing.





相关问题
Spring Properties File

Hi have this j2ee web application developed using spring framework. I have a problem with rendering mnessages in nihongo characters from the properties file. I tried converting the file to ascii using ...

Logging a global ID in multiple components

I have a system which contains multiple applications connected together using JMS and Spring Integration. Messages get sent along a chain of applications. [App A] -> [App B] -> [App C] We set a ...

Java Library Size

If I m given two Java Libraries in Jar format, 1 having no bells and whistles, and the other having lots of them that will mostly go unused.... my question is: How will the larger, mostly unused ...

How to get the Array Class for a given Class in Java?

I have a Class variable that holds a certain type and I need to get a variable that holds the corresponding array class. The best I could come up with is this: Class arrayOfFooClass = java.lang....

SQLite , Derby vs file system

I m working on a Java desktop application that reads and writes from/to different files. I think a better solution would be to replace the file system by a SQLite database. How hard is it to migrate ...

热门标签