Hi Jeremias, FYI I've now had time to try the latest FOP trunk and patch it into my code (instead of my workaround) and I can confirm the the URL resolving issues when deploying FOP in a webapp so that URL's can be relative to the ServletContext are gone when using the ServletContextURIResolver and the FopFactory helper methods to set it up. External graphics url's in the xsl-fo file are resolved OK (when the URL scheme is servlet-context: ) And all references to the font "metrics-url" and "embed-url" in the fopconfig xml are also resolved OK (again using the servlet-context: scheme)
Thanks for all your help, it's a pleasure to use such an activly maintained piece of software like FOP. Cheers Karl PS for anyone wondering what this thread is about see the following code snippets and config xml to see how to use the ServletContextURIResolver to resolve URL's in XSL-FO and FOP config file relative to a web applications ServletContext. // code snippet ....... public void PDFDocumentGenerator(InputSource fopconfigInputSource, ServletContext context, Source xmlSrc, Source xslSrc){ //Set up stuff from fop config file if it exists if(fopconfigInputSource!=null) { try{ DefaultConfigurationBuilder cfgBuilder = new DefaultConfigurationBuilder(); Configuration cfg = cfgBuilder.build(this.fopconfigInputSource); FopFactory ff =FopFactory.newInstance(); ff.setUserConfig(cfg); FOUserAgent userAgent=ff.newFOUserAgent(); //If ServletContext is not null then add ServletContextURIResolver // incase URI's in the config file and xsl-fo input are special ones that are relative to servlet-context: if(context!=null) { ff.setURIResolver(new ServletContextURIResolver(context)); } ByteArrayOutputStream out = new ByteArrayOutputStream(); // Construct fop with desired output format Fop fop = ff.newFop(MimeConstants.MIME_PDF, userAgent,out); // Setup XSLT if exists// if not then we are assuming src is already in xsl-fo format TransformerFactory factory = TransformerFactory.newInstance(); Transformer transformer; if(xslSource!=null) { transformer = factory.newTransformer(xslSrc); } else { transformer = factory.newTransformer(); } // Resulting SAX events (the generated FO) must be piped through // to FOP Result res = new SAXResult(fop.getDefaultHandler()); // Start XSLT transformation and FOP processing transformer.transform(xmlSrc, res); //got here so no transform exceptions now deal with the output collect as byte array (or just stream it somewhere) byte[] theBytes= out.toByteArray(); .....etc.... }catch(Exception e) { ....deal with it ...} } } // fopconfig.xml using url's with servlet-context scheme <fop version="1.0"> <!-- Base URL for resolving relative URLs --> <base>./</base> <source-resolution>72</source-resolution> <target-resolution>72</target-resolution> <!-- ie A4 --> <default-page-settings height="29.7cm" width="21cm"/> <renderers> <renderer mime="application/pdf"> <filterList> <value>flate</value> </filterList> <fonts> <font metrics-url="servlet-context:///WEB-INF/Arial.xml" kerning="no" embed-url="servlet-context:///WEB-INF/arial.ttf" > <font-triplet name="Arial" style="normal" weight="normal"/> <font-triplet name="ArialMT" style="normal" weight="normal"/> </font> <font metrics-url="servlet-context:///WEB-INF/ArialBd.xml" kerning="no" embed-url="servlet-context:///WEB-INF/arialbd.ttf" > <font-triplet name="Arial" style="normal" weight="bold"/> <font-triplet name="ArialMT" style="normal" weight="bold"/> </font> </fonts> </renderer> </renderers> </fop> -----Original Message----- From: Karl Roberts Sent: Tuesday, 28 March 2006 8:48 AM To: fop-users@xmlgraphics.apache.org Subject: RE: <SOLVED - sort of> Re how to embed a font programatically Cheers Jeremias, FYI BEFORE you fix it, the issue exists in another place too! When embedding a TTF font (before I was using enc-ansi so never saw the issue) inside the ServletContext the following method also calls "URL.openstream()" rather than using the URIResolver org.apache.fop.pdf.PDFDocument.resolveURI(String uri) The TODO gives it away! "todo Temporary hack to compile, improve later" ;-) Cheers Karl PS my code looked too complex to me too, I agree that a direct setter method is a nicer option and look forward to testing it! My code was just a hack to get around the issue while highlighting the problem, with as little change to the existing code as possible, so that we wouldn't have to maintain too much difference in a separate branch until the fix came through. -----Original Message----- From: Jeremias Maerki [mailto:[EMAIL PROTECTED] Sent: Monday, 27 March 2006 5:24 PM To: fop-users@xmlgraphics.apache.org Subject: Re: <SOLVED - sort of> Re how to embed a font programatically Hi Karl On 27.03.2006 05:39:01 Karl Roberts wrote: > Hi Jeremias, > Don't worry next time I'll create a patch for bugzilla! :-) Where are > the changes so I can test them? In our Subversion repository in "Trunk", of course. See: http://xmlgraphics.apache.org/fop/download.html#source You should download the latest sources using Subversion. > I am not using FOUserAgent more than once per rendering run. > > The ThreadLocal stuff was there to guarantee that the FOUserAgent > being used was thread safe, when the "FontReder.createFont(String > path)" method calls "AgentHelper.getInstance().getFOUserAgent()". Ah, I see. FontReader (or any other class from the font package for that matter) should not reference FOUserAgent. That's why I added the FontResolver. The DefaultFontResolver in the render package contains the reference to FOUserAgent to keep the dependencies clean. > The reason is because I am using FOP embedded from within a clustered > Web App environment and putting a ServletContextURIReader in > FOUserAgent. ServletContextURIReader has a reference to the > ServletContext in it's constructor, and so I just wanted to guarantee > that the FOUserAgent I'm using had the same ServletContext reference > if it was pre-empted, given that the AgentHelper uses a static Singleton. Looks too complicated to me. It's probably better to add a setter method to ServletContextURIResolver (not "Reader"!) to update the ServletContext if that changes. This can be done in the doGet() method. When I've finished my current task of merging our API finalization branch back into Trunk, I'll do that, too. > If the UserAgent had been referencable to "FontReder.createFont(String > path)" I'd have used it. <snip/> Jeremias Maerki --------------------------------------------------------------------- To unsubscribe, e-mail: [EMAIL PROTECTED] For additional commands, e-mail: [EMAIL PROTECTED] NOTICE This e-mail and any attachments are confidential and may contain copyright material of Macquarie Bank or third parties. If you are not the intended recipient of this email you should not read, print, re-transmit, store or act in reliance on this e-mail or any attachments, and should destroy all copies of them. Macquarie Bank does not guarantee the integrity of any emails or any attached files. The views or opinions expressed are the author's own and may not reflect the views or opinions of Macquarie Bank. --------------------------------------------------------------------- To unsubscribe, e-mail: [EMAIL PROTECTED] For additional commands, e-mail: [EMAIL PROTECTED] --------------------------------------------------------------------- To unsubscribe, e-mail: [EMAIL PROTECTED] For additional commands, e-mail: [EMAIL PROTECTED]