[
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)