ch.entwine.weblounge.kernel.fop.FopEndpoint.java Source code

Java tutorial

Introduction

Here is the source code for ch.entwine.weblounge.kernel.fop.FopEndpoint.java

Source

/*
 *  Weblounge: Web Content Management System
 *  Copyright (c) 2003 - 2011 The Weblounge Team
 *  http://entwinemedia.com/weblounge
 *
 *  This program 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
 *  of the License, or (at your option) any later version.
 *
 *  This program 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 program; if not, write to the Free Software Foundation
 *  Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
 */

package ch.entwine.weblounge.kernel.fop;

import ch.entwine.weblounge.common.site.Environment;

import org.apache.commons.io.FilenameUtils;
import org.apache.commons.io.IOUtils;
import org.apache.commons.lang.StringUtils;
import org.apache.fop.apps.FOPException;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.w3c.dom.Document;
import org.xml.sax.SAXException;

import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
import java.net.MalformedURLException;
import java.net.URL;
import java.util.ArrayList;
import java.util.Date;
import java.util.List;

import javax.servlet.http.HttpServletRequest;
import javax.ws.rs.FormParam;
import javax.ws.rs.GET;
import javax.ws.rs.POST;
import javax.ws.rs.Path;
import javax.ws.rs.Produces;
import javax.ws.rs.WebApplicationException;
import javax.ws.rs.core.Context;
import javax.ws.rs.core.MediaType;
import javax.ws.rs.core.Response;
import javax.ws.rs.core.Response.ResponseBuilder;
import javax.ws.rs.core.Response.Status;
import javax.ws.rs.core.StreamingOutput;
import javax.xml.parsers.DocumentBuilder;
import javax.xml.parsers.DocumentBuilderFactory;
import javax.xml.parsers.ParserConfigurationException;
import javax.xml.transform.TransformerConfigurationException;
import javax.xml.transform.TransformerException;

/**
 * This class implements the <code>REST</code> endpoint for the FOP service.
 */
@Path("/")
@Produces(MediaType.TEXT_XML)
public class FopEndpoint {

    /** The loggin facility */
    private static final Logger logger = LoggerFactory.getLogger(FopEndpoint.class);

    /** The FOP service */
    protected transient FopService fopService = null;

    /** The request environment */
    protected Environment environment = Environment.Production;

    /** The endpoint documentation */
    private String docs = null;

    /**
     * Downloads both XML and XSL document and transforms them to PDF.
     * 
     * @param xmlURL
     *          the URL to the XML document
     * @param xslURL
     *          the URL to the XSL document
     * @return the generated PDF
     * @throws WebApplicationException
     *           if the XML document cannot be downloaded
     * @throws WebApplicationException
     *           if the XSL document cannot be downloaded
     * @throws WebApplicationException
     *           if the PDF creation fails
     */
    @POST
    @Path("/pdf")
    public Response transformToPdf(@FormParam("xml") String xmlURL, @FormParam("xsl") String xslURL,
            @FormParam("parameters") String params) {

        // Make sure we have a service
        if (fopService == null)
            throw new WebApplicationException(Status.SERVICE_UNAVAILABLE);

        final Document xml;
        final Document xsl;

        // Load the xml document
        InputStream xmlInputStream = null;
        try {
            DocumentBuilder documentBuilder = DocumentBuilderFactory.newInstance().newDocumentBuilder();
            xmlInputStream = new URL(xmlURL).openStream();
            xml = documentBuilder.parse(xmlInputStream);
        } catch (MalformedURLException e) {
            logger.warn("Error creating xml url from '{}'", xmlURL);
            throw new WebApplicationException(Status.BAD_REQUEST);
        } catch (IOException e) {
            logger.warn("Error accessing xml document at '{}': {}", xmlURL, e.getMessage());
            throw new WebApplicationException(Status.NOT_FOUND);
        } catch (ParserConfigurationException e) {
            logger.warn("Error setting up xml parser: {}", e.getMessage());
            throw new WebApplicationException(Status.BAD_REQUEST);
        } catch (SAXException e) {
            logger.warn("Error parsing xml document from {}: {}", xmlURL, e.getMessage());
            throw new WebApplicationException(Status.BAD_REQUEST);
        } finally {
            IOUtils.closeQuietly(xmlInputStream);
        }

        // Load the XLST stylesheet
        InputStream xslInputStream = null;
        try {
            DocumentBuilder documentBuilder = DocumentBuilderFactory.newInstance().newDocumentBuilder();
            xslInputStream = new URL(xslURL).openStream();
            xsl = documentBuilder.parse(xslInputStream);
        } catch (MalformedURLException e) {
            logger.warn("Error creating xsl url from '{}'", xslURL);
            throw new WebApplicationException(Status.BAD_REQUEST);
        } catch (IOException e) {
            logger.warn("Error accessing xsl stylesheet at '{}': {}", xslURL, e.getMessage());
            throw new WebApplicationException(Status.NOT_FOUND);
        } catch (ParserConfigurationException e) {
            logger.warn("Error setting up xml parser: {}", e.getMessage());
            throw new WebApplicationException(Status.BAD_REQUEST);
        } catch (SAXException e) {
            logger.warn("Error parsing xml document from {}: {}", xslURL, e.getMessage());
            throw new WebApplicationException(Status.BAD_REQUEST);
        } finally {
            IOUtils.closeQuietly(xslInputStream);
        }

        // Create the filename
        String name = FilenameUtils.getBaseName(xmlURL) + ".pdf";

        // Process the parameters
        final List<String[]> parameters = new ArrayList<String[]>();
        if (StringUtils.isNotBlank(params)) {
            for (String param : StringUtils.split(params, ";")) {
                String[] parameterValue = StringUtils.split(param, "=");
                if (parameterValue.length != 2) {
                    logger.warn("Parameter for PDF generation is malformed: {}", param);
                    throw new WebApplicationException(Status.BAD_REQUEST);
                }
                parameters.add(
                        new String[] { StringUtils.trim(parameterValue[0]), StringUtils.trim(parameterValue[1]) });
            }
        }

        // Write the file contents back
        ResponseBuilder response = Response.ok(new StreamingOutput() {
            public void write(OutputStream os) throws IOException, WebApplicationException {
                try {
                    fopService.xml2pdf(xml, xsl, parameters.toArray(new String[parameters.size()][2]), os);
                } catch (IOException e) {
                    Throwable cause = e.getCause();
                    if (cause == null || !"Broken pipe".equals(cause.getMessage()))
                        logger.warn("Error writing file contents to response", e);
                } catch (TransformerConfigurationException e) {
                    logger.error("Error setting up the XSL transfomer: {}", e.getMessage());
                    throw new WebApplicationException(Status.INTERNAL_SERVER_ERROR);
                } catch (FOPException e) {
                    logger.error("Error creating PDF document: {}", e.getMessage());
                    throw new WebApplicationException(Status.INTERNAL_SERVER_ERROR);
                } catch (TransformerException e) {
                    logger.error("Error transforming to PDF: {}", e.getMessage());
                    throw new WebApplicationException(Status.INTERNAL_SERVER_ERROR);
                } finally {
                    IOUtils.closeQuietly(os);
                }
            }
        });

        // Set response information
        response.type("application/pdf");
        response.header("Content-Disposition", "inline; filename=" + name);
        response.lastModified(new Date());

        return response.build();
    }

    /**
     * Returns the endpoint documentation.
     * 
     * @return the endpoint documentation
     */
    @GET
    @Path("/docs")
    @Produces(MediaType.TEXT_HTML)
    public String getDocumentation(@Context HttpServletRequest request) {
        if (docs == null) {
            String docsPath = request.getRequestURI();
            String docsPathExtension = request.getPathInfo();
            String servicePath = request.getRequestURI().substring(0,
                    docsPath.length() - docsPathExtension.length());
            docs = FopEndpointDocs.createDocumentation(servicePath);
        }
        return docs;
    }

    /**
     * Callback for OSGi to set the FOP service.
     * 
     * @param fopService
     *          the FOP service
     */
    void setFopService(FopService fopService) {
        this.fopService = fopService;
    }

    /**
     * Callback for OSGi to remove the FOP service.
     * 
     * @param fopService
     *          the FOP service
     */
    void removeFopService(FopService fopService) {
        this.fopService = null;
    }

    /**
     * {@inheritDoc}
     * 
     * @see java.lang.Object#toString()
     */
    @Override
    public String toString() {
        return "Fop rest endpoint";
    }

}