001: /*
002: * Licensed to the Apache Software Foundation (ASF) under one or more
003: * contributor license agreements. See the NOTICE file distributed with
004: * this work for additional information regarding copyright ownership.
005: * The ASF licenses this file to You under the Apache License, Version 2.0
006: * (the "License"); you may not use this file except in compliance with
007: * the License. You may obtain a copy of the License at
008: *
009: * http://www.apache.org/licenses/LICENSE-2.0
010: *
011: * Unless required by applicable law or agreed to in writing, software
012: * distributed under the License is distributed on an "AS IS" BASIS,
013: * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
014: * See the License for the specific language governing permissions and
015: * limitations under the License.
016: */
017:
018: /* $Id: FopServlet.java 513845 2007-03-02 17:11:41Z jeremias $ */
019:
020: package org.apache.fop.servlet;
021:
022: import java.io.File;
023: import java.io.IOException;
024: import java.io.PrintWriter;
025:
026: import javax.servlet.ServletException;
027: import javax.servlet.http.HttpServlet;
028: import javax.servlet.http.HttpServletRequest;
029: import javax.servlet.http.HttpServletResponse;
030: import javax.xml.transform.Result;
031: import javax.xml.transform.Source;
032: import javax.xml.transform.Transformer;
033: import javax.xml.transform.TransformerException;
034: import javax.xml.transform.TransformerFactory;
035: import javax.xml.transform.URIResolver;
036: import javax.xml.transform.sax.SAXResult;
037: import javax.xml.transform.stream.StreamSource;
038:
039: import org.apache.commons.io.output.ByteArrayOutputStream;
040: import org.apache.commons.logging.impl.SimpleLog;
041:
042: import org.apache.fop.apps.FOUserAgent;
043: import org.apache.fop.apps.Fop;
044: import org.apache.fop.apps.FOPException;
045: import org.apache.fop.apps.FopFactory;
046: import org.apache.fop.apps.MimeConstants;
047:
048: /**
049: * Example servlet to generate a PDF from a servlet.
050: * <br/>
051: * Servlet param is:
052: * <ul>
053: * <li>fo: the path to a XSL-FO file to render
054: * </ul>
055: * or
056: * <ul>
057: * <li>xml: the path to an XML file to render</li>
058: * <li>xslt: the path to an XSLT file that can transform the above XML to XSL-FO</li>
059: * </ul>
060: * <br/>
061: * Example URL: http://servername/fop/servlet/FopServlet?fo=readme.fo
062: * <br/>
063: * Example URL: http://servername/fop/servlet/FopServlet?xml=data.xml&xslt=format.xsl
064: * <br/>
065: * For this to work with Internet Explorer, you might need to append "&ext=.pdf"
066: * to the URL.
067: *
068: * @author <a href="mailto:fop-dev@xmlgraphics.apache.org">Apache FOP Development Team</a>
069: * @version $Id: FopServlet.java 513845 2007-03-02 17:11:41Z jeremias $
070: * (todo) Ev. add caching mechanism for Templates objects
071: */
072: public class FopServlet extends HttpServlet {
073:
074: /** Name of the parameter used for the XSL-FO file */
075: protected static final String FO_REQUEST_PARAM = "fo";
076: /** Name of the parameter used for the XML file */
077: protected static final String XML_REQUEST_PARAM = "xml";
078: /** Name of the parameter used for the XSLT file */
079: protected static final String XSLT_REQUEST_PARAM = "xslt";
080:
081: /** Logger to give to FOP */
082: protected SimpleLog log = null;
083: /** The TransformerFactory used to create Transformer instances */
084: protected TransformerFactory transFactory = null;
085: /** The FopFactory used to create Fop instances */
086: protected FopFactory fopFactory = null;
087: /** URIResolver for use by this servlet */
088: protected URIResolver uriResolver;
089:
090: /**
091: * @see javax.servlet.GenericServlet#init()
092: */
093: public void init() throws ServletException {
094: this .log = new SimpleLog("FOP/Servlet");
095: log.setLevel(SimpleLog.LOG_LEVEL_WARN);
096: this .uriResolver = new ServletContextURIResolver(
097: getServletContext());
098: this .transFactory = TransformerFactory.newInstance();
099: this .transFactory.setURIResolver(this .uriResolver);
100: //Configure FopFactory as desired
101: this .fopFactory = FopFactory.newInstance();
102: this .fopFactory.setURIResolver(this .uriResolver);
103: configureFopFactory();
104: }
105:
106: /**
107: * This method is called right after the FopFactory is instantiated and can be overridden
108: * by subclasses to perform additional configuration.
109: */
110: protected void configureFopFactory() {
111: //Subclass and override this method to perform additional configuration
112: }
113:
114: /**
115: * @see javax.servlet.http.HttpServlet#doGet(HttpServletRequest, HttpServletResponse)
116: */
117: public void doGet(HttpServletRequest request,
118: HttpServletResponse response) throws ServletException {
119: try {
120: //Get parameters
121: String foParam = request.getParameter(FO_REQUEST_PARAM);
122: String xmlParam = request.getParameter(XML_REQUEST_PARAM);
123: String xsltParam = request.getParameter(XSLT_REQUEST_PARAM);
124:
125: //Analyze parameters and decide with method to use
126: if (foParam != null) {
127: renderFO(foParam, response);
128: } else if ((xmlParam != null) && (xsltParam != null)) {
129: renderXML(xmlParam, xsltParam, response);
130: } else {
131: response.setContentType("text/html");
132: PrintWriter out = response.getWriter();
133: out.println("<html><head><title>Error</title></head>\n"
134: + "<body><h1>FopServlet Error</h1><h3>No 'fo' "
135: + "request param given.</body></html>");
136: }
137: } catch (Exception ex) {
138: throw new ServletException(ex);
139: }
140: }
141:
142: /**
143: * Converts a String parameter to a JAXP Source object.
144: * @param param a String parameter
145: * @return Source the generated Source object
146: */
147: protected Source convertString2Source(String param) {
148: Source src;
149: try {
150: src = uriResolver.resolve(param, null);
151: } catch (TransformerException e) {
152: src = null;
153: }
154: if (src == null) {
155: src = new StreamSource(new File(param));
156: }
157: return src;
158: }
159:
160: private void sendPDF(byte[] content, HttpServletResponse response)
161: throws IOException {
162: //Send the result back to the client
163: response.setContentType("application/pdf");
164: response.setContentLength(content.length);
165: response.getOutputStream().write(content);
166: response.getOutputStream().flush();
167: }
168:
169: /**
170: * Renders an XSL-FO file into a PDF file. The PDF is written to a byte
171: * array that is returned as the method's result.
172: * @param fo the XSL-FO file
173: * @param response HTTP response object
174: * @throws FOPException If an error occurs during the rendering of the
175: * XSL-FO
176: * @throws TransformerException If an error occurs while parsing the input
177: * file
178: * @throws IOException In case of an I/O problem
179: */
180: protected void renderFO(String fo, HttpServletResponse response)
181: throws FOPException, TransformerException, IOException {
182:
183: //Setup source
184: Source foSrc = convertString2Source(fo);
185:
186: //Setup the identity transformation
187: Transformer transformer = this .transFactory.newTransformer();
188: transformer.setURIResolver(this .uriResolver);
189:
190: //Start transformation and rendering process
191: render(foSrc, transformer, response);
192: }
193:
194: /**
195: * Renders an XML file into a PDF file by applying a stylesheet
196: * that converts the XML to XSL-FO. The PDF is written to a byte array
197: * that is returned as the method's result.
198: * @param xml the XML file
199: * @param xslt the XSLT file
200: * @param response HTTP response object
201: * @throws FOPException If an error occurs during the rendering of the
202: * XSL-FO
203: * @throws TransformerException If an error occurs during XSL
204: * transformation
205: * @throws IOException In case of an I/O problem
206: */
207: protected void renderXML(String xml, String xslt,
208: HttpServletResponse response) throws FOPException,
209: TransformerException, IOException {
210:
211: //Setup sources
212: Source xmlSrc = convertString2Source(xml);
213: Source xsltSrc = convertString2Source(xslt);
214:
215: //Setup the XSL transformation
216: Transformer transformer = this .transFactory
217: .newTransformer(xsltSrc);
218: transformer.setURIResolver(this .uriResolver);
219:
220: //Start transformation and rendering process
221: render(xmlSrc, transformer, response);
222: }
223:
224: /**
225: * Renders an input file (XML or XSL-FO) into a PDF file. It uses the JAXP
226: * transformer given to optionally transform the input document to XSL-FO.
227: * The transformer may be an identity transformer in which case the input
228: * must already be XSL-FO. The PDF is written to a byte array that is
229: * returned as the method's result.
230: * @param src Input XML or XSL-FO
231: * @param transformer Transformer to use for optional transformation
232: * @param response HTTP response object
233: * @throws FOPException If an error occurs during the rendering of the
234: * XSL-FO
235: * @throws TransformerException If an error occurs during XSL
236: * transformation
237: * @throws IOException In case of an I/O problem
238: */
239: protected void render(Source src, Transformer transformer,
240: HttpServletResponse response) throws FOPException,
241: TransformerException, IOException {
242:
243: FOUserAgent foUserAgent = getFOUserAgent();
244:
245: //Setup output
246: ByteArrayOutputStream out = new ByteArrayOutputStream();
247:
248: //Setup FOP
249: Fop fop = fopFactory.newFop(MimeConstants.MIME_PDF,
250: foUserAgent, out);
251:
252: //Make sure the XSL transformation's result is piped through to FOP
253: Result res = new SAXResult(fop.getDefaultHandler());
254:
255: //Start the transformation and rendering process
256: transformer.transform(src, res);
257:
258: //Return the result
259: sendPDF(out.toByteArray(), response);
260: }
261:
262: /** @return a new FOUserAgent for FOP */
263: protected FOUserAgent getFOUserAgent() {
264: FOUserAgent userAgent = fopFactory.newFOUserAgent();
265: //Configure foUserAgent as desired
266: return userAgent;
267: }
268:
269: }
|