How to force Java 7 to create "directory symlinks" on Windows instead of "file symlinks"?
Asked Answered
P

1

6

I'm using Oracle Java 7 on Windows 64 bit.

When I create a symlink using Files.createSymbolicLink, I notice this behavior:

  1. If the target is a directory, a "directory symlink" is created.
  2. If the target is a file, a "file symlink" is created.
  3. If the target does not exist, a "file symlink" is created.

The type of the symlink is fixed and never changes, regardless of any changes to its target.

Using Windows' native mklink command, it is possible to force the link type to be a "directory symlink". Is it possible to achieve this using the native Java API or some library?

One trivial and ugly way is:

  1. If the target is a directory, just create the link
  2. If the target doesn't exist, create a new empty target directory, create the link, and delete the directory.
  3. If the target is a file ... handle it (move it, apply #2, move it back).

Fugly.

Preventive answered 20/9, 2012 at 8:49 Comment(0)
P
3

Unfortunately I don't see a way within the Java APIs to do it.

I checked the Windows JRE code and it looks like the decision is based on the file attributes themselves:

try
{
   WindowsFileAttributes windowsfileattributes = WindowsFileAttributes.get(windowspath2, false);
   if(windowsfileattributes.isDirectory() || windowsfileattributes.isDirectoryLink())
      i |= 1;
}

The attributes themselves originate from native code, and it looks like there is no way to affect them.

Clearly you have other options like manually invoking mklink or even manipulating the returned objects using something like PowerMock (which is clearly not meant for this purpose).

Another dirty option is to create proxys of all the relevant classes: Path, FileSystem and FileSystemProvider.
The way that it works is that the Path returns a FileSystem which returns a FileSystemProvider - what you need to do is modify how the FileSystemProvider.createSymbolicLink methods behaves.

The createSymbolicLink method receives a varargs argument which is currently not used - you can pass an argument to it that will indicate your wrapper that it needs to override the way symbolic links are created - and there you go :)

After writing all of this - the only question I have is - why do you need this kind of behavior?

Pierro answered 3/10, 2012 at 11:57 Comment(1)
Actually there's no great need, I just discovered this behavior via a bug in my program that caused the symlink's target not to be created.Preventive

© 2022 - 2024 — McMap. All rights reserved.