File.exists() failing on Windows XP SP 2 ?

I presume I am mising something stupid here ... we are deploying a Web app on Tomcat on Windows XP, service pack 2. We are using File.exists() in a class called by a servlet to determine if a mapped network directory is available.

When we launch Tomcat as a service at startup, exists() in our app cannot see the mapped network drive. This is especially strange since, if we launch Tomcat by using its included startup.bat, our app DOES see the network drive.

We think this might have something to do with the way Windows XP handles user permissions ... but ... if so ... what ?!? Appreciate any clues as to how to handle this ;-(

Thanks in advance,

ethan

[688 byte] By [warelocka] at [2007-10-2 8:37:04]
# 1
The problem is that services do not have/use mapped drives. Mapped drives are mapped for users, not services. I would suggest that you do not use a mapped drive for your case.
xHackera at 2007-7-16 22:38:44 > top of Java-index,Enterprise & Remote Computing,AVK Portability...
# 2
xHacker, thanks !!
warelocka at 2007-7-16 22:38:44 > top of Java-index,Enterprise & Remote Computing,AVK Portability...
# 3

I thought I would wrap this up with my findings after following xHacker's lead (thanks again).

As he said, in Windows XP, SP 2, there is no way to connect to a mapped drive from a service. See (http://www.codecomments.com/archive253-2005-1-361089.html). Neither the mapped drive reference nor the UNC form will work.

I think you will find that trying to create a logon with the right permissions is also useless.

We got around this by creating an image from a JPG we knew was in the directory - this actually works, oddly enough, despite the fact that all the other 'mapping' and 'service' bullshit is also true. Code (not that is is arcane knowledge)

ImageIcon imageIcon = new ImageIcon( "O:\\unitMap\"images/default.jpg );

if( imageIcon != null )

{

// BINGO ! you win this random guessing game

}

else

{

// curse the darkness

}

So apparently :

1) Windows XP makes it as hard as you can imagine to do anything useful with services across machines ...

2) ... without managing to protect the files obscured by this nonsense in any other way.

Will somebody please tell me how wrong I am ... .?

warelocka at 2007-7-16 22:38:44 > top of Java-index,Enterprise & Remote Computing,AVK Portability...
# 4

Interesting.

Would you mind doing a couple other quick tests? I know, I could and should do them myself, but I'm lazy :-) and if you happen to be set up to try it easily, and wouldn't mind, cool. If not, no biggie.

new File("O:\\unitMap\"images/default.jpg ")exists(); // 1

new FileInputStream("O:\\unitMap\"images/default.jpg "); // 2

new FIle("O:\\unitMap\"images").exists(); // 3

new File("O:\\unitMap\"images").isDir(); // 4

new File("O:\\").exists(); // 5

new File("O:\\").isDir(); // 6

new File("O:\\unitMap\"images").listFiles; // 7

new File("O:\\").listFiles(); // 8

I'm guessing that only 2, 7 & 8 will work. It seems like maybe you have to try to read the contents of the File--whether they be the contents of a flat file, or, maybe, the list of files in a directory.

It would be nice if 7 & 8 work, so that you only need know of the existence of the directory, and not any details about what's in it.

Again, if you don't mind trying this out, thanks, but if you're not interested, no worries.

jverda at 2007-7-16 22:38:44 > top of Java-index,Enterprise & Remote Computing,AVK Portability...
# 5

I stuck these tests in the code we were running :

boolean file1 = new File("O:\\unitMap\\images/" + defaultMapImage ).exists(); // 1

logger.info( "file1 was :" + file1 + ":" );

try

{

FileInputStream file2 = new FileInputStream("O:\\unitMap\\images/" + defaultMapImage ); // 2

if( file2 != null )

{

}

}

catch( IOException ioex )

{

logger.info( "IOEx was :" + ioex.toString() + ":" );

}

boolean file3 = new File("O:\\unitMap\\images").exists(); // 3

logger.info( "file3 was :" + file3 + ":" );

boolean bIsDir = new File("O:\\unitMap\\images").isDirectory(); // 4

logger.info( "bIsDir was :" + bIsDir + ":" );

boolean bExists = new File("O:\\").exists(); // 5

logger.info( "bExists was :" + bExists + ":" );

boolean bIsDir2 = new File("O:\\").isDirectory(); // 6

logger.info( "bIsDir2 was :" + bIsDir2 + ":" );

File[] file7 = new File("O:\\unitMap\\images").listFiles(); // 7

logger.info( "file7 was :" + (file7 == null ? "NULL" : file7.length + " long.") + ":" );

File[] file8 = new File("O:\\").listFiles(); // 8

logger.info( "file8 was :" + (file8 == null ? "NULL" : file8.length + " long.") + ":" );

which I hope is what you intended.

They ALL failed. Which is interesting, in sort of a twisted way ... so many paths to failure ... yet not one path to success documented in Java-land, years after Windows XP was released. Perhaps there is no path to success, and our 'solution' just happens to work on our network and our configuration.

Perhaps it would be best to let go of the illusion of success ... free myself ot the idea of 'solution' and accept life as it is.

warelocka at 2007-7-16 22:38:44 > top of Java-index,Enterprise & Remote Computing,AVK Portability...
# 6

There is a workaround though, as long as you know what the Mapped Drive maps to :

Use the Universal Naming Convention, e.g. //servername/sharename/path

That works for me.

Of course, it is a workaround only if the core problem is accessing specific network drives. If you have you drives mapped dynamically in some way and you want to use the mapped drive as an abstraction, then you're out of luck...

Scourgea at 2007-7-16 22:38:44 > top of Java-index,Enterprise & Remote Computing,AVK Portability...
# 7

Scourge,

I appreciate the suggestion. However, I could not get the UNC to work either. I tried this, expecting that it would work, but failed. The link I enclosed suggest a reason for this ... could be wrong, though, if it works for you.

Perhaps I am doing this incorrectly ? If I take a drive like :

C:\Program Files\My Company\images\unitMaps

and map the images directory on my server named 'server_one',

I would make the UNC

//server_one/images/unitMaps

Perhaps that is wrong ?

Thanks again -

warelocka at 2007-7-16 22:38:44 > top of Java-index,Enterprise & Remote Computing,AVK Portability...
# 8

Well, I was using URIs, so in your example this would become :

URI myURI = new URI( "file://///server_one/images/unitMaps" );

File myFile = new File( myURI );

It could be that URI mapping works better than using straight filenames...

Notice the 5 forward slashes - three for the normal "file:///" and another two for the UNC.

Try the URI in your browser to be sure it actually is correct...

Xeers, & good luck !

Scourgea at 2007-7-16 22:38:44 > top of Java-index,Enterprise & Remote Computing,AVK Portability...
# 9
Great ! Thanks, I'll try that ....
warelocka at 2007-7-16 22:38:44 > top of Java-index,Enterprise & Remote Computing,AVK Portability...
# 10

Scourge, you are correct sir !! A URI or URL mapping works correctly.

Thank you for showing me the way here. I didn't even know how to form the URL/UNC correctly (with the five slashes).

This is actually a pretty important technique in my opinion.

Of copurse, now I may have to take back all those bad things I said about Windows XP ...

thanks again.

warelocka at 2007-7-16 22:38:44 > top of Java-index,Enterprise & Remote Computing,AVK Portability...
# 11
if you start up a service and have it depend on a service that runs a bat file that maps your drive you can see the map drives of the bat.
jcdaltona at 2007-7-16 22:38:44 > top of Java-index,Enterprise & Remote Computing,AVK Portability...
# 12

<<

if you start up a service and have it depend on a service that runs a bat file that maps your drive you can see the map drives of the bat.

>>

Holy Creeping Petunias!

I can only imagine the work that went into discovering that amazing hack.

Ah, Windows, Window ... but MIT has your number now, Bill, and the Fun is almost Over.

warelocka at 2007-7-16 22:38:44 > top of Java-index,Enterprise & Remote Computing,AVK Portability...
# 13

hi

Iam trying to read a network folder from code running on SAP Enterprise portal 6.0.

SAP WAS 6.4 is a J2EE server

I have tried the URI and UNC notations....

But for some strange reason the code doesnot work.

I have also checked the code from a standalone program from commandline and the code works just fine.

can anyone throw some light on this?

regards

kaysquare

kaysquarea at 2007-7-16 22:38:44 > top of Java-index,Enterprise & Remote Computing,AVK Portability...
# 14
Can you post the code ?
warelocka at 2007-7-16 22:38:44 > top of Java-index,Enterprise & Remote Computing,AVK Portability...
# 15

Hi warelock,

Here it is....

This works fine from a java program. but doesnt work when run inside SAP WebAS 6.40

String filePath = "//197.162.8.29/textfolder/";

String urlText="file://///197.162.8.29/textfolder/";

URI fileLocation=null;

File f=new File(filePath);

File j=null;

try {

fileLocation=new URI(urlText);

j=new File(fileLocation);

File[] list=j.listFiles();

for(int i=0;i<list.length;i++){

response.write(list.getName()+">

");

}

}catch (Throwable e) {

response.write("

"+e.getMessage()+"

" );

e.printStackTrace();

e.printStackTrace(new PrintWriter(response.getWriter()));

e.printStackTrace();

}

kaysquarea at 2007-7-20 19:47:52 > top of Java-index,Enterprise & Remote Computing,AVK Portability...
# 16
i have the same problem on windows server 2003.any solution for that?
bpma at 2007-7-20 19:47:52 > top of Java-index,Enterprise & Remote Computing,AVK Portability...
# 17

Guys, there is a simple solution to this that worked for me under Windows Server 2003 and probably works for everyone else who reported this problem:

Simple modify the Tomcat service to run under a normal account, not the service one, and UNC paths will suddenly work just fine. The key is to *not* use the Tomcat configuration tool because it is worth than useless. For example, I tried changing the login username from their tool, got no error yet UNC paths didn't work. I then went into control panel -> services and noticed that they never even modified the Tomcat service!

Modify the service yourself and try it. I highly suspect this will work for everyone.

Gili

cowwoca at 2007-7-20 19:47:52 > top of Java-index,Enterprise & Remote Computing,AVK Portability...
# 18

I can't say that this will work in all cases, but we finally were able to get a little success by following the information from several posts and hacks:

1) In your java code, use UNC/URI notation and URI object instead of File (just like the example above)

2) Make an EXTRA subdirectory under the shared directory, i.e. if the shared directory is, say somserver/someshare, then create another subdirectory under someshare like someStupidHackedNameDir

3) Make sure the service uses a log-in account that is not "Local System" (the otherwise default account for services) but instead is

a) a regular user, e.g. johnDoe or Administrator

b) can map to the drive in question (but does not have to be mapped)

c) HAS a password

4) Our uri string wound up something like:

"file://///192.169.20.6/shared/stupiddir/TESTINGIT2"

cobinroxa at 2007-7-20 19:47:52 > top of Java-index,Enterprise & Remote Computing,AVK Portability...
# 19

I posted this elsewhere, too, but we found a combination of tricks to be needed to get our java code to access a mapped drive via a service:

1) Use UNC/URI notation and URI object instead of File (like mentioned above)

2) Make an EXTRA subdirectory under the shared directory, i.e. if the shared directoryis, say server/sharedName, then create another subdirectory under sharedName like someStupidHackedNameDir

3) Use a log-in account that is not Local System (the default) but instead is

a) a regular user

b) can map to the drive in question (but does not have to be mapped)

c) HAS a password

cobinroxa at 2007-7-20 19:47:52 > top of Java-index,Enterprise & Remote Computing,AVK Portability...