se.altrusoft.docserv.controllers.Application.java Source code

Java tutorial

Introduction

Here is the source code for se.altrusoft.docserv.controllers.Application.java

Source

/*
 * Copyright (c) 2013 Altrusoft AB.
 * This Source Code Form is subject to the terms of the Mozilla Public
 * License, v. 2.0. If a copy of the MPL was not distributed with this
 * file, You can obtain one at http://mozilla.org/MPL/2.0/.
 */
package se.altrusoft.docserv.controllers;

import java.io.ByteArrayInputStream;
import java.io.ByteArrayOutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
import java.util.LinkedHashMap;
import java.util.Map;

import org.apache.commons.codec.binary.Base64;
import org.apache.commons.io.IOUtils;
import org.springframework.beans.factory.annotation.Autowired;

import play.Logger;
import play.mvc.BodyParser;
import play.mvc.BodyParser.Json;
import play.mvc.Controller;
import play.mvc.Result;
import se.altrusoft.docserv.controllers.ooconverter.OOoInputStream;
import se.altrusoft.docserv.controllers.ooconverter.OOoOutputStream;
import se.altrusoft.docserv.controllers.ooconverter.OOoStreamConverter;
import se.altrusoft.docserv.models.DynamicModel;
import se.altrusoft.docserv.models.TemplateModel;
import se.altrusoft.docserv.models.TemplateType;
import se.altrusoft.docserv.odsprocessor.ODSProcessor;

import com.fasterxml.jackson.core.JsonParseException;
import com.fasterxml.jackson.databind.JsonMappingException;
import com.fasterxml.jackson.databind.ObjectMapper;
import com.sun.star.comp.helper.Bootstrap;
import com.sun.star.comp.helper.BootstrapException;
import com.sun.star.uno.Exception;
import com.sun.star.uno.XComponentContext;

import fr.opensagres.xdocreport.core.XDocReportException;
import fr.opensagres.xdocreport.document.IXDocReport;
import fr.opensagres.xdocreport.document.registry.XDocReportRegistry;
import fr.opensagres.xdocreport.template.IContext;
import fr.opensagres.xdocreport.template.TemplateEngineKind;

@org.springframework.stereotype.Controller
public class Application extends Controller {
    private static final String ENCODING_BASE64 = "base64";

    @Autowired
    private Map<String, TemplateModel> templates;

    private static void generateDocumentFromTemplate(TemplateModel templateModel, OutputStream out)
            throws XDocReportException, IOException {
        InputStream in = null;
        try {
            in = templateModel.getTemplateFile().getInputStream();

            IXDocReport report = null;
            if (TemplateType.VELOCITY.equals(templateModel.getTemplateType())) {
                report = XDocReportRegistry.getRegistry().loadReport(in, TemplateEngineKind.Velocity);
            } else {
                report = XDocReportRegistry.getRegistry().loadReport(in, TemplateEngineKind.Freemarker);
            }

            IContext context = report.createContext();
            context.put(templateModel.getInTemplateDesignation(), templateModel);

            if (templateModel.getPostProcessor() != null) {
                ByteArrayOutputStream tempOutputStream = new ByteArrayOutputStream();
                report.process(context, tempOutputStream);
                InputStream tempInputStream = new ByteArrayInputStream(tempOutputStream.toByteArray());
                ODSProcessor.transformODS(tempInputStream, out, templateModel.getPostProcessor());
            } else {
                report.process(context, out);
            }
        } finally {
            IOUtils.closeQuietly(in);
        }
    }

    @SuppressWarnings("unchecked")
    @BodyParser.Of(Json.class)
    public Result getDocument(String templateName, String encoding) {
        // TODO: Use one static ObjectMapper of re-creating?
        ObjectMapper mapper = new ObjectMapper();
        String json = request().body().asJson().toString();
        String acceptHeader = request().getHeader(ACCEPT);

        TemplateModel templateModel = templates.get(templateName);

        try {
            if (!templateModel.isDynamic()) {
                mapper.readerForUpdating(templateModel).readValue(json);

                templateModel.translateProperties();

                /* Expand model - if needed -HH */
                templateModel.expandModel();
            } else {
                Object readValue = mapper.readValue(json, Object.class);
                LinkedHashMap<String, Object> jsonValue = (LinkedHashMap<String, Object>) readValue;
                TemplateModel dynamicTemplateModel = DynamicModel.getTemplateModel(templateName, jsonValue);
                // TODO: applicationContext properties has to injected in
                // the new dynamically generated model ...
                // This is only partially done here for the template file -
                // needs design?
                dynamicTemplateModel.setTemplateFile(templateModel.getTemplateFile());
                templateModel = dynamicTemplateModel;
            }
        } catch (JsonParseException e) {
            Logger.warn("Unable to parse received Json data - bad request", e);
            return badRequest("JsonParseException");
        } catch (JsonMappingException e) {
            Logger.warn("Received Json data does not map to template model - bad resquest", e);
            return badRequest("Received Json data does not map to template model");
        } catch (IOException e) {
            Logger.error("IOException while reading Json data", e);
            return internalServerError("IOException while reading Json data");
        } catch (java.lang.Exception e) {
            // TODO Auto-generated catch block
            e.printStackTrace();
        }

        ByteArrayOutputStream generatedDocumentOutputStream = null;

        try {
            MimeType mimeType = MimeType.getMimeType(acceptHeader);

            if (mimeType != null) {
                generatedDocumentOutputStream = new ByteArrayOutputStream();

                generateDocumentFromTemplate(templateModel, generatedDocumentOutputStream);

                if (mimeType.getConvertFilterName() != null) {
                    Logger.debug("Generating " + mimeType.getValue() + "...");

                    generatedDocumentOutputStream = convert(generatedDocumentOutputStream,
                            mimeType.getConvertFilterName(), mimeType.getFilterParameters());
                }
            } else {
                String warnMessage = "Unsupported mime-type: " + acceptHeader;
                Logger.warn(warnMessage);
                return badRequest(warnMessage);
            }

            // TODO: Do this in parallel, i.e. do not produce the ByteArray...
            // --HH
            if (encoding != null && encoding.equalsIgnoreCase(ENCODING_BASE64)) {
                byte[] content = generatedDocumentOutputStream.toByteArray();
                byte[] bs64EncodedContent = new Base64().encode(content);
                Logger.info("Returning base 64 encoded content OK");
                response().setHeader(CONTENT_TRANSFER_ENCODING, ENCODING_BASE64);
                return ok(new ByteArrayInputStream(bs64EncodedContent)).as(mimeType.getValue());
            } else {
                Logger.info("Returning OK");
                return ok(new ByteArrayInputStream(generatedDocumentOutputStream.toByteArray()))
                        .as(mimeType.getValue());
            }
        } catch (XDocReportException e) {
            String errorMessage = "Unable to generate document";
            Logger.error(errorMessage, e);
            e.printStackTrace();
            return internalServerError(errorMessage);
        } catch (IOException e) {
            String errorMessage = "Unexpected error when generating document";
            Logger.error(errorMessage, e);
            e.printStackTrace();
            return internalServerError(errorMessage);
        } catch (BootstrapException e) {
            String errorMessage = "Unable to bootstrap LibreOffice";
            Logger.error(errorMessage, e);
            e.printStackTrace();
            return internalServerError(errorMessage);
        } catch (Exception e) {
            String errorMessage = "LibreOffice Exception";
            Logger.error(errorMessage, e);
            e.printStackTrace();
            return internalServerError(errorMessage);
        } finally {
            IOUtils.closeQuietly(generatedDocumentOutputStream);
        }
    }

    private static ByteArrayOutputStream convert(ByteArrayOutputStream odxStream, String targetFormat,
            Map<String, Object> filterParameters) throws BootstrapException, Exception, IOException {
        // TODO: Can this be done once during app init?
        XComponentContext xContext = Bootstrap.bootstrap();

        OOoStreamConverter converter = new OOoStreamConverter(xContext);

        ByteArrayOutputStream generatedPDFOutputStream = new ByteArrayOutputStream();
        OOoOutputStream convertedOutputStream = null;
        OOoInputStream generatedODFInputStream = null;
        try {
            convertedOutputStream = null;
            generatedODFInputStream = new OOoInputStream(odxStream.toByteArray());
            convertedOutputStream = new OOoOutputStream();
            converter.convert(generatedODFInputStream, convertedOutputStream, targetFormat, filterParameters);

            generatedPDFOutputStream.write(convertedOutputStream.toByteArray());
        } finally {
            IOUtils.closeQuietly(generatedODFInputStream);
            IOUtils.closeQuietly(convertedOutputStream);
        }

        return generatedPDFOutputStream;
    }

    public Map<String, TemplateModel> getTemplates() {
        return templates;
    }

    public void setTemplates(Map<String, TemplateModel> templates) {
        this.templates = templates;
    }
}