javahtmlswingjeditorpane

JEditorPane with inline image from jar file


I have a JEditorPane which shows HTML content with images. I found this article: JEditorPane with inline image. In this article is mentioned to use a protocol handler "resource:" for class path resources.

I tried this and got it working, when I run the application from Eclipse. But when I run it with a generated JAR file I'm not able to read the image out of the JAR file.

This is my version of the connection class:

public class ResourceConnection extends URLConnection {
    protected ResourceConnection(URL url) {
        super(url);
    }

    @Override
    public void connect() throws IOException {
        connected = true;
    }

    @Override
    public InputStream getInputStream() throws IOException {
        String filename = url.getFile();
        URL resourceURL = ResourceConnection.class.getResource(filename);
        String resourcePath = resourceURL.toString();

        Path path = null;
        if (resourcePath.startsWith("file:")) {
            resourcePath = resourcePath.substring(5);
            path = Paths.get(resourcePath);
        } else if (resourcePath.startsWith("jar:")) {
            // TODO path to image in jar file
        }

        if (path != null) {
          byte[] bytes = Files.readAllBytes(path);
          return new ByteArrayInputStream(bytes);
        } else {
          return null;
        }
    }
}

When I run it from Eclipse, the resourcePath looks like file:/path/to/my/project/bin/path/to/image.png. From this I have to remove the file: and the image will be shown.

When I run it with a JAR file, the resourcePath looks like jar:file:/path/to/the/jarfile.jar!/path/to/image.png. I don't how I have to manipulate the path so that Files.readAllBytes can read it. I tried the following:

The interessting thing is, when I create an ImageIcon with resourceURL the image is loaded (getIconWidth() and getIconHeight() return the correct values).

Edit:

The tag in the HTML source looks like <img src="resource:/path/to/image.png">.

Edit:

The answer of Andrew Thompson gave me the idea to use a FileInputStream.

public InputStream getInputStream() throws IOException {
    try {
        String filename = url.getFile();
        URL resourceURL = ResourceConnection.class.getResource(filename);
        return new FileInputStream(new File(resourceURL.toURI()));
    } catch (FileNotFoundException | URISyntaxException e) {
        e.printStackTrace();
        return null;
    }
}

This again works fine from Eclipse but with the JAR file I get java.lang.IllegalArgumentException: URI is not hierarchical. Probably because the URL begins with jar:file:.


Solution

  • I got it finally working.

    public class ResourceConnection extends URLConnection {
        protected ResourceConnection(URL url) {
            super(url);
        }
    
        @Override
        public void connect() throws IOException {
            connected = true;
        }
    
        @Override
        public InputStream getInputStream() throws IOException {
            return ResourceConnection.class.getResource(url.getFile()).openConnection().getInputStream();
        }
    }
    

    Thanks to Andrew Thompson for the idea to work with streams.