Bug 218947 - [api] FileServiceSubSystem#getRemoteFileObject returns null for the root folder on WinCE
Summary: [api] FileServiceSubSystem#getRemoteFileObject returns null for the root fold...
Status: RESOLVED DUPLICATE of bug 221556
Alias: None
Product: Target Management
Classification: Tools
Component: RSE (show other bugs)
Version: unspecified   Edit
Hardware: PC Windows 2000
: P2 enhancement with 1 vote (vote)
Target Milestone: 3.0 M6   Edit
Assignee: David McKnight CLA
QA Contact: Martin Oberhuber CLA
URL:
Whiteboard:
Keywords: api
Depends on: 162950 219098
Blocks:
  Show dependency tree
 
Reported: 2008-02-14 09:32 EST by Radoslav Gerganov CLA
Modified: 2008-04-02 13:58 EDT (History)
1 user (show)

See Also:


Attachments

Note You need to log in before you can comment on or make changes to this bug.
Description Radoslav Gerganov CLA 2008-02-14 09:32:22 EST
This problem is similar to bug #218491 but represents another issue.
There are special cases in getRemoteFileObject to determine if the requested path represents the root folder on the given filesystem:

public IRemoteFile getRemoteFileObject(String folderOrFileName) {
  ...
  if (fofName.equals("/")) {
    //special case for Linux
  }
  ...
  if (fofName.endsWith(":")) {
    //special case for Windows
  }
  ...
}

On WinCE the root folder is "\" and this method fails to construct IRemoteFile for it because there is no such "special case".
As a result all copy operations with destination folder \ fail with NPE. I am going to release my file subsystem for WinCE (bug #214887) soon, it is very easy to reproduce the bug with it.
Comment 1 Martin Oberhuber CLA 2008-02-14 10:17:42 EST
The knowledge whether some path is a root or not really should not be in the subsystem in this case, but in the Service.

I think, though, that you should be able to just subclass FileServiceSubSystem, override the getRemoteFileObject() method to do what you need, an instantiate the subclassed one in your custom SubSystemConfiguration.

It's a little bit more code but it should be possible (you'll need to subclass FileServiceSubSystemConfiguration as well in order to instantiate your custom subsystem).

Because I think there is a workaround I don't think that this is a major issue but rather an API Change enhancement request that I'd like to see by M6.

DaveM what do you think?
Comment 2 David McKnight CLA 2008-02-14 10:38:01 EST
(In reply to comment #1)
> The knowledge whether some path is a root or not really should not be in the
> subsystem in this case, but in the Service.
> I think, though, that you should be able to just subclass FileServiceSubSystem,
> override the getRemoteFileObject() method to do what you need, an instantiate
> the subclassed one in your custom SubSystemConfiguration.
> It's a little bit more code but it should be possible (you'll need to subclass
> FileServiceSubSystemConfiguration as well in order to instantiate your custom
> subsystem).
> Because I think there is a workaround I don't think that this is a major issue
> but rather an API Change enhancement request that I'd like to see by M6.
> DaveM what do you think?


I agree that for now you can override getRemoteFileObject().  In M6 we can add an API to the service layer.
Comment 3 Radoslav Gerganov CLA 2008-02-14 10:55:36 EST
Thanks guys, I will go with the override approach for now. I do have a custom subsystem already, so it will be relatively small change.
Comment 4 Radoslav Gerganov CLA 2008-02-15 04:00:16 EST
Just want to let you know that I've found one more place where this API is needed - RemoteFile#getParentPathFor. This method is causing infite loop in my case.
Comment 5 Martin Oberhuber CLA 2008-02-15 04:20:04 EST
Ok - in the case of RemoteFile, that's an abstract class so it's intended to be overridden by extenders anyways. I see two options here:

a) make RemoteFile#getParentPathFor() protected to allow extenders to override
   it (currently it is private), or

b) move the code for path handling into the Service, adding new API for 
   things like

   boolean IFileService#isRoot(String aPath);
   String IFileService#getParentPath(String aPath);
   String IFileService#concat(String aFolder, String aName);

Rather than having this in the Service, we could also try to encapsulate absolute pathes in an IRemotePath object rather than using String. In that case, we'd want something like this:

   interface IRemotePathFactory {
      IRemotePath getRemotePath(String absPath);
   }

where IRemotePath would provide similar methods as Eclipse IPath, and we'd have

   class MyFileService implements IFileService, IRemotePathFactory {
      ...
   }

One important difference between IRemotePath and IHostFile would be, that all operations on IRemotePath can be performed without being connected to the remote system, and they cannot fail -- because they don't rely on being connected [[NB: This assumption could perhaps be hard to maintain for services like SSH that can connect to EITHER UNIX or Windows so they don't know much about the kind of remote pathes]]

The change could even be backward compatible, because for "old-style" IFileService implementations which do not implement the new interface we could just fall back to the current implementation. I'd think, though, that if we go with the IRemotePath interface we'd want to replace all instances of "String" for path names by IRemotePath instances -- something like this has been requested in bug 162950 already.

Marking this as related to bug 162950 for now. If we want such a big API change we better do it soon, so I'm putting in Priority P2.

On a completely different note -- Radoslav, have you thought about normalizing your pathes in the WinCEFileService already? Such that only the service would know about the native kind of pathes (like "\foo\bar.txt") but would always pass these pathes up in a normalized way (like "/foo/bar.txt")? Note that the current FTPService performs path normalization for VMS connections: e.g.
  Remote VMS       [PARENT.DIR]FILE.TXT;1
  --> normalized   /PARENT/DIR/FILE.TXT

Normalizing the pathes in the Service would certainly make it easier for the RSE Subsystems to deal with them. The little disadvantage is that a user performs copy&paste of a normalized path it cannot immediately be used in a tool you have outside RSE which does not know about normalization. What do you think?
Comment 6 Martin Oberhuber CLA 2008-02-15 04:32:55 EST
Thinking about this again, the IRemotePath approach seems to have a lot of advantages:

 * Path Normalization in the Service, allows caching of pathes or using
   IRemotePath objects as a key in other caches
 * Can always present remote pathes in their native forms in the UI rather
   than normalizing to a UNIX format -- better user experience
 * Improved code re-use

We might even want to introduce the IRemotePath interface for the generic subsystems. Pathes are not necessarily something that only exists for files: a Path is a serialized representation of a context. Even SWT TreeViewer has this concept:
  TreePath
  ILazyTreePathContentProvider

In RSE, the concept of an "absolutePath" representing a remote object is pretty deep at the core of our subsystems: See
  String IRemoteObjectIdentifier#getAbsolutePath(Object anOjbect);
The big disadvantage of Strings is that from just a String one cannot know how to find the parent object or child object - unless they are normalized to a standard format (e.g. always use "/" as separator, but how to escape "/" then).

Moving from String to IRemotePath everywhere seems like a really big change. We might want to think about a gradual approach, keeping String in some places for now but converting between String and IRemotePath where needed (using the IRemotePathFactory if provided).
Comment 7 Martin Oberhuber CLA 2008-02-15 04:36:37 EST
(In reply to comment #4)
> Just want to let you know that I've found one more place where this API is
> needed - RemoteFile#getParentPathFor. This method is causing infite loop in my
> case.

So - for the short term, you have two possible workarounds:

a) Normalize your pathes in the Service -- converting from \some\path to 
   /some/path in the Service already.

b) private RemoteFile#getParentPathFor() is currently only called from
   getEncoding() so you can override getEncoding() to ensure the bad method
   isn't called.

(a) seems the safer choice because if you keep passing "\a\b" kind of pathes into RSE you might find other similar bugs [which might be a good thing though].

Comment 8 Radoslav Gerganov CLA 2008-02-15 05:27:51 EST
> So - for the short term, you have two possible workarounds:
> 
> a) Normalize your pathes in the Service -- converting from \some\path to 
>    /some/path in the Service already.
> 
> b) private RemoteFile#getParentPathFor() is currently only called from
>    getEncoding() so you can override getEncoding() to ensure the bad method
>    isn't called.
> 

I prefer option b) for now, at least for the first version of my file subsystem. Currently I am able to perform almost all file operations from RSE using the native paths without problems except those I've reported.
For the long term I like your idea about IRemotePath and I believe it is a real solution to this kind of problems.
Comment 9 Radoslav Gerganov CLA 2008-02-15 05:45:46 EST
I just noticed that FileServiceSubSystem is final class :(
It seems that I have no choice but to use linux paths and normalize them in the FileService ...
Comment 10 Martin Oberhuber CLA 2008-02-15 07:41:00 EST
Hum, making a class final is a hard measure which I also don't quite understand in this case. Perhaps the original idea was that all customizations should be done via the Service alone, but this bug shows it isn't possible in practice.

DaveM -- I'd be in favor of relieving this limitation and removing the "final" clause unless you have any objections.

For now, it looks like you fortunately have the other option of normalizing paths. How much effort do you think will it be adding the normalization? I'm wondering whether we should quickly remove the "final" limitation even for M5 in order to avoid unnecessary work on your end.
Comment 11 Radoslav Gerganov CLA 2008-02-15 07:48:44 EST
I am afraid that users will not be able to use native paths for creating file filters because in this case getRemoteFileObject is called directly without using the FileService.
Comment 12 David McKnight CLA 2008-02-15 09:09:38 EST
(In reply to comment #10)
> Hum, making a class final is a hard measure which I also don't quite understand
> in this case. Perhaps the original idea was that all customizations should be
> done via the Service alone, but this bug shows it isn't possible in practice.
> DaveM -- I'd be in favor of relieving this limitation and removing the "final"
> clause unless you have any objections.
> For now, it looks like you fortunately have the other option of normalizing
> paths. How much effort do you think will it be adding the normalization? I'm
> wondering whether we should quickly remove the "final" limitation even for M5
> in order to avoid unnecessary work on your end.

I'm okay removing the final clause for now.  We originally put it there because we thought all customizations should occur in the service layer.  Apparently, it's not so easy to handle this particular case.     
Comment 13 Martin Oberhuber CLA 2008-02-15 09:50:40 EST
That's correct. When you decide to use normalized paths, users need to use normalized paths in all places in RSE - including the filters they set up.

However we decide to finally fix this, I think it's right to remove the "final" clause for now. I'm tracking this separately through bug 219098 in order to document that the API change is complete for M5.
Comment 14 Lothar Werzinger CLA 2008-03-05 13:34:15 EST
I am in favor of an API change to use the IRemotePath approach.
IMHO you need at least getting this new API in while still offering the String based API (to be deprecated /removed later).

In the long run I think that the diversity of RSE will make the String based API always be brittle and cumbersome. As we can never anticipate every usecase bugs are unavoidable. The VMS/WINCE issues are a good example. The IRemotePath (IHostPath for local?) approach clearly leads to a better API and as Martin has mentioned even can improve implementations by supplying additional information.

Comment 15 David McKnight CLA 2008-03-05 13:37:45 EST
For IRemotePath (or IHostPath), I think we can continue the discussion in Bug 221556.
Comment 16 David McKnight CLA 2008-04-02 13:58:16 EDT
I'm closing this defect.  Discussions for the remote path idea should continue with bug 221556.

*** This bug has been marked as a duplicate of bug 221556 ***