Is it possible to resolve css as a classpath resou

2019-06-25 04:25发布

问题:

I'm trying to package up resources into a jar, but I'm having trouble getting Flying Saucer to find the css on the classpath - I can't construct a URL easily to be able to resolve this seamlessly.

Does Flying saucer have a way of specifying resource packages on the classpath to resolve items and images?

Note: I'm running this in a webstart application that does not have file system writing permissions, so jar expansion is not really an option.

回答1:

You should implement a UserAgentCallback that you feed to the XHTMLPanel, something like this:

private static class UAC extends NaiveUserAgent {
    @Override
    public String resolveURI(String uri) {
        return uri;
    }

    @Override
    protected InputStream resolveAndOpenStream(String uri) {
        java.io.InputStream is = null;
        URL url = UAC.class.getResource(uri);
        if (url == null) {
            XRLog.load("Didn't find resource [" + uri + "].");
            return null;
        }
        try {
            is = url.openStream();
        }
        catch (java.net.MalformedURLException e) {
            XRLog.exception("bad URL given: " + uri, e);
        }
        catch (java.io.FileNotFoundException e) {
            XRLog.exception("item at URI " + uri + " not found");
        }
        catch (java.io.IOException e) {
            XRLog.exception("IO problem for " + uri, e);
        }
        return is;
    }
}

XHTMLPanel panel = new XHTMLPanel(new UAC());


回答2:

My solution is

private static class UserAgentCallback extends ITextUserAgent {
    public UserAgentCallback(ITextOutputDevice outputDevice, SharedContext sharedContext) {
        super(outputDevice);
        setSharedContext(sharedContext);
    }

    @Override
    public String resolveURI(String uri) {
        return uri;
    }

    @Override
    protected InputStream resolveAndOpenStream(String uri) {
        java.io.InputStream is = null;
        URL url = null;
        try {
            url = new ClassPathResource("/META-INF/pdfTemplates/" + uri).getURL();
        } catch (IOException e) {
            XRLog.exception("bad URL given: " + uri, e);
        }
        if (url == null) {
            XRLog.load("Didn't find resource [" + uri + "].");
            return null;
        }
        try {
            is = url.openStream();
        } catch (java.net.MalformedURLException e) {
            XRLog.exception("bad URL given: " + uri, e);
        } catch (java.io.FileNotFoundException e) {
            XRLog.exception("item at URI " + uri + " not found");
        } catch (java.io.IOException e) {
            XRLog.exception("IO problem for " + uri, e);
        }
        return is;
    }
}

and invocation:

renderer.getSharedContext()
                .setUserAgentCallback(new UserAgentCallback(renderer.getOutputDevice(), renderer.getSharedContext()));


回答3:

It would seem that flying saucer does not have a way of specifying resources on the classpath, so I work around by making a classpath: protocol url handler at the linked question

Post Implementation Findings

It would seem that the some of the premises of this question are invalid. After writing my own classpath URL loader, I found that you need to request <all-permissions/> in the jnlp to be able to use URL.setURLStreamHandlerFactory(). In fact, you need to request all permissions to do just about anything fancy (even though you're only modifying your own sand-box). See the full list here.

In short, this means that I am able to extract files to the operating system. But it's nice having a classpath loader now...