Martin Spamer
Martin Spamer

Reputation: 5585

Looking for suggestions on workaround for java.net.URL inconsistency/bug

The following code exposes the bug, I know I could just tail the the results of getFile() & getPath() but I'm looking for something a big more elegant and robust. I want to be able to walk the folders in both the containing jar by default and with user selected/configuration paths to find & load resources.

import java.net.MalformedURLException;
import java.net.URISyntaxException;
import java.net.URL;

public class UrlBug {

UrlBug() {
    try {
        final URL resourceRoot = this.getClass().getClassLoader().getResource(".");
        System.out.println(resourceRoot.getFile());
        System.out.println(resourceRoot.getPath());
        System.out.println(resourceRoot.toURI());
        System.out.println(resourceRoot.toExternalForm());
        System.out.println(resourceRoot.toString());
        new URL(resourceRoot.getFile());
    } catch (final URISyntaxException e) {
        e.printStackTrace();
    } catch (final MalformedURLException e) {
        e.printStackTrace();
    }
}
public static void main(final String[] args) {
    new UrlBug();
}
}

The output produced below with 'bug'

/C:/Users/Me/workspaces/.../target/classes/            <-- Malformed filename
/C:/Users/Me/workspaces/.../target/classes/            <-- Malformed path
file:/C:/Users/Me/workspaces/.../target/classes/
file:/C:/Users/Me/workspaces/.../target/classes/
file:/C:/Users/Me/workspaces/.../target/classes/

java.net.MalformedURLException: no protocol:
/C:/Users/Me/workspaces/scratch/target/classes/     at
java.net.URL.<init>(URL.java:585)   at
java.net.URL.<init>(URL.java:482)   at
java.net.URL.<init>(URL.java:431)   at
scratch.UrlBug.<init>(UrlBug.java:20)   at
scratch.UrlBug.main(UrlBug.java:39)

I'm quite prepared to accept the bug is in my code. However I think this is a problem with URL class and Kohsuke seems to agree

Upvotes: 0

Views: 751

Answers (1)

mttdbrd
mttdbrd

Reputation: 1831

I'm not sure why you want to walk the jar directory structure yourself. Java has existing classes designed to handle just this case. To fix your code, you can just use the toString() method:

new URL(resourceRoot.toString());

The "file:/" prefix is the "protocol". Using the toString() method guarantees that the "file:/" protocol is prepended to the string. According to the docs:

Protocol handlers for the following protocols are guaranteed to exist on the search path:

     http, https, ftp, file, and jar

http://docs.oracle.com/javase/7/docs/api/java/net/URL.html#URL(java.lang.String, java.lang.String, int, java.lang.String)

Upvotes: 2

Related Questions