google/jimfs

Allow configuration that has "\" and "/" as separator

Katharsas opened this issue · 0 comments

I want to create a virtual FileSystem similar to Configuration.unix() that is able to handle both / and \ as separators, like the default Java filesystem.

I regularly read relative file paths from default FileSystem or configuration and need to convert them to relative JimFs paths. Those paths happily mix / and \ if the program is executed on windows, and i do not want to manually replace the separators at every occation since actually JimFs has this functionality built in, but I don't see a way to use it.

A PathType for this would be nice. Or the possibility to configure this somehow. The only way I see to do this is to create my own PathType adapter class that forwards all methods to UnixPathType but has a different constructor that specified additional separators.

Edit:
Implementing adapter is somewhat cumbersome because toUriPath(...) and parseUriPath(...) are protected, so i cannot call them unless i put my adapter into the same package as UnixPathType, but thats only nitpicking.

Edit2:
I need to implement parsePath(String path) as well so it uses the custom Splitter. This solution is not great.

code

package com.google.common.jimfs;

import static com.google.common.jimfs.Feature.FILE_CHANNEL;
import static com.google.common.jimfs.Feature.LINKS;
import static com.google.common.jimfs.Feature.SECURE_DIRECTORY_STREAM;
import static com.google.common.jimfs.Feature.SYMBOLIC_LINKS;

import java.nio.file.InvalidPathException;

/**
 * Very similar to normal Configuration.unix(), but is able to parse windows separators in
 * addition to unix separator.
 * 
 */
public class UnixCompatible {
	
	public static Configuration config() {
		return Configuration.builder(new CompatiblePathType())
	            .setRoots("/")
	            .setWorkingDirectory("/work")
	            .setAttributeViews("basic")
	            .setSupportedFeatures(LINKS, SYMBOLIC_LINKS, SECURE_DIRECTORY_STREAM, FILE_CHANNEL)
	            .build();
	}
	
	static class CompatiblePathType extends PathType {

		final PathType unix;
		
		public CompatiblePathType() {
			super(false, '/', '\\');
			unix = PathType.unix();
		}
		
		/** Copied from UnixPathType, custom splitter */
		@Override
		public ParseResult parsePath(String path) {
			if (path.isEmpty()) {
				return emptyPath();
			}

			checkValid(path);

			final String root = path.startsWith("/") ? "/" : null;
			return new ParseResult(root, splitter().split(path));
		}
		
		/** Copied from UnixPathType */
		private static void checkValid(String path) {
			final int nulIndex = path.indexOf('\0');
			if (nulIndex != -1) {
				throw new InvalidPathException(path, "nul character not allowed", nulIndex);
			}
		}

		@Override
		public String toString(String root, Iterable<String> names) {
			return unix.toString(root, names);
		}

		@Override
		public String toString() {
			return unix.toString();
		}

		@Override
		protected String toUriPath(String root, Iterable<String> names, boolean directory) {
			return unix.toUriPath(root, names, directory);
		}

		@Override
		protected ParseResult parseUriPath(String uriPath) {
			return unix.parseUriPath(uriPath);
		}
	}
}