1

It looks like java.net.URL can be extended with custom URLHandlers in principle, and that it currently does not support data: URLs.

I'm working with a third-party library that uses URLs constructed from strings to retrieve images and want to pass image data directly. Is there an existing implementation of a suitable handler anyone can recommend?

2 Answers 2

2

If you read the RFC 2397 carefully, you'll see that the "data" URL scheme is defined like that:

data:[<mediatype>][;base64],<data>

So to generate this data, you'd use something like that:

byte[] fakeImage = new byte[1];
StringBuilder sb = new StringBuilder();

// acquired from file extension
String mimeType = "image/jpg";
sb.append("data:");
sb.append(mimeType);
sb.append(";base64,");
sb.append(Base64.getEncoder().encodeToString(fakeImage));

The interesting part comes now: You'll have to register you own protocol handler, which however is well defined:

If this is the first URL object being created with the specifiedprotocol, a stream protocol handler object, an instance ofclass URLStreamHandler, is created for that protocol: 
1.If the application has previously set up an instance of URLStreamHandlerFactory as the stream handler factory,then the createURLStreamHandler method of that instanceis called with the protocol string as an argument to create thestream protocol handler. 
2.If no URLStreamHandlerFactory has yet been set up,or if the factory's createURLStreamHandler methodreturns null, then the constructor finds thevalue of the system property: 
         java.protocol.handler.pkgs

If the value of that system property is not null,it is interpreted as a list of packages separated by a verticalslash character '|'. The constructor tries to loadthe class named: 
         <package>.<protocol>.Handler

where <package> is replaced by the name of the packageand <protocol> is replaced by the name of the protocol.If this class does not exist, or if the class exists but it is nota subclass of URLStreamHandler, then the next packagein the list is tried. 
3.If the previous step fails to find a protocol handler, then theconstructor tries to load from a system default package. 
         <system default package>.<protocol>.Handler

If this class does not exist, or if the class exists but it is not asubclass of URLStreamHandler, then a MalformedURLException is thrown.

So you just write the following:

String previousValue = System.getProperty("java.protocol.handler.pkgs") == null ? "" : System.getProperty("java.protocol.handler.pkgs")+"|";
System.setProperty("java.protocol.handler.pkgs", previousValue+"stackoverflow");

In order to this for work, you'll have to create a package named stackoverflow.data and within a class named Handler with the following content:

package stackoverflow.data;

import java.io.IOException;
import java.net.URL;
import java.net.URLConnection;
import java.net.URLStreamHandler;

public class Handler extends URLStreamHandler {

    @Override
    protected URLConnection openConnection(URL u) throws IOException {
        return null;
    }

}

Then you can just create a new URL without getting any exception:

URL url = new URL(sb.toString());

I have no clue why you need it this way, but there you are.

Sign up to request clarification or add additional context in comments.

6 Comments

Thanks, I understood that. The actual implementation of open connection was what I was hoping for, I thought there must be existing libraries. The third party library I'm using takes Strings, interprets them as URLs and reads images from them. So I don't just need to construct the URL objects; I need them to actually deliver the image data.
Since I have no clue how your third party libraries uses these URLs (do they even invoke openConnection?), you might have to implement your way down to all the functions you need. Actually, I find it pretty weird to use the java.net.URL class for this, are you sure they haven't their propriety URL class? Because creating an URL for a data String doesn't seem very intuitive here, because the URL class is actually designed to open some things, but a static String isn't really something you can open.
They basically pass them to ImageIO, which does call openConnection. The fact they're using URLs is pretty braindead, I'm basically trying to work around this stupid API so I can use my rendered images. As for static strings not being something you can open, that's the whole idea behind RFC 2397, isn't it? I was surprised there isn't support for it already.
Ah, now it makes kind of sense. You don't have to pass them a data scheme URL, just store the byte[] from the decoded base64 String to the file system and hand over the file URL.
I wanted to avoid using tons of tiny image files. Thanks anyway!
|
-1

You can add this dependency to your classpath: java-data-url-handler

Disclaimer: I am the author

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.