4

We have resolve which transforms a/b + c/d to a/b/c/d.

We have relativize which transforms a/b + a/b/c/d to c/d.

Is there a way to transform a/b/c/d + c/d to a/b?


For my special problem (classpaths) the URIs are not convertible to java.nio.file.Paths, with the error

java.nio.file.InvalidPathException: Illegal char <:> at index 3: jar:file:/D:/devel/somejar.jar!/foo/Bar.class

I want to resolve the directory of an entry (for example given Bar.class) and the URI as yielded by getClassLoader().getResource().toURI() to jar:file:/D:/devel/somejar.jar!/foo.

WorldSEnder
  • 4,875
  • 2
  • 28
  • 64

3 Answers3

1

You can use a java.nio.file.Path but you'd have to use a custom file system since the URI scheme here is jar not file. This page shows an example.

URI uri = URI.create("jar:file:/D:/devel/somejar.jar!/foo/Bar.class");

String[] array = uri.toString().split("!");
String jarFile = array[0];
String entryPath = array[1];
try(FileSystem fs = FileSystems.newFileSystem(URI.create(jarFile), new HashMap<>())) {
    Path path = fs.getPath(entryPath);
    URI parentUri = path.getParent().toUri();
    ...
}

Or the easy way using a substring:

URI uri = URI.create("jar:file:/D:/devel/somejar.jar!/foo/Bar.class");
URI parent = URI.create(uri.toString().substring(0, uri.toString().lastIndexOf("/")));
M A
  • 71,713
  • 13
  • 134
  • 174
  • This approach requires that the classloader returns a `jar:` path. Any way to make the first part (`toString.split()`) more general? – WorldSEnder Feb 07 '16 at 16:43
  • What are the possible types of URIs that can be returned by the classloader? If the resource is always on the filesystem, i.e. either a class file or inside a Jar, then `java.nio.file.Path` and `java.io.File` should be more than enough to get parent paths. – M A Feb 07 '16 at 17:45
  • I'm not quite sure that everything is on the filesystem, but when you put it that way, I think it is enough. I won't accept the answer yet, as the more general question hasn't been sufficently answer though (when `c` is a complete path, I'll make that more clear) – WorldSEnder Feb 07 '16 at 17:53
1
URI uri = Main.class.getClassLoader().getResource("java/net/URISyntaxException.class").toURI();
//URI uri = URI.create("jar:file:/D:/devel/somejar.jar!/foo/Bar.class");
System.out.println(uri.toString());
System.out.println(Paths.get(uri.toString()).getParent());

jar:file:/Library/Java/JavaVirtualMachines/jdk1.8.0_31.jdk/Contents/Home/jre/lib/rt.jar!/java/net/URISyntaxException.class jar:file:/Library/Java/JavaVirtualMachines/jdk1.8.0_31.jdk/Contents/Home/jre/lib/rt.jar!/java/net

toString is the trick

Amod Pandey
  • 1,336
  • 3
  • 14
  • 22
  • I get `Exception in thread "main" java.nio.file.InvalidPathException: Illegal char <:> at index 3: jar:file:/D:/bin/Java/jdk8u65/jre/lib/rt.jar!/java/net/URISyntaxException.class` at line 4. – WorldSEnder Feb 13 '16 at 02:09
  • Ah! http://stackoverflow.com/questions/9834776/java-nio-file-path-issue Windows vs Linux saga continues :) – Amod Pandey Feb 13 '16 at 11:41
0

I'm not sure exactly what you want to achieve. You can simply remove the end portion of the path using regex. I have used the String.class as an example.

public static void main(final String[] args) throws Exception {
    // get URI of class
    String clazz = "String.class";

    URI resourceURI = String.class.getResource(clazz).toURI();
    System.out.println(resourceURI);
    System.out.println(resourceURI.toString().replaceAll("^(.+?)!?/?" + clazz + "$", "$1"));

    clazz = "/lang/String.class";
    System.out.println(resourceURI.toString().replaceAll("^(.+?)!?/?" + clazz + "$", "$1"));

    clazz = "java/lang/String.class";
    System.out.println(resourceURI.toString().replaceAll("^(.+?)!?/?" + clazz +  "$", "$1"));
}

If you want to try and load the data into a Path then you can do the following:

public static void main(final String[] args) throws Exception {
    // get URI of class
    String clazz = "String.class";

    URI resourceURI = String.class.getResource(clazz).toURI();
    System.out.println(resourceURI.getScheme());
    System.out.println(resourceURI.getRawSchemeSpecificPart());
    URI fileURI = new URI(resourceURI.getRawSchemeSpecificPart());
    System.out.println(fileURI.getScheme());
    System.out.println(fileURI.getRawSchemeSpecificPart());
    Path path = Paths.get(fileURI);
    System.out.println(path);
    System.out.println(path.getParent());
}
roblovelock
  • 1,971
  • 2
  • 23
  • 41