Java hack to deal with Windows file paths in Linux

Say you have a large legacy ColdFusion app on top of Java that runs on Windows. File access is done both via java.io.File and by CFFILE (which in turn also uses java.io.File), but not centralised in any way into a single file access library. Further, say you have file paths both hard-coded in the code, and also in a database.

In other words, the file paths themselves cannot change. They could be either local or remote Windows file paths, such as "c:\temp\file.txt" or "\\server\share\file.txt ".

How would you run this application on Linux without changing the code?

First, I tried running the application in WINE. This worked surprisingly well. WINE actually has awesome path conversion, including UNC support.

Don't want to run WINE? I have another solution. It's actually possible to implement your own version of java.io.File, and have the classloader pick up your version when the JVM starts. The tricky part is that since your class needs to actually be named java.io.File, you can't just extend Sun's java.io.File.

However, you can download the code for java.io.File from the JDK, and make modifications as needed.


 // added to each constructor
 pathname = translate(pathname);

 ...

 private static Pattern regexDriveLetter = Pattern.compile("^[a-zA-Z]:");
 private static Pattern regexSlashes = Pattern.compile("\\\\");
 private static Pattern regexUnc = Pattern.compile("^//");
 
 public static String translate(String pathname) {
  
  if (pathname == null) {
      return null;
  }
  
  pathname = regexDriveLetter.matcher(pathname).replaceAll("");
  pathname = regexSlashes.matcher(pathname).replaceAll("/");
  pathname = regexUnc.matcher(pathname).replaceAll("/mnt/");
  return pathname;
 }

The regular expression rules convert "c:\temp\text.txt" to "/temp/text.txt", and "\\fileserver\userfiles\test.txt" to "/mnt/fileserver/userfiles/test.txt", but of course you can customize them to do anything you like.

To load your java.io.File when the JVM starts, just compile it into a JAR, and add "-Xbootclasspath/p:javafilehack.jar" to your java command-line. Xbootclasspath/p simply places your JAR at the head of the line when the classpath is processed.

I'm not saying I recommend this approach. If you can modify the legacy code to support Linux file paths, that would be far better. If that's not an option, I would say that the WINE approach is more maintainable. With the Java hack, you would need to merge your changes separately into each version of the JVM you want to run, due to the serialVersionUID if nothing else.

I'm working on a compromise solution using AoP. I'll keep you posted.



I'm currently working at NerdWallet, a startup in San Francisco trying to bring clarity to all of life's financial decisions. We're hiring like crazy. Hit me up on Twitter, I would love to talk.

Follow @chase_seibert on Twitter