This Bugzilla instance is a read-only archive of historic NetBeans bug reports. To report a bug in NetBeans please follow the project's instructions for reporting issues.

Bug 36162 - Can not open a project
Summary: Can not open a project
Status: CLOSED WONTFIX
Alias: None
Product: projects
Classification: Unclassified
Component: Generic Infrastructure (show other bugs)
Version: 3.x
Hardware: PC Windows ME/2000
: P2 blocker (vote)
Assignee: Vitezslav Stejskal
URL:
Keywords: API, SPACE_IN_PATH
Depends on:
Blocks:
 
Reported: 2003-09-17 14:18 UTC by Petr Jiricka
Modified: 2003-12-11 14:25 UTC (History)
2 users (show)

See Also:
Issue Type: DEFECT
Exception Reporter:


Attachments
Exceptions which cause the failure (1.49 KB, text/plain)
2003-09-17 14:22 UTC, Petr Jiricka
Details
A quick patch which fixes the spaces, but more may need to be done (1.06 KB, patch)
2003-09-17 14:23 UTC, Petr Jiricka
Details | Diff

Note You need to log in before you can comment on or make changes to this bug.
Description Petr Jiricka 2003-09-17 14:18:22 UTC
In Projects build 20030915, I am unable to open an
existing project on windows. The exception in the
attachment is thrown.

The cause of the problem is in
org.openide.util.Utilities, method toFile(URL), as
this method is unable to deal with files
containing spaces. E.g. the following URL:

file:/C:/Documents and Settings/pj97932/Projects/

is not translated to a File correctly. The patch
should probably be something like URL-encoding
parts of the URL string, however I am not sure
what exactly needs to be done. Could we come
across similar problems with e.g. multibyte file
names?

So the immediate patch could be replacing spaces
by + (as URLEncoder would do), and we can think of
a solution for the more general case.
Comment 1 Petr Jiricka 2003-09-17 14:22:19 UTC
Created attachment 11650 [details]
Exceptions which cause the failure
Comment 2 Petr Jiricka 2003-09-17 14:23:16 UTC
Created attachment 11651 [details]
A quick patch which fixes the spaces, but more may need to be done
Comment 3 Petr Jiricka 2003-09-22 15:47:20 UTC
Now I noticed that method Utilities.toFile(URL) (used from URLMapper)
is deprecated, so it probably should be avoided altogether.

But how? The one way I can think of is to deprecate URLMapper and
introduce URIMapper. java.net.URI is nicer than java.net.URL - it has
e.g. the toASCIIString() method, which can be useful.
Comment 4 rmatous 2003-09-26 09:06:00 UTC
Two static method methods in org.openide.util.Utilities were
deprecated [snip]:
     * @deprecated Use {@link URI#URI(String)} and {@link
File#File(URI)} instead under JDK 1.4.
     *             (There was no proper equivalent under JDK 1.3.)
 public static File toFile(URL u)

     * @deprecated Use {@link File#toURI} and {@link URI#toURL}
instead under JDK 1.4.
     *             ({@link File#toURL} is buggy in JDK 1.3 and the
bugs are not fixed in JDK 1.4.)
 public static URL toURL(File f)

I don't think, that these two methods should be deprecated. Problems
will appear for space and hash chars in path names  .

According to above description developers will write anything like that:
File f = new File (new URI (myUrl.toExternalForm () ));

1/  Spaces in path:
URI constructor in this case fires URISyntaxException for following
URL : myUrll = new URL ("file:/C:/Documents and
Settings/admin/Windows/"). This can be avoided by calling new URI
(myUrl.getProtocol (), myUrl.getFile (), null).

2/ '#' as fragment in path (new URL ("file:/C:/Documents and
Settings/admin/my#Folder/data/"))
myUrl.toExternalForm () doesn't escape # here. then new URI (myUrl)
accept # as fragment and new File (new URI (myUrl)) then fires
IllegalArgumentException because there is not expected fragment at all. 

So, there must be some explicit decision if # is really fragment or is
part of path and must be somehow escaped e.g.:      
replaceAll ("#",URLEncoder.encode("#"));

I think this could be just responsibility of methods toFile and toURL.
Comment 5 Petr Jiricka 2003-09-26 16:08:49 UTC
Radek, thanks for your comments. I don't really know what should be
done, so I defer to Jesse. But in general, using deprecated API is
evil (especially since it causes bugs), and I see three potential
solutions:

1) Un-deprecating the deprecated method and fixing it. The fix must
also make sure that we correctly handle non-ASCII and multibyte
characters.

2) Replacing the call to the deprecated API with a non-deprecated
equivalent, however in this case I can't think of one.

3) Deprecating the class that calls deprecated API, and the
corresponding API class (i.e. URLMapper), and providing a replacement
(URIMapper ?) 

Jesse, what do you think?
Comment 6 Jesse Glick 2003-09-26 17:47:59 UTC
I'm afraid I don't understand what the problem is here - other than a
bug in some projects code that I don't know about.

file:/C:/Documents and Settings/pj97932/Projects/

is an invalid URL, which you should not pass to toFile. (The Utilities
methods now just delegate to the new JDK 1.4 methods, which should be
used directly.) If you passed

file:/C:/Documents%20and%20Settings/pj97932/Projects/

then probably it would work - I don't have access to a Windows machine
to test.

toURL should create URLs of the above form. If not, it is a JRE bug
which should be filed, and we don't deal with it further. In my
experience everything works smoothly in JRE 1.4 - spaces and hash
marks are escaped perfectly well.

Grepping prj40_prototype branch, I find:

              return new URL ("file:."); // NOI18N
          return new URL ("file:" + relName.toString()); // NOI18N
  -rw-rw-r--    1 jglick   jglick       6415 Jun 26 02:24
projects/ide/src/org/netbeans/modules/projects/ide/RelativeResolver.java

Which is crap. If to == from, the relative URL is ".". "file:." is
wrong, it is a bogus URL. In any case, a relative URL should have no
protocol. If you write "file:foo/bar", this means the same as new
File("foo/bar"), which is to say $nbhome/bin/foo/bar usually.

Not sure if that code is at fault, or something else. But I don't see
anything wrong in org.openide.filesystems, or in the impls of the
now-deprecated methods. Probably some other piece of code makes bad URLs.
Comment 7 Petr Jiricka 2003-09-26 21:38:39 UTC
Ok, I am starting to understand what's going on. JDK does not make
sure that URLs are properly encoded, so if you do 

new File("C:\\Documents and Settings\\pj97932\\Projects").toURL(),

this returns a URL that contains spaces. For this reason, I thought it
was ok to pass this URL to URLMapper.findFileObjects(...). I think it
should be clarified in the URLMapper javadoc that such URLs are not
acceptable.

Note that the JDK 1.4 Javadoc for File.toURL() contains the following
disclaimer:

"Usage note: This method does not automatically escape characters that
are illegal in URLs. It is recommended that new code convert an
abstract pathname into a URL by first converting it into a URI, via
the toURI method, and then converting the URI into a URL via the
URI.toURL method."

Regading the Projects code - you are right, this is flawed. On the
other hand, manipulating relative URLs (which is needed in Projects)
is not easy with JDK, the URI class is much more suitable for this. I
believe if Projects stored URIs in the project file instead of URLs,
the implementation could be simplified considerably.

Adding Vita to cc:, so he can comment.


Comment 8 Petr Jiricka 2003-09-26 21:45:29 UTC
See also enhancement request 36188, which is somewhat related.
Comment 9 Jesse Glick 2003-09-27 01:13:35 UTC
It is very simple - do not use File.toURL, ever. It generates unusable
results. Consider it deprecated. Always use File.toURI().toURL() (or
just File.toURI()) instead. I would have liked the JRE team to
@deprecate the method, or (better) fix it to return toURI().toURL(),
but for some reason they did not do either.

Some likely culprits:

          return f.toURL();
  -rw-rw-r--    1 jglick   jglick       6208 Jul 17 12:24
projects/compilation/test/unit/src/org/netbeans/api/compilation/BuildTargetOutputFolderTest.java
                              url : resolver.toURL(fos[0]);
  -rw-rw-r--    1 jglick   jglick       9708 Jul  9 07:30
projects/ide/src/org/netbeans/modules/projects/ide/ProjectGroupDataObject.java
                  u = f.toURL();
  -rw-rw-r--    1 jglick   jglick       9282 Apr 21 05:48
projects/ide/src/org/netbeans/modules/projects/ide/ui/BaseOutputFolder.java
                  setValue(new File(text).toURL());
                      setValue(f.toURL());
  -rw-rw-r--    1 jglick   jglick      23969 Aug  6 10:36
projects/ide/src/org/netbeans/modules/projects/ide/ui/looks/OutputLook.java
              URL rememberedProjectHome = new File(home).toURL();
  -rw-rw-r--    1 jglick   jglick      26710 Sep  3 15:47
projects/ide/src/org/netbeans/modules/projects/ide/wizards/ProjectLocationPanel.java

Assuming this is a projects problem.
Comment 10 Vitezslav Stejskal 2003-10-01 11:22:42 UTC
OK, there are two problems mentioned here: #1 - project's resolvers
create bogus URLs when trying to relativize them. This can be easily
fixed I think. #2 - we are using File.toURL() or generaly we aren't
using correct methods for following conversions String <-> URL <->
File/FileObject.

I admit I am confused a bit. Is there any guideline on what is the
right way to do these conversions in regards of JDK bugs, etc. Or
could you approve/disapprove that following is correct:

String -> URI: new URI(string)
URI -> String: URI.toASCIIString()
File -> URI: File.toURI()
URI -> File: new File(uri)
URL -> FileObject: URLMapper.findFileObjects(url)
FileObject -> URL: FileObject.getURL()
URI -> URL: URI.toURL()
URL -> URI: new URI(url.toExternalForm())

Any other conversions possible and safe?

I remember we already had some troubles with persisting URLs and I
would generaly prefere to use URIs, but all netbeans APIs are working
with URLs and that's why I thought URLs are ok. It's unclear to me
whether if I get URL from netbeans API (e.g. FileObject, URLMapper,
etc) it's safe to persist it directly or if I have to convert it to
URI and persist this URI instead?
Comment 11 Jesse Glick 2003-10-01 15:01:33 UTC
OK, I'll try to go through the listed conversions as best I know:

new URI(String) - fine
URI.toASCIIString() - OK, but toExternalForm = toString is fine
File.toURI() - fine
new File(URI) - fine
URLMapper.findFileObjects(URL) - fine
FileObject.getURL() - works, but URLMapper.findURL(FileObject,int) is
probably more useful
URI.toURL() - fine
new URI(URL.toExternalForm()) - fine

You forgot:

File.toURI().toURL()
new File(new URI(URL.toExternalForm())

What is *not* safe:

File.toURL() - does not work correctly
new File(URL.getPath().replace('/', File.separatorChar)) - does not work

Should be safe to persist URLs directly.
Comment 12 Petr Jiricka 2003-10-02 21:30:29 UTC
Thanks, I think this explains what needs to be fixed and how. However,
shouldn't we still think of gradually moving the IDE to use URI
instead of URL? I.e. create a URIMapper class etc. The one notable
advantage of URIs is that they have a better support for relative
locations and relativizing a location against another location. Also,
if FileSystems API intends to be an abstraction over java.io.File, it
should have the same capabilities as java.io.File. Lastly, the support
for File <-> URI conversion is better than the support for File <->
URL conversion, although that's a very minor advantage.
Comment 13 Jesse Glick 2003-10-03 00:09:49 UTC
I think it would be fine to support URIs more consistently, though I
disagree that they are a *replacement* for URLs - they serve somewhat
different purposes, as outlined in the Javadoc for URI. File RFEs as
needed.

File <-> URL conversion is perfectly safe so long as you go through
URI and do not attempt to use the broken File.toURL call.
Comment 14 Vitezslav Stejskal 2003-11-24 14:35:04 UTC
As described in
http://www.netbeans.org/servlets/ReadMsg?msgId=619519&listName=nbdiscuss the
current work on projects prototype has been stopped.
Comment 15 Jan Becicka 2003-11-25 13:47:02 UTC
Marking issue as VERIFIED --->
Comment 16 Jan Becicka 2003-11-25 13:51:33 UTC
---> CLOSED