Accept either path seperator within AssetManager; either "/" or local seperator

Current implementation
As is documented the assetmanager takes only the path seperator “/” irrespective of the system.

While this is obviously well documented it was not what I expected, in order to maintain cross system support I have gotten into the habit of writing file paths as following:

[java]
public static final String PATHSEPERATOR=System.getProperty(“file.separator”);
location=directory + PATHSEPERATOR + “fileName.png”;
[/java]

Obviously this works fine on any system where the local path seperator is “/” but on windows it breaks the assetmanager because on windows the path seperator is “”. The result is a somewhat confusing exception:

[java]
com.jme3.asset.AssetNotFoundException: assets\Textures\PlayerTooling\emptySlot.png (Flipped) (Mipmapped)
[/java]

When I first started out this exception confused me no end since the file mentioned clearly exists.

So could I request either:

Could the assetmanager be altered to accept either the standard “/” file seperator or the local file seperator. This could be achieved by including the following reprocessing function within it

[java]public static final String LOCAL_PATH_SEPERATOR=System.getProperty(“file.separator”);
public static String reprocessFileLocationForAssetLoader(String in){

        return in.replace(LOCAL_PATH_SEPERATOR , "/");

}
[/java]

Or:

Could the assetmanager throw a more understandable exception when an asset string contains the local path sperator instead of “/”

Note: on every platform, in Java / will always work. \ only works on Windows. Using file separate is really only necessary when you are interacting with paths that might be platform specific (things passed from the environment, matching with canonical file paths, etc.) Otherwise, you can just always use /

…but at any rate, the asset manager always works with / just like class resources. We can’t accept \ without lots of nasty code to search and replace the \ with / so that we can properly access 99.9% of assets.

Assets are also case sensitive. Do you think we should add a bunch of code to guess at how many ways the asset name might be wrong that is specific to how assets are implemented? Or do you think we can just leave this as a (usually) brief lesson that people can learn once and not worry about it again.

@pspeed I do get what you are saying. I’d be happy with a more specific exception; to make this a quick lesson rather than a long one. (after the assetmanager throws an exception check for .contains(LOCAL_PATH_SEPERATOR) then if so append a “may be caused by use of incorrect path seperator, use /” to the exception

When I first recieved the exception I did a letter by letter comparison with the path given by windows and every letter was correct which only confused me further that it claimed it didn’t exist. (Case errors would show up in a letter by letter comparison)

@richtea said: @pspeed I do get what you are saying. I'd be happy with a more specific exception; to make this a quick lesson rather than a long one. (after the assetmanager throws an exception check for .contains(LOCAL_PATH_SEPERATOR) then if so append a "may be caused by use of incorrect path seperator, use /" to the exception

When I first recieved the exception I did a letter by letter comparison with the path given by windows and every letter was correct which only confused me further that it claimed it didn’t exist. (Case errors would show up in a letter by letter comparison)

LOCAL_PATH_SEPARATOR is not good enough because then if you really did get the name wrong then it would tell you that the slashes were wrong on platforms that use /. So it would always have to check for .… but the issue is that I guess \ is potentially a valid character in a non-WinDOS path.

So the code would have to check that that local path separator was a \ and then check to see if the path had that .… do you see that this starts to get convoluted for an error that only a few people hit and most learn the lesson once and don’t do it again?

By default on Windows, the file extensions are hidden… which is why I suggested that a similar line of thinking means we should flag when someone uses something like myFile.JPG instead of myFile.jpg or vice versa.

Personally, I don’t think these changes are necessary but maybe one of the other core devs will be more sympathetic.

No it shouldn’t accept this, asset paths are not windows folders. The fact that you have the “assets/” part in your error message is a hint that you misunderstood this too.

@pspeed Of course the real solution is for windows (or in fact dos before it) to use the same seperator as everyone else, but alas that may require the invention of a time machine.

@richtea said: @pspeed Of course the real solution is for windows (or in fact dos before it) to use the same seperator as everyone else, but alas that may require the invention of a time machine.

Windows uses normal slashes for java classpath entries too. Again, this isn’t folders.

@norman I do understand it now, I didn’t 2 years ago though and it cost me a day. Its all early barriers to entry. (the assets part is actually part of the legacy of the workaround between half my program working on local style paths and half on JMonkey style, my version of reprocessFileLocationForAssetLoader strips that out as well as changing the local path to /)

Windows uses normal slashes for java classpath entries too. Again, this isn’t folders.

And as of about 3 months ago I know that too, but I didn’t then and the problem wasn’t obvious. These days I like to work mostly with File objects which avoids the problem.

The change to the code wouldn’t be too significant. All I would change is within DesktopAssetManager#loadAsset(AssetKey<T> key) change

[java]throw new AssetNotFoundException(key.toString());[/java]

to

[java]
if (!System.getProperty(“file.separator”).equals("/") && key.getName().contains(System.getProperty(“file.separator”))){
throw new AssetNotFoundException(key.toString() + “. May be caused by use of incorrect path seperator, use the system independant ‘/’ path seperator”);
}else{
throw new AssetNotFoundException(key.toString());
}
[/java]

This has the following advantages

  • Only triggers when there is already a problem, will never interfere with correct asset paths - so if it works on one system it will work on all
  • Only offers a potential cause of the problem (although it would be pretty unlikely to be wrong - who uses the local path seperator on their development machine within file or foldernames?)

I’m out of this conversation at this point but I just thought I’d point out that you do this the hard way by accessing the system property directly.
http://docs.oracle.com/javase/6/docs/api/java/io/File.html#separatorChar

@richtea said: The change to the code wouldn't be too significant. All I would change is within DesktopAssetManager#loadAsset(AssetKey<T> key) change

[java]throw new AssetNotFoundException(key.toString());[/java]

to

[java]
if (!System.getProperty(“file.separator”).equals(“/”) && key.getName().contains(System.getProperty(“file.separator”))){
throw new AssetNotFoundException(key.toString() + “. May be caused by use of incorrect path seperator, use the system independant ‘/’ path seperator”);
}else{
throw new AssetNotFoundException(key.toString());
}
[/java]

This has the following advantages

  • Only triggers when there is already a problem, will never interfere with correct asset paths - so if it works on one system it will work on all
  • Only offers a potential cause of the problem (although it would be pretty unlikely to be wrong - who uses the local path seperator on their development machine within file or foldernames?)

Note: we’ve had about 10x the people complaining about upper case versus lower case issues. I’m sure they’d make a very compelling case for checking for that too.

I’m sorry you lost a whole day on this originally. I guess most people figure it out quicker and just look at the docs when they can’t figure out why it’s failing. Or look in the source code which is generally just a click away in the IDE.

@pspeed I’m sure you could have found a nicer way to phrase that, usually I find you very tactful. Regardless; I suppose I have very little personally invested in this being fixed given that I have been aware of it for over 2 years and it won’t cause me a problem in the future. I posted this merely to give a perspective of a problem new people to JMonkey may well experience, something which I know becomes less and less relatable as skills increase.

@richtea said: @pspeed I'm sure you could have found a nicer way to phrase that, usually I find you very tactful. Regardless; I suppose I have very little personally invested in this being fixed given that I have been aware of it for over 2 years and it won't cause me a problem in the future. I posted this merely to give a perspective of a problem new people to JMonkey may well experience, something which I know becomes less and less relatable as skills increase.

I didn’t mean to be insulting. We all take random paths through solving problems and only in retrospect can we see where we could have saved time. I was merely trying to add some perspective as to why you might be the only person (so far) who has worried this much about it.

In fact, it could be that you had too much skill already in this case where as someone brand new might have floundered into the documentation or debugger immediately instead of trying to blast through.

@pspeed Thats fair enough, as I say, usually I think you are very helpful (and its a fair critism that I tend to view documentation as a last resort (well one to last - I’d usually check the docs as the last step before asking someone else)).

Perhaps I was more likely than average to fall into this because I had both assetManager based loading and core java based loading (which I believed at the time had to use the localised pathseperator) whereas most people would probably only have assetManager based loading. If I am the only person to have mentioned this then you are right that it probably isn’t worth including as a specific exception message.