play.modules.pdf.PDF.java Source code

Java tutorial

Introduction

Here is the source code for play.modules.pdf.PDF.java

Source

/**
 *
 * Copyright 2010, Lunatech Labs.
 *
 * 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.
 *
 * User: nicolas
 * Date: Feb 14, 2010
 *
 */
package play.modules.pdf;

import java.io.File;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.OutputStream;
import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;
import java.util.HashMap;
import java.util.LinkedList;
import java.util.List;
import java.util.Map;

import org.allcolor.yahp.converter.IHtmlToPdfTransformer;
import org.apache.commons.io.FilenameUtils;

import play.Play;
import play.classloading.enhancers.LVEnhancer.LVEnhancerRuntime;
import play.data.validation.Validation;
import play.exceptions.PlayException;
import play.exceptions.TemplateNotFoundException;
import play.exceptions.UnexpectedException;
import play.mvc.Http;
import play.mvc.Scope;
import play.mvc.Http.Request;
import play.vfs.VirtualFile;

public class PDF {

    public static class Options {

        public String FOOTER = null;
        public String FOOTER_TEMPLATE = null;
        public String HEADER = null;
        public String HEADER_TEMPLATE = null;
        public String ALL_PAGES = null;
        public String EVEN_PAGES = null;
        public String ODD_PAGES = null;

        public String filename = null;

        public IHtmlToPdfTransformer.PageSize pageSize = IHtmlToPdfTransformer.A4P;
    }

    public static class PDFDocument {
        public String template;
        public Options options;
        public Map<String, Object> args = new HashMap<String, Object>();
        List<IHtmlToPdfTransformer.CHeaderFooter> headerFooterList = new LinkedList<IHtmlToPdfTransformer.CHeaderFooter>();
        String content;

        private PDFDocument(String template, Options options) {
            this.template = template;
            this.options = options;
        }

        public PDFDocument(String template, Options options, Object... args) {
            this(template, options);
            try {
                // play <= v1.2.3
                Class<?> clazz = Class.forName(
                        "play.classloading.enhancers.LocalvariablesNamesEnhancer.LocalVariablesNamesTracer");
                Method method = clazz.getMethod("getAllLocalVariableNames", Object.class);
                for (Object o : args) {

                    List<String> names = (List<String>) method.invoke(null, o);
                    for (String name : names) {
                        this.args.put(name, o);
                    }
                }
            } catch (ClassNotFoundException e) {
                // play > v1.2.3
                String[] names = LVEnhancerRuntime.getParamNames().varargs;
                if (args != null && args.length > 0 && names == null)
                    throw new UnexpectedException("no varargs names while args.length > 0 !");
                for (int i = 0; i < args.length; i++) {
                    this.args.put(names[i], args[i]);
                }
            } catch (Exception e) {
                throw new UnexpectedException(e);
            }
        }

        public PDFDocument(String template, Options options, Map<String, Object> args) {
            this(template, options);
            this.args.putAll(args);
        }

        public PDFDocument() {
        }
    }

    public static class MultiPDFDocuments {
        public List<PDFDocument> documents = new LinkedList<PDFDocument>();
        public String filename;

        public MultiPDFDocuments(String filename) {
            this.filename = filename;
        }

        public MultiPDFDocuments() {
            // TODO Auto-generated constructor stub
        }

        public MultiPDFDocuments add(PDFDocument singleDoc) {
            documents.add(singleDoc);
            return this;
        }

        public MultiPDFDocuments add(String template, Options options, Object... args) {
            documents.add(new PDFDocument(template, options, args));
            return this;
        }

        public MultiPDFDocuments add(String template, Options options, Map<String, Object> args) {
            documents.add(new PDFDocument(template, options, args));
            return this;
        }
    }

    /**
     * Render the corresponding template
     *
     * @param args The template data
     */
    public static void renderPDF(Object... args) {
        // stuuuuuupid typing
        OutputStream os = null;
        writePDF(os, args);
    }

    /**
     * Render the corresponding template into a file
     * @param file the file to render to, or null to render to the current Response object
     * @param args the template data
     */
    public static void writePDF(File file, Object... args) {
        try {
            OutputStream os = new FileOutputStream(file);
            writePDF(os, args);
            os.flush();
            os.close();
        } catch (IOException e) {
            throw new UnexpectedException(e);
        }
    }

    /**
     * Render the corresponding template into a file
     * @param out the stream to render to, or null to render to the current Response object
     * @param args the template data
     */
    public static void writePDF(OutputStream out, Object... args) {
        final Http.Request request = Http.Request.current();
        final String format = request.format;

        PDFDocument singleDoc = new PDFDocument();
        MultiPDFDocuments docs = null;

        if (args.length > 0) {
            boolean firstEmpty = false;
            try {
                // play <= v1.2.3
                Class<?> clazz = Class.forName(
                        "play.classloading.enhancers.LocalvariablesNamesEnhancer.LocalVariablesNamesTracer");
                Method method = clazz.getMethod("getAllLocalVariableNames", Object.class);
                firstEmpty = ((List<String>) method.invoke(null, args[0])).isEmpty();
            } catch (ClassNotFoundException e) {
                // play <= v1.2.3
                firstEmpty = LVEnhancerRuntime.getParamNames().varargs[0].isEmpty();
            } catch (Exception e) {
                throw new UnexpectedException(e);
            }

            if (args[0] instanceof String && firstEmpty) {
                singleDoc.template = args[0].toString();
            } else if (args[0] instanceof MultiPDFDocuments) {
                docs = (MultiPDFDocuments) args[0];
            }
            if (docs == null) {
                for (Object arg : args) {
                    if (arg instanceof Options) {
                        singleDoc.options = (Options) arg;
                    }
                }
            }
        }
        if (docs == null) {
            docs = new MultiPDFDocuments();
            docs.add(singleDoc);
            if (singleDoc.template == null) {
                singleDoc.template = request.action.replace(".", "/") + "." + (format == null ? "html" : format);
            }
            if (singleDoc.options != null && singleDoc.options.filename != null)
                docs.filename = singleDoc.options.filename;
            else
                docs.filename = FilenameUtils.getBaseName(singleDoc.template) + ".pdf";
        }

        renderTemplateAsPDF(out, docs, args);
    }

    static String resolveTemplateName(String templateName, Request request, String format) {
        if (templateName.startsWith("@")) {
            templateName = templateName.substring(1);
            if (!templateName.contains(".")) {
                templateName = request.controller + "." + templateName;
            }
            templateName = templateName.replace(".", "/") + "." + (format == null ? "html" : format);
        }
        Boolean templateExists = false;
        for (VirtualFile vf : Play.templatesPath) {
            if (vf == null) {
                continue;
            }
            VirtualFile tf = vf.child(templateName);
            if (tf.exists()) {
                templateExists = true;
                break;
            }
        }
        if (!templateExists) {
            if (templateName.lastIndexOf("." + format) != -1) {
                templateName = templateName.substring(0, templateName.lastIndexOf("." + format)) + ".html";
            }
        }
        return templateName;
    }

    /**
      * Render a specific template
      *
      * @param templateName The template name
      * @param args         The template data
      */
    public static void renderTemplateAsPDF(OutputStream out, MultiPDFDocuments docs, Object... args) {
        Scope.RenderArgs templateBinding = Scope.RenderArgs.current();

        try {
            // play <= v1.2.3
            Class<?> clazz = Class
                    .forName("play.classloading.enhancers.LocalvariablesNamesEnhancer.LocalVariablesNamesTracer");
            Method method = clazz.getMethod("getAllLocalVariableNames", Object.class);
            for (Object o : args) {
                List<String> names = (List<String>) method.invoke(null, o);
                for (String name : names) {
                    templateBinding.put(name, o);
                }
            }
        } catch (ClassNotFoundException e) {
            // play <= v1.2.3
            String[] names = LVEnhancerRuntime.getParamNames().varargs;
            if (args != null && args.length > 0 && names == null)
                throw new UnexpectedException("no varargs names while args.length > 0 !");
            for (int i = 0; i < args.length; i++) {
                templateBinding.put(names[i], args[i]);
            }
        } catch (Exception e) {
            throw new UnexpectedException(e);
        }

        templateBinding.put("session", Scope.Session.current());
        templateBinding.put("request", Http.Request.current());
        templateBinding.put("flash", Scope.Flash.current());
        templateBinding.put("params", Scope.Params.current());
        try {
            templateBinding.put("errors", Validation.errors());
        } catch (Exception ex) {
            throw new UnexpectedException(ex);
        }
        try {
            if (out == null) {
                // we're rendering to the current Response object
                throw new RenderPDFTemplate(docs, templateBinding.data);
            } else {
                RenderPDFTemplate renderer = new RenderPDFTemplate(docs, templateBinding.data);
                renderer.writePDF(out, Http.Request.current(), Http.Response.current());
            }
        } catch (TemplateNotFoundException ex) {
            if (ex.isSourceAvailable()) {
                throw ex;
            }
            StackTraceElement element = PlayException.getInterestingStrackTraceElement(ex);
            if (element != null) {
                throw new TemplateNotFoundException(ex.getPath(),
                        Play.classes.getApplicationClass(element.getClassName()), element.getLineNumber());
            } else {
                throw ex;
            }
        }
    }

}