JDK-4785848 : JNLPClassLoader does not encode URL paths (but must) - 4754763 revisit
  • Type: Bug
  • Component: deploy
  • Sub-Component: webstart
  • Affected Version: 1.2.0
  • Priority: P4
  • Status: Closed
  • Resolution: Duplicate
  • OS: windows_2000
  • CPU: x86
  • Submitted: 2002-11-27
  • Updated: 2002-12-03
  • Resolved: 2002-12-03
Related Reports
Duplicate :  
Description

Name: nt126004			Date: 11/27/2002


FULL PRODUCT VERSION :
java version "1.4.1_01"
Java(TM) 2 Runtime Environment, Standard Edition (build 1.4.1_01-b01)
Java HotSpot(TM) Client VM (build 1.4.1_01-b01, mixed mode)

FULL OPERATING SYSTEM VERSION :

Microsoft Windows 2000 [Version 5.00.2195]

A DESCRIPTION OF THE PROBLEM :
This is a duplicate of what I entered in bug 4754763 which
has been marked as "closed, fixed".  Sorry for the
duplicate but I think this is a serious problem that needs
to be revisited so I'm opening a new bug on it.

I have a JWS application that uses some XML files which
have DOCTYPE and ENTITY declarations as follows:

<!DOCTYPE descriptor-repository
SYSTEM "../dao/repository.dtd" [
  <!ENTITY alexpriced SYSTEM "../dao/repository-
alexpriced.xml">
  <!ENTITY internal SYSTEM "../dao/repository-
internal.xml">
]>

Note the relative URL's defining the dtd and included xml
files.  This poses a problem for JWS in a roundabout way as
follows. In my example, I invoke a high level class like
this:

   PBKey repositoryPBKey = new PBKey
("resources/ojb/repository.xml");
   broker = PersistenceBrokerFactory.createPersistenceBroker
(repositoryPBKey);

Deep in the bowels of OJB (a third party database mapping
framework from Jakarta), it needs to obtain a URL to this
XML file and does so like this:

URL url = Thread.currentThread().getContextClassLoader
().getResource(repositoryFileName);

In the case of a JWS application, the class loader is an
instance of JNLPClassLoader.  In my case, this is running
on a Windows machine and the URL returned by the above
  statement is this:

jar:file:/C:/Documents and
Settings/g1urct/.javaws/cache/http/Ddfin01/P7777/DMLittleAle
x/DMcommon/DMdist/RMLittleAlex-
common.jar!/resources/ojb/repository.xml

The prefix up to ".javaws" is the JWS cache directory on
the local machine.  Note the spaces imbedded in the URL --
in "Documents and Settings" -- which are part of the
standard Windows path.  This is the problem.

This URL is passed to the XML parser -- by default the jaxp
parser, but I've also tried Xerces.  While the XML parser
is interpreting the file, it needs to read the DTD file.
It tries to create an aboslute URL for the DTD file by
adding the relative URL it found to its base URL.  This
results in code approximately like this:

   URL url = new URL("jar:file:/C:/Documents and
Settings/g1urct/.javaws/cache/http/Ddfin01/P7777/DMLittleAle
x/DMcommon/DMdist/RMLittleAlex-
common.jar!/resources/ojb/../dao/repository.dtd");

This causes a MalformedURLException deep in the bowels of
Xerces which leads to the parser being unable to obtain the
DTD.

The root of the bug is that the JNLPClassLoader does not
encode the URL's it creates when loading files.  By
contrast. the sun.misc.Launcher$AppClassLoader does perform
this encoding, which means that this bug doesn't appear in
standalone Java applications.  The implications I believe
can be very widespread since basically any resource
obtained through JWS's class loader can have an invalid URL
if the base directory path contains characters not allowed
in URL's such as a space.

I gave this roundabout explanation (sorry for taking up a
little extra of your time) to demonstrate that an
application developer does not have a hook to work around
the problem.  For obvious security reasons, it isn't
possible to subclass the JNLPClassLoader, substitute a
different class path or base dir, etc.  Resources are often
obtained from the class loader deep in the bowels of
toolkit code (in my example OJB and Xerces but it could be
anywhere).  This really needs to be fixed in JWS.

STEPS TO FOLLOW TO REPRODUCE THE PROBLEM :
1. Set your JWS cache directory in Windows to a directory
that includes characters that are not valid in URL's, such
as a space.  Something like "C:\Documents and
Settings\myhome\.javaws\cache" will do it.

2. In the code for your JWS application, get the URL for a
resource from a jar file using a relative path, like this:

URL url = Thread.currentThread().getContextClassLoader
().getResource("resources/ojb/repository.xml");

3. Try to create a new URL from that URL like this:

  URL url2 = new URL(url.toExternalForm());

This will result in a MalformedURLException because there
will be unencoded spaced imbedded in "url".  This
demonstrates the general problem.

EXPECTED VERSUS ACTUAL BEHAVIOR :
I would expect JNLPClassLoader to encode the URL's it
returns for getResource() and similar methods, similar to
the way that sun.misc.Launcher$AppClassLoader does.

It does not currently encode the URL's.

ERROR MESSAGES/STACK TRACES THAT OCCUR :
The lowest level error is the MalformedURLException, but this often leads to
more serious problems deep within toolkit code when it can't get a valid URL
for a resource that it needs.

REPRODUCIBILITY :
This bug can be reproduced always.

---------- BEGIN SOURCE ----------
Include this code in a JWS application with a jar file that contains a file
at "resources/ojb/repository.xml".

String path = "resources/ojb/repository.xml";
URL url = Thread.currentThread().getContextClassLoader().getResource(path);
URL url2 = new URL(url.toExternalForm());

---------- END SOURCE ----------
(Review ID: 166757) 
======================================================================

Comments
EVALUATION this is a dupe of 4778185, which is now fixed in mantis. ###@###.### 2002-12-03
03-12-2002