diff --git a/.gitignore b/.gitignore index 9998373..36cdea7 100644 --- a/.gitignore +++ b/.gitignore @@ -1,8 +1,10 @@ /.settings dist +classes lib/play-pdf.jar samples-and-tests/pdf/tmp samples-and-tests/pdf/log +samples-and-tests/pdf/modules build.cmd build.properties *.iws @@ -10,6 +12,7 @@ build.properties *iml .classpath .project +.settings build-stamp debian/files debian/play-1.1-pdf-module-* diff --git a/conf/dependencies.yml b/conf/dependencies.yml index 1f31d5b..ffe7ab7 100644 --- a/conf/dependencies.yml +++ b/conf/dependencies.yml @@ -1,4 +1,4 @@ -self: play -> pdf 0.9 +self: play -> pdf 0.10 require: - play \ No newline at end of file diff --git a/samples-and-tests/pdf/conf/application.conf b/samples-and-tests/pdf/conf/application.conf index 7e19aee..47da350 100644 --- a/samples-and-tests/pdf/conf/application.conf +++ b/samples-and-tests/pdf/conf/application.conf @@ -15,21 +15,12 @@ application.mode=dev # If you deploy your application to several instances be sure to use the same key ! application.secret=ef0hrz5qauwlql87vocx02i7v9jpndw05y0t39snbj0l2agxj596ztqz3rrqvbpt -# Additional modules -# ~~~~~ -# A module is another play! application. Add a line for each module you want -# to add to your application. Modules path are either absolutes or relative to -# the application root. They get loaded from top to bottom. -# -# Syntax: module.{name}={path} -module.pdf=../../ - # i18n # ~~~~~ # Define locales used by your application. # You can then place localized messages in conf/messages.{locale} files -# application.langs=fr,en,ja +application.langs=en # Date format # ~~~~~ diff --git a/samples-and-tests/pdf/conf/dependencies.yml b/samples-and-tests/pdf/conf/dependencies.yml new file mode 100644 index 0000000..775cf31 --- /dev/null +++ b/samples-and-tests/pdf/conf/dependencies.yml @@ -0,0 +1,20 @@ +# Application dependencies + +require: + - play + - play -> pdf 0.10 + +repositories: + - playModules: + type: chain + using: + - playLocalModules: + type: local + descriptor: "${application.path}/../../../play--[module]/conf/dependencies.yml" + artifact: "${application.path}/../../../play--[module]" + contains: + - play -> pdf 0.10 + - playContributedModules: + type: http + descriptor: "http://www.playframework.org/modules/repo/[module]/[revision]/dependencies.yml" + artifact: "http://www.playframework.org/modules/[module]-[revision].zip" \ No newline at end of file diff --git a/src/play/modules/pdf/PDF.java b/src/play/modules/pdf/PDF.java index 7a3d10d..0437e43 100644 --- a/src/play/modules/pdf/PDF.java +++ b/src/play/modules/pdf/PDF.java @@ -27,8 +27,6 @@ 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; @@ -38,14 +36,14 @@ 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.modules.pdf.helpers.PdfBinderHelper; import play.mvc.Http; -import play.mvc.Scope; import play.mvc.Http.Request; +import play.mvc.Scope; import play.vfs.VirtualFile; public class PDF { @@ -66,112 +64,122 @@ public static class Options { } public static class PDFDocument { - public String template; - public Options options; + public String template; + public Options options; public Map args = new HashMap(); - List headerFooterList = new LinkedList(); - 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 names = (List) 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 args) { - this(template, options); - this.args.putAll(args); - } - - public PDFDocument() { - } + List headerFooterList = new LinkedList(); + 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); + + PdfBinderHelper binderHelper = new PdfBinderHelper(); + switch (binderHelper.binderType) { + case LOCAL_VARIABLE: + for (Object o : args) { + List names = (List) binderHelper.getVariableNames(o); + if (names != null) { + for (String name : names) { + this.args.put(name, o); + } + } + } + break; + case LVENHANCER: + String[] names = (String[]) binderHelper.getVariableNames(); + + 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]); + } + break; + } + } + + public PDFDocument(String template, Options options, Map args) { + this(template, options); + this.args.putAll(args); + } + + public PDFDocument() { + // Detect the Binder of play that we need to use + } } public static class MultiPDFDocuments { - public List documents = new LinkedList(); - 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 args) { - documents.add(new PDFDocument(template, options, args)); - return this; - } + public List documents = new LinkedList(); + 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 args) { + documents.add(new PDFDocument(template, options, args)); + return this; + } } /** * Render the corresponding template - * - * @param args The template data + * + * @param args + * The template data */ public static void renderPDF(Object... args) { - // stuuuuuupid typing - OutputStream os = null; - writePDF(os, 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 + * + * @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); - } + 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 + * + * @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(); @@ -180,44 +188,47 @@ public static void writePDF(OutputStream out, Object... args) { 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) 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 (args.length > 0) { + boolean firstEmpty = false; + + PdfBinderHelper binderHelper = new PdfBinderHelper(); + switch (binderHelper.binderType) { + case LOCAL_VARIABLE: + List names = (List) binderHelper.getVariableNames(args[0]); + if (names != null) { + firstEmpty = names.isEmpty(); + } + break; + case LVENHANCER: + String[] varNames = (String[]) binderHelper.getVariableNames(); + if (varNames != null && varNames.length > 0) { + firstEmpty = varNames[0].isEmpty(); + } + break; + } + 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"; + 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); @@ -244,44 +255,45 @@ static String resolveTemplateName(String templateName, Request request, String f } if (!templateExists) { if (templateName.lastIndexOf("." + format) != -1) { - templateName = templateName.substring(0, templateName.lastIndexOf("." + format)) + ".html"; + templateName = templateName.substring(0, templateName.lastIndexOf("." + format)) + ".html"; } } return templateName; - } + } - /** + /** * Render a specific template - * - * @param templateName The template name - * @param args The template data + * + * @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 names = (List) method.invoke(null, o); - for (String name : names) { - templateBinding.put(name, o); + + PdfBinderHelper binderHelper = new PdfBinderHelper(); + switch (binderHelper.binderType) { + case LOCAL_VARIABLE: + for (Object o : args) { + List names = (List) binderHelper.getVariableNames(o); + if (names != null) { + 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) + break; + case LVENHANCER: + String[] names = (String[]) binderHelper.getVariableNames(); + 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++) { + for (int i = 0; i < args.length; i++) { templateBinding.put(names[i], args[i]); } - } catch (Exception e) { - throw new UnexpectedException(e); - } - + break; + } + templateBinding.put("session", Scope.Session.current()); templateBinding.put("request", Http.Request.current()); templateBinding.put("flash", Scope.Flash.current()); @@ -292,12 +304,12 @@ public static void renderTemplateAsPDF(OutputStream out, MultiPDFDocuments docs, 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()); + 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()) { @@ -305,13 +317,11 @@ public static void renderTemplateAsPDF(OutputStream out, MultiPDFDocuments docs, } StackTraceElement element = PlayException.getInterestingStrackTraceElement(ex); if (element != null) { - throw new TemplateNotFoundException(ex.getPath(), - Play.classes.getApplicationClass(element.getClassName()), element.getLineNumber()); + throw new TemplateNotFoundException(ex.getPath(), Play.classes.getApplicationClass(element + .getClassName()), element.getLineNumber()); } else { throw ex; } } } - } - diff --git a/src/play/modules/pdf/helpers/PdfBinderHelper.java b/src/play/modules/pdf/helpers/PdfBinderHelper.java new file mode 100644 index 0000000..40622a8 --- /dev/null +++ b/src/play/modules/pdf/helpers/PdfBinderHelper.java @@ -0,0 +1,95 @@ +package play.modules.pdf.helpers; + +import java.lang.reflect.Field; +import java.lang.reflect.Method; + +import play.exceptions.UnexpectedException; + +/** + * Class to manage the two different Binder user in Play + *
    + *
  • LVEnhancerRuntimer in Play master
  • + *
  • LocalVariablesNamesTracer in Play 1.2.x, 1.3.x
  • + *
+ * User: Alexandre Date: Sep 14, 2013 + * + */ +public class PdfBinderHelper { + + public enum BinderType { + /** + * Binder of Play V1.2.x, V1.3.x + */ + LOCAL_VARIABLE, + /** + * Binder of Play master + */ + LVENHANCER; + } + + public BinderType binderType; + private Method getVariablesNameMethod; + + public PdfBinderHelper() { + this.init(); + } + + public Object getVariableNames() { + return getVariableNames(null); + } + + public Object getVariableNames(Object o) { + try { + switch (binderType) { + case LOCAL_VARIABLE: + return getVariablesNameMethod.invoke(null, o); + case LVENHANCER: + Object paramsNames = getVariablesNameMethod.invoke(null); + Class paramsNamesClazz = Class + .forName("play.classloading.enhancers.LVEnhancer$LVEnhancerRuntime$ParamsNames"); + if (paramsNamesClazz != null) { + Field field = paramsNamesClazz.getDeclaredField("varargs"); + if (field != null) { + return field.get(paramsNames); + } + } + break; + } + } catch (Exception e) { + // TODO Auto-generated catch block + e.printStackTrace(); + } + return null; + } + + /** + * Init the class to detect the binder + * + */ + private void init() { + try { + // play <= v1.2.3 + Class clazz = Class + .forName("play.classloading.enhancers.LocalvariablesNamesEnhancer$LocalVariablesNamesTracer"); + if (clazz != null) { + getVariablesNameMethod = clazz.getMethod("getAllLocalVariableNames", Object.class); + this.binderType = BinderType.LOCAL_VARIABLE; + } + } catch (ClassNotFoundException e) { + // play > v1.2.3 + try { + Class clazz = Class.forName("play.classloading.enhancers.LVEnhancer$LVEnhancerRuntime"); + if (clazz != null) { + getVariablesNameMethod = clazz.getMethod("getParamNames"); + this.binderType = BinderType.LVENHANCER; + } + } catch (Exception e1) { + throw new UnexpectedException(e1); + } + } catch (Exception e) { + throw new UnexpectedException(e); + } + + } + +}