[ https://issues.apache.org/jira/browse/FOP-2861?page=com.atlassian.jira.plugin.system.issuetabpanels:comment-tabpanel&focusedCommentId=17496892#comment-17496892 ]
Beat Hörmann commented on FOP-2861: ----------------------------------- My project requires font-embedding and displaying a logo.png-image. Years ago, I became aware of the problem you, Ole, described in this thread. So I decided to write my own resource resolver which I pass to FOP with the intention that FOP uses it whenever it needs to resolve a relative path against the absolute base path {{{}base_uri{}}}. (This was also the suggested way by Simon in 26/Apr/19 11:45, 30/Mar/21 06:47, and 30/Mar/21 07:10 which fails because FOP does not consistently use the passed resource resolver.) Since the problem only arises if {{base_uri}} is an opaque jar-URI, hence, an URI starting with "jar:file:", I only create my resource resolver in such a case. My {{JarResourceResolver}} looks as follows: {code:java} private static final class JarResourceResolver implements ResourceResolver { private final URI schemelessURI; private final String scheme; private final ResourceResolver rr; /** * The constructor. * * @param baseURI The opaque jar base URI, not allowed to be {@code null}. */ public JarResourceResolver(URI baseURI) { this.schemelessURI = URI.create(baseURI.getRawSchemeSpecificPart()); this.scheme = baseURI.getScheme(); this.rr = ResourceResolverFactory.createDefaultResourceResolver(); } @Override public Resource getResource(URI uri) throws IOException { return new Resource(new URL(scheme, null, -1, schemelessURI.resolve(uri).toString()).openStream()); } @Override public OutputStream getOutputStream(URI uri) throws IOException { return rr.getOutputStream(uri); } } {code} and later I create and pass an instance of {{JarResourceResolver}} to FOP: {code:java} final FopFactoryBuilder builder; if (baseURI == null) builder = new FopFactoryBuilder(new File(".").toURI()); else if (!baseURI.getScheme().equals("jar")) builder = new FopFactoryBuilder(baseURI); else { // baseURI != null && baseURI points into a jar file. builder = new FopFactoryBuilder(baseURI, new JarResourceResolver(baseURI)); } {code} I also disable font-caching because ever since font-caching exists it suffered from the fact that it does not use the provided {{{}JarResourceResolver{}}}. Thus, {code:java} builder.getFontManager().disableFontCache(); {code} (So at least the problem that the font-cache has with an opaque jar-URI as mentioned by Yannick in 30/Mar/21 07:00, 30/Mar/21 07:34, and 30/Mar/21 10:34 can be solved by just disabling the font-cache - which is not a problem for me.) With all that, everything was fine. But now, with 2.7, the problem arises again, but only for the font to embed, not for the logo.png-image, both referenced by their names, hence, with a relative URI. So my first conclusion (from yesterday) was that your hack went into 2.6 and went out in 2.7. But now I realize that the font-manager doesn't use the provided {{{}JarResourceResolver{}}}, as it did in 2.6, because when I add {code:java} builder.getFontManager().setResourceResolver(ResourceResolverFactory.createInternalResourceResolver(baseURI, new JarResourceResolver(baseURI))); {code} everything works fine again with 2.7. It is not clear to me why in 2.7 my {{JarResourceResolver}} doesn't make its way into the font-manager. Obviously, no external {{JarResourceResolver}} would be required if your hack made its way into the source code of FOP at exactly the place you mentioned: within the {{resolveFromBase(uri)}} method of the {{InternalResourceResolver}} class. Executing {code:java} baseUri.resolve(uri) {code} is apparently always wrong (or at least the result is not one expects) if {{baseUri}} is an opaque-jar-uri that describes a legal (non-opaque) absolute URI without the "jar:"-prefix, because in such a case, as we know, this call does not make a path resolution at all but just returns the normalized {{uri}} argument even if {{uri}} is a relative URI. > Allow resource loading from jar: URI > ------------------------------------ > > Key: FOP-2861 > URL: https://issues.apache.org/jira/browse/FOP-2861 > Project: FOP > Issue Type: Improvement > Affects Versions: 2.0, 2.1, 2.2, 2.3, 2.4, 2.6, 2.7 > Reporter: Ole Sandum > Priority: Major > Attachments: FopResourceResolver.java, uri_resolve.diff, > uri_resolve_decoded.diff > > > We would like to load our FOP config.xml along with related fonts and > hyphenation files using the common classloader URL, e.g.: > {{ URL configXml = getClass().getResource("config.xml");}} > {{ FopConfParser confParser = }} > {{ new FopConfParser(configXml.openStream(), configXml.toURI());}} > This makes for easy deployment, and works nicely as long as classes and > resources are loaded from separate files, i.e. from > file:/some/path/config.xml URIs. However, it fails when classes and resources > are packaged and loaded directly from a jar, i.e. from > jar:file:/some/archive.jar!/path/config.xml URIs, as is the case when > deploying with JWS or running an all-in-one executable jar, as it will fail > to properly resolve the related font and hyphenation file URIs. > See [https://github.com/osandum/fop-test.git] for a test to illustrate. > This is a consequence of a long standing issue (reported in > [https://bugs.openjdk.java.net/browse/JDK-8020755)] that > URI.resolve(childUri) doesn't work as expected on jar:file: URIs. > In this case, it can be easily remedied by a work-around to the call in > InternalResourceResolver.resolveFromBase(URI uri). Patch attached. -- This message was sent by Atlassian Jira (v8.20.1#820001)