/* * See the NOTICE file distributed with this work for additional * information regarding copyright ownership. * * This is free software; you can redistribute it and/or modify it * under the terms of the GNU Lesser General Public License as * published by the Free Software Foundation; either version 2.1 of * the License, or (at your option) any later version. * * This software is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General Public * License along with this software; if not, write to the Free * Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA * 02110-1301 USA, or see the FSF site: http://www.fsf.org. */ package com.xpn.xwiki.pdf.impl; import java.io.ByteArrayInputStream; import java.util.Map; import javax.xml.transform.Source; import javax.xml.transform.TransformerException; import javax.xml.transform.URIResolver; import javax.xml.transform.stream.StreamSource; import org.xwiki.formula.ImageData; import org.xwiki.formula.ImageStorage; import org.xwiki.model.EntityType; import org.xwiki.model.reference.AttachmentReference; import com.xpn.xwiki.XWikiContext; import com.xpn.xwiki.doc.XWikiAttachment; import com.xpn.xwiki.doc.XWikiDocument; import com.xpn.xwiki.web.Utils; /** * Resolves URIs sent by Apache FOP to embed images in the exported PDF. The strategy is the following: * <ul> * <li>When an attachment is rendered during the export (specifically when {@code pdf.vm} is rendered), the * {@link PdfURLFactory} is called and it saves the Attachment Entity Reference in a map in the XWiki Context</li> * <li>When Apache FOP embeds an image it calls this URI Resolver and we try to locate the Attachment Entity * Reference from that map and return the attachment stream.</li> * <li>Attachment links do not call the Resolver and are thus exported correctly using a full URL to the XWiki * server</li> * </ul> * * @version $Id: 91acdb8af85632ebcde5d3f20e8cb4f494bac402 $ * @since 5.0RC1 * @deprecated since 7.4M2, use {@link PDFResourceResolver} component instead */ @Deprecated public class PDFURIResolver implements URIResolver { private static final String TEX_ACTION = "/tex/"; /** * @see #PDFURIResolver(com.xpn.xwiki.XWikiContext) */ private Map<String, AttachmentReference> attachmentMap; /** * @see #PDFURIResolver(com.xpn.xwiki.XWikiContext) */ private XWikiContext context; /** * @param context the XWiki Context from where we try to find the attachment map saved in the {@link PdfURLFactory} * earlier on */ public PDFURIResolver(XWikiContext context) { this.attachmentMap = (Map<String, AttachmentReference>) context.get(PdfURLFactory.PDF_EXPORT_CONTEXT_KEY); this.context = context; } @Override public Source resolve(String href, String base) throws TransformerException { if (this.attachmentMap != null) { // TODO: HACK // We're going through the getAttachmentURL() API so that when the PdfURLFactory is used, the generated // image is saved and then embedded in the exported PDF thanks to PDFURIResolver. In the future we need // to remove this hack by introduce a proper Resource for generated image (say TemporaryResource), // implement a TemporaryResourceSerializer<URL> and introduce a ResourceLoader interface and have it // implemented for TemporaryResource... if (href.contains(TEX_ACTION)) { // Note: See the comments in FormulaMacro to understand why we do a replace... AttachmentReference reference = this.attachmentMap.get(href.replace(TEX_ACTION, "/download/")); if (reference != null) { // Get the generated image's input stream ImageStorage storage = Utils.getComponent(ImageStorage.class); ImageData image = storage.get(reference.getName()); return new StreamSource(new ByteArrayInputStream(image.getData())); } } // TODO: end HACK AttachmentReference reference = this.attachmentMap.get(href); if (reference != null) { try { XWikiDocument xdoc = this.context.getWiki().getDocument( reference.extractReference(EntityType.DOCUMENT), this.context); // TODO: handle revisions XWikiAttachment attachment = xdoc.getAttachment( reference.extractReference(EntityType.ATTACHMENT).getName()); return new StreamSource(attachment.getContentInputStream(this.context)); } catch (Exception e) { throw new TransformerException(String.format("Failed to resolve export URI [%s]", href), e); } } } // Defaults to the default URI Resolver in FO return null; } }