This is the mail archive of the
java@gcc.gnu.org
mailing list for the Java project.
Regressions from gcj 4.2 to 4.3 involving XML
- From: Andrew Haley <aph at redhat dot com>
- To: Gary Benson <gbenson at redhat dot com>
- Cc: java at gcc dot gnu dot org, classpath at gnu dot org
- Date: Fri, 9 Mar 2007 17:23:13 +0000
- Subject: Regressions from gcj 4.2 to 4.3 involving XML
- References: <20070309101505.GA4140@redhat.com>
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.