Regressions from gcj 4.2 to 4.3 involving XML

Andrew Haley aph@redhat.com
Fri Mar 9 17:23:00 GMT 2007


I've been mystified why Xerces suddenly stopped working with this
release of gcj. I think I've found the root cause that triggered
this.
In sumary: in gcj 4.2 and previous releases, the handling of "core"
URLs was broken. As a result of this, we never found
"/META-INF/services/javax.xml.parsers.DocumentBuilderFactory" in
libgcj, so we used Xerces' DocumentBuilderFactory instead. This
worked perfectly.
Now, the handling of "core" URLs is fixed, so we do find
"/META-INF/services/javax.xml.parsers.DocumentBuilderFactory" in
libgcj, which is incompatible with Xerces.
The reason Xerces worked for us in the past is this bug. We have
*never* used gnu.xml.dom.DomDocumentBuilderFactory in gcj before now.
The bug:
In gcj 4.2, getFactoryClassName() returns
"org.apache.xerces.jaxp.DocumentBuilderFactoryImpl" when invoked with
xerces in the classpath, but gcj 4.3 returns
"gnu.xml.dom.DomDocumentBuilderFactory".
This happens because in gcj 4.3,
"/META-INF/services/javax.xml.parsers.DocumentBuilderFactory" is found
in libgcj.so as a "core" resource, whereas in gcj 4.2
"file:/usr/share/java/xerces-j2.jar!/META-INF/services/javax.xml.parsers.DocumentBuilderFactory" is found as a "jar" resource.
So, why does gcj 4.2 not find
"/META-INF/services/javax.xml.parsers.DocumentBuilderFactory" as a
"core" resource?
Because the string passed to _Jv_FindCore is
"//META-INF/services/javax.xml.parsers.DocumentBuilderFactory"
Note the two slashes: "//"
Why does this happen in gcj 4.2? It's because we do this in
RemoteURLLoader.getResource:
 /** get resource with the name "name" in the core url */
 Resource getResource(String name)
 {
 Core core = Core.find (dir + name);
 if (core != null)
 return new CoreResource(this, name, core);
 return null;
 }
 }
where dir is "/" and name is
"/META-INF/services/javax.xml.parsers.DocumentBuilderFactory"
We don't do this in gcj 4.3: instead we do
 /**
 * Get a remote resource.
 * Returns null if no such resource exists.
 */
 public Resource getResource(String name)
 {
 try
 {
 URL url = new URL(baseURL, name, cache.get(factory, protocol));
 URLConnection connection = url.openConnection();
 // Open the connection and check the stream
 // just to be sure it exists.
 int length = connection.getContentLength();
 InputStream stream = connection.getInputStream();
 // We can do some extra checking if it is a http request
 if (connection instanceof HttpURLConnection)
 {
 int response =
 ((HttpURLConnection) connection).getResponseCode();
 if (response / 100 != 2)
 return null;
 }
 if (stream != null)
 return new RemoteResource(this, name, url, stream, length);
 else
 return null;
 }
 catch (IOException ioe)
 {
 return null;
 }
 }
which eventually finds its way down to
gnu.java.net.protocol.core.Connection.connect():
 // If not connected, then file needs to be opened.
 core = Core.create (url.getFile());
so the error of adding another "/" to the start of the filename never
occurs.
Andrew.


More information about the Java mailing list

AltStyle によって変換されたページ (->オリジナル) /