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

Reply via email to