/********************************************************************************** * $URL: https://source.sakaiproject.org/svn/rwiki/trunk/rwiki-impl/impl/src/java/uk/ac/cam/caret/sakai/rwiki/component/service/impl/BaseFOPSerializer.java $ * $Id: BaseFOPSerializer.java 109558 2012-06-25 11:50:49Z matthew.buckett@oucs.ox.ac.uk $ *********************************************************************************** * * Copyright (c) 2003, 2004, 2005, 2006 The Sakai Foundation. * * Licensed under the Educational Community License, Version 1.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.opensource.org/licenses/ecl1.php * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. * **********************************************************************************/ package uk.ac.cam.caret.sakai.rwiki.component.service.impl; import java.io.IOException; import java.io.InputStream; import java.io.OutputStream; import java.io.Writer; import java.net.URI; import java.util.Properties; import javax.servlet.http.HttpServletRequest; import javax.xml.transform.Source; import javax.xml.transform.TransformerException; import javax.xml.transform.URIResolver; import javax.xml.transform.stream.StreamSource; import org.apache.avalon.framework.configuration.Configuration; import org.apache.avalon.framework.configuration.DefaultConfigurationBuilder; import org.apache.commons.logging.Log; import org.apache.commons.logging.LogFactory; import org.apache.fop.apps.FOPException; import org.apache.fop.apps.FOUserAgent; import org.apache.fop.apps.Fop; import org.apache.fop.apps.FopFactory; import org.apache.fop.apps.MimeConstants; import org.apache.xml.serializer.DOMSerializer; import org.apache.xml.serializer.ToXMLSAXHandler; import org.sakaiproject.component.cover.ServerConfigurationService; import org.sakaiproject.content.api.ContentResource; import org.sakaiproject.content.cover.ContentHostingService; import org.sakaiproject.entity.api.Reference; import org.sakaiproject.entity.cover.EntityManager; import org.xml.sax.Attributes; import org.xml.sax.ContentHandler; import org.xml.sax.Locator; import org.xml.sax.SAXException; import org.xml.sax.helpers.DefaultHandler; public class BaseFOPSerializer extends ToXMLSAXHandler implements ContentHandler { private static final Log logger = LogFactory .getLog(BaseFOPSerializer.class); private static final String configfile = "/uk/ac/cam/caret/sakai/rwiki/component/service/impl/fop.cfg.xml"; private Properties outputFormat = null; private Writer writer = null; private OutputStream outputStream = null; private ContentHandler contentHandler = null; private Fop fop = null; protected String mimeType = MimeConstants.MIME_PDF; /** * {@inheritDoc} */ public void setOutputStream(OutputStream arg0) { this.outputStream = arg0; } /** * {@inheritDoc} */ public OutputStream getOutputStream() { return outputStream; } /** * {@inheritDoc} */ public void setWriter(Writer arg0) { this.writer = arg0; } /** * {@inheritDoc} */ public Writer getWriter() { return writer; } /** * {@inheritDoc} */ public void setOutputFormat(Properties arg0) { this.outputFormat = arg0; } /** * {@inheritDoc} */ public Properties getOutputFormat() { return outputFormat; } /** * {@inheritDoc} */ public ContentHandler asContentHandler() throws IOException { if (fop == null) { InputStream stream = null; try { DefaultConfigurationBuilder cfgBuild = new DefaultConfigurationBuilder(); stream = getClass() .getResourceAsStream(configfile); Configuration cfg = cfgBuild.build(stream); final FopFactory ff = FopFactory.newInstance(); ff.setUserConfig(cfg); FOUserAgent userAgent = ff.newFOUserAgent(); userAgent.setURIResolver(new URIResolver() { public Source resolve(String href, String base) throws TransformerException { Source source = null; try { logger.info("Resolving " + href + " from " + base); HttpServletRequest request = XSLTEntityHandler .getCurrentRequest(); if (request != null && href.startsWith("/access")) { // going direct into the ContentHandler Service try { String path = href.substring("/access" .length()); Reference ref = EntityManager .newReference(path); ContentResource resource = ContentHostingService .getResource(ref.getId()); return new StreamSource(resource .streamContent()); } catch (Exception ex) { URI uri = new URI(base); String content = uri.resolve(href) .toString(); source = new StreamSource(content); } } else { // use default resolver to resolve font if (base == null) { return ff.resolveURI(href, base); } URI uri = new URI(base); String content = uri.resolve(href).toString(); source = new StreamSource(content); } } catch (Exception ex) { throw new TransformerException("Failed to get " + href, ex); } return source; } }); userAgent.setBaseURL(ServerConfigurationService .getString("serverUrl")); fop = ff.newFop(mimeType, userAgent, outputStream); } catch (Exception e) { logger.error("Failed to create Handler ",e); throw new IOException("Failed to create " + mimeType + " Serializer: " + e.getMessage()); } finally { if (stream != null) { stream.close(); } } } DefaultHandler dh; try { dh = fop.getDefaultHandler(); } catch (FOPException e) { logger.error("Failed to get FOP Handler ",e); throw new RuntimeException("Failed to get FOP Handler ", e); } return dh; } /** * {@inheritDoc} */ public DOMSerializer asDOMSerializer() { return null; } /** * {@inheritDoc} */ public boolean reset() { fop = null; outputFormat = null; writer = null; outputStream = null; return false; } /* (non-Javadoc) * @see org.xml.sax.ContentHandler#characters(char[], int, int) */ public void characters(char[] ch, int start, int length) throws SAXException { initContentHandler(); contentHandler.characters(ch, start, length); } /** * @throws SAXException * */ private void initContentHandler() throws SAXException { if ( contentHandler == null ) { try { contentHandler = asContentHandler(); } catch (IOException e) { throw new SAXException(e); } } } /* (non-Javadoc) * @see org.xml.sax.ContentHandler#endDocument() */ public void endDocument() throws SAXException { initContentHandler(); contentHandler.endDocument(); } /* (non-Javadoc) * @see org.xml.sax.ContentHandler#endElement(java.lang.String, java.lang.String, java.lang.String) */ public void endElement(String uri, String localName, String qName) throws SAXException { initContentHandler(); contentHandler.endElement(uri, localName, qName); } /* (non-Javadoc) * @see org.xml.sax.ContentHandler#endPrefixMapping(java.lang.String) */ public void endPrefixMapping(String prefix) throws SAXException { initContentHandler(); contentHandler.endPrefixMapping(prefix); } /* (non-Javadoc) * @see org.xml.sax.ContentHandler#ignorableWhitespace(char[], int, int) */ public void ignorableWhitespace(char[] ch, int start, int length) throws SAXException { initContentHandler(); contentHandler.ignorableWhitespace(ch, start, length); } /* (non-Javadoc) * @see org.xml.sax.ContentHandler#processingInstruction(java.lang.String, java.lang.String) */ public void processingInstruction(String target, String data) throws SAXException { initContentHandler(); contentHandler.processingInstruction(target, data); } /* (non-Javadoc) * @see org.xml.sax.ContentHandler#setDocumentLocator(org.xml.sax.Locator) */ public void setDocumentLocator(Locator locator) { try { initContentHandler(); } catch (SAXException e) { logger.error(e); e.printStackTrace(); } contentHandler.setDocumentLocator(locator); } /* (non-Javadoc) * @see org.xml.sax.ContentHandler#skippedEntity(java.lang.String) */ public void skippedEntity(String name) throws SAXException { initContentHandler(); contentHandler.skippedEntity(name); } /* (non-Javadoc) * @see org.xml.sax.ContentHandler#startDocument() */ public void startDocument() throws SAXException { initContentHandler(); contentHandler.startDocument(); } /* (non-Javadoc) * @see org.xml.sax.ContentHandler#startElement(java.lang.String, java.lang.String, java.lang.String, org.xml.sax.Attributes) */ public void startElement(String uri, String localName, String qName, Attributes atts) throws SAXException { initContentHandler(); contentHandler.startElement(uri, localName, qName, atts); } /* (non-Javadoc) * @see org.xml.sax.ContentHandler#startPrefixMapping(java.lang.String, java.lang.String) */ public void startPrefixMapping(String prefix, String uri) throws SAXException { initContentHandler(); contentHandler.startPrefixMapping(prefix, uri); } }